mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r23678: Update to current lorikeet-heimdal (-r 767), which should fix the
panics on hosts without /dev/random. Andrew Bartlett
This commit is contained in:
parent
d2fba8faf0
commit
14a4ddb131
@ -36,10 +36,9 @@
|
||||
#include <getarg.h>
|
||||
#include <parse_bytes.h>
|
||||
|
||||
RCSID("$Id: default_config.c 20532 2007-04-23 07:46:57Z lha $");
|
||||
RCSID("$Id: default_config.c 21296 2007-06-25 14:49:11Z lha $");
|
||||
|
||||
|
||||
int
|
||||
krb5_error_code
|
||||
krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
|
||||
{
|
||||
krb5_kdc_configuration *c;
|
||||
@ -62,7 +61,8 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
|
||||
c->enable_524 = FALSE;
|
||||
c->enable_v4_cross_realm = FALSE;
|
||||
c->enable_pkinit = FALSE;
|
||||
c->enable_pkinit_princ_in_cert = TRUE;
|
||||
c->pkinit_princ_in_cert = TRUE;
|
||||
c->pkinit_require_binding = TRUE;
|
||||
c->db = NULL;
|
||||
c->num_db = 0;
|
||||
c->logf = NULL;
|
||||
@ -257,12 +257,19 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
|
||||
krb5_config_free_strings(pool_list);
|
||||
krb5_config_free_strings(revoke_list);
|
||||
|
||||
c->enable_pkinit_princ_in_cert =
|
||||
c->pkinit_princ_in_cert =
|
||||
krb5_config_get_bool_default(context, NULL,
|
||||
c->enable_pkinit_princ_in_cert,
|
||||
c->pkinit_princ_in_cert,
|
||||
"kdc",
|
||||
"pkinit_principal_in_certificate",
|
||||
NULL);
|
||||
|
||||
c->pkinit_require_binding =
|
||||
krb5_config_get_bool_default(context, NULL,
|
||||
c->pkinit_require_binding,
|
||||
"kdc",
|
||||
"pkinit_win2k_require_binding",
|
||||
NULL);
|
||||
}
|
||||
|
||||
c->pkinit_dh_min_bits =
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "kdc_locl.h"
|
||||
#include <hex.h>
|
||||
|
||||
RCSID("$Id: digest.c 20877 2007-06-04 04:07:26Z lha $");
|
||||
RCSID("$Id: digest.c 21241 2007-06-20 11:30:19Z lha $");
|
||||
|
||||
#define MS_CHAP_V2 0x20
|
||||
#define CHAP_MD5 0x10
|
||||
@ -156,6 +156,44 @@ static const unsigned char ms_rfc3079_magic1[27] = {
|
||||
0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
static krb5_error_code
|
||||
get_password_entry(krb5_context context,
|
||||
krb5_kdc_configuration *config,
|
||||
const char *username,
|
||||
char **password)
|
||||
{
|
||||
krb5_principal clientprincipal;
|
||||
krb5_error_code ret;
|
||||
hdb_entry_ex *user;
|
||||
HDB *db;
|
||||
|
||||
/* get username */
|
||||
ret = krb5_parse_name(context, username, &clientprincipal);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = _kdc_db_fetch(context, config, clientprincipal,
|
||||
HDB_F_GET_CLIENT, &db, &user);
|
||||
krb5_free_principal(context, clientprincipal);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hdb_entry_get_password(context, db, &user->entry, password);
|
||||
if (ret || password == NULL) {
|
||||
if (ret == 0) {
|
||||
ret = EINVAL;
|
||||
krb5_set_error_string(context, "password missing");
|
||||
}
|
||||
memset(user, 0, sizeof(*user));
|
||||
}
|
||||
_kdc_free_ent (context, user);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
@ -461,9 +499,6 @@ _kdc_do_digest(krb5_context context,
|
||||
break;
|
||||
}
|
||||
case choice_DigestReqInner_digestRequest: {
|
||||
krb5_principal clientprincipal;
|
||||
HDB *db;
|
||||
|
||||
sp = krb5_storage_emem();
|
||||
if (sp == NULL) {
|
||||
ret = ENOMEM;
|
||||
@ -571,29 +606,6 @@ _kdc_do_digest(krb5_context context,
|
||||
}
|
||||
}
|
||||
|
||||
/* get username */
|
||||
ret = krb5_parse_name(context,
|
||||
ireq.u.digestRequest.username,
|
||||
&clientprincipal);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = _kdc_db_fetch(context, config, clientprincipal,
|
||||
HDB_F_GET_CLIENT, &db, &user);
|
||||
|
||||
krb5_free_principal(context, clientprincipal);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = hdb_entry_get_password(context, db, &user->entry, &password);
|
||||
if (ret || password == NULL) {
|
||||
if (ret == 0) {
|
||||
ret = EINVAL;
|
||||
krb5_set_error_string(context, "password missing");
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcasecmp(ireq.u.digestRequest.type, "CHAP") == 0) {
|
||||
MD5_CTX ctx;
|
||||
unsigned char md[MD5_DIGEST_LENGTH];
|
||||
@ -618,6 +630,12 @@ _kdc_do_digest(krb5_context context,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = get_password_entry(context, config,
|
||||
ireq.u.digestRequest.username,
|
||||
&password);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, &id, 1);
|
||||
MD5_Update(&ctx, password, strlen(password));
|
||||
@ -664,6 +682,12 @@ _kdc_do_digest(krb5_context context,
|
||||
if (ireq.u.digestRequest.realm == NULL)
|
||||
goto out;
|
||||
|
||||
ret = get_password_entry(context, config,
|
||||
ireq.u.digestRequest.username,
|
||||
&password);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, ireq.u.digestRequest.username,
|
||||
strlen(ireq.u.digestRequest.username));
|
||||
@ -692,7 +716,7 @@ _kdc_do_digest(krb5_context context,
|
||||
if (A1 == NULL) {
|
||||
krb5_set_error_string(context, "out of memory");
|
||||
ret = ENOMEM;
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
MD5_Init(&ctx);
|
||||
@ -712,7 +736,7 @@ _kdc_do_digest(krb5_context context,
|
||||
krb5_set_error_string(context, "out of memory");
|
||||
ret = ENOMEM;
|
||||
free(A1);
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
MD5_Init(&ctx);
|
||||
@ -758,6 +782,7 @@ _kdc_do_digest(krb5_context context,
|
||||
|
||||
} else if (strcasecmp(ireq.u.digestRequest.type, "MS-CHAP-V2") == 0) {
|
||||
unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];
|
||||
krb5_principal clientprincipal = NULL;
|
||||
char *mdx;
|
||||
const char *username;
|
||||
struct ntlm_buf answer;
|
||||
@ -766,20 +791,20 @@ _kdc_do_digest(krb5_context context,
|
||||
|
||||
if ((config->digests_allowed & MS_CHAP_V2) == 0) {
|
||||
kdc_log(context, config, 0, "MS-CHAP-V2 not allowed");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ireq.u.digestRequest.clientNonce == NULL) {
|
||||
krb5_set_error_string(context,
|
||||
"MS-CHAP-V2 clientNonce missing");
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
if (serverNonce.length != 16) {
|
||||
krb5_set_error_string(context,
|
||||
"MS-CHAP-V2 serverNonce wrong length");
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* strip of the domain component */
|
||||
@ -821,7 +846,7 @@ _kdc_do_digest(krb5_context context,
|
||||
/* NtPasswordHash */
|
||||
ret = krb5_parse_name(context, username, &clientprincipal);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto failed;
|
||||
|
||||
ret = _kdc_db_fetch(context, config, clientprincipal,
|
||||
HDB_F_GET_CLIENT, NULL, &user);
|
||||
@ -830,7 +855,7 @@ _kdc_do_digest(krb5_context context,
|
||||
krb5_set_error_string(context,
|
||||
"MS-CHAP-V2 user %s not in database",
|
||||
username);
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ret = hdb_enctype2key(context, &user->entry,
|
||||
@ -839,7 +864,7 @@ _kdc_do_digest(krb5_context context,
|
||||
krb5_set_error_string(context,
|
||||
"MS-CHAP-V2 missing arcfour key %s",
|
||||
username);
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* ChallengeResponse */
|
||||
@ -848,7 +873,7 @@ _kdc_do_digest(krb5_context context,
|
||||
challange, &answer);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context, "NTLM missing arcfour key");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
hex_encode(answer.data, answer.length, &mdx);
|
||||
@ -861,15 +886,15 @@ _kdc_do_digest(krb5_context context,
|
||||
|
||||
r.element = choice_DigestRepInner_response;
|
||||
ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);
|
||||
free(mdx);
|
||||
if (ret == 0) {
|
||||
r.u.response.success = TRUE;
|
||||
} else {
|
||||
kdc_log(context, config, 0,
|
||||
"MS-CHAP-V2 reply mismatch for %s",
|
||||
"MS-CHAP-V2 hash mismatch for %s",
|
||||
ireq.u.digestRequest.username);
|
||||
r.u.response.success = FALSE;
|
||||
}
|
||||
free(mdx);
|
||||
|
||||
if (r.u.response.success) {
|
||||
unsigned char hashhash[MD4_DIGEST_LENGTH];
|
||||
@ -958,7 +983,7 @@ _kdc_do_digest(krb5_context context,
|
||||
|
||||
if ((config->digests_allowed & (NTLM_V1|NTLM_V1_SESSION|NTLM_V2)) == 0) {
|
||||
kdc_log(context, config, 0, "NTLM not allowed");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
r.element = choice_DigestRepInner_ntlmInitReply;
|
||||
@ -967,14 +992,14 @@ _kdc_do_digest(krb5_context context,
|
||||
|
||||
if ((ireq.u.ntlmInit.flags & NTLM_NEG_UNICODE) == 0) {
|
||||
kdc_log(context, config, 0, "NTLM client have no unicode");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ireq.u.ntlmInit.flags & NTLM_NEG_NTLM)
|
||||
r.u.ntlmInitReply.flags |= NTLM_NEG_NTLM;
|
||||
else {
|
||||
kdc_log(context, config, 0, "NTLM client doesn't support NTLM");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
r.u.ntlmInitReply.flags |=
|
||||
@ -1095,7 +1120,7 @@ _kdc_do_digest(krb5_context context,
|
||||
ireq.u.ntlmRequest.username,
|
||||
&clientprincipal);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto failed;
|
||||
|
||||
ret = _kdc_db_fetch(context, config, clientprincipal,
|
||||
HDB_F_GET_CLIENT, NULL, &user);
|
||||
@ -1103,20 +1128,23 @@ _kdc_do_digest(krb5_context context,
|
||||
if (ret) {
|
||||
krb5_set_error_string(context, "NTLM user %s not in database",
|
||||
ireq.u.ntlmRequest.username);
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ret = get_digest_key(context, config, server, &crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto failed;
|
||||
|
||||
ret = krb5_decrypt(context, crypto, KRB5_KU_DIGEST_OPAQUE,
|
||||
ireq.u.ntlmRequest.opaque.data,
|
||||
ireq.u.ntlmRequest.opaque.length, &buf);
|
||||
krb5_crypto_destroy(context, crypto);
|
||||
crypto = NULL;
|
||||
if (ret)
|
||||
goto out;
|
||||
if (ret) {
|
||||
kdc_log(context, config, 0,
|
||||
"Failed to decrypt nonce from %s", from);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
sp = krb5_storage_from_data(&buf);
|
||||
if (sp == NULL) {
|
||||
@ -1185,7 +1213,7 @@ _kdc_do_digest(krb5_context context,
|
||||
free(targetname);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context, "NTLM v2 verify failed");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* XXX verify infotarget matches client (checksum ?) */
|
||||
@ -1205,14 +1233,14 @@ _kdc_do_digest(krb5_context context,
|
||||
if ((config->digests_allowed & NTLM_V1_SESSION) == 0) {
|
||||
kdc_log(context, config, 0, "NTLM v1-session not allowed");
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ireq.u.ntlmRequest.lm.length != 24) {
|
||||
krb5_set_error_string(context, "LM hash have wrong length "
|
||||
"for NTLM session key");
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
MD5_Init(&md5ctx);
|
||||
@ -1223,7 +1251,7 @@ _kdc_do_digest(krb5_context context,
|
||||
} else {
|
||||
if ((config->digests_allowed & NTLM_V1) == 0) {
|
||||
kdc_log(context, config, 0, "NTLM v1 not allowed");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1232,7 +1260,7 @@ _kdc_do_digest(krb5_context context,
|
||||
challange, &answer);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context, "NTLM missing arcfour key");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ireq.u.ntlmRequest.ntlm.length != answer.length ||
|
||||
@ -1241,7 +1269,7 @@ _kdc_do_digest(krb5_context context,
|
||||
free(answer.data);
|
||||
ret = EINVAL;
|
||||
krb5_set_error_string(context, "NTLM hash mismatch");
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
free(answer.data);
|
||||
|
||||
@ -1265,7 +1293,7 @@ _kdc_do_digest(krb5_context context,
|
||||
"NTLM client failed to neg key "
|
||||
"exchange but still sent key");
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
len = ireq.u.ntlmRequest.sessionkey->length;
|
||||
@ -1273,7 +1301,7 @@ _kdc_do_digest(krb5_context context,
|
||||
krb5_set_error_string(context,
|
||||
"NTLM master key wrong length: %lu",
|
||||
(unsigned long)len);
|
||||
goto out;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
RC4_set_key(&rc4, sizeof(sessionkey), sessionkey);
|
||||
@ -1301,12 +1329,12 @@ _kdc_do_digest(krb5_context context,
|
||||
r.u.ntlmResponse.success = 1;
|
||||
kdc_log(context, config, 0, "NTLM version %d successful for %s",
|
||||
version, ireq.u.ntlmRequest.username);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
failed:
|
||||
r.element = choice_DigestRepInner_error;
|
||||
r.u.error.reason = strdup("unknown operation");
|
||||
r.u.error.reason = strdup("unknown/failed operation");
|
||||
if (r.u.error.reason == NULL) {
|
||||
krb5_set_error_string(context, "out of memory");
|
||||
ret = ENOMEM;
|
||||
|
@ -37,7 +37,7 @@ kdc_openlog (
|
||||
krb5_context /*context*/,
|
||||
krb5_kdc_configuration */*config*/);
|
||||
|
||||
int
|
||||
krb5_error_code
|
||||
krb5_kdc_get_config (
|
||||
krb5_context /*context*/,
|
||||
krb5_kdc_configuration **/*config*/);
|
||||
@ -74,6 +74,11 @@ krb5_kdc_save_request (
|
||||
const krb5_data */*reply*/,
|
||||
const struct sockaddr */*sa*/);
|
||||
|
||||
krb5_error_code
|
||||
krb5_kdc_set_dbinfo (
|
||||
krb5_context /*context*/,
|
||||
struct krb5_kdc_configuration */*c*/);
|
||||
|
||||
void
|
||||
krb5_kdc_update_time (struct timeval */*tv*/);
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: kdc.h 19907 2007-01-14 23:10:24Z lha $
|
||||
* $Id: kdc.h 21287 2007-06-25 14:09:03Z lha $
|
||||
*/
|
||||
|
||||
#ifndef __KDC_H__
|
||||
@ -73,13 +73,13 @@ typedef struct krb5_kdc_configuration {
|
||||
krb5_boolean enable_524;
|
||||
|
||||
krb5_boolean enable_pkinit;
|
||||
krb5_boolean enable_pkinit_princ_in_cert;
|
||||
krb5_boolean pkinit_princ_in_cert;
|
||||
char *pkinit_kdc_ocsp_file;
|
||||
int pkinit_dh_min_bits;
|
||||
int pkinit_require_binding;
|
||||
|
||||
krb5_log_facility *logf;
|
||||
|
||||
int pkinit_dh_min_bits;
|
||||
|
||||
int enable_digest;
|
||||
int digests_allowed;
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "kdc_locl.h"
|
||||
|
||||
RCSID("$Id: krb5tgs.c 21041 2007-06-10 06:21:12Z lha $");
|
||||
RCSID("$Id: krb5tgs.c 21262 2007-06-21 15:18:37Z lha $");
|
||||
|
||||
/*
|
||||
* return the realm of a krbtgt-ticket or NULL
|
||||
@ -475,12 +475,14 @@ check_tgs_flags(krb5_context context,
|
||||
et->endtime = min(*et->renew_till, et->endtime);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* checks for excess flags */
|
||||
if(f.request_anonymous && !config->allow_anonymous){
|
||||
kdc_log(context, config, 0,
|
||||
"Request for anonymous ticket");
|
||||
return KRB5KDC_ERR_BADOPTION;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -731,10 +733,12 @@ tgs_make_reply(krb5_context context,
|
||||
&rep.ticket.realm);
|
||||
_krb5_principal2principalname(&rep.ticket.sname, server->entry.principal);
|
||||
copy_Realm(&tgt_name->realm, &rep.crealm);
|
||||
/*
|
||||
if (f.request_anonymous)
|
||||
_kdc_make_anonymous_principalname (&rep.cname);
|
||||
else
|
||||
copy_PrincipalName(&tgt_name->name, &rep.cname);
|
||||
else */
|
||||
|
||||
copy_PrincipalName(&tgt_name->name, &rep.cname);
|
||||
rep.ticket.tkt_vno = 5;
|
||||
|
||||
ek.caddr = et.caddr;
|
||||
@ -1707,24 +1711,20 @@ server_lookup:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check PAC if there is one */
|
||||
{
|
||||
/* check PAC if not cross realm and if there is one */
|
||||
if (!cross_realm) {
|
||||
Key *tkey;
|
||||
krb5_keyblock *tgtkey = NULL;
|
||||
|
||||
if (!cross_realm) {
|
||||
ret = hdb_enctype2key(context, &krbtgt->entry,
|
||||
krbtgt_etype, &tkey);
|
||||
if(ret) {
|
||||
kdc_log(context, config, 0,
|
||||
"Failed to find key for krbtgt PAC check");
|
||||
goto out;
|
||||
}
|
||||
tgtkey = &tkey->key;
|
||||
ret = hdb_enctype2key(context, &krbtgt->entry,
|
||||
krbtgt_etype, &tkey);
|
||||
if(ret) {
|
||||
kdc_log(context, config, 0,
|
||||
"Failed to find key for krbtgt PAC check");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = check_PAC(context, config, client_principal,
|
||||
client, server, ekey, tgtkey,
|
||||
client, server, ekey, &tkey->key,
|
||||
tgt, &rspac, &require_signedpath);
|
||||
if (ret) {
|
||||
kdc_log(context, config, 0,
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "kdc_locl.h"
|
||||
|
||||
RCSID("$Id: misc.c 17951 2006-08-28 14:41:49Z lha $");
|
||||
RCSID("$Id: misc.c 21106 2007-06-18 10:18:11Z lha $");
|
||||
|
||||
struct timeval _kdc_now;
|
||||
|
||||
@ -46,12 +46,14 @@ _kdc_db_fetch(krb5_context context,
|
||||
hdb_entry_ex **h)
|
||||
{
|
||||
hdb_entry_ex *ent;
|
||||
krb5_error_code ret = HDB_ERR_NOENTRY;
|
||||
krb5_error_code ret;
|
||||
int i;
|
||||
|
||||
ent = calloc (1, sizeof (*ent));
|
||||
if (ent == NULL)
|
||||
if (ent == NULL) {
|
||||
krb5_set_error_string(context, "out of memory");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
for(i = 0; i < config->num_db; i++) {
|
||||
ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0);
|
||||
@ -74,7 +76,8 @@ _kdc_db_fetch(krb5_context context,
|
||||
}
|
||||
}
|
||||
free(ent);
|
||||
return ret;
|
||||
krb5_set_error_string(context, "no such entry found in hdb");
|
||||
return HDB_ERR_NOENTRY;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "kdc_locl.h"
|
||||
|
||||
RCSID("$Id: pkinit.c 21039 2007-06-10 06:20:31Z lha $");
|
||||
RCSID("$Id: pkinit.c 21290 2007-06-25 14:13:23Z lha $");
|
||||
|
||||
#ifdef PKINIT
|
||||
|
||||
@ -380,6 +380,7 @@ _kdc_pk_rd_padata(krb5_context context,
|
||||
*ret_params = NULL;
|
||||
|
||||
if (!config->enable_pkinit) {
|
||||
kdc_log(context, config, 0, "PK-INIT request but PK-INIT not enabled");
|
||||
krb5_clear_error_string(context);
|
||||
return 0;
|
||||
}
|
||||
@ -676,6 +677,7 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
|
||||
|
||||
static krb5_error_code
|
||||
pk_mk_pa_reply_enckey(krb5_context context,
|
||||
krb5_kdc_configuration *config,
|
||||
pk_client_params *client_params,
|
||||
const KDC_REQ *req,
|
||||
const krb5_data *req_buffer,
|
||||
@ -700,8 +702,11 @@ pk_mk_pa_reply_enckey(krb5_context context,
|
||||
switch (client_params->type) {
|
||||
case PKINIT_COMPAT_WIN2K: {
|
||||
int i = 0;
|
||||
if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL)
|
||||
if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL
|
||||
&& config->pkinit_require_binding == 0)
|
||||
{
|
||||
do_win2k = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PKINIT_COMPAT_27:
|
||||
@ -1015,6 +1020,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
|
||||
goto out;
|
||||
}
|
||||
ret = pk_mk_pa_reply_enckey(context,
|
||||
config,
|
||||
client_params,
|
||||
req,
|
||||
req_buffer,
|
||||
@ -1110,6 +1116,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
|
||||
goto out;
|
||||
}
|
||||
ret = pk_mk_pa_reply_enckey(context,
|
||||
config,
|
||||
client_params,
|
||||
req,
|
||||
req_buffer,
|
||||
@ -1384,7 +1391,7 @@ _kdc_pk_check_client(krb5_context context,
|
||||
"Trying to authorize PK-INIT subject DN %s",
|
||||
*subject_name);
|
||||
|
||||
if (config->enable_pkinit_princ_in_cert) {
|
||||
if (config->pkinit_princ_in_cert) {
|
||||
ret = match_rfc_san(context, config,
|
||||
client_params->cert,
|
||||
client->entry.principal);
|
||||
@ -1508,7 +1515,8 @@ _kdc_add_inital_verified_cas(krb5_context context,
|
||||
krb5_abortx(context, "internal asn.1 encoder error");
|
||||
|
||||
ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
|
||||
ad_initial_verified_cas, &data);
|
||||
KRB5_AUTHDATA_INITIAL_VERIFIED_CAS,
|
||||
&data);
|
||||
krb5_data_free(&data);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
-- $Id: k5.asn1 21004 2007-06-08 01:53:10Z lha $
|
||||
-- $Id: k5.asn1 21092 2007-06-15 19:47:46Z lha $
|
||||
|
||||
KERBEROS5 DEFINITIONS ::=
|
||||
BEGIN
|
||||
@ -88,6 +88,7 @@ AUTHDATA-TYPE ::= INTEGER {
|
||||
KRB5-AUTHDATA-MANDATORY-TICKET-EXTENSIONS(6),
|
||||
KRB5-AUTHDATA-IN-TICKET-EXTENSIONS(7),
|
||||
KRB5-AUTHDATA-MANDATORY-FOR-KDC(8),
|
||||
KRB5-AUTHDATA-INITIAL-VERIFIED-CAS(9),
|
||||
KRB5-AUTHDATA-OSF-DCE(64),
|
||||
KRB5-AUTHDATA-SESAME(65),
|
||||
KRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66),
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "config.h"
|
||||
|
||||
#line 3 "lex.yy.c"
|
||||
#line 3 "lex.c"
|
||||
|
||||
#define YY_INT_ALIGNED short int
|
||||
|
||||
@ -343,6 +342,9 @@ FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
|
||||
typedef int yy_state_type;
|
||||
|
||||
extern int yylineno;
|
||||
|
||||
int yylineno = 1;
|
||||
|
||||
extern char *yytext;
|
||||
#define yytext_ptr yytext
|
||||
|
||||
@ -824,7 +826,7 @@ char *yytext;
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id: lex.l,v 1.31 2006/10/21 11:57:22 lha Exp $ */
|
||||
/* $Id: lex.l 18738 2006-10-21 11:57:22Z lha $ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -849,7 +851,7 @@ static unsigned lineno = 1;
|
||||
static void unterminated(const char *, unsigned);
|
||||
|
||||
/* This is for broken old lexes (solaris 10 and hpux) */
|
||||
#line 852 "lex.yy.c"
|
||||
#line 855 "lex.c"
|
||||
|
||||
#define INITIAL 0
|
||||
|
||||
@ -1004,7 +1006,7 @@ YY_DECL
|
||||
|
||||
#line 68 "lex.l"
|
||||
|
||||
#line 1007 "lex.yy.c"
|
||||
#line 1010 "lex.c"
|
||||
|
||||
if ( !(yy_init) )
|
||||
{
|
||||
@ -1673,7 +1675,7 @@ YY_RULE_SETUP
|
||||
#line 274 "lex.l"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 1676 "lex.yy.c"
|
||||
#line 1679 "lex.c"
|
||||
case YY_STATE_EOF(INITIAL):
|
||||
yyterminate();
|
||||
|
||||
@ -2483,6 +2485,15 @@ static void yy_fatal_error (yyconst char* msg )
|
||||
|
||||
/* Accessor methods (get/set functions) to struct members. */
|
||||
|
||||
/** Get the current line number.
|
||||
*
|
||||
*/
|
||||
int yyget_lineno (void)
|
||||
{
|
||||
|
||||
return yylineno;
|
||||
}
|
||||
|
||||
/** Get the input stream.
|
||||
*
|
||||
*/
|
||||
@ -2516,6 +2527,16 @@ char *yyget_text (void)
|
||||
return yytext;
|
||||
}
|
||||
|
||||
/** Set the current line number.
|
||||
* @param line_number
|
||||
*
|
||||
*/
|
||||
void yyset_lineno (int line_number )
|
||||
{
|
||||
|
||||
yylineno = line_number;
|
||||
}
|
||||
|
||||
/** Set the input stream. This does not discard the current
|
||||
* input buffer.
|
||||
* @param in_str A readable stream.
|
||||
|
@ -34,8 +34,6 @@ MS-UPN-SAN ::= UTF8String
|
||||
pa-pk-as-req INTEGER ::= 16
|
||||
pa-pk-as-rep INTEGER ::= 17
|
||||
|
||||
ad-initial-verified-cas INTEGER ::= 9
|
||||
|
||||
td-trusted-certifiers INTEGER ::= 104
|
||||
td-invalid-certificates INTEGER ::= 105
|
||||
td-dh-parameters INTEGER ::= 109
|
||||
@ -160,7 +158,7 @@ KDCDHKeyInfo-Win2k ::= SEQUENCE {
|
||||
|
||||
ReplyKeyPack-Win2k ::= SEQUENCE {
|
||||
replyKey [0] EncryptionKey,
|
||||
nonce [1] INTEGER (0..4294967295),
|
||||
nonce [1] INTEGER (-2147483648..2147483647),
|
||||
...
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "config.h"
|
||||
|
||||
#line 3 "lex.yy.c"
|
||||
#line 3 "lex.c"
|
||||
|
||||
#define YY_INT_ALIGNED short int
|
||||
|
||||
@ -343,6 +342,9 @@ FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
|
||||
typedef int yy_state_type;
|
||||
|
||||
extern int yylineno;
|
||||
|
||||
int yylineno = 1;
|
||||
|
||||
extern char *yytext;
|
||||
#define yytext_ptr yytext
|
||||
|
||||
@ -521,7 +523,7 @@ char *yytext;
|
||||
#include "parse.h"
|
||||
#include "lex.h"
|
||||
|
||||
RCSID("$Id: lex.l,v 1.8 2005/05/16 08:52:54 lha Exp $");
|
||||
RCSID("$Id: lex.l 15143 2005-05-16 08:52:54Z lha $");
|
||||
|
||||
static unsigned lineno = 1;
|
||||
static int getstring(void);
|
||||
@ -530,7 +532,7 @@ static int getstring(void);
|
||||
|
||||
#undef ECHO
|
||||
|
||||
#line 533 "lex.yy.c"
|
||||
#line 536 "lex.c"
|
||||
|
||||
#define INITIAL 0
|
||||
|
||||
@ -685,7 +687,7 @@ YY_DECL
|
||||
|
||||
#line 59 "lex.l"
|
||||
|
||||
#line 688 "lex.yy.c"
|
||||
#line 691 "lex.c"
|
||||
|
||||
if ( !(yy_init) )
|
||||
{
|
||||
@ -849,7 +851,7 @@ YY_RULE_SETUP
|
||||
#line 75 "lex.l"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 852 "lex.yy.c"
|
||||
#line 855 "lex.c"
|
||||
case YY_STATE_EOF(INITIAL):
|
||||
yyterminate();
|
||||
|
||||
@ -1659,6 +1661,15 @@ static void yy_fatal_error (yyconst char* msg )
|
||||
|
||||
/* Accessor methods (get/set functions) to struct members. */
|
||||
|
||||
/** Get the current line number.
|
||||
*
|
||||
*/
|
||||
int yyget_lineno (void)
|
||||
{
|
||||
|
||||
return yylineno;
|
||||
}
|
||||
|
||||
/** Get the input stream.
|
||||
*
|
||||
*/
|
||||
@ -1692,6 +1703,16 @@ char *yyget_text (void)
|
||||
return yytext;
|
||||
}
|
||||
|
||||
/** Set the current line number.
|
||||
* @param line_number
|
||||
*
|
||||
*/
|
||||
void yyset_lineno (int line_number )
|
||||
{
|
||||
|
||||
yylineno = line_number;
|
||||
}
|
||||
|
||||
/** Set the input stream. This does not discard the current
|
||||
* input buffer.
|
||||
* @param in_str A readable stream.
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5/gsskrb5_locl.h"
|
||||
|
||||
RCSID("$Id: acquire_cred.c 20688 2007-05-17 18:44:31Z lha $");
|
||||
RCSID("$Id: acquire_cred.c 21221 2007-06-20 08:42:10Z lha $");
|
||||
|
||||
OM_uint32
|
||||
__gsskrb5_ccache_lifetime(OM_uint32 *minor_status,
|
||||
@ -256,8 +256,8 @@ static OM_uint32 acquire_acceptor_cred
|
||||
if (kret)
|
||||
goto end;
|
||||
krb5_kt_free_entry(context, &entry);
|
||||
ret = GSS_S_COMPLETE;
|
||||
}
|
||||
ret = GSS_S_COMPLETE;
|
||||
|
||||
end:
|
||||
if (ret != GSS_S_COMPLETE) {
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5/gsskrb5_locl.h"
|
||||
|
||||
RCSID("$Id: display_name.c 19031 2006-11-13 18:02:57Z lha $");
|
||||
RCSID("$Id: display_name.c 21077 2007-06-12 22:42:56Z lha $");
|
||||
|
||||
OM_uint32 _gsskrb5_display_name
|
||||
(OM_uint32 * minor_status,
|
||||
@ -50,7 +50,8 @@ OM_uint32 _gsskrb5_display_name
|
||||
|
||||
GSSAPI_KRB5_INIT (&context);
|
||||
|
||||
kret = krb5_unparse_name (context, name, &buf);
|
||||
kret = krb5_unparse_name_flags (context, name,
|
||||
KRB5_PRINCIPAL_UNPARSE_DISPLAY, &buf);
|
||||
if (kret) {
|
||||
*minor_status = kret;
|
||||
return GSS_S_FAILURE;
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5/gsskrb5_locl.h"
|
||||
|
||||
RCSID("$Id: prf.c 20679 2007-05-14 03:12:05Z lha $");
|
||||
RCSID("$Id: prf.c 21129 2007-06-18 20:28:44Z lha $");
|
||||
|
||||
OM_uint32
|
||||
_gsskrb5_pseudo_random(OM_uint32 *minor_status,
|
||||
@ -67,6 +67,7 @@ _gsskrb5_pseudo_random(OM_uint32 *minor_status,
|
||||
switch(prf_key) {
|
||||
case GSS_C_PRF_KEY_FULL:
|
||||
_gsskrb5i_get_acceptor_subkey(ctx, context, &key);
|
||||
break;
|
||||
case GSS_C_PRF_KEY_PARTIAL:
|
||||
_gsskrb5i_get_initiator_subkey(ctx, context, &key);
|
||||
break;
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5/gsskrb5_locl.h"
|
||||
|
||||
RCSID("$Id: release_name.c 19031 2006-11-13 18:02:57Z lha $");
|
||||
RCSID("$Id: release_name.c 21128 2007-06-18 20:26:50Z lha $");
|
||||
|
||||
OM_uint32 _gsskrb5_release_name
|
||||
(OM_uint32 * minor_status,
|
||||
@ -43,8 +43,7 @@ OM_uint32 _gsskrb5_release_name
|
||||
krb5_context context;
|
||||
krb5_principal name = (krb5_principal)*input_name;
|
||||
|
||||
if (minor_status)
|
||||
*minor_status = 0;
|
||||
*minor_status = 0;
|
||||
|
||||
GSSAPI_KRB5_INIT (&context);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "mech/mech_locl.h"
|
||||
#include "heim_threads.h"
|
||||
|
||||
RCSID("$Id: context.c 19924 2007-01-16 10:17:01Z lha $");
|
||||
RCSID("$Id: context.c 21248 2007-06-21 00:45:13Z lha $");
|
||||
|
||||
struct mg_thread_ctx {
|
||||
gss_OID mech;
|
||||
@ -79,7 +79,7 @@ _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
|
||||
|
||||
switch (type) {
|
||||
case GSS_C_GSS_CODE: {
|
||||
if (value != mg->maj_stat)
|
||||
if (value != mg->maj_stat || mg->maj_error.length == 0)
|
||||
break;
|
||||
string->value = malloc(mg->maj_error.length);
|
||||
string->length = mg->maj_error.length;
|
||||
@ -87,7 +87,7 @@ _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
case GSS_C_MECH_CODE: {
|
||||
if (value != mg->min_stat)
|
||||
if (value != mg->min_stat || mg->min_error.length == 0)
|
||||
break;
|
||||
string->value = malloc(mg->min_error.length);
|
||||
string->length = mg->min_error.length;
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_accept_sec_context.c 20626 2007-05-08 13:56:49Z lha $");
|
||||
RCSID("$Id: gss_accept_sec_context.c 21237 2007-06-20 11:21:09Z lha $");
|
||||
|
||||
static OM_uint32
|
||||
parse_header(const gss_buffer_t input_token, gss_OID mech_oid)
|
||||
@ -237,9 +237,7 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
|
||||
return (major_status);
|
||||
}
|
||||
|
||||
if (!src_name) {
|
||||
m->gm_release_name(minor_status, &src_mn);
|
||||
} else {
|
||||
if (src_name && src_mn) {
|
||||
/*
|
||||
* Make a new name and mark it as an MN.
|
||||
*/
|
||||
@ -250,13 +248,15 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
|
||||
return (GSS_S_FAILURE);
|
||||
}
|
||||
*src_name = (gss_name_t) name;
|
||||
} else if (src_mn) {
|
||||
m->gm_release_name(minor_status, &src_mn);
|
||||
}
|
||||
|
||||
if (mech_ret_flags & GSS_C_DELEG_FLAG) {
|
||||
if (!delegated_cred_handle) {
|
||||
m->gm_release_cred(minor_status, &delegated_mc);
|
||||
*ret_flags &= ~GSS_C_DELEG_FLAG;
|
||||
} else {
|
||||
} else if (delegated_mc) {
|
||||
struct _gss_cred *dcred;
|
||||
struct _gss_mechanism_cred *dmc;
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_display_name.c 19952 2007-01-17 10:16:15Z lha $");
|
||||
RCSID("$Id: gss_display_name.c 21246 2007-06-20 15:25:19Z lha $");
|
||||
|
||||
OM_uint32
|
||||
gss_display_name(OM_uint32 *minor_status,
|
||||
@ -43,6 +43,11 @@ gss_display_name(OM_uint32 *minor_status,
|
||||
if (output_name_type)
|
||||
*output_name_type = GSS_C_NO_OID;
|
||||
|
||||
if (name == NULL) {
|
||||
*minor_status = 0;
|
||||
return (GSS_S_BAD_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we know it, copy the buffer used to import the name in
|
||||
* the first place. Otherwise, ask all the MNs in turn if
|
||||
|
@ -59,7 +59,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_display_status.c 20084 2007-01-31 12:12:08Z lha $");
|
||||
RCSID("$Id: gss_display_status.c 21247 2007-06-21 00:37:27Z lha $");
|
||||
|
||||
static const char *
|
||||
calling_error(OM_uint32 v)
|
||||
@ -85,7 +85,7 @@ static const char *
|
||||
routine_error(OM_uint32 v)
|
||||
{
|
||||
static const char *msgs[] = {
|
||||
NULL, /* 0 */
|
||||
"Function completed successfully", /* 0 */
|
||||
"An unsupported mechanism was requested",
|
||||
"An invalid name was supplied",
|
||||
"A supplied name was of an unsupported type",
|
||||
@ -109,9 +109,7 @@ routine_error(OM_uint32 v)
|
||||
|
||||
v >>= GSS_C_ROUTINE_ERROR_OFFSET;
|
||||
|
||||
if (v == 0)
|
||||
return "";
|
||||
else if (v >= sizeof(msgs)/sizeof(*msgs))
|
||||
if (v >= sizeof(msgs)/sizeof(*msgs))
|
||||
return "unknown routine error";
|
||||
else
|
||||
return msgs[v];
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_duplicate_name.c 19953 2007-01-17 11:16:35Z lha $");
|
||||
RCSID("$Id: gss_duplicate_name.c 21219 2007-06-20 08:27:11Z lha $");
|
||||
|
||||
OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
|
||||
const gss_name_t src_name,
|
||||
@ -44,7 +44,7 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
|
||||
/*
|
||||
* If this name has a value (i.e. it didn't come from
|
||||
* gss_canonicalize_name(), we re-import the thing. Otherwise,
|
||||
* we make an empty name to hold the MN copy.
|
||||
* we make copy of each mech names.
|
||||
*/
|
||||
if (name->gn_value.value) {
|
||||
major_status = gss_import_name(minor_status,
|
||||
@ -52,6 +52,10 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
|
||||
if (major_status != GSS_S_COMPLETE)
|
||||
return (major_status);
|
||||
new_name = (struct _gss_name *) *dest_name;
|
||||
|
||||
SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
|
||||
_gss_find_mn(new_name, mn->gmn_mech_oid);
|
||||
}
|
||||
} else {
|
||||
new_name = malloc(sizeof(struct _gss_name));
|
||||
if (!new_name) {
|
||||
@ -59,17 +63,30 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
|
||||
return (GSS_S_FAILURE);
|
||||
}
|
||||
memset(new_name, 0, sizeof(struct _gss_name));
|
||||
SLIST_INIT(&name->gn_mn);
|
||||
SLIST_INIT(&new_name->gn_mn);
|
||||
*dest_name = (gss_name_t) new_name;
|
||||
}
|
||||
|
||||
SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
|
||||
struct _gss_mechanism_name *new_mn;
|
||||
|
||||
new_mn = malloc(sizeof(*new_mn));
|
||||
if (!new_mn) {
|
||||
*minor_status = ENOMEM;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
new_mn->gmn_mech = mn->gmn_mech;
|
||||
new_mn->gmn_mech_oid = mn->gmn_mech_oid;
|
||||
|
||||
major_status =
|
||||
mn->gmn_mech->gm_duplicate_name(minor_status,
|
||||
mn->gmn_name, &new_mn->gmn_name);
|
||||
if (major_status != GSS_S_COMPLETE) {
|
||||
free(new_mn);
|
||||
continue;
|
||||
}
|
||||
SLIST_INSERT_HEAD(&new_name->gn_mn, new_mn, gmn_link);
|
||||
}
|
||||
|
||||
/*
|
||||
* Import the new name into any mechanisms listed in the
|
||||
* original name. We could probably get away with only doing
|
||||
* this if the original was canonical.
|
||||
*/
|
||||
SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
|
||||
_gss_find_mn(new_name, mn->gmn_mech_oid);
|
||||
}
|
||||
|
||||
return (GSS_S_COMPLETE);
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_inquire_context.c 19958 2007-01-17 13:56:18Z lha $");
|
||||
RCSID("$Id: gss_inquire_context.c 21125 2007-06-18 20:11:07Z lha $");
|
||||
|
||||
OM_uint32
|
||||
gss_inquire_context(OM_uint32 *minor_status,
|
||||
@ -79,7 +79,8 @@ gss_inquire_context(OM_uint32 *minor_status,
|
||||
if (src_name) {
|
||||
name = _gss_make_name(m, src_mn);
|
||||
if (!name) {
|
||||
*mech_type = GSS_C_NO_OID;
|
||||
if (mech_type)
|
||||
*mech_type = GSS_C_NO_OID;
|
||||
m->gm_release_name(minor_status, &src_mn);
|
||||
*minor_status = 0;
|
||||
return (GSS_S_FAILURE);
|
||||
@ -90,8 +91,10 @@ gss_inquire_context(OM_uint32 *minor_status,
|
||||
if (targ_name) {
|
||||
name = _gss_make_name(m, targ_mn);
|
||||
if (!name) {
|
||||
*mech_type = GSS_C_NO_OID;
|
||||
gss_release_name(minor_status, src_name);
|
||||
if (mech_type)
|
||||
*mech_type = GSS_C_NO_OID;
|
||||
if (src_name)
|
||||
gss_release_name(minor_status, src_name);
|
||||
m->gm_release_name(minor_status, &targ_mn);
|
||||
*minor_status = 0;
|
||||
return (GSS_S_FAILURE);
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_inquire_cred_by_mech.c 19960 2007-01-17 15:09:24Z lha $");
|
||||
RCSID("$Id: gss_inquire_cred_by_mech.c 21124 2007-06-18 20:08:24Z lha $");
|
||||
|
||||
OM_uint32
|
||||
gss_inquire_cred_by_mech(OM_uint32 *minor_status,
|
||||
@ -78,12 +78,16 @@ gss_inquire_cred_by_mech(OM_uint32 *minor_status,
|
||||
return (major_status);
|
||||
}
|
||||
|
||||
name = _gss_make_name(m, mn);
|
||||
if (!name) {
|
||||
if (cred_name) {
|
||||
name = _gss_make_name(m, mn);
|
||||
if (!name) {
|
||||
m->gm_release_name(minor_status, &mn);
|
||||
return (GSS_S_NO_CRED);
|
||||
}
|
||||
}
|
||||
*cred_name = (gss_name_t) name;
|
||||
} else
|
||||
m->gm_release_name(minor_status, &mn);
|
||||
|
||||
|
||||
*cred_name = (gss_name_t) name;
|
||||
return (GSS_S_COMPLETE);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_krb5.c 20383 2007-04-18 08:49:53Z lha $");
|
||||
RCSID("$Id: gss_krb5.c 21123 2007-06-18 20:05:26Z lha $");
|
||||
|
||||
#include <krb5.h>
|
||||
#include <roken.h>
|
||||
@ -650,7 +650,7 @@ gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
|
||||
if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,
|
||||
oid_flat.length, &oid, &size) != 0) {
|
||||
free(oid.components);
|
||||
|
||||
free(oid_flat.elements);
|
||||
*minor_status = EINVAL;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "mech_locl.h"
|
||||
RCSID("$Id: gss_set_cred_option.c 20626 2007-05-08 13:56:49Z lha $");
|
||||
RCSID("$Id: gss_set_cred_option.c 21126 2007-06-18 20:19:59Z lha $");
|
||||
|
||||
OM_uint32
|
||||
gss_set_cred_option (OM_uint32 *minor_status,
|
||||
@ -64,7 +64,9 @@ gss_set_cred_option (OM_uint32 *minor_status,
|
||||
|
||||
mc = malloc(sizeof(*mc));
|
||||
if (mc == NULL) {
|
||||
/* XXX free the other mc's */
|
||||
*cred_handle = (gss_cred_id_t)cred;
|
||||
gss_release_cred(minor_status, cred_handle);
|
||||
*minor_status = ENOMEM;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "spnego/spnego_locl.h"
|
||||
|
||||
RCSID("$Id: accept_sec_context.c 20929 2007-06-05 21:19:22Z lha $");
|
||||
RCSID("$Id: accept_sec_context.c 21243 2007-06-20 15:16:22Z lha $");
|
||||
|
||||
static OM_uint32
|
||||
send_reject (OM_uint32 *minor_status,
|
||||
@ -540,12 +540,12 @@ acceptor_start
|
||||
gss_cred_id_t *delegated_cred_handle
|
||||
)
|
||||
{
|
||||
OM_uint32 ret, ret2, minor;
|
||||
NegTokenInit ni;
|
||||
size_t ni_len;
|
||||
OM_uint32 ret, junk, minor;
|
||||
NegotiationToken nt;
|
||||
size_t nt_len;
|
||||
NegTokenInit *ni;
|
||||
int i;
|
||||
gss_buffer_desc data;
|
||||
size_t len, taglen;
|
||||
gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
|
||||
gss_buffer_desc mech_output_token;
|
||||
gss_buffer_desc mech_buf;
|
||||
@ -555,6 +555,9 @@ acceptor_start
|
||||
int get_mic = 0;
|
||||
int first_ok = 0;
|
||||
|
||||
if (src_name)
|
||||
*src_name = GSS_C_NO_NAME;
|
||||
|
||||
mech_output_token.value = NULL;
|
||||
mech_output_token.length = 0;
|
||||
mech_buf.value = NULL;
|
||||
@ -582,39 +585,30 @@ acceptor_start
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = der_match_tag_and_length(data.value, data.length,
|
||||
ASN1_C_CONTEXT, CONS,
|
||||
0,
|
||||
&len, &taglen);
|
||||
if (ret) {
|
||||
*minor_status = ret;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
if (len > data.length - taglen) {
|
||||
*minor_status = ASN1_OVERRUN;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
ret = decode_NegTokenInit((const unsigned char *)data.value + taglen,
|
||||
len, &ni, &ni_len);
|
||||
ret = decode_NegotiationToken(data.value, data.length, &nt, &nt_len);
|
||||
gss_release_buffer(minor_status, &data);
|
||||
if (ret) {
|
||||
*minor_status = ret;
|
||||
return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
if (nt.element != choice_NegotiationToken_negTokenInit) {
|
||||
*minor_status = 0;
|
||||
return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
ni = &nt.u.negTokenInit;
|
||||
|
||||
if (ni.mechTypes.len < 1) {
|
||||
free_NegTokenInit(&ni);
|
||||
if (ni->mechTypes.len < 1) {
|
||||
free_NegotiationToken(&nt);
|
||||
*minor_status = 0;
|
||||
return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
|
||||
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
|
||||
|
||||
ret = copy_MechTypeList(&ni.mechTypes, &ctx->initiator_mech_types);
|
||||
ret = copy_MechTypeList(&ni->mechTypes, &ctx->initiator_mech_types);
|
||||
if (ret) {
|
||||
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||
free_NegTokenInit(&ni);
|
||||
free_NegotiationToken(&nt);
|
||||
*minor_status = ret;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
@ -627,17 +621,17 @@ acceptor_start
|
||||
*/
|
||||
|
||||
ret = select_mech(minor_status,
|
||||
&ni.mechTypes.val[0],
|
||||
&ni->mechTypes.val[0],
|
||||
0,
|
||||
&preferred_mech_type);
|
||||
|
||||
if (ret == 0 && ni.mechToken != NULL) {
|
||||
if (ret == 0 && ni->mechToken != NULL) {
|
||||
gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL;
|
||||
gss_cred_id_t mech_cred;
|
||||
gss_buffer_desc ibuf;
|
||||
|
||||
ibuf.length = ni.mechToken->length;
|
||||
ibuf.value = ni.mechToken->data;
|
||||
ibuf.length = ni->mechToken->length;
|
||||
ibuf.value = ni->mechToken->data;
|
||||
mech_input_token = &ibuf;
|
||||
|
||||
if (acceptor_cred != NULL)
|
||||
@ -668,12 +662,12 @@ acceptor_start
|
||||
if (ret == GSS_S_COMPLETE)
|
||||
ctx->open = 1;
|
||||
|
||||
if (delegated_cred_handle)
|
||||
if (mech_delegated_cred && delegated_cred_handle)
|
||||
ret = _gss_spnego_alloc_cred(minor_status,
|
||||
mech_delegated_cred,
|
||||
delegated_cred_handle);
|
||||
else
|
||||
gss_release_cred(&ret2, &mech_delegated_cred);
|
||||
gss_release_cred(&junk, &mech_delegated_cred);
|
||||
|
||||
ret = acceptor_complete(minor_status,
|
||||
ctx,
|
||||
@ -681,7 +675,7 @@ acceptor_start
|
||||
&mech_buf,
|
||||
mech_input_token,
|
||||
&mech_output_token,
|
||||
ni.mechListMIC,
|
||||
ni->mechListMIC,
|
||||
output_token);
|
||||
if (ret != GSS_S_COMPLETE)
|
||||
goto out;
|
||||
@ -697,9 +691,9 @@ acceptor_start
|
||||
if (!first_ok) {
|
||||
|
||||
/* Call glue layer to find first mech we support */
|
||||
for (i = 1; i < ni.mechTypes.len; ++i) {
|
||||
for (i = 1; i < ni->mechTypes.len; ++i) {
|
||||
ret = select_mech(minor_status,
|
||||
&ni.mechTypes.val[i],
|
||||
&ni->mechTypes.val[i],
|
||||
1,
|
||||
&preferred_mech_type);
|
||||
if (ret == 0)
|
||||
@ -707,7 +701,7 @@ acceptor_start
|
||||
}
|
||||
if (preferred_mech_type == GSS_C_NO_OID) {
|
||||
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||
free_NegTokenInit(&ni);
|
||||
free_NegotiationToken(&nt);
|
||||
return GSS_S_BAD_MECH;
|
||||
}
|
||||
|
||||
@ -735,7 +729,8 @@ out:
|
||||
free(mech_buf.value);
|
||||
mech_buf.value = NULL;
|
||||
}
|
||||
free_NegTokenInit(&ni);
|
||||
free_NegotiationToken(&nt);
|
||||
|
||||
|
||||
if (ret == GSS_S_COMPLETE) {
|
||||
if (src_name != NULL && ctx->mech_src_name != NULL) {
|
||||
@ -746,8 +741,7 @@ out:
|
||||
name->mech = ctx->mech_src_name;
|
||||
ctx->mech_src_name = NULL;
|
||||
*src_name = (gss_name_t)name;
|
||||
} else
|
||||
*src_name = GSS_C_NO_NAME;
|
||||
}
|
||||
}
|
||||
if (delegated_cred_handle != NULL) {
|
||||
*delegated_cred_handle = ctx->delegated_cred_id;
|
||||
@ -790,10 +784,9 @@ acceptor_continue
|
||||
)
|
||||
{
|
||||
OM_uint32 ret, ret2, minor;
|
||||
NegTokenResp na;
|
||||
size_t na_len;
|
||||
gss_buffer_desc data;
|
||||
size_t len, taglen;
|
||||
NegotiationToken nt;
|
||||
size_t nt_len;
|
||||
NegTokenResp *na;
|
||||
unsigned int negResult = accept_incomplete;
|
||||
gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
|
||||
gss_buffer_t mech_output_token = GSS_C_NO_BUFFER;
|
||||
@ -810,45 +803,34 @@ acceptor_continue
|
||||
* context token (negTokenInit).
|
||||
*/
|
||||
|
||||
data.value = input_token_buffer->value;
|
||||
data.length = input_token_buffer->length;
|
||||
|
||||
ret = der_match_tag_and_length(data.value, data.length,
|
||||
ASN1_C_CONTEXT, CONS,
|
||||
1,
|
||||
&len, &taglen);
|
||||
if (ret) {
|
||||
*minor_status = ret;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
if (len > data.length - taglen) {
|
||||
*minor_status = ASN1_OVERRUN;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
ret = decode_NegTokenResp((const unsigned char *)data.value + taglen,
|
||||
len, &na, &na_len);
|
||||
ret = decode_NegotiationToken(input_token_buffer->value,
|
||||
input_token_buffer->length,
|
||||
&nt, &nt_len);
|
||||
if (ret) {
|
||||
*minor_status = ret;
|
||||
return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
if (nt.element != choice_NegotiationToken_negTokenResp) {
|
||||
*minor_status = 0;
|
||||
return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
na = &nt.u.negTokenResp;
|
||||
|
||||
if (na.negResult != NULL) {
|
||||
negResult = *(na.negResult);
|
||||
if (na->negResult != NULL) {
|
||||
negResult = *(na->negResult);
|
||||
}
|
||||
|
||||
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
|
||||
|
||||
{
|
||||
gss_buffer_desc ibuf, obuf;
|
||||
int require_mic, get_mic;
|
||||
int require_mic, get_mic = 0;
|
||||
int require_response;
|
||||
heim_octet_string *mic;
|
||||
|
||||
if (na.responseToken != NULL) {
|
||||
ibuf.length = na.responseToken->length;
|
||||
ibuf.value = na.responseToken->data;
|
||||
if (na->responseToken != NULL) {
|
||||
ibuf.length = na->responseToken->length;
|
||||
ibuf.value = na->responseToken->data;
|
||||
mech_input_token = &ibuf;
|
||||
} else {
|
||||
ibuf.value = NULL;
|
||||
@ -901,7 +883,7 @@ acceptor_continue
|
||||
mech_output_token = &obuf;
|
||||
}
|
||||
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
|
||||
free_NegTokenResp(&na);
|
||||
free_NegotiationToken(&nt);
|
||||
send_reject (minor_status, output_token);
|
||||
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||
return ret;
|
||||
@ -919,7 +901,7 @@ acceptor_continue
|
||||
|
||||
ctx->require_mic = require_mic;
|
||||
|
||||
mic = na.mechListMIC;
|
||||
mic = na->mechListMIC;
|
||||
if (mic != NULL)
|
||||
require_mic = 1;
|
||||
|
||||
@ -930,7 +912,7 @@ acceptor_continue
|
||||
&mech_buf,
|
||||
mech_input_token,
|
||||
mech_output_token,
|
||||
na.mechListMIC,
|
||||
na->mechListMIC,
|
||||
output_token);
|
||||
|
||||
if (ctx->mech_flags & GSS_C_DCE_STYLE)
|
||||
@ -964,16 +946,19 @@ acceptor_continue
|
||||
gss_release_buffer(&minor, mech_output_token);
|
||||
if (mech_buf.value != NULL)
|
||||
free(mech_buf.value);
|
||||
free_NegTokenResp(&na);
|
||||
free_NegotiationToken(&nt);
|
||||
}
|
||||
|
||||
if (ret == GSS_S_COMPLETE) {
|
||||
if (src_name != NULL) {
|
||||
ret2 = gss_duplicate_name(minor_status,
|
||||
ctx->mech_src_name,
|
||||
src_name);
|
||||
if (ret2 != GSS_S_COMPLETE)
|
||||
ret = ret2;
|
||||
if (src_name != NULL && ctx->mech_src_name != NULL) {
|
||||
spnego_name name;
|
||||
|
||||
name = calloc(1, sizeof(*name));
|
||||
if (name) {
|
||||
name->mech = ctx->mech_src_name;
|
||||
ctx->mech_src_name = NULL;
|
||||
*src_name = (gss_name_t)name;
|
||||
}
|
||||
}
|
||||
if (delegated_cred_handle != NULL) {
|
||||
*delegated_cred_handle = ctx->delegated_cred_id;
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
RCSID("$Id: pkcs12.c 20661 2007-05-10 21:57:58Z lha $");
|
||||
RCSID("$Id: pkcs12.c 21155 2007-06-18 21:59:44Z lha $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -93,8 +93,11 @@ PKCS12_key_gen(const void *key, size_t keylen,
|
||||
while (1) {
|
||||
BIGNUM *bnB, *bnOne;
|
||||
|
||||
if (!EVP_DigestInit_ex(&ctx, md, NULL))
|
||||
if (!EVP_DigestInit_ex(&ctx, md, NULL)) {
|
||||
free(I);
|
||||
free(v);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < vlen; i++)
|
||||
EVP_DigestUpdate(&ctx, &idc, 1);
|
||||
EVP_DigestUpdate(&ctx, I, size_I);
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
RCSID("$Id: rand-egd.c 20093 2007-01-31 12:44:28Z lha $");
|
||||
RCSID("$Id: rand-egd.c 21156 2007-06-18 22:00:59Z lha $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
@ -255,7 +255,7 @@ RAND_egd_bytes(const char *filename, int size)
|
||||
|
||||
RAND_seed(data, size);
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
memset(data, 0, size);
|
||||
free(data);
|
||||
|
||||
return 1;
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
RCSID("$Id: rand-fortuna.c 20029 2007-01-21 09:55:42Z lha $");
|
||||
RCSID("$Id: rand-fortuna.c 21196 2007-06-20 05:08:58Z lha $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -427,6 +427,8 @@ extract_data(FState * st, unsigned count, unsigned char *dst)
|
||||
static FState main_state;
|
||||
static int init_done;
|
||||
static int have_entropy;
|
||||
#define FORTUNA_RESEED_BYTE 10000
|
||||
static unsigned resend_bytes;
|
||||
|
||||
/*
|
||||
* Try our best to do an inital seed
|
||||
@ -472,6 +474,35 @@ fortuna_reseed(void)
|
||||
memset(buf, 0, sizeof(buf));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Fall back to gattering data from timer and secret files, this
|
||||
* is really the last resort.
|
||||
*/
|
||||
if (!entropy_p) {
|
||||
/* to save stackspace */
|
||||
union {
|
||||
unsigned char buf[INIT_BYTES];
|
||||
unsigned char shad[1001];
|
||||
} u;
|
||||
int fd;
|
||||
|
||||
/* add timer info */
|
||||
if ((*hc_rand_timer_method.bytes)(u.buf, sizeof(u.buf)) == 1)
|
||||
add_entropy(&main_state, u.buf, sizeof(u.buf));
|
||||
/* add /etc/shadow */
|
||||
fd = open("/etc/shadow", O_RDONLY, 0);
|
||||
if (fd >= 0) {
|
||||
ssize_t n;
|
||||
/* add_entropy will hash the buf */
|
||||
while ((n = read(fd, (char *)u.shad, sizeof(u.shad))) > 0)
|
||||
add_entropy(&main_state, u.shad, sizeof(u.shad));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
memset(&u, 0, sizeof(u));
|
||||
|
||||
entropy_p = 1; /* sure about this ? */
|
||||
}
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
add_entropy(&main_state, (void *)&pid, sizeof(pid));
|
||||
@ -517,6 +548,11 @@ fortuna_bytes(unsigned char *outdata, int size)
|
||||
{
|
||||
if (!fortuna_init())
|
||||
return 0;
|
||||
resend_bytes += size;
|
||||
if (resend_bytes > FORTUNA_RESEED_BYTE || resend_bytes < size) {
|
||||
resend_bytes = 0;
|
||||
fortuna_reseed();
|
||||
}
|
||||
extract_data(&main_state, size, outdata);
|
||||
return 1;
|
||||
}
|
||||
|
206
source/heimdal/lib/hcrypto/rand-timer.c
Normal file
206
source/heimdal/lib/hcrypto/rand-timer.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1996, 1997, 1999, 2007 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
RCSID("$Id$");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <rand.h>
|
||||
|
||||
#include <roken.h>
|
||||
|
||||
#include "randi.h"
|
||||
|
||||
#ifndef WIN32 /* don't bother with this on windows */
|
||||
|
||||
static volatile int counter;
|
||||
static volatile unsigned char *gdata; /* Global data */
|
||||
static volatile int igdata; /* Index into global data */
|
||||
static int gsize;
|
||||
|
||||
static
|
||||
RETSIGTYPE
|
||||
sigALRM(int sig)
|
||||
{
|
||||
if (igdata < gsize)
|
||||
gdata[igdata++] ^= counter & 0xff;
|
||||
|
||||
#ifndef HAVE_SIGACTION
|
||||
signal(SIGALRM, sigALRM); /* Reinstall SysV signal handler */
|
||||
#endif
|
||||
SIGRETURN(0);
|
||||
}
|
||||
|
||||
#ifndef HAVE_SETITIMER
|
||||
static void
|
||||
pacemaker(struct timeval *tv)
|
||||
{
|
||||
fd_set fds;
|
||||
pid_t pid;
|
||||
pid = getppid();
|
||||
while(1){
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(0, &fds);
|
||||
select(1, &fds, NULL, NULL, tv);
|
||||
kill(pid, SIGALRM);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
/* XXX ugly hack, should perhaps use function from roken */
|
||||
static RETSIGTYPE
|
||||
(*fake_signal(int sig, RETSIGTYPE (*f)(int)))(int)
|
||||
{
|
||||
struct sigaction sa, osa;
|
||||
sa.sa_handler = f;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(sig, &sa, &osa);
|
||||
return osa.sa_handler;
|
||||
}
|
||||
#define signal(S, F) fake_signal((S), (F))
|
||||
#endif
|
||||
|
||||
#endif /* WIN32*/
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
timer_seed(const void *indata, int size)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
timer_bytes(unsigned char *outdata, int size)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return 0;
|
||||
#else /* WIN32 */
|
||||
struct itimerval tv, otv;
|
||||
RETSIGTYPE (*osa)(int);
|
||||
int i, j;
|
||||
#ifndef HAVE_SETITIMER
|
||||
RETSIGTYPE (*ochld)(int);
|
||||
pid_t pid;
|
||||
#endif
|
||||
|
||||
gdata = outdata;
|
||||
gsize = size;
|
||||
igdata = 0;
|
||||
|
||||
osa = signal(SIGALRM, sigALRM);
|
||||
|
||||
/* Start timer */
|
||||
tv.it_value.tv_sec = 0;
|
||||
tv.it_value.tv_usec = 10 * 1000; /* 10 ms */
|
||||
tv.it_interval = tv.it_value;
|
||||
#ifdef HAVE_SETITIMER
|
||||
setitimer(ITIMER_REAL, &tv, &otv);
|
||||
#else
|
||||
ochld = signal(SIGCHLD, SIG_IGN);
|
||||
pid = fork();
|
||||
if(pid == -1){
|
||||
signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
|
||||
des_not_rand_data(data, size);
|
||||
return;
|
||||
}
|
||||
if(pid == 0)
|
||||
pacemaker(&tv.it_interval);
|
||||
#endif
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
for (igdata = 0; igdata < size;) /* igdata++ in sigALRM */
|
||||
counter++;
|
||||
for (j = 0; j < size; j++) /* Only use 2 bits each lap */
|
||||
gdata[j] = (gdata[j]>>2) | (gdata[j]<<6);
|
||||
}
|
||||
#ifdef HAVE_SETITIMER
|
||||
setitimer(ITIMER_REAL, &otv, 0);
|
||||
#else
|
||||
kill(pid, SIGKILL);
|
||||
while(waitpid(pid, NULL, 0) != pid);
|
||||
signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
|
||||
#endif
|
||||
signal(SIGALRM, osa != SIG_ERR ? osa : SIG_DFL);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
timer_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
timer_add(const void *indata, int size, double entropi)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
timer_pseudorand(unsigned char *outdata, int size)
|
||||
{
|
||||
return timer_bytes(outdata, size);
|
||||
}
|
||||
|
||||
static int
|
||||
timer_status(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
const RAND_METHOD hc_rand_timer_method = {
|
||||
timer_seed,
|
||||
timer_bytes,
|
||||
timer_cleanup,
|
||||
timer_add,
|
||||
timer_pseudorand,
|
||||
timer_status
|
||||
};
|
||||
|
||||
const RAND_METHOD *
|
||||
RAND_timer_method(void)
|
||||
{
|
||||
return &hc_rand_timer_method;
|
||||
}
|
@ -35,7 +35,7 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
RCSID("$Id: rand.c 20126 2007-02-01 22:08:41Z lha $");
|
||||
RCSID("$Id: rand.c 21198 2007-06-20 05:10:41Z lha $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -56,11 +56,7 @@ init_method(void)
|
||||
{
|
||||
if (selected_meth != NULL)
|
||||
return;
|
||||
|
||||
if ((*hc_rand_unix_method.status)() == 1)
|
||||
selected_meth = &hc_rand_unix_method;
|
||||
else
|
||||
selected_meth = &hc_rand_fortuna_method;
|
||||
selected_meth = &hc_rand_fortuna_method;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: randi.h 20027 2007-01-21 09:54:00Z lha $
|
||||
* $Id: randi.h 21101 2007-06-18 03:53:46Z lha $
|
||||
*/
|
||||
|
||||
#ifndef _HEIM_RANDI_H
|
||||
@ -41,5 +41,8 @@
|
||||
extern const RAND_METHOD hc_rand_fortuna_method;
|
||||
extern const RAND_METHOD hc_rand_unix_method;
|
||||
extern const RAND_METHOD hc_rand_egd_method;
|
||||
extern const RAND_METHOD hc_rand_timer_method;
|
||||
|
||||
const RAND_METHOD * RAND_timer_method(void);
|
||||
|
||||
#endif /* _HEIM_RANDI_H */
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
RCSID("$Id: rsa-imath.c 19750 2007-01-06 13:45:25Z lha $");
|
||||
RCSID("$Id: rsa-imath.c 21154 2007-06-18 21:58:12Z lha $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -180,7 +180,6 @@ imath_rsa_public_encrypt(int flen, const unsigned char* from,
|
||||
}
|
||||
|
||||
padlen = size - flen - 3;
|
||||
assert(padlen >= 8);
|
||||
|
||||
*p++ = 2;
|
||||
if (RAND_bytes(p, padlen) != 1) {
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "hdb_locl.h"
|
||||
#include <der.h>
|
||||
|
||||
RCSID("$Id: ext.c 20236 2007-02-16 23:52:29Z lha $");
|
||||
RCSID("$Id: ext.c 21113 2007-06-18 12:59:32Z lha $");
|
||||
|
||||
krb5_error_code
|
||||
hdb_entry_check_mandatory(krb5_context context, const hdb_entry *ent)
|
||||
@ -268,6 +268,7 @@ hdb_entry_get_password(krb5_context context, HDB *db,
|
||||
const hdb_entry *entry, char **p)
|
||||
{
|
||||
HDB_extension *ext;
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
ext = hdb_find_extension(entry, choice_HDB_extension_data_password);
|
||||
@ -314,7 +315,14 @@ hdb_entry_get_password(krb5_context context, HDB *db,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
krb5_set_error_string(context, "password attribute not found");
|
||||
|
||||
ret = krb5_unparse_name(context, entry->principal, &str);
|
||||
if (ret == 0) {
|
||||
krb5_set_error_string(context, "no password attributefor %s", str);
|
||||
free(str);
|
||||
} else
|
||||
krb5_clear_error_string(context);
|
||||
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: cert.c 20915 2007-06-05 03:58:56Z lha $");
|
||||
RCSID("$Id: cert.c 21294 2007-06-25 14:37:15Z lha $");
|
||||
#include "crypto-headers.h"
|
||||
#include <rtbl.h>
|
||||
|
||||
@ -43,6 +43,7 @@ struct hx509_verify_ctx_data {
|
||||
#define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
|
||||
#define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
|
||||
#define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
|
||||
#define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
|
||||
time_t time_now;
|
||||
unsigned int max_depth;
|
||||
#define HX509_VERIFY_MAX_DEPTH 30
|
||||
@ -51,6 +52,7 @@ struct hx509_verify_ctx_data {
|
||||
|
||||
#define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
|
||||
#define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
|
||||
#define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
|
||||
|
||||
struct _hx509_cert_attrs {
|
||||
size_t len;
|
||||
@ -76,22 +78,6 @@ typedef struct hx509_name_constraints {
|
||||
#define GeneralSubtrees_SET(g,var) \
|
||||
(g)->len = (var)->len, (g)->val = (var)->val;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
_hx509_abort(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
@ -227,10 +213,37 @@ hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
|
||||
if (ret) {
|
||||
free((*cert)->data);
|
||||
free(*cert);
|
||||
*cert = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
hx509_cert_init_data(hx509_context context,
|
||||
const void *ptr,
|
||||
size_t len,
|
||||
hx509_cert *cert)
|
||||
{
|
||||
Certificate t;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
ret = decode_Certificate(ptr, len, &t, &size);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
|
||||
return ret;
|
||||
}
|
||||
if (size != len) {
|
||||
hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
|
||||
"Extra data after certificate");
|
||||
return HX509_EXTRA_DATA_AFTER_STRUCTURE;
|
||||
}
|
||||
|
||||
ret = hx509_cert_init(context, &t, cert);
|
||||
free_Certificate(&t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_hx509_cert_set_release(hx509_cert cert,
|
||||
_hx509_cert_release_func release,
|
||||
@ -291,10 +304,10 @@ hx509_cert
|
||||
hx509_cert_ref(hx509_cert cert)
|
||||
{
|
||||
if (cert->ref <= 0)
|
||||
_hx509_abort("refcount <= 0");
|
||||
_hx509_abort("cert refcount <= 0");
|
||||
cert->ref++;
|
||||
if (cert->ref == 0)
|
||||
_hx509_abort("refcount == 0");
|
||||
_hx509_abort("cert refcount == 0");
|
||||
return cert;
|
||||
}
|
||||
|
||||
@ -341,6 +354,12 @@ hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
|
||||
ctx->time_now = t;
|
||||
}
|
||||
|
||||
void
|
||||
hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
|
||||
{
|
||||
ctx->max_depth = max_depth;
|
||||
}
|
||||
|
||||
void
|
||||
hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
|
||||
{
|
||||
@ -359,6 +378,15 @@ hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
|
||||
ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
|
||||
}
|
||||
|
||||
void
|
||||
hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
|
||||
{
|
||||
if (boolean)
|
||||
ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
|
||||
else
|
||||
ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
|
||||
}
|
||||
|
||||
static const Extension *
|
||||
find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
|
||||
{
|
||||
@ -1295,13 +1323,15 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match)
|
||||
return 0;
|
||||
}
|
||||
case choice_GeneralName_dNSName: {
|
||||
size_t len1, len2;
|
||||
size_t lenc, lenn;
|
||||
|
||||
len1 = strlen(c->u.dNSName);
|
||||
len2 = strlen(n->u.dNSName);
|
||||
if (len1 > len2)
|
||||
lenc = strlen(c->u.dNSName);
|
||||
lenn = strlen(n->u.dNSName);
|
||||
if (lenc > lenn)
|
||||
return HX509_NAME_CONSTRAINT_ERROR;
|
||||
if (strcasecmp(&n->u.dNSName[len2 - len1], c->u.dNSName) != 0)
|
||||
if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
|
||||
return HX509_NAME_CONSTRAINT_ERROR;
|
||||
if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
|
||||
return HX509_NAME_CONSTRAINT_ERROR;
|
||||
*match = 1;
|
||||
return 0;
|
||||
@ -1488,15 +1518,15 @@ hx509_verify_path(hx509_context context,
|
||||
/*
|
||||
*
|
||||
*/
|
||||
ret = hx509_certs_init(context, "MEMORY:trust-anchors", 0, NULL, &anchors);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = hx509_certs_merge(context, anchors, ctx->trust_anchors);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = hx509_certs_merge(context, anchors, context->default_trust_anchors);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (ctx->trust_anchors)
|
||||
anchors = _hx509_certs_ref(ctx->trust_anchors);
|
||||
else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
|
||||
anchors = _hx509_certs_ref(context->default_trust_anchors);
|
||||
else {
|
||||
ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the path from the certificate user presented to the
|
||||
@ -1843,17 +1873,82 @@ hx509_verify_signature(hx509_context context,
|
||||
return _hx509_verify_signature(context, signer->data, alg, data, sig);
|
||||
}
|
||||
|
||||
#define HX509_VHN_F_ALLOW_NO_MATCH 1
|
||||
|
||||
int
|
||||
hx509_verify_hostname(hx509_context context,
|
||||
const hx509_cert cert,
|
||||
int require_match,
|
||||
int flags,
|
||||
hx509_hostname_type type,
|
||||
const char *hostname,
|
||||
const struct sockaddr *sa,
|
||||
/* XXX krb5_socklen_t */ int sa_size)
|
||||
{
|
||||
GeneralNames san;
|
||||
int ret, i, j;
|
||||
|
||||
if (sa && sa_size <= 0)
|
||||
return EINVAL;
|
||||
return 0;
|
||||
|
||||
memset(&san, 0, sizeof(san));
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
ret = find_extension_subject_alt_name(cert->data, &i, &san);
|
||||
if (ret == HX509_EXTENSION_NOT_FOUND) {
|
||||
ret = 0;
|
||||
break;
|
||||
} else if (ret != 0)
|
||||
break;
|
||||
|
||||
for (j = 0; j < san.len; j++) {
|
||||
switch (san.val[j].element) {
|
||||
case choice_GeneralName_dNSName:
|
||||
if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
|
||||
free_GeneralNames(&san);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
free_GeneralNames(&san);
|
||||
} while (1);
|
||||
|
||||
{
|
||||
Name *name = &cert->data->tbsCertificate.subject;
|
||||
|
||||
/* match if first component is a CN= */
|
||||
if (name->u.rdnSequence.len > 0
|
||||
&& name->u.rdnSequence.val[0].len == 1
|
||||
&& der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
|
||||
oid_id_at_commonName()) == 0)
|
||||
{
|
||||
DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
|
||||
|
||||
switch (ds->element) {
|
||||
case choice_DirectoryString_printableString:
|
||||
if (strcasecmp(ds->u.printableString, hostname) == 0)
|
||||
return 0;
|
||||
break;
|
||||
case choice_DirectoryString_ia5String:
|
||||
if (strcasecmp(ds->u.ia5String, hostname) == 0)
|
||||
return 0;
|
||||
break;
|
||||
case choice_DirectoryString_utf8String:
|
||||
if (strcasecmp(ds->u.utf8String, hostname) == 0)
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
|
||||
ret = HX509_NAME_CONSTRAINT_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
@ -2434,3 +2529,24 @@ hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Last to avoid lost __attribute__s due to #undef.
|
||||
*/
|
||||
|
||||
#undef __attribute__
|
||||
#define __attribute__(X)
|
||||
|
||||
void
|
||||
_hx509_abort(const char *fmt, ...)
|
||||
__attribute__ ((noreturn, format (printf, 1, 2)))
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: cms.c 20937 2007-06-06 20:50:55Z lha $");
|
||||
RCSID("$Id: cms.c 21319 2007-06-25 19:46:52Z lha $");
|
||||
|
||||
#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
|
||||
#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
|
||||
@ -115,24 +115,42 @@ hx509_cms_unwrap_ContentInfo(const heim_octet_string *in,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CMS_ID_SKI 0
|
||||
#define CMS_ID_NAME 1
|
||||
|
||||
static int
|
||||
fill_CMSIdentifier(const hx509_cert cert, CMSIdentifier *id)
|
||||
fill_CMSIdentifier(const hx509_cert cert,
|
||||
int type,
|
||||
CMSIdentifier *id)
|
||||
{
|
||||
hx509_name name;
|
||||
int ret;
|
||||
|
||||
id->element = choice_CMSIdentifier_issuerAndSerialNumber;
|
||||
ret = hx509_cert_get_issuer(cert, &name);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = copy_Name(&name->der_name,
|
||||
&id->u.issuerAndSerialNumber.issuer);
|
||||
hx509_name_free(&name);
|
||||
if (ret)
|
||||
return ret;
|
||||
switch (type) {
|
||||
case CMS_ID_SKI:
|
||||
id->element = choice_CMSIdentifier_subjectKeyIdentifier;
|
||||
ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert),
|
||||
&id->u.subjectKeyIdentifier);
|
||||
if (ret == 0)
|
||||
break;
|
||||
/* FALL THOUGH */
|
||||
case CMS_ID_NAME: {
|
||||
hx509_name name;
|
||||
|
||||
ret = hx509_cert_get_serialnumber(cert,
|
||||
&id->u.issuerAndSerialNumber.serialNumber);
|
||||
id->element = choice_CMSIdentifier_issuerAndSerialNumber;
|
||||
ret = hx509_cert_get_issuer(cert, &name);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer);
|
||||
hx509_name_free(&name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
_hx509_abort("CMS fill identifier with unknown type");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -467,6 +485,13 @@ hx509_cms_envelope_1(hx509_context context,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hx509_crypto_random_iv(crypto, &ivec);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Failed to create a random iv");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hx509_crypto_encrypt(crypto,
|
||||
data,
|
||||
length,
|
||||
@ -518,7 +543,7 @@ hx509_cms_envelope_1(hx509_context context,
|
||||
ri = &ed.recipientInfos.val[0];
|
||||
|
||||
ri->version = 0;
|
||||
ret = fill_CMSIdentifier(cert, &ri->rid);
|
||||
ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Failed to set CMS identifier info "
|
||||
@ -585,22 +610,12 @@ any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < sd->certificates->len; i++) {
|
||||
Certificate cert;
|
||||
hx509_cert c;
|
||||
|
||||
const void *p = sd->certificates->val[i].data;
|
||||
size_t size, length = sd->certificates->val[i].length;
|
||||
|
||||
ret = decode_Certificate(p, length, &cert, &size);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Failed to decode certificate %d "
|
||||
"in SignedData.certificates", i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hx509_cert_init(context, &cert, &c);
|
||||
free_Certificate(&cert);
|
||||
ret = hx509_cert_init_data(context,
|
||||
sd->certificates->val[i].data,
|
||||
sd->certificates->val[i].length,
|
||||
&c);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = hx509_certs_add(context, certs, c);
|
||||
@ -951,6 +966,7 @@ hx509_cms_create_signed_1(hx509_context context,
|
||||
int ret;
|
||||
size_t size;
|
||||
hx509_path path;
|
||||
int cmsidflag = CMS_ID_SKI;
|
||||
|
||||
memset(&sd, 0, sizeof(sd));
|
||||
memset(&name, 0, sizeof(name));
|
||||
@ -960,6 +976,9 @@ hx509_cms_create_signed_1(hx509_context context,
|
||||
content.data = rk_UNCONST(data);
|
||||
content.length = length;
|
||||
|
||||
if (flags & HX509_CMS_SIGATURE_ID_NAME)
|
||||
cmsidflag = CMS_ID_NAME;
|
||||
|
||||
if (_hx509_cert_private_key(cert) == NULL) {
|
||||
hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
|
||||
"Private key missing for signing");
|
||||
@ -1014,7 +1033,7 @@ hx509_cms_create_signed_1(hx509_context context,
|
||||
|
||||
signer_info->version = 1;
|
||||
|
||||
ret = fill_CMSIdentifier(cert, &signer_info->sid);
|
||||
ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid);
|
||||
if (ret) {
|
||||
hx509_clear_error_string(context);
|
||||
goto out;
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: crypto.c 20939 2007-06-06 20:53:02Z lha $");
|
||||
RCSID("$Id: crypto.c 21318 2007-06-25 19:46:32Z lha $");
|
||||
|
||||
struct hx509_crypto;
|
||||
|
||||
@ -362,6 +362,7 @@ rsa_create_signature(hx509_context context,
|
||||
sig->length = RSA_size(signer->private_key.rsa);
|
||||
sig->data = malloc(sig->length);
|
||||
if (sig->data == NULL) {
|
||||
der_free_octet_string(&indata);
|
||||
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
|
||||
return ENOMEM;
|
||||
}
|
||||
@ -1761,15 +1762,17 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
|
||||
p->maximum_effective_key = 128;
|
||||
break;
|
||||
default:
|
||||
free(p);
|
||||
free_CMSRC2CBCParameter(&rc2param);
|
||||
return HX509_CRYPTO_SIG_INVALID_FORMAT;
|
||||
}
|
||||
if (ivec)
|
||||
ret = der_copy_octet_string(&rc2param.iv, ivec);
|
||||
free_CMSRC2CBCParameter(&rc2param);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
free(p);
|
||||
hx509_clear_error_string(context);
|
||||
else
|
||||
} else
|
||||
crypto->param = p;
|
||||
|
||||
return ret;
|
||||
@ -2008,11 +2011,30 @@ hx509_crypto_get_params(hx509_context context,
|
||||
return (*crypto->cipher->get_params)(context, crypto, ivec, param);
|
||||
}
|
||||
|
||||
int
|
||||
hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)
|
||||
{
|
||||
ivec->length = EVP_CIPHER_iv_length(crypto->c);
|
||||
ivec->data = malloc(ivec->length);
|
||||
if (ivec->data == NULL) {
|
||||
ivec->length = 0;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (RAND_bytes(ivec->data, ivec->length) <= 0) {
|
||||
free(ivec->data);
|
||||
ivec->data = NULL;
|
||||
ivec->length = 0;
|
||||
return HX509_CRYPTO_INTERNAL_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hx509_crypto_encrypt(hx509_crypto crypto,
|
||||
const void *data,
|
||||
const size_t length,
|
||||
heim_octet_string *ivec,
|
||||
const heim_octet_string *ivec,
|
||||
heim_octet_string **ciphertext)
|
||||
{
|
||||
EVP_CIPHER_CTX evp;
|
||||
@ -2021,20 +2043,10 @@ hx509_crypto_encrypt(hx509_crypto crypto,
|
||||
|
||||
*ciphertext = NULL;
|
||||
|
||||
assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length);
|
||||
|
||||
EVP_CIPHER_CTX_init(&evp);
|
||||
|
||||
ivec->length = EVP_CIPHER_iv_length(crypto->c);
|
||||
ivec->data = malloc(ivec->length);
|
||||
if (ivec->data == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (RAND_bytes(ivec->data, ivec->length) <= 0) {
|
||||
ret = HX509_CRYPTO_INTERNAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
|
||||
crypto->key.data, ivec->data, 1);
|
||||
if (ret != 1) {
|
||||
@ -2082,10 +2094,6 @@ hx509_crypto_encrypt(hx509_crypto crypto,
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
if (ivec->data) {
|
||||
free(ivec->data);
|
||||
memset(ivec, 0, sizeof(*ivec));
|
||||
}
|
||||
if (*ciphertext) {
|
||||
if ((*ciphertext)->data) {
|
||||
free((*ciphertext)->data);
|
||||
@ -2286,6 +2294,24 @@ find_string2key(const heim_oid *oid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
_hx509_pbe_encrypt(hx509_context context,
|
||||
hx509_lock lock,
|
||||
const AlgorithmIdentifier *ai,
|
||||
const heim_octet_string *content,
|
||||
heim_octet_string *econtent)
|
||||
{
|
||||
hx509_clear_error_string(context);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
_hx509_pbe_decrypt(hx509_context context,
|
||||
|
@ -134,3 +134,243 @@ _hx509_write_file(const char *fn, const void *data, size_t length)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
header(FILE *f, const char *type, const char *str)
|
||||
{
|
||||
fprintf(f, "-----%s %s-----\n", type, str);
|
||||
}
|
||||
|
||||
int
|
||||
hx509_pem_write(hx509_context context, const char *type,
|
||||
hx509_pem_header *headers, FILE *f,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
const char *p = data;
|
||||
size_t length;
|
||||
char *line;
|
||||
|
||||
#define ENCODE_LINE_LENGTH 54
|
||||
|
||||
header(f, "BEGIN", type);
|
||||
|
||||
while (headers) {
|
||||
fprintf(f, "%s: %s\n%s",
|
||||
headers->header, headers->value,
|
||||
headers->next ? "" : "\n");
|
||||
headers = headers->next;
|
||||
}
|
||||
|
||||
while (size > 0) {
|
||||
ssize_t l;
|
||||
|
||||
length = size;
|
||||
if (length > ENCODE_LINE_LENGTH)
|
||||
length = ENCODE_LINE_LENGTH;
|
||||
|
||||
l = base64_encode(p, length, &line);
|
||||
if (l < 0) {
|
||||
hx509_set_error_string(context, 0, ENOMEM,
|
||||
"malloc - out of memory");
|
||||
return ENOMEM;
|
||||
}
|
||||
size -= length;
|
||||
fprintf(f, "%s\n", line);
|
||||
p += length;
|
||||
free(line);
|
||||
}
|
||||
|
||||
header(f, "END", type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
hx509_pem_add_header(hx509_pem_header **headers,
|
||||
const char *header, const char *value)
|
||||
{
|
||||
hx509_pem_header *h;
|
||||
|
||||
h = calloc(1, sizeof(*h));
|
||||
if (h == NULL)
|
||||
return ENOMEM;
|
||||
h->header = strdup(header);
|
||||
if (h->header == NULL) {
|
||||
free(h);
|
||||
return ENOMEM;
|
||||
}
|
||||
h->value = strdup(value);
|
||||
if (h->value == NULL) {
|
||||
free(h->header);
|
||||
free(h);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
h->next = *headers;
|
||||
*headers = h;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hx509_pem_free_header(hx509_pem_header *headers)
|
||||
{
|
||||
hx509_pem_header *h;
|
||||
while (headers) {
|
||||
h = headers;
|
||||
headers = headers->next;
|
||||
free(h->header);
|
||||
free(h->value);
|
||||
free(h);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
const char *
|
||||
hx509_pem_find_header(const hx509_pem_header *h, const char *header)
|
||||
{
|
||||
while(h) {
|
||||
if (strcmp(header, h->header) == 0)
|
||||
return h->value;
|
||||
h = h->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
hx509_pem_read(hx509_context context,
|
||||
FILE *f,
|
||||
hx509_pem_read_func func,
|
||||
void *ctx)
|
||||
{
|
||||
hx509_pem_header *headers = NULL;
|
||||
char *type = NULL;
|
||||
void *data = NULL;
|
||||
size_t len = 0;
|
||||
char buf[1024];
|
||||
int ret = HX509_PARSING_KEY_FAILED;
|
||||
|
||||
enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
|
||||
|
||||
where = BEFORE;
|
||||
|
||||
while (fgets(buf, sizeof(buf), f) != NULL) {
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
i = strcspn(buf, "\n");
|
||||
if (buf[i] == '\n') {
|
||||
buf[i] = '\0';
|
||||
if (i > 0)
|
||||
i--;
|
||||
}
|
||||
if (buf[i] == '\r') {
|
||||
buf[i] = '\0';
|
||||
if (i > 0)
|
||||
i--;
|
||||
}
|
||||
|
||||
switch (where) {
|
||||
case BEFORE:
|
||||
if (strncmp("-----BEGIN ", buf, 11) == 0) {
|
||||
type = strdup(buf + 11);
|
||||
if (type == NULL)
|
||||
break;
|
||||
p = strchr(type, '-');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
where = SEARCHHEADER;
|
||||
}
|
||||
break;
|
||||
case SEARCHHEADER:
|
||||
p = strchr(buf, ':');
|
||||
if (p == NULL) {
|
||||
where = INDATA;
|
||||
goto indata;
|
||||
}
|
||||
/* FALLTHOUGH */
|
||||
case INHEADER:
|
||||
if (buf[0] == '\0') {
|
||||
where = INDATA;
|
||||
break;
|
||||
}
|
||||
p = strchr(buf, ':');
|
||||
if (p) {
|
||||
*p++ = '\0';
|
||||
while (isspace((int)*p))
|
||||
p++;
|
||||
ret = hx509_pem_add_header(&headers, buf, p);
|
||||
if (ret)
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case INDATA:
|
||||
indata:
|
||||
|
||||
if (strncmp("-----END ", buf, 9) == 0) {
|
||||
where = DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
p = emalloc(i);
|
||||
i = base64_decode(buf, p);
|
||||
if (i < 0) {
|
||||
free(p);
|
||||
goto out;
|
||||
}
|
||||
|
||||
data = erealloc(data, len + i);
|
||||
memcpy(((char *)data) + len, p, i);
|
||||
free(p);
|
||||
len += i;
|
||||
break;
|
||||
case DONE:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (where == DONE) {
|
||||
ret = (*func)(context, type, headers, data, len, ctx);
|
||||
out:
|
||||
free(data);
|
||||
data = NULL;
|
||||
len = 0;
|
||||
free(type);
|
||||
type = NULL;
|
||||
where = BEFORE;
|
||||
hx509_pem_free_header(headers);
|
||||
headers = NULL;
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (where != BEFORE) {
|
||||
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
|
||||
"File ends before end of PEM end tag");
|
||||
ret = HX509_PARSING_KEY_FAILED;
|
||||
}
|
||||
if (data)
|
||||
free(data);
|
||||
if (type)
|
||||
free(type);
|
||||
if (headers)
|
||||
hx509_pem_free_header(headers);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !defined(__GNUC__) && !defined(__attribute__)
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
int
|
||||
_hx509_Certificate_cmp (
|
||||
const Certificate */*p*/,
|
||||
@ -20,7 +24,8 @@ _hx509_Time2time_t (const Time */*t*/);
|
||||
void
|
||||
_hx509_abort (
|
||||
const char */*fmt*/,
|
||||
...);
|
||||
...)
|
||||
__attribute__ ((noreturn, format (printf, 1, 2)));
|
||||
|
||||
int
|
||||
_hx509_calculate_path (
|
||||
@ -104,6 +109,9 @@ _hx509_certs_keys_get (
|
||||
hx509_certs /*certs*/,
|
||||
hx509_private_key **/*keys*/);
|
||||
|
||||
hx509_certs
|
||||
_hx509_certs_ref (hx509_certs /*certs*/);
|
||||
|
||||
int
|
||||
_hx509_check_key_usage (
|
||||
hx509_context /*context*/,
|
||||
@ -306,6 +314,14 @@ _hx509_pbe_decrypt (
|
||||
const heim_octet_string */*econtent*/,
|
||||
heim_octet_string */*content*/);
|
||||
|
||||
int
|
||||
_hx509_pbe_encrypt (
|
||||
hx509_context /*context*/,
|
||||
hx509_lock /*lock*/,
|
||||
const AlgorithmIdentifier */*ai*/,
|
||||
const heim_octet_string */*content*/,
|
||||
heim_octet_string */*econtent*/);
|
||||
|
||||
void
|
||||
_hx509_pi_printf (
|
||||
int (*/*func*/)(void *, const char *),
|
||||
@ -406,11 +422,35 @@ _hx509_request_add_email (
|
||||
void
|
||||
_hx509_request_free (hx509_request */*req*/);
|
||||
|
||||
int
|
||||
_hx509_request_get_SubjectPublicKeyInfo (
|
||||
hx509_context /*context*/,
|
||||
hx509_request /*req*/,
|
||||
SubjectPublicKeyInfo */*key*/);
|
||||
|
||||
int
|
||||
_hx509_request_get_name (
|
||||
hx509_context /*context*/,
|
||||
hx509_request /*req*/,
|
||||
hx509_name */*name*/);
|
||||
|
||||
int
|
||||
_hx509_request_init (
|
||||
hx509_context /*context*/,
|
||||
hx509_request */*req*/);
|
||||
|
||||
int
|
||||
_hx509_request_parse (
|
||||
hx509_context /*context*/,
|
||||
const char */*path*/,
|
||||
hx509_request */*req*/);
|
||||
|
||||
int
|
||||
_hx509_request_print (
|
||||
hx509_context /*context*/,
|
||||
hx509_request /*req*/,
|
||||
FILE */*f*/);
|
||||
|
||||
int
|
||||
_hx509_request_set_SubjectPublicKeyInfo (
|
||||
hx509_context /*context*/,
|
||||
|
@ -236,6 +236,13 @@ hx509_cert_init (
|
||||
const Certificate */*c*/,
|
||||
hx509_cert */*cert*/);
|
||||
|
||||
int
|
||||
hx509_cert_init_data (
|
||||
hx509_context /*context*/,
|
||||
const void */*ptr*/,
|
||||
size_t /*len*/,
|
||||
hx509_cert */*cert*/);
|
||||
|
||||
int
|
||||
hx509_cert_keyusage_print (
|
||||
hx509_context /*context*/,
|
||||
@ -479,7 +486,7 @@ hx509_crypto_encrypt (
|
||||
hx509_crypto /*crypto*/,
|
||||
const void */*data*/,
|
||||
const size_t /*length*/,
|
||||
heim_octet_string */*ivec*/,
|
||||
const heim_octet_string */*ivec*/,
|
||||
heim_octet_string **/*ciphertext*/);
|
||||
|
||||
const heim_oid *
|
||||
@ -507,6 +514,11 @@ hx509_crypto_init (
|
||||
const char *
|
||||
hx509_crypto_provider (hx509_crypto /*crypto*/);
|
||||
|
||||
int
|
||||
hx509_crypto_random_iv (
|
||||
hx509_crypto /*crypto*/,
|
||||
heim_octet_string */*ivec*/);
|
||||
|
||||
int
|
||||
hx509_crypto_select (
|
||||
const hx509_context /*context*/,
|
||||
@ -740,6 +752,36 @@ hx509_peer_info_set_cms_algs (
|
||||
const AlgorithmIdentifier */*val*/,
|
||||
size_t /*len*/);
|
||||
|
||||
int
|
||||
hx509_pem_add_header (
|
||||
hx509_pem_header **/*headers*/,
|
||||
const char */*header*/,
|
||||
const char */*value*/);
|
||||
|
||||
const char *
|
||||
hx509_pem_find_header (
|
||||
const hx509_pem_header */*h*/,
|
||||
const char */*header*/);
|
||||
|
||||
void
|
||||
hx509_pem_free_header (hx509_pem_header */*headers*/);
|
||||
|
||||
int
|
||||
hx509_pem_read (
|
||||
hx509_context /*context*/,
|
||||
FILE */*f*/,
|
||||
hx509_pem_read_func /*func*/,
|
||||
void */*ctx*/);
|
||||
|
||||
int
|
||||
hx509_pem_write (
|
||||
hx509_context /*context*/,
|
||||
const char */*type*/,
|
||||
hx509_pem_header */*headers*/,
|
||||
FILE */*f*/,
|
||||
const void */*data*/,
|
||||
size_t /*size*/);
|
||||
|
||||
void
|
||||
hx509_print_func (
|
||||
hx509_vprint_func /*func*/,
|
||||
@ -930,6 +972,11 @@ hx509_verify_attach_revoke (
|
||||
hx509_verify_ctx /*ctx*/,
|
||||
hx509_revoke_ctx /*revoke_ctx*/);
|
||||
|
||||
void
|
||||
hx509_verify_ctx_f_allow_default_trustanchors (
|
||||
hx509_verify_ctx /*ctx*/,
|
||||
int /*boolean*/);
|
||||
|
||||
void
|
||||
hx509_verify_destroy_ctx (hx509_verify_ctx /*ctx*/);
|
||||
|
||||
@ -937,7 +984,8 @@ int
|
||||
hx509_verify_hostname (
|
||||
hx509_context /*context*/,
|
||||
const hx509_cert /*cert*/,
|
||||
int /*require_match*/,
|
||||
int /*flags*/,
|
||||
hx509_hostname_type /*type*/,
|
||||
const char */*hostname*/,
|
||||
const struct sockaddr */*sa*/,
|
||||
int /*sa_size*/);
|
||||
@ -954,6 +1002,11 @@ hx509_verify_path (
|
||||
hx509_cert /*cert*/,
|
||||
hx509_certs /*pool*/);
|
||||
|
||||
void
|
||||
hx509_verify_set_max_depth (
|
||||
hx509_verify_ctx /*ctx*/,
|
||||
unsigned int /*max_depth*/);
|
||||
|
||||
void
|
||||
hx509_verify_set_proxy_certificate (
|
||||
hx509_verify_ctx /*ctx*/,
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id: hx509.h 20798 2007-06-02 03:28:55Z lha $ */
|
||||
/* $Id: hx509.h 21310 2007-06-25 18:26:06Z lha $ */
|
||||
|
||||
typedef struct hx509_cert_attribute_data *hx509_cert_attribute;
|
||||
typedef struct hx509_cert_data *hx509_cert;
|
||||
@ -84,6 +84,16 @@ typedef struct hx509_octet_string_list {
|
||||
heim_octet_string *val;
|
||||
} hx509_octet_string_list;
|
||||
|
||||
typedef struct hx509_pem_header {
|
||||
struct hx509_pem_header *next;
|
||||
char *header;
|
||||
char *value;
|
||||
} hx509_pem_header;
|
||||
|
||||
typedef int
|
||||
(*hx509_pem_read_func)(hx509_context, const char *, const hx509_pem_header *,
|
||||
const void *, size_t, void *ctx);
|
||||
|
||||
/*
|
||||
* Options passed to hx509_query_match_option.
|
||||
*/
|
||||
@ -122,5 +132,12 @@ typedef enum {
|
||||
|
||||
/* flags hx509_cms_create_signed* */
|
||||
#define HX509_CMS_SIGATURE_DETACHED 1
|
||||
#define HX509_CMS_SIGATURE_ID_NAME 2
|
||||
|
||||
/* hx509_verify_hostname nametype */
|
||||
typedef enum {
|
||||
HX509_HN_HOSTNAME = 0,
|
||||
HX509_HN_DNSSRV
|
||||
} hx509_hostname_type;
|
||||
|
||||
#include <hx509-protos.h>
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id: hx_locl.h 20930 2007-06-06 00:23:42Z lha $ */
|
||||
/* $Id: hx_locl.h 21083 2007-06-13 02:11:19Z lha $ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -194,6 +194,6 @@ extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg;
|
||||
* Configurable options
|
||||
*/
|
||||
|
||||
#if 0 /* fdef __APPLE__*/
|
||||
#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system"
|
||||
#ifdef __APPLE__
|
||||
#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system-anchors"
|
||||
#endif
|
||||
|
@ -32,9 +32,10 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: keyset.c 20911 2007-06-05 03:41:17Z lha $");
|
||||
RCSID("$Id: keyset.c 21140 2007-06-18 21:24:19Z lha $");
|
||||
|
||||
struct hx509_certs_data {
|
||||
int ref;
|
||||
struct hx509_keyset_ops *ops;
|
||||
void *ops_data;
|
||||
};
|
||||
@ -99,18 +100,20 @@ hx509_certs_init(hx509_context context,
|
||||
}
|
||||
|
||||
ops = _hx509_ks_type(context, type);
|
||||
free(type);
|
||||
if (ops == NULL) {
|
||||
hx509_set_error_string(context, 0, ENOENT,
|
||||
"Keyset type %s is not supported", type);
|
||||
free(type);
|
||||
return ENOENT;
|
||||
}
|
||||
free(type);
|
||||
c = calloc(1, sizeof(*c));
|
||||
if (c == NULL) {
|
||||
hx509_clear_error_string(context);
|
||||
return ENOMEM;
|
||||
}
|
||||
c->ops = ops;
|
||||
c->ref = 1;
|
||||
|
||||
ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock);
|
||||
if (ret) {
|
||||
@ -140,10 +143,26 @@ hx509_certs_store(hx509_context context,
|
||||
}
|
||||
|
||||
|
||||
hx509_certs
|
||||
_hx509_certs_ref(hx509_certs certs)
|
||||
{
|
||||
if (certs->ref <= 0)
|
||||
_hx509_abort("certs refcount <= 0");
|
||||
certs->ref++;
|
||||
if (certs->ref == 0)
|
||||
_hx509_abort("certs refcount == 0");
|
||||
return certs;
|
||||
}
|
||||
|
||||
void
|
||||
hx509_certs_free(hx509_certs *certs)
|
||||
{
|
||||
if (*certs) {
|
||||
if ((*certs)->ref <= 0)
|
||||
_hx509_abort("refcount <= 0");
|
||||
if (--(*certs)->ref > 0)
|
||||
return;
|
||||
|
||||
(*(*certs)->ops->free)(*certs, (*certs)->ops_data);
|
||||
free(*certs);
|
||||
*certs = NULL;
|
||||
|
@ -32,68 +32,16 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: ks_file.c 20776 2007-06-01 22:02:01Z lha $");
|
||||
RCSID("$Id: ks_file.c 21314 2007-06-25 18:45:07Z lha $");
|
||||
|
||||
typedef enum { USE_PEM, USE_DER } outformat;
|
||||
|
||||
struct ks_file {
|
||||
hx509_certs certs;
|
||||
char *fn;
|
||||
outformat format;
|
||||
};
|
||||
|
||||
struct header {
|
||||
char *header;
|
||||
char *value;
|
||||
struct header *next;
|
||||
};
|
||||
|
||||
static int
|
||||
add_headers(struct header **headers, const char *header, const char *value)
|
||||
{
|
||||
struct header *h;
|
||||
h = calloc(1, sizeof(*h));
|
||||
if (h == NULL)
|
||||
return ENOMEM;
|
||||
h->header = strdup(header);
|
||||
if (h->header == NULL) {
|
||||
free(h);
|
||||
return ENOMEM;
|
||||
}
|
||||
h->value = strdup(value);
|
||||
if (h->value == NULL) {
|
||||
free(h->header);
|
||||
free(h);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
h->next = *headers;
|
||||
*headers = h;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_headers(struct header *headers)
|
||||
{
|
||||
struct header *h;
|
||||
while (headers) {
|
||||
h = headers;
|
||||
headers = headers->next;
|
||||
free(h->header);
|
||||
free(h->value);
|
||||
free(h);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
find_header(const struct header *headers, const char *header)
|
||||
{
|
||||
while(headers) {
|
||||
if (strcmp(header, headers->header) == 0)
|
||||
return headers->value;
|
||||
headers = headers->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
@ -101,24 +49,13 @@ find_header(const struct header *headers, const char *header)
|
||||
static int
|
||||
parse_certificate(hx509_context context, const char *fn,
|
||||
struct hx509_collector *c,
|
||||
const struct header *headers,
|
||||
const hx509_pem_header *headers,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
hx509_cert cert;
|
||||
Certificate t;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
ret = decode_Certificate(data, len, &t, &size);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Failed to parse certificate in %s",
|
||||
fn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hx509_cert_init(context, &t, &cert);
|
||||
free_Certificate(&t);
|
||||
ret = hx509_cert_init_data(context, data, len, &cert);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -195,13 +132,13 @@ out:
|
||||
static int
|
||||
parse_rsa_private_key(hx509_context context, const char *fn,
|
||||
struct hx509_collector *c,
|
||||
const struct header *headers,
|
||||
const hx509_pem_header *headers,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
const char *enc;
|
||||
|
||||
enc = find_header(headers, "Proc-Type");
|
||||
enc = hx509_pem_find_header(headers, "Proc-Type");
|
||||
if (enc) {
|
||||
const char *dek;
|
||||
char *type, *iv;
|
||||
@ -229,7 +166,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
|
||||
return HX509_PARSING_KEY_FAILED;
|
||||
}
|
||||
|
||||
dek = find_header(headers, "DEK-Info");
|
||||
dek = hx509_pem_find_header(headers, "DEK-Info");
|
||||
if (dek == NULL) {
|
||||
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
|
||||
"Encrypted RSA missing DEK-Info");
|
||||
@ -243,8 +180,14 @@ parse_rsa_private_key(hx509_context context, const char *fn,
|
||||
}
|
||||
|
||||
iv = strchr(type, ',');
|
||||
if (iv)
|
||||
*iv++ = '\0';
|
||||
if (iv == NULL) {
|
||||
free(type);
|
||||
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
|
||||
"IV missing");
|
||||
return HX509_PARSING_KEY_FAILED;
|
||||
}
|
||||
|
||||
*iv++ = '\0';
|
||||
|
||||
size = strlen(iv);
|
||||
ivdata = malloc(size);
|
||||
@ -339,7 +282,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
|
||||
struct pem_formats {
|
||||
const char *name;
|
||||
int (*func)(hx509_context, const char *, struct hx509_collector *,
|
||||
const struct header *, const void *, size_t);
|
||||
const hx509_pem_header *, const void *, size_t);
|
||||
} formats[] = {
|
||||
{ "CERTIFICATE", parse_certificate },
|
||||
{ "RSA PRIVATE KEY", parse_rsa_private_key }
|
||||
@ -347,152 +290,27 @@ struct pem_formats {
|
||||
|
||||
|
||||
static int
|
||||
parse_pem_file(hx509_context context,
|
||||
const char *fn,
|
||||
struct hx509_collector *c,
|
||||
int *found_data)
|
||||
pem_func(hx509_context context, const char *type,
|
||||
const hx509_pem_header *header,
|
||||
const void *data, size_t len, void *ctx)
|
||||
{
|
||||
struct header *headers = NULL;
|
||||
char *type = NULL;
|
||||
void *data = NULL;
|
||||
size_t len = 0;
|
||||
char buf[1024];
|
||||
int ret;
|
||||
FILE *f;
|
||||
struct hx509_collector *c = ctx;
|
||||
int ret, j;
|
||||
|
||||
|
||||
enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
|
||||
|
||||
where = BEFORE;
|
||||
*found_data = 0;
|
||||
|
||||
if ((f = fopen(fn, "r")) == NULL) {
|
||||
hx509_set_error_string(context, 0, ENOENT,
|
||||
"Failed to open PEM file \"%s\": %s",
|
||||
fn, strerror(errno));
|
||||
return ENOENT;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
while (fgets(buf, sizeof(buf), f) != NULL) {
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
i = strcspn(buf, "\n");
|
||||
if (buf[i] == '\n') {
|
||||
buf[i] = '\0';
|
||||
if (i > 0)
|
||||
i--;
|
||||
}
|
||||
if (buf[i] == '\r') {
|
||||
buf[i] = '\0';
|
||||
if (i > 0)
|
||||
i--;
|
||||
}
|
||||
|
||||
switch (where) {
|
||||
case BEFORE:
|
||||
if (strncmp("-----BEGIN ", buf, 11) == 0) {
|
||||
type = strdup(buf + 11);
|
||||
if (type == NULL)
|
||||
break;
|
||||
p = strchr(type, '-');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
*found_data = 1;
|
||||
where = SEARCHHEADER;
|
||||
}
|
||||
for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) {
|
||||
const char *q = formats[j].name;
|
||||
if (strcasecmp(type, q) == 0) {
|
||||
ret = (*formats[j].func)(context, NULL, c, header, data, len);
|
||||
break;
|
||||
case SEARCHHEADER:
|
||||
p = strchr(buf, ':');
|
||||
if (p == NULL) {
|
||||
where = INDATA;
|
||||
goto indata;
|
||||
}
|
||||
/* FALLTHOUGH */
|
||||
case INHEADER:
|
||||
if (buf[0] == '\0') {
|
||||
where = INDATA;
|
||||
break;
|
||||
}
|
||||
p = strchr(buf, ':');
|
||||
if (p) {
|
||||
*p++ = '\0';
|
||||
while (isspace((int)*p))
|
||||
p++;
|
||||
add_headers(&headers, buf, p);
|
||||
}
|
||||
break;
|
||||
case INDATA:
|
||||
indata:
|
||||
|
||||
if (strncmp("-----END ", buf, 9) == 0) {
|
||||
where = DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
p = emalloc(i);
|
||||
i = base64_decode(buf, p);
|
||||
if (i < 0) {
|
||||
free(p);
|
||||
goto out;
|
||||
}
|
||||
|
||||
data = erealloc(data, len + i);
|
||||
memcpy(((char *)data) + len, p, i);
|
||||
free(p);
|
||||
len += i;
|
||||
break;
|
||||
case DONE:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (where == DONE) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) {
|
||||
const char *q = formats[j].name;
|
||||
if (strcasecmp(type, q) == 0) {
|
||||
ret = (*formats[j].func)(context, fn, c,
|
||||
headers, data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == sizeof(formats)/sizeof(formats[0])) {
|
||||
ret = HX509_UNSUPPORTED_OPERATION;
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Found no matching PEM format for %s",
|
||||
type);
|
||||
}
|
||||
out:
|
||||
free(data);
|
||||
data = NULL;
|
||||
len = 0;
|
||||
free(type);
|
||||
type = NULL;
|
||||
where = BEFORE;
|
||||
free_headers(headers);
|
||||
headers = NULL;
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (where != BEFORE) {
|
||||
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
|
||||
"File ends before end of PEM end tag");
|
||||
ret = HX509_PARSING_KEY_FAILED;
|
||||
if (j == sizeof(formats)/sizeof(formats[0])) {
|
||||
ret = HX509_UNSUPPORTED_OPERATION;
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Found no matching PEM format for %s", type);
|
||||
return ret;
|
||||
}
|
||||
if (data)
|
||||
free(data);
|
||||
if (type)
|
||||
free(type);
|
||||
if (headers)
|
||||
free_headers(headers);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -500,9 +318,9 @@ parse_pem_file(hx509_context context,
|
||||
*/
|
||||
|
||||
static int
|
||||
file_init(hx509_context context,
|
||||
hx509_certs certs, void **data, int flags,
|
||||
const char *residue, hx509_lock lock)
|
||||
file_init_common(hx509_context context,
|
||||
hx509_certs certs, void **data, int flags,
|
||||
const char *residue, hx509_lock lock, outformat format)
|
||||
{
|
||||
char *p, *pnext;
|
||||
struct ks_file *f = NULL;
|
||||
@ -520,6 +338,7 @@ file_init(hx509_context context,
|
||||
hx509_clear_error_string(context);
|
||||
return ENOMEM;
|
||||
}
|
||||
f->format = format;
|
||||
|
||||
f->fn = strdup(residue);
|
||||
if (f->fn == NULL) {
|
||||
@ -547,17 +366,26 @@ file_init(hx509_context context,
|
||||
goto out;
|
||||
|
||||
for (p = f->fn; p != NULL; p = pnext) {
|
||||
int found_data;
|
||||
FILE *f;
|
||||
|
||||
pnext = strchr(p, ',');
|
||||
if (pnext)
|
||||
*pnext++ = '\0';
|
||||
|
||||
ret = parse_pem_file(context, p, c, &found_data);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!found_data) {
|
||||
if ((f = fopen(p, "r")) == NULL) {
|
||||
ret = ENOENT;
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Failed to open PEM file \"%s\": %s",
|
||||
p, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hx509_pem_read(context, f, pem_func, c);
|
||||
fclose(f);
|
||||
if (ret != 0 && ret != HX509_PARSING_KEY_FAILED)
|
||||
goto out;
|
||||
else if (ret == HX509_PARSING_KEY_FAILED) {
|
||||
size_t length;
|
||||
void *ptr;
|
||||
int i;
|
||||
@ -605,6 +433,22 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
file_init_pem(hx509_context context,
|
||||
hx509_certs certs, void **data, int flags,
|
||||
const char *residue, hx509_lock lock)
|
||||
{
|
||||
return file_init_common(context, certs, data, flags, residue, lock, USE_PEM);
|
||||
}
|
||||
|
||||
static int
|
||||
file_init_der(hx509_context context,
|
||||
hx509_certs certs, void **data, int flags,
|
||||
const char *residue, hx509_lock lock)
|
||||
{
|
||||
return file_init_common(context, certs, data, flags, residue, lock, USE_DER);
|
||||
}
|
||||
|
||||
static int
|
||||
file_free(hx509_certs certs, void *data)
|
||||
{
|
||||
@ -615,66 +459,15 @@ file_free(hx509_certs certs, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pem_header(FILE *f, const char *type, const char *str)
|
||||
{
|
||||
fprintf(f, "-----%s %s-----\n", type, str);
|
||||
}
|
||||
|
||||
static int
|
||||
dump_pem_file(hx509_context context, const char *header,
|
||||
FILE *f, const void *data, size_t size)
|
||||
{
|
||||
const char *p = data;
|
||||
size_t length;
|
||||
char *line;
|
||||
|
||||
#define ENCODE_LINE_LENGTH 54
|
||||
|
||||
pem_header(f, "BEGIN", header);
|
||||
|
||||
while (size > 0) {
|
||||
ssize_t l;
|
||||
|
||||
length = size;
|
||||
if (length > ENCODE_LINE_LENGTH)
|
||||
length = ENCODE_LINE_LENGTH;
|
||||
|
||||
l = base64_encode(p, length, &line);
|
||||
if (l < 0) {
|
||||
hx509_set_error_string(context, 0, ENOMEM,
|
||||
"malloc - out of memory");
|
||||
return ENOMEM;
|
||||
}
|
||||
size -= length;
|
||||
fprintf(f, "%s\n", line);
|
||||
p += length;
|
||||
free(line);
|
||||
}
|
||||
|
||||
pem_header(f, "END", header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
store_private_key(hx509_context context, FILE *f, hx509_private_key key)
|
||||
{
|
||||
heim_octet_string data;
|
||||
int ret;
|
||||
|
||||
ret = _hx509_private_key_export(context, key, &data);
|
||||
if (ret == 0)
|
||||
dump_pem_file(context, _hx509_private_pem_name(key), f,
|
||||
data.data, data.length);
|
||||
free(data.data);
|
||||
return ret;
|
||||
}
|
||||
struct store_ctx {
|
||||
FILE *f;
|
||||
outformat format;
|
||||
};
|
||||
|
||||
static int
|
||||
store_func(hx509_context context, void *ctx, hx509_cert c)
|
||||
{
|
||||
FILE *f = (FILE *)ctx;
|
||||
struct store_ctx *sc = ctx;
|
||||
heim_octet_string data;
|
||||
int ret;
|
||||
|
||||
@ -682,11 +475,26 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dump_pem_file(context, "CERTIFICATE", f, data.data, data.length);
|
||||
free(data.data);
|
||||
|
||||
if (_hx509_cert_private_key_exportable(c))
|
||||
store_private_key(context, f, _hx509_cert_private_key(c));
|
||||
switch (sc->format) {
|
||||
case USE_DER:
|
||||
fwrite(data.data, data.length, 1, sc->f);
|
||||
free(data.data);
|
||||
break;
|
||||
case USE_PEM:
|
||||
hx509_pem_write(context, "CERTIFICATE", NULL, sc->f,
|
||||
data.data, data.length);
|
||||
free(data.data);
|
||||
if (_hx509_cert_private_key_exportable(c)) {
|
||||
hx509_private_key key = _hx509_cert_private_key(c);
|
||||
ret = _hx509_private_key_export(context, key, &data);
|
||||
if (ret)
|
||||
break;
|
||||
hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f,
|
||||
data.data, data.length);
|
||||
free(data.data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -696,18 +504,19 @@ file_store(hx509_context context,
|
||||
hx509_certs certs, void *data, int flags, hx509_lock lock)
|
||||
{
|
||||
struct ks_file *f = data;
|
||||
FILE *fh;
|
||||
struct store_ctx sc;
|
||||
int ret;
|
||||
|
||||
fh = fopen(f->fn, "w");
|
||||
if (fh == NULL) {
|
||||
sc.f = fopen(f->fn, "w");
|
||||
if (sc.f == NULL) {
|
||||
hx509_set_error_string(context, 0, ENOENT,
|
||||
"Failed to open file %s for writing");
|
||||
return ENOENT;
|
||||
}
|
||||
sc.format = f->format;
|
||||
|
||||
ret = hx509_certs_iter(context, f->certs, store_func, fh);
|
||||
fclose(fh);
|
||||
ret = hx509_certs_iter(context, f->certs, store_func, &sc);
|
||||
fclose(sc.f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -767,7 +576,7 @@ file_addkey(hx509_context context,
|
||||
static struct hx509_keyset_ops keyset_file = {
|
||||
"FILE",
|
||||
0,
|
||||
file_init,
|
||||
file_init_pem,
|
||||
file_store,
|
||||
file_free,
|
||||
file_add,
|
||||
@ -780,8 +589,43 @@ static struct hx509_keyset_ops keyset_file = {
|
||||
file_addkey
|
||||
};
|
||||
|
||||
static struct hx509_keyset_ops keyset_pemfile = {
|
||||
"PEM-FILE",
|
||||
0,
|
||||
file_init_pem,
|
||||
file_store,
|
||||
file_free,
|
||||
file_add,
|
||||
NULL,
|
||||
file_iter_start,
|
||||
file_iter,
|
||||
file_iter_end,
|
||||
NULL,
|
||||
file_getkeys,
|
||||
file_addkey
|
||||
};
|
||||
|
||||
static struct hx509_keyset_ops keyset_derfile = {
|
||||
"DER-FILE",
|
||||
0,
|
||||
file_init_der,
|
||||
file_store,
|
||||
file_free,
|
||||
file_add,
|
||||
NULL,
|
||||
file_iter_start,
|
||||
file_iter,
|
||||
file_iter_end,
|
||||
NULL,
|
||||
file_getkeys,
|
||||
file_addkey
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
_hx509_ks_file_register(hx509_context context)
|
||||
{
|
||||
_hx509_ks_register(context, &keyset_file);
|
||||
_hx509_ks_register(context, &keyset_pemfile);
|
||||
_hx509_ks_register(context, &keyset_derfile);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: ks_keychain.c 20945 2007-06-06 22:17:17Z lha $");
|
||||
RCSID("$Id: ks_keychain.c 21097 2007-06-16 07:00:49Z lha $");
|
||||
|
||||
#ifdef HAVE_FRAMEWORK_SECURITY
|
||||
|
||||
@ -254,6 +254,7 @@ set_private_key(hx509_context context,
|
||||
*/
|
||||
|
||||
struct ks_keychain {
|
||||
int anchors;
|
||||
SecKeychainRef keychain;
|
||||
};
|
||||
|
||||
@ -263,7 +264,6 @@ keychain_init(hx509_context context,
|
||||
const char *residue, hx509_lock lock)
|
||||
{
|
||||
struct ks_keychain *ctx;
|
||||
OSStatus ret;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
@ -272,13 +272,20 @@ keychain_init(hx509_context context,
|
||||
}
|
||||
|
||||
if (residue) {
|
||||
if (strcasecmp(residue, "system") == 0)
|
||||
residue = "/System/Library/Keychains/X509Anchors";
|
||||
if (strcasecmp(residue, "system-anchors") == 0) {
|
||||
ctx->anchors = 1;
|
||||
} else if (strncasecmp(residue, "FILE:", 5) == 0) {
|
||||
OSStatus ret;
|
||||
|
||||
ret = SecKeychainOpen(residue, &ctx->keychain);
|
||||
if (ret != noErr) {
|
||||
ret = SecKeychainOpen(residue + 5, &ctx->keychain);
|
||||
if (ret != noErr) {
|
||||
hx509_set_error_string(context, 0, ENOENT,
|
||||
"Failed to open %s", residue);
|
||||
return ENOENT;
|
||||
}
|
||||
} else {
|
||||
hx509_set_error_string(context, 0, ENOENT,
|
||||
"Failed to open %s", residue);
|
||||
"Unknown subtype %s", residue);
|
||||
return ENOENT;
|
||||
}
|
||||
}
|
||||
@ -307,6 +314,8 @@ keychain_free(hx509_certs certs, void *data)
|
||||
*/
|
||||
|
||||
struct iter {
|
||||
hx509_certs certs;
|
||||
void *cursor;
|
||||
SecKeychainSearchRef searchRef;
|
||||
};
|
||||
|
||||
@ -316,7 +325,6 @@ keychain_iter_start(hx509_context context,
|
||||
{
|
||||
struct ks_keychain *ctx = data;
|
||||
struct iter *iter;
|
||||
OSStatus ret;
|
||||
|
||||
iter = calloc(1, sizeof(*iter));
|
||||
if (iter == NULL) {
|
||||
@ -324,15 +332,66 @@ keychain_iter_start(hx509_context context,
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
|
||||
kSecCertificateItemClass,
|
||||
NULL,
|
||||
&iter->searchRef);
|
||||
if (ret) {
|
||||
free(iter);
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Failed to start search for attributes");
|
||||
return ENOMEM;
|
||||
if (ctx->anchors) {
|
||||
CFArrayRef anchors;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = hx509_certs_init(context, "MEMORY:ks-file-create",
|
||||
0, NULL, &iter->certs);
|
||||
if (ret) {
|
||||
free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = SecTrustCopyAnchorCertificates(&anchors);
|
||||
if (ret != 0) {
|
||||
hx509_certs_free(&iter->certs);
|
||||
free(iter);
|
||||
hx509_set_error_string(context, 0, ENOMEM,
|
||||
"Can't get trust anchors from Keychain");
|
||||
return ENOMEM;
|
||||
}
|
||||
for (i = 0; i < CFArrayGetCount(anchors); i++) {
|
||||
SecCertificateRef cr;
|
||||
hx509_cert cert;
|
||||
CSSM_DATA cssm;
|
||||
|
||||
cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i);
|
||||
|
||||
SecCertificateGetData(cr, &cssm);
|
||||
|
||||
ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
ret = hx509_certs_add(context, iter->certs, cert);
|
||||
hx509_cert_free(cert);
|
||||
}
|
||||
CFRelease(anchors);
|
||||
}
|
||||
|
||||
if (iter->certs) {
|
||||
int ret;
|
||||
ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor);
|
||||
if (ret) {
|
||||
hx509_certs_free(&iter->certs);
|
||||
free(iter);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
OSStatus ret;
|
||||
|
||||
ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
|
||||
kSecCertificateItemClass,
|
||||
NULL,
|
||||
&iter->searchRef);
|
||||
if (ret) {
|
||||
free(iter);
|
||||
hx509_set_error_string(context, 0, ret,
|
||||
"Failed to start search for attributes");
|
||||
return ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
*cursor = iter;
|
||||
@ -349,15 +408,16 @@ keychain_iter(hx509_context context,
|
||||
{
|
||||
SecKeychainAttributeList *attrs = NULL;
|
||||
SecKeychainAttributeInfo attrInfo;
|
||||
uint32 attrFormat = 0;
|
||||
uint32 attrFormat[1] = { 0 };
|
||||
SecKeychainItemRef itemRef;
|
||||
SecItemAttr item;
|
||||
SecItemAttr item[1];
|
||||
struct iter *iter = cursor;
|
||||
Certificate t;
|
||||
OSStatus ret;
|
||||
UInt32 len;
|
||||
void *ptr = NULL;
|
||||
size_t size;
|
||||
|
||||
if (iter->certs)
|
||||
return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert);
|
||||
|
||||
*cert = NULL;
|
||||
|
||||
@ -371,26 +431,18 @@ keychain_iter(hx509_context context,
|
||||
* Pick out certificate and matching "keyid"
|
||||
*/
|
||||
|
||||
item = kSecPublicKeyHashItemAttr;
|
||||
item[0] = kSecPublicKeyHashItemAttr;
|
||||
|
||||
attrInfo.count = 1;
|
||||
attrInfo.tag = &item;
|
||||
attrInfo.format = &attrFormat;
|
||||
attrInfo.tag = item;
|
||||
attrInfo.format = attrFormat;
|
||||
|
||||
ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
|
||||
&attrs, &len, &ptr);
|
||||
if (ret)
|
||||
return EINVAL;
|
||||
|
||||
ret = decode_Certificate(ptr, len, &t, &size);
|
||||
CFRelease(itemRef);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret, "Failed to parse certificate");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hx509_cert_init(context, &t, cert);
|
||||
free_Certificate(&t);
|
||||
ret = hx509_cert_init_data(context, ptr, len, cert);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -449,7 +501,14 @@ keychain_iter_end(hx509_context context,
|
||||
{
|
||||
struct iter *iter = cursor;
|
||||
|
||||
CFRelease(iter->searchRef);
|
||||
if (iter->certs) {
|
||||
int ret;
|
||||
ret = hx509_certs_end_seq(context, iter->certs, iter->cursor);
|
||||
hx509_certs_free(&iter->certs);
|
||||
} else {
|
||||
CFRelease(iter->searchRef);
|
||||
}
|
||||
|
||||
memset(iter, 0, sizeof(*iter));
|
||||
free(iter);
|
||||
return 0;
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: ks_p11.c 20920 2007-06-05 05:47:06Z lha $");
|
||||
RCSID("$Id: ks_p11.c 21085 2007-06-13 06:39:53Z lha $");
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
@ -682,7 +682,6 @@ collect_cert(hx509_context context,
|
||||
{
|
||||
struct hx509_collector *collector = ptr;
|
||||
hx509_cert cert;
|
||||
Certificate t;
|
||||
int ret;
|
||||
|
||||
if ((CK_LONG)query[0].ulValueLen == -1 ||
|
||||
@ -691,16 +690,8 @@ collect_cert(hx509_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ret = decode_Certificate(query[1].pValue, query[1].ulValueLen,
|
||||
&t, NULL);
|
||||
if (ret) {
|
||||
hx509_clear_error_string(context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = hx509_cert_init(context, &t, &cert);
|
||||
free_Certificate(&t);
|
||||
ret = hx509_cert_init_data(context, query[1].pValue,
|
||||
query[1].ulValueLen, &cert);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: ks_p12.c 20909 2007-06-05 03:09:13Z lha $");
|
||||
RCSID("$Id: ks_p12.c 21146 2007-06-18 21:37:25Z lha $");
|
||||
|
||||
struct ks_pkcs12 {
|
||||
hx509_certs certs;
|
||||
@ -90,7 +90,7 @@ keyBag_parser(hx509_context context,
|
||||
&ki.privateKeyAlgorithm,
|
||||
NULL,
|
||||
&ki.privateKey,
|
||||
&attr->attrValues);
|
||||
os);
|
||||
free_PKCS8PrivateKeyInfo(&ki);
|
||||
return 0;
|
||||
}
|
||||
@ -132,7 +132,6 @@ certBag_parser(hx509_context context,
|
||||
const PKCS12_Attributes *attrs)
|
||||
{
|
||||
heim_octet_string os;
|
||||
Certificate t;
|
||||
hx509_cert cert;
|
||||
PKCS12_CertBag cb;
|
||||
int ret;
|
||||
@ -154,16 +153,11 @@ certBag_parser(hx509_context context,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = decode_Certificate(os.data, os.length, &t, NULL);
|
||||
ret = hx509_cert_init_data(context, os.data, os.length, &cert);
|
||||
der_free_octet_string(&os);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hx509_cert_init(context, &t, &cert);
|
||||
free_Certificate(&t);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = _hx509_collector_certs_add(context, c, cert);
|
||||
if (ret) {
|
||||
hx509_cert_free(cert);
|
||||
@ -437,7 +431,9 @@ p12_init(hx509_context context,
|
||||
out:
|
||||
_hx509_collector_free(c);
|
||||
|
||||
if (ret) {
|
||||
if (ret && p12) {
|
||||
if (p12->fn)
|
||||
free(p12->fn);
|
||||
if (p12->certs)
|
||||
hx509_certs_free(&p12->certs);
|
||||
free(p12);
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "hx_locl.h"
|
||||
#include <pkcs10_asn1.h>
|
||||
RCSID("$Id: req.c 20934 2007-06-06 15:30:02Z lha $");
|
||||
RCSID("$Id: req.c 21344 2007-06-26 14:22:34Z lha $");
|
||||
|
||||
struct hx509_request_data {
|
||||
hx509_name name;
|
||||
@ -84,6 +84,18 @@ _hx509_request_set_name(hx509_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_hx509_request_get_name(hx509_context context,
|
||||
hx509_request req,
|
||||
hx509_name *name)
|
||||
{
|
||||
if (req->name == NULL) {
|
||||
hx509_set_error_string(context, 0, EINVAL, "Request have no name");
|
||||
return EINVAL;
|
||||
}
|
||||
return hx509_name_copy(context, req->name, name);
|
||||
}
|
||||
|
||||
int
|
||||
_hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
|
||||
hx509_request req,
|
||||
@ -93,6 +105,14 @@ _hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
|
||||
return copy_SubjectPublicKeyInfo(key, &req->key);
|
||||
}
|
||||
|
||||
int
|
||||
_hx509_request_get_SubjectPublicKeyInfo(hx509_context context,
|
||||
hx509_request req,
|
||||
SubjectPublicKeyInfo *key)
|
||||
{
|
||||
return copy_SubjectPublicKeyInfo(&req->key, key);
|
||||
}
|
||||
|
||||
int
|
||||
_hx509_request_add_eku(hx509_context context,
|
||||
hx509_request req,
|
||||
@ -215,3 +235,91 @@ out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
_hx509_request_parse(hx509_context context,
|
||||
const char *path,
|
||||
hx509_request *req)
|
||||
{
|
||||
CertificationRequest r;
|
||||
CertificationRequestInfo *rinfo;
|
||||
hx509_name subject;
|
||||
size_t len, size;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
if (strncmp(path, "PKCS10:", 7) != 0) {
|
||||
hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
|
||||
"unsupport type in %s", path);
|
||||
return HX509_UNSUPPORTED_OPERATION;
|
||||
}
|
||||
path += 7;
|
||||
|
||||
/* XXX PEM request */
|
||||
|
||||
ret = _hx509_map_file(path, &p, &len, NULL);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret, "Failed to map file %s", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = decode_CertificationRequest(p, len, &r, &size);
|
||||
_hx509_unmap_file(p, len);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret, "Failed to decode %s", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = _hx509_request_init(context, req);
|
||||
if (ret) {
|
||||
free_CertificationRequest(&r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rinfo = &r.certificationRequestInfo;
|
||||
|
||||
ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req,
|
||||
&rinfo->subjectPKInfo);
|
||||
if (ret) {
|
||||
free_CertificationRequest(&r);
|
||||
_hx509_request_free(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = _hx509_name_from_Name(&rinfo->subject, &subject);
|
||||
if (ret) {
|
||||
free_CertificationRequest(&r);
|
||||
_hx509_request_free(req);
|
||||
return ret;
|
||||
}
|
||||
ret = _hx509_request_set_name(context, *req, subject);
|
||||
hx509_name_free(&subject);
|
||||
free_CertificationRequest(&r);
|
||||
if (ret) {
|
||||
_hx509_request_free(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_hx509_request_print(hx509_context context, hx509_request req, FILE *f)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (req->name) {
|
||||
char *subject;
|
||||
ret = hx509_name_to_string(req->name, &subject);
|
||||
if (ret) {
|
||||
hx509_set_error_string(context, 0, ret, "Failed to print name");
|
||||
return ret;
|
||||
}
|
||||
fprintf(f, "name: %s\n", subject);
|
||||
free(subject);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "hx_locl.h"
|
||||
RCSID("$Id: revoke.c 20871 2007-06-03 21:22:51Z lha $");
|
||||
RCSID("$Id: revoke.c 21153 2007-06-18 21:55:46Z lha $");
|
||||
|
||||
struct revoke_crl {
|
||||
char *path;
|
||||
@ -572,10 +572,10 @@ hx509_revoke_verify(hx509_context context,
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < ocsp->ocsp.tbsResponseData.responses.len; i++) {
|
||||
for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) {
|
||||
heim_octet_string os;
|
||||
|
||||
ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[i].certID.serialNumber,
|
||||
ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber,
|
||||
&c->tbsCertificate.serialNumber);
|
||||
if (ret != 0)
|
||||
continue;
|
||||
@ -594,13 +594,13 @@ hx509_revoke_verify(hx509_context context,
|
||||
|
||||
ret = _hx509_verify_signature(context,
|
||||
NULL,
|
||||
&ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
|
||||
&ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm,
|
||||
&os,
|
||||
&ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerKeyHash);
|
||||
&ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash);
|
||||
if (ret != 0)
|
||||
continue;
|
||||
|
||||
switch (ocsp->ocsp.tbsResponseData.responses.val[i].certStatus.element) {
|
||||
switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) {
|
||||
case choice_OCSPCertStatus_good:
|
||||
break;
|
||||
case choice_OCSPCertStatus_revoked:
|
||||
@ -609,13 +609,13 @@ hx509_revoke_verify(hx509_context context,
|
||||
}
|
||||
|
||||
/* don't allow the update to be in the future */
|
||||
if (ocsp->ocsp.tbsResponseData.responses.val[i].thisUpdate >
|
||||
if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate >
|
||||
now + context->ocsp_time_diff)
|
||||
continue;
|
||||
|
||||
/* don't allow the next updte to be in the past */
|
||||
if (ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate) {
|
||||
if (*ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate < now)
|
||||
if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) {
|
||||
if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now)
|
||||
continue;
|
||||
} else
|
||||
/* Should force a refetch, but can we ? */;
|
||||
@ -1077,6 +1077,7 @@ hx509_crl_alloc(hx509_context context, hx509_crl *crl)
|
||||
if (ret) {
|
||||
free(*crl);
|
||||
*crl = NULL;
|
||||
return ret;
|
||||
}
|
||||
(*crl)->expire = 0;
|
||||
return ret;
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "krb5_locl.h"
|
||||
RCSID("$Id: crypto.c 20981 2007-06-07 20:05:50Z lha $");
|
||||
RCSID("$Id: crypto.c 21130 2007-06-18 20:45:21Z lha $");
|
||||
|
||||
#undef CRYPTO_DEBUG
|
||||
#ifdef CRYPTO_DEBUG
|
||||
@ -3162,8 +3162,9 @@ decrypt_internal_derived(krb5_context context,
|
||||
unsigned long l;
|
||||
|
||||
checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
|
||||
if (len < checksum_sz) {
|
||||
krb5_set_error_string(context, "Encrypted data shorter then checksum");
|
||||
if (len < checksum_sz + et->confoundersize) {
|
||||
krb5_set_error_string(context, "Encrypted data shorter then "
|
||||
"checksum + confunder");
|
||||
return KRB5_BAD_MSIZE;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include <krb5_locl.h>
|
||||
|
||||
RCSID("$Id: get_cred.c 21004 2007-06-08 01:53:10Z lha $");
|
||||
RCSID("$Id: get_cred.c 21327 2007-06-26 10:54:15Z lha $");
|
||||
|
||||
/*
|
||||
* Take the `body' and encode it into `padata' using the credentials
|
||||
@ -411,7 +411,6 @@ get_cred_kdc_usage(krb5_context context,
|
||||
krb5_keyblock *subkey = NULL;
|
||||
size_t len;
|
||||
Ticket second_ticket_data;
|
||||
int send_to_kdc_flags = 0;
|
||||
METHOD_DATA padata;
|
||||
|
||||
krb5_data_zero(&resp);
|
||||
@ -511,11 +510,18 @@ get_cred_kdc_usage(krb5_context context,
|
||||
/*
|
||||
* Send and receive
|
||||
*/
|
||||
again:
|
||||
ret = krb5_sendto_kdc_flags (context, &enc,
|
||||
&krbtgt->server->name.name_string.val[1],
|
||||
&resp,
|
||||
send_to_kdc_flags);
|
||||
{
|
||||
krb5_sendto_ctx stctx;
|
||||
ret = krb5_sendto_ctx_alloc(context, &stctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
|
||||
|
||||
ret = krb5_sendto_context (context, stctx, &enc,
|
||||
krbtgt->server->name.name_string.val[1],
|
||||
&resp);
|
||||
krb5_sendto_ctx_free(context, stctx);
|
||||
}
|
||||
if(ret)
|
||||
goto out;
|
||||
|
||||
@ -550,12 +556,6 @@ again:
|
||||
} else if(krb5_rd_error(context, &resp, &error) == 0) {
|
||||
ret = krb5_error_from_rd_error(context, &error, in_creds);
|
||||
krb5_free_error_contents(context, &error);
|
||||
|
||||
if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) {
|
||||
send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
|
||||
krb5_data_free(&resp);
|
||||
goto again;
|
||||
}
|
||||
} else if(resp.data && ((char*)resp.data)[0] == 4) {
|
||||
ret = KRB5KRB_AP_ERR_V4_REPLY;
|
||||
krb5_clear_error_string(context);
|
||||
@ -1191,6 +1191,10 @@ krb5_get_creds(krb5_context context,
|
||||
flags.b.forwardable = 1;
|
||||
if (options & KRB5_GC_NO_TRANSIT_CHECK)
|
||||
flags.b.disable_transited_check = 1;
|
||||
if (options & KRB5_GC_CONSTRAINED_DELEGATION) {
|
||||
flags.b.request_anonymous = 1; /* XXX ARGH confusion */
|
||||
flags.b.constrained_delegation = 1;
|
||||
}
|
||||
|
||||
tgts = NULL;
|
||||
ret = get_cred_from_kdc_flags(context, flags, ccache,
|
||||
@ -1206,3 +1210,62 @@ krb5_get_creds(krb5_context context,
|
||||
krb5_cc_store_cred(context, ccache, *out_creds);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_get_renewed_creds(krb5_context context,
|
||||
krb5_creds *creds,
|
||||
krb5_const_principal client,
|
||||
krb5_ccache ccache,
|
||||
const char *in_tkt_service)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_kdc_flags flags;
|
||||
krb5_creds in, *template;
|
||||
|
||||
memset(&in, 0, sizeof(in));
|
||||
|
||||
ret = krb5_copy_principal(context, client, &in.client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (in_tkt_service) {
|
||||
ret = krb5_parse_name(context, in_tkt_service, &in.server);
|
||||
if (ret) {
|
||||
krb5_free_principal(context, in.client);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
const char *realm = krb5_principal_get_realm(context, client);
|
||||
|
||||
ret = krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME,
|
||||
realm, NULL);
|
||||
if (ret) {
|
||||
krb5_free_principal(context, in.client);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
flags.i = 0;
|
||||
flags.b.renewable = flags.b.renew = 1;
|
||||
|
||||
/*
|
||||
* Get template from old credential cache for the same entry, if
|
||||
* this failes, no worries.
|
||||
*/
|
||||
ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &in, &template);
|
||||
if (ret == 0) {
|
||||
flags.b.forwardable = template->flags.b.forwardable;
|
||||
flags.b.proxiable = template->flags.b.proxiable;
|
||||
krb5_free_creds (context, template);
|
||||
}
|
||||
|
||||
ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &creds);
|
||||
krb5_free_principal(context, in.client);
|
||||
krb5_free_principal(context, in.server);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
RCSID("$Id: init_creds_pw.c 20262 2007-02-18 00:33:01Z lha $");
|
||||
RCSID("$Id: init_creds_pw.c 21061 2007-06-12 17:56:30Z lha $");
|
||||
|
||||
typedef struct krb5_get_init_creds_ctx {
|
||||
KDCOptions flags;
|
||||
@ -1221,8 +1221,8 @@ init_cred_loop(krb5_context context,
|
||||
krb5_data resp;
|
||||
size_t len;
|
||||
size_t size;
|
||||
int send_to_kdc_flags = 0;
|
||||
krb5_krbhst_info *hi = NULL;
|
||||
krb5_sendto_ctx stctx = NULL;
|
||||
|
||||
|
||||
memset(&md, 0, sizeof(md));
|
||||
@ -1238,6 +1238,11 @@ init_cred_loop(krb5_context context,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = krb5_sendto_ctx_alloc(context, &stctx);
|
||||
if (ret)
|
||||
goto out;
|
||||
krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
|
||||
|
||||
/* Set a new nonce. */
|
||||
krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
|
||||
ctx->nonce &= 0xffffffff;
|
||||
@ -1281,10 +1286,9 @@ init_cred_loop(krb5_context context,
|
||||
if(len != ctx->req_buffer.length)
|
||||
krb5_abortx(context, "internal error in ASN.1 encoder");
|
||||
|
||||
ret = krb5_sendto_kdc_flags (context, &ctx->req_buffer,
|
||||
&creds->client->realm, &resp,
|
||||
send_to_kdc_flags);
|
||||
if (ret)
|
||||
ret = krb5_sendto_context (context, stctx, &ctx->req_buffer,
|
||||
creds->client->realm, &resp);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
memset (&rep, 0, sizeof(rep));
|
||||
@ -1329,16 +1333,6 @@ init_cred_loop(krb5_context context,
|
||||
krb5_free_error_contents(context, &error);
|
||||
if (ret)
|
||||
goto out;
|
||||
} else if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
|
||||
if (send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG) {
|
||||
if (ret_as_reply)
|
||||
rep.error = error;
|
||||
else
|
||||
krb5_free_error_contents(context, &error);
|
||||
goto out;
|
||||
}
|
||||
krb5_free_error_contents(context, &error);
|
||||
send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
|
||||
} else {
|
||||
_krb5_get_init_creds_opt_set_krb5_error(context,
|
||||
init_cred_opts,
|
||||
@ -1437,6 +1431,8 @@ init_cred_loop(krb5_context context,
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (stctx)
|
||||
krb5_sendto_ctx_free(context, stctx);
|
||||
krb5_data_free(&ctx->req_buffer);
|
||||
free_METHOD_DATA(&md);
|
||||
memset(&md, 0, sizeof(md));
|
||||
|
@ -149,6 +149,14 @@ _krb5_kcm_noop (
|
||||
krb5_context /*context*/,
|
||||
krb5_ccache /*id*/);
|
||||
|
||||
krb5_error_code
|
||||
_krb5_kdc_retry (
|
||||
krb5_context /*context*/,
|
||||
krb5_sendto_ctx /*ctx*/,
|
||||
void */*data*/,
|
||||
const krb5_data */*reply*/,
|
||||
int */*action*/);
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
_krb5_krb_cr_err_reply (
|
||||
krb5_context /*context*/,
|
||||
|
@ -2243,6 +2243,14 @@ krb5_get_pw_salt (
|
||||
krb5_const_principal /*principal*/,
|
||||
krb5_salt */*salt*/);
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_get_renewed_creds (
|
||||
krb5_context /*context*/,
|
||||
krb5_creds */*creds*/,
|
||||
krb5_const_principal /*client*/,
|
||||
krb5_ccache /*ccache*/,
|
||||
const char */*in_tkt_service*/);
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_get_server_rcache (
|
||||
krb5_context /*context*/,
|
||||
@ -2868,6 +2876,12 @@ krb5_parse_name_flags (
|
||||
int /*flags*/,
|
||||
krb5_principal */*principal*/);
|
||||
|
||||
krb5_error_code
|
||||
krb5_parse_nametype (
|
||||
krb5_context /*context*/,
|
||||
const char */*str*/,
|
||||
int32_t */*nametype*/);
|
||||
|
||||
const char* KRB5_LIB_FUNCTION
|
||||
krb5_passwd_result_to_string (
|
||||
krb5_context /*context*/,
|
||||
@ -3071,7 +3085,7 @@ krb5_rd_cred2 (
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_rd_error (
|
||||
krb5_context /*context*/,
|
||||
krb5_data */*msg*/,
|
||||
const krb5_data */*msg*/,
|
||||
KRB_ERROR */*result*/);
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
@ -3346,6 +3360,43 @@ krb5_sendto (
|
||||
krb5_krbhst_handle /*handle*/,
|
||||
krb5_data */*receive*/);
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_sendto_context (
|
||||
krb5_context /*context*/,
|
||||
krb5_sendto_ctx /*ctx*/,
|
||||
const krb5_data */*send_data*/,
|
||||
const krb5_realm /*realm*/,
|
||||
krb5_data */*receive*/);
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_add_flags (
|
||||
krb5_sendto_ctx /*ctx*/,
|
||||
int /*flags*/);
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_alloc (
|
||||
krb5_context /*context*/,
|
||||
krb5_sendto_ctx */*ctx*/);
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_free (
|
||||
krb5_context /*context*/,
|
||||
krb5_sendto_ctx /*ctx*/);
|
||||
|
||||
int KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_get_flags (krb5_sendto_ctx /*ctx*/);
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_set_func (
|
||||
krb5_sendto_ctx /*ctx*/,
|
||||
krb5_sendto_ctx_func /*func*/,
|
||||
void */*data*/);
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_set_type (
|
||||
krb5_sendto_ctx /*ctx*/,
|
||||
int /*type*/);
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_sendto_kdc (
|
||||
krb5_context /*context*/,
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $Id: krb5.h 20245 2007-02-17 00:09:57Z lha $ */
|
||||
/* $Id: krb5.h 21252 2007-06-21 04:18:28Z lha $ */
|
||||
|
||||
#ifndef __KRB5_H__
|
||||
#define __KRB5_H__
|
||||
@ -361,6 +361,7 @@ typedef union {
|
||||
#define KRB5_GC_NO_STORE (1U << 3)
|
||||
#define KRB5_GC_FORWARDABLE (1U << 4)
|
||||
#define KRB5_GC_NO_TRANSIT_CHECK (1U << 5)
|
||||
#define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6)
|
||||
|
||||
/* constants for compare_creds (and cc_retrieve_cred) */
|
||||
#define KRB5_TC_DONT_MATCH_REALM (1U << 31)
|
||||
@ -753,9 +754,18 @@ enum {
|
||||
/* flags for krb5_unparse_name_flags */
|
||||
enum {
|
||||
KRB5_PRINCIPAL_UNPARSE_SHORT = 1,
|
||||
KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2
|
||||
KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2,
|
||||
KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4
|
||||
};
|
||||
|
||||
typedef struct krb5_sendto_ctx *krb5_sendto_ctx;
|
||||
|
||||
#define KRB5_SENDTO_DONE 0
|
||||
#define KRB5_SENDTO_RESTART 1
|
||||
#define KRB5_SENDTO_CONTINUE 2
|
||||
|
||||
typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *);
|
||||
|
||||
struct credentials; /* this is to keep the compiler happy */
|
||||
struct getargs;
|
||||
struct sockaddr;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# This might look like a com_err file, but is not
|
||||
#
|
||||
id "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $"
|
||||
id "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $"
|
||||
|
||||
error_table krb5
|
||||
|
||||
@ -35,8 +35,10 @@ error_code KEY_EXPIRED, "Password has expired"
|
||||
error_code PREAUTH_FAILED, "Preauthentication failed"
|
||||
error_code PREAUTH_REQUIRED, "Additional pre-authentication required"
|
||||
error_code SERVER_NOMATCH, "Requested server and ticket don't match"
|
||||
error_code KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only"
|
||||
error_code PATH_NOT_ACCEPTED, "KDC Policy rejects transited path"
|
||||
error_code SVC_UNAVAILABLE, "A service is not available"
|
||||
|
||||
# 27-30 are reserved
|
||||
index 31
|
||||
prefix KRB5KRB_AP
|
||||
error_code ERR_BAD_INTEGRITY, "Decrypt integrity check failed"
|
||||
@ -108,7 +110,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo
|
||||
|
||||
index 128
|
||||
prefix
|
||||
error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $"
|
||||
error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $"
|
||||
|
||||
error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode"
|
||||
error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password"
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <resolve.h>
|
||||
#include "locate_plugin.h"
|
||||
|
||||
RCSID("$Id: krbhst.c 19198 2006-11-30 17:23:08Z lha $");
|
||||
RCSID("$Id: krbhst.c 21131 2007-06-18 20:48:09Z lha $");
|
||||
|
||||
static int
|
||||
string_to_proto(const char *string)
|
||||
@ -501,10 +501,8 @@ add_locate(void *ctx, int type, struct sockaddr *addr)
|
||||
hostlen = strlen(host);
|
||||
|
||||
hi = calloc(1, sizeof(*hi) + hostlen);
|
||||
if(hi == NULL) {
|
||||
free(host);
|
||||
if(hi == NULL)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
hi->proto = krbhst_get_default_proto(kd);
|
||||
hi->port = hi->def_port = socket_get_port(addr);
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
RCSID("$Id: misc.c 17616 2006-06-06 14:57:47Z lha $");
|
||||
RCSID("$Id: misc.c 21174 2007-06-19 10:10:58Z lha $");
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
_krb5_s4u2self_to_checksumdata(krb5_context context,
|
||||
@ -51,6 +51,7 @@ _krb5_s4u2self_to_checksumdata(krb5_context context,
|
||||
krb5_clear_error_string(context);
|
||||
return ENOMEM;
|
||||
}
|
||||
krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
|
||||
ret = krb5_store_int32(sp, self->name.name_type);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
RCSID("$Id: pac.c 20845 2007-06-03 14:31:16Z lha $");
|
||||
RCSID("$Id: pac.c 21149 2007-06-18 21:50:22Z lha $");
|
||||
|
||||
struct PAC_INFO_BUFFER {
|
||||
uint32_t type;
|
||||
@ -409,6 +409,8 @@ verify_checksum(krb5_context context,
|
||||
krb5_error_code ret;
|
||||
Checksum cksum;
|
||||
|
||||
memset(&cksum, 0, sizeof(cksum));
|
||||
|
||||
sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo,
|
||||
sig->buffersize);
|
||||
if (sp == NULL) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan
|
||||
* Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
RCSID("$Id: pkinit.c 21004 2007-06-08 01:53:10Z lha $");
|
||||
RCSID("$Id: pkinit.c 21321 2007-06-26 05:21:56Z lha $");
|
||||
|
||||
struct krb5_dh_moduli {
|
||||
char *name;
|
||||
@ -554,18 +554,13 @@ pk_mk_padata(krb5_context context,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(),
|
||||
&content_info);
|
||||
ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf);
|
||||
krb5_data_free(&sd_buf);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
krb5_set_error_string(context,
|
||||
"ContentInfo wrapping of signedData failed");
|
||||
goto out;
|
||||
|
||||
ASN1_MALLOC_ENCODE(ContentInfo, buf.data, buf.length,
|
||||
&content_info, &size, ret);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (buf.length != size)
|
||||
krb5_abortx(context, "Internal ASN1 encoder error");
|
||||
}
|
||||
|
||||
if (ctx->type == COMPAT_WIN2K) {
|
||||
PA_PK_AS_REQ_Win2k winreq;
|
||||
@ -794,6 +789,7 @@ get_reply_key_win(krb5_context context,
|
||||
if (ret) {
|
||||
krb5_set_error_string(context, "PKINIT failed copying reply key");
|
||||
free(*key);
|
||||
*key = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -856,6 +852,7 @@ get_reply_key(krb5_context context,
|
||||
if (ret) {
|
||||
krb5_set_error_string(context, "PKINIT failed copying reply key");
|
||||
free(*key);
|
||||
*key = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -929,6 +926,7 @@ pk_verify_host(krb5_context context,
|
||||
if (hi) {
|
||||
ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert,
|
||||
ctx->require_hostname_match,
|
||||
HX509_HN_HOSTNAME,
|
||||
hi->hostname,
|
||||
hi->ai->ai_addr, hi->ai->ai_addrlen);
|
||||
|
||||
@ -942,7 +940,8 @@ pk_verify_host(krb5_context context,
|
||||
static krb5_error_code
|
||||
pk_rd_pa_reply_enckey(krb5_context context,
|
||||
int type,
|
||||
const ContentInfo *rep,
|
||||
const heim_octet_string *indata,
|
||||
const heim_oid *dataType,
|
||||
const char *realm,
|
||||
krb5_pk_init_ctx ctx,
|
||||
krb5_enctype etype,
|
||||
@ -954,27 +953,19 @@ pk_rd_pa_reply_enckey(krb5_context context,
|
||||
{
|
||||
krb5_error_code ret;
|
||||
struct krb5_pk_cert *host = NULL;
|
||||
size_t size;
|
||||
int length;
|
||||
void *p;
|
||||
krb5_data content;
|
||||
heim_oid contentType = { 0, NULL };
|
||||
|
||||
if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) {
|
||||
if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) {
|
||||
krb5_set_error_string(context, "PKINIT: Invalid content type");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (rep->content == NULL) {
|
||||
krb5_set_error_string(context, "PKINIT: No content in reply");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
|
||||
ctx->id->certs,
|
||||
HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT,
|
||||
rep->content->data,
|
||||
rep->content->length,
|
||||
indata->data,
|
||||
indata->length,
|
||||
NULL,
|
||||
&contentType,
|
||||
&content);
|
||||
@ -983,41 +974,52 @@ pk_rd_pa_reply_enckey(krb5_context context,
|
||||
"Failed to unenvelope CMS data in PK-INIT reply");
|
||||
return ret;
|
||||
}
|
||||
der_free_oid(&contentType);
|
||||
|
||||
p = content.data;
|
||||
length = content.length;
|
||||
#if 0 /* windows LH with interesting CMS packets, leaks memory */
|
||||
{
|
||||
size_t ph = 1 + der_length_len (length);
|
||||
unsigned char *ptr = malloc(length + ph);
|
||||
size_t l;
|
||||
|
||||
memcpy(ptr + ph, p, length);
|
||||
|
||||
ret = der_put_length_and_tag (ptr + ph - 1, ph, length,
|
||||
ASN1_C_UNIV, CONS, UT_Sequence, &l);
|
||||
if (ret)
|
||||
return ret;
|
||||
ptr += ph - l;
|
||||
length += l;
|
||||
p = ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* win2k uses ContentInfo */
|
||||
if (type == COMPAT_WIN2K) {
|
||||
ContentInfo ci;
|
||||
heim_oid type;
|
||||
heim_octet_string out;
|
||||
|
||||
ret = decode_ContentInfo(p, length, &ci, &size);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context,
|
||||
"PKINIT: failed decoding ContentInfo: %d",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) {
|
||||
ret = EINVAL; /* XXX */
|
||||
krb5_set_error_string(context, "PKINIT: Invalid content type");
|
||||
goto out;
|
||||
}
|
||||
if (ci.content == NULL) {
|
||||
ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
|
||||
if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) {
|
||||
ret = EINVAL; /* XXX */
|
||||
krb5_set_error_string(context, "PKINIT: Invalid content type");
|
||||
der_free_oid(&type);
|
||||
der_free_octet_string(&out);
|
||||
goto out;
|
||||
}
|
||||
der_free_oid(&type);
|
||||
krb5_data_free(&content);
|
||||
content = *ci.content;
|
||||
p = ci.content->data;
|
||||
length = ci.content->length;
|
||||
ret = krb5_data_copy(&content, out.data, out.length);
|
||||
der_free_octet_string(&out);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context, "PKINIT: out of memory");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = _krb5_pk_verify_sign(context,
|
||||
p,
|
||||
length,
|
||||
content.data,
|
||||
content.length,
|
||||
ctx->id,
|
||||
&contentType,
|
||||
&content,
|
||||
@ -1073,7 +1075,8 @@ pk_rd_pa_reply_enckey(krb5_context context,
|
||||
|
||||
static krb5_error_code
|
||||
pk_rd_pa_reply_dh(krb5_context context,
|
||||
const ContentInfo *rep,
|
||||
const heim_octet_string *indata,
|
||||
const heim_oid *dataType,
|
||||
const char *realm,
|
||||
krb5_pk_init_ctx ctx,
|
||||
krb5_enctype etype,
|
||||
@ -1097,19 +1100,14 @@ pk_rd_pa_reply_dh(krb5_context context,
|
||||
krb5_data_zero(&content);
|
||||
memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
|
||||
|
||||
if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) {
|
||||
if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) {
|
||||
krb5_set_error_string(context, "PKINIT: Invalid content type");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (rep->content == NULL) {
|
||||
krb5_set_error_string(context, "PKINIT: No content in reply");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ret = _krb5_pk_verify_sign(context,
|
||||
rep->content->data,
|
||||
rep->content->length,
|
||||
indata->data,
|
||||
indata->length,
|
||||
ctx->id,
|
||||
&contentType,
|
||||
&content,
|
||||
@ -1261,20 +1259,19 @@ _krb5_pk_rd_pa_reply(krb5_context context,
|
||||
{
|
||||
krb5_pk_init_ctx ctx = c;
|
||||
krb5_error_code ret;
|
||||
ContentInfo ci;
|
||||
size_t size;
|
||||
|
||||
/* Check for IETF PK-INIT first */
|
||||
if (ctx->type == COMPAT_IETF) {
|
||||
PA_PK_AS_REP rep;
|
||||
heim_octet_string os, data;
|
||||
heim_oid oid;
|
||||
|
||||
if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
|
||||
krb5_set_error_string(context, "PKINIT: wrong padata recv");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
memset(&rep, 0, sizeof(rep));
|
||||
|
||||
ret = decode_PA_PK_AS_REP(pa->padata_value.data,
|
||||
pa->padata_value.length,
|
||||
&rep,
|
||||
@ -1286,50 +1283,43 @@ _krb5_pk_rd_pa_reply(krb5_context context,
|
||||
|
||||
switch (rep.element) {
|
||||
case choice_PA_PK_AS_REP_dhInfo:
|
||||
ret = decode_ContentInfo(rep.u.dhInfo.dhSignedData.data,
|
||||
rep.u.dhInfo.dhSignedData.length,
|
||||
&ci,
|
||||
&size);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context,
|
||||
"PKINIT: decoding failed DH "
|
||||
"ContentInfo: %d", ret);
|
||||
|
||||
free_PA_PK_AS_REP(&rep);
|
||||
break;
|
||||
}
|
||||
ret = pk_rd_pa_reply_dh(context, &ci, realm, ctx, etype, hi,
|
||||
ctx->clientDHNonce,
|
||||
rep.u.dhInfo.serverDHNonce,
|
||||
nonce, pa, key);
|
||||
free_ContentInfo(&ci);
|
||||
free_PA_PK_AS_REP(&rep);
|
||||
|
||||
os = rep.u.dhInfo.dhSignedData;
|
||||
break;
|
||||
case choice_PA_PK_AS_REP_encKeyPack:
|
||||
ret = decode_ContentInfo(rep.u.encKeyPack.data,
|
||||
rep.u.encKeyPack.length,
|
||||
&ci,
|
||||
&size);
|
||||
free_PA_PK_AS_REP(&rep);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context,
|
||||
"PKINIT: -25 decoding failed "
|
||||
"ContentInfo: %d", ret);
|
||||
break;
|
||||
}
|
||||
ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, realm, ctx,
|
||||
etype, hi, nonce, req_buffer, pa, key);
|
||||
free_ContentInfo(&ci);
|
||||
return ret;
|
||||
os = rep.u.encKeyPack;
|
||||
break;
|
||||
default:
|
||||
free_PA_PK_AS_REP(&rep);
|
||||
krb5_set_error_string(context, "PKINIT: -27 reply "
|
||||
"invalid content type");
|
||||
ret = EINVAL;
|
||||
break;
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL);
|
||||
if (ret) {
|
||||
free_PA_PK_AS_REP(&rep);
|
||||
krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (rep.element) {
|
||||
case choice_PA_PK_AS_REP_dhInfo:
|
||||
ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi,
|
||||
ctx->clientDHNonce,
|
||||
rep.u.dhInfo.serverDHNonce,
|
||||
nonce, pa, key);
|
||||
break;
|
||||
case choice_PA_PK_AS_REP_encKeyPack:
|
||||
ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm,
|
||||
ctx, etype, hi, nonce, req_buffer, pa, key);
|
||||
break;
|
||||
default:
|
||||
krb5_abortx(context, "pk-init as-rep case not possible to happen");
|
||||
}
|
||||
der_free_octet_string(&data);
|
||||
der_free_oid(&oid);
|
||||
free_PA_PK_AS_REP(&rep);
|
||||
|
||||
} else if (ctx->type == COMPAT_WIN2K) {
|
||||
PA_PK_AS_REP_Win2k w2krep;
|
||||
|
||||
@ -1357,23 +1347,25 @@ _krb5_pk_rd_pa_reply(krb5_context context,
|
||||
krb5_clear_error_string(context);
|
||||
|
||||
switch (w2krep.element) {
|
||||
case choice_PA_PK_AS_REP_Win2k_encKeyPack:
|
||||
ret = decode_ContentInfo(w2krep.u.encKeyPack.data,
|
||||
w2krep.u.encKeyPack.length,
|
||||
&ci,
|
||||
&size);
|
||||
case choice_PA_PK_AS_REP_Win2k_encKeyPack: {
|
||||
heim_octet_string data;
|
||||
heim_oid oid;
|
||||
|
||||
ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack,
|
||||
&oid, &data, NULL);
|
||||
free_PA_PK_AS_REP_Win2k(&w2krep);
|
||||
if (ret) {
|
||||
krb5_set_error_string(context,
|
||||
"PKINIT: decoding failed "
|
||||
"ContentInfo: %d",
|
||||
ret);
|
||||
krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
|
||||
return ret;
|
||||
}
|
||||
ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, realm, ctx,
|
||||
etype, hi, nonce, req_buffer, pa, key);
|
||||
free_ContentInfo(&ci);
|
||||
|
||||
ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm,
|
||||
ctx, etype, hi, nonce, req_buffer, pa, key);
|
||||
der_free_octet_string(&data);
|
||||
der_free_oid(&oid);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
free_PA_PK_AS_REP_Win2k(&w2krep);
|
||||
krb5_set_error_string(context, "PKINIT: win2k reply invalid "
|
||||
@ -1473,8 +1465,7 @@ _krb5_pk_load_id(krb5_context context,
|
||||
id = calloc(1, sizeof(*id));
|
||||
if (id == NULL) {
|
||||
krb5_set_error_string(context, "malloc: out of memory");
|
||||
ret = ENOMEM;
|
||||
goto out;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
ret = hx509_context_init(&id->hx509ctx);
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "krb5_locl.h"
|
||||
RCSID("$Id: plugin.c 19789 2007-01-09 17:46:01Z lha $");
|
||||
RCSID("$Id: plugin.c 21134 2007-06-18 21:02:23Z lha $");
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
@ -96,6 +96,7 @@ loadlib(krb5_context context,
|
||||
(*e)->dsohandle = dlopen(lib, RTLD_LAZY);
|
||||
if ((*e)->dsohandle == NULL) {
|
||||
free(*e);
|
||||
*e = NULL;
|
||||
krb5_set_error_string(context, "Failed to load %s: %s",
|
||||
lib, dlerror());
|
||||
return ENOMEM;
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <fnmatch.h>
|
||||
#include "resolve.h"
|
||||
|
||||
RCSID("$Id: principal.c 20223 2007-02-15 04:17:04Z lha $");
|
||||
RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $");
|
||||
|
||||
#define princ_num_comp(P) ((P)->name.name_string.len)
|
||||
#define princ_type(P) ((P)->name.name_type)
|
||||
@ -281,15 +281,19 @@ krb5_parse_name(krb5_context context,
|
||||
|
||||
static const char quotable_chars[] = " \n\t\b\\/@";
|
||||
static const char replace_chars[] = " ntb\\/@";
|
||||
static const char nq_chars[] = " \\/@";
|
||||
|
||||
#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0);
|
||||
|
||||
static size_t
|
||||
quote_string(const char *s, char *out, size_t idx, size_t len)
|
||||
quote_string(const char *s, char *out, size_t idx, size_t len, int display)
|
||||
{
|
||||
const char *p, *q;
|
||||
for(p = s; *p && idx < len; p++){
|
||||
if((q = strchr(quotable_chars, *p))){
|
||||
q = strchr(quotable_chars, *p);
|
||||
if (q && display) {
|
||||
add_char(out, idx, len, replace_chars[q - quotable_chars]);
|
||||
} else if (q) {
|
||||
add_char(out, idx, len, '\\');
|
||||
add_char(out, idx, len, replace_chars[q - quotable_chars]);
|
||||
}else
|
||||
@ -312,6 +316,7 @@ unparse_name_fixed(krb5_context context,
|
||||
int i;
|
||||
int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0;
|
||||
int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0;
|
||||
int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0;
|
||||
|
||||
if (!no_realm && princ_realm(principal) == NULL) {
|
||||
krb5_set_error_string(context, "Realm missing from principal, "
|
||||
@ -322,7 +327,7 @@ unparse_name_fixed(krb5_context context,
|
||||
for(i = 0; i < princ_num_comp(principal); i++){
|
||||
if(i)
|
||||
add_char(name, idx, len, '/');
|
||||
idx = quote_string(princ_ncomp(principal, i), name, idx, len);
|
||||
idx = quote_string(princ_ncomp(principal, i), name, idx, len, display);
|
||||
if(idx == len) {
|
||||
krb5_set_error_string(context, "Out of space printing principal");
|
||||
return ERANGE;
|
||||
@ -341,7 +346,7 @@ unparse_name_fixed(krb5_context context,
|
||||
}
|
||||
if(!short_form && !no_realm) {
|
||||
add_char(name, idx, len, '@');
|
||||
idx = quote_string(princ_realm(principal), name, idx, len);
|
||||
idx = quote_string(princ_realm(principal), name, idx, len, display);
|
||||
if(idx == len) {
|
||||
krb5_set_error_string(context,
|
||||
"Out of space printing realm of principal");
|
||||
@ -1213,3 +1218,37 @@ krb5_sname_to_principal (krb5_context context,
|
||||
krb5_free_host_realm(context, realms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *type;
|
||||
int32_t value;
|
||||
} nametypes[] = {
|
||||
{ "UNKNOWN", KRB5_NT_UNKNOWN },
|
||||
{ "PRINCIPAL", KRB5_NT_PRINCIPAL },
|
||||
{ "SRV_INST", KRB5_NT_SRV_INST },
|
||||
{ "SRV_HST", KRB5_NT_SRV_HST },
|
||||
{ "SRV_XHST", KRB5_NT_SRV_XHST },
|
||||
{ "UID", KRB5_NT_UID },
|
||||
{ "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL },
|
||||
{ "SMTP_NAME", KRB5_NT_SMTP_NAME },
|
||||
{ "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL },
|
||||
{ "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID },
|
||||
{ "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL },
|
||||
{ "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
krb5_error_code
|
||||
krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; nametypes[i].type; i++) {
|
||||
if (strcasecmp(nametypes[i].type, str) == 0) {
|
||||
*nametype = nametypes[i].value;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
krb5_set_error_string(context, "Failed to find name type %s", str);
|
||||
return KRB5_PARSE_MALFORMED;
|
||||
}
|
||||
|
@ -33,11 +33,11 @@
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
RCSID("$Id: rd_error.c 20304 2007-04-11 11:15:05Z lha $");
|
||||
RCSID("$Id: rd_error.c 21057 2007-06-12 17:22:31Z lha $");
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_rd_error(krb5_context context,
|
||||
krb5_data *msg,
|
||||
const krb5_data *msg,
|
||||
KRB_ERROR *result)
|
||||
{
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
RCSID("$Id: send_to_kdc.c 19973 2007-01-17 17:19:52Z lha $");
|
||||
RCSID("$Id: send_to_kdc.c 21062 2007-06-12 17:58:57Z lha $");
|
||||
|
||||
struct send_to_kdc {
|
||||
krb5_send_to_kdc_func func;
|
||||
@ -413,26 +413,16 @@ krb5_sendto_kdc_flags(krb5_context context,
|
||||
int flags)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_krbhst_handle handle;
|
||||
int type;
|
||||
krb5_sendto_ctx ctx;
|
||||
|
||||
if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
|
||||
type = KRB5_KRBHST_ADMIN;
|
||||
else
|
||||
type = KRB5_KRBHST_KDC;
|
||||
|
||||
if (send_data->length > context->large_msg_size)
|
||||
flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
|
||||
|
||||
ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle);
|
||||
ret = krb5_sendto_ctx_alloc(context, &ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
krb5_sendto_ctx_add_flags(ctx, flags);
|
||||
krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL);
|
||||
|
||||
ret = krb5_sendto(context, send_data, handle, receive);
|
||||
krb5_krbhst_free(context, handle);
|
||||
if (ret == KRB5_KDC_UNREACH)
|
||||
krb5_set_error_string(context,
|
||||
"unable to reach any KDC in realm %s", *realm);
|
||||
ret = krb5_sendto_context(context, ctx, send_data, *realm, receive);
|
||||
krb5_sendto_ctx_free(context, ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -458,4 +448,157 @@ krb5_set_send_to_kdc_func(krb5_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct krb5_sendto_ctx {
|
||||
int flags;
|
||||
int type;
|
||||
krb5_sendto_ctx_func func;
|
||||
void *data;
|
||||
};
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx)
|
||||
{
|
||||
*ctx = calloc(1, sizeof(**ctx));
|
||||
if (*ctx == NULL) {
|
||||
krb5_set_error_string(context, "out of memory");
|
||||
return ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_add_flags(krb5_sendto_ctx ctx, int flags)
|
||||
{
|
||||
ctx->flags |= flags;
|
||||
}
|
||||
|
||||
int KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_get_flags(krb5_sendto_ctx ctx)
|
||||
{
|
||||
return ctx->flags;
|
||||
}
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_set_type(krb5_sendto_ctx ctx, int type)
|
||||
{
|
||||
ctx->type = type;
|
||||
}
|
||||
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_set_func(krb5_sendto_ctx ctx,
|
||||
krb5_sendto_ctx_func func,
|
||||
void *data)
|
||||
{
|
||||
ctx->func = func;
|
||||
ctx->data = data;
|
||||
}
|
||||
|
||||
void KRB5_LIB_FUNCTION
|
||||
krb5_sendto_ctx_free(krb5_context context, krb5_sendto_ctx ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
krb5_error_code KRB5_LIB_FUNCTION
|
||||
krb5_sendto_context(krb5_context context,
|
||||
krb5_sendto_ctx ctx,
|
||||
const krb5_data *send_data,
|
||||
const krb5_realm realm,
|
||||
krb5_data *receive)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_krbhst_handle handle = NULL;
|
||||
int type, freectx = 0;
|
||||
int action;
|
||||
|
||||
krb5_data_zero(receive);
|
||||
|
||||
if (ctx == NULL) {
|
||||
freectx = 1;
|
||||
ret = krb5_sendto_ctx_alloc(context, &ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
type = ctx->type;
|
||||
if (type == 0) {
|
||||
if ((ctx->flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
|
||||
type = KRB5_KRBHST_ADMIN;
|
||||
else
|
||||
type = KRB5_KRBHST_KDC;
|
||||
}
|
||||
|
||||
if (send_data->length > context->large_msg_size)
|
||||
ctx->flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
|
||||
|
||||
/* loop until we get back a appropriate response */
|
||||
|
||||
do {
|
||||
action = KRB5_SENDTO_DONE;
|
||||
|
||||
krb5_data_free(receive);
|
||||
|
||||
if (handle == NULL) {
|
||||
ret = krb5_krbhst_init_flags(context, realm, type,
|
||||
ctx->flags, &handle);
|
||||
if (ret) {
|
||||
if (freectx)
|
||||
krb5_sendto_ctx_free(context, ctx);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = krb5_sendto(context, send_data, handle, receive);
|
||||
if (ret)
|
||||
break;
|
||||
if (ctx->func) {
|
||||
ret = (*ctx->func)(context, ctx, ctx->data, receive, &action);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
if (action != KRB5_SENDTO_CONTINUE) {
|
||||
krb5_krbhst_free(context, handle);
|
||||
handle = NULL;
|
||||
}
|
||||
} while (action != KRB5_SENDTO_DONE);
|
||||
if (handle)
|
||||
krb5_krbhst_free(context, handle);
|
||||
if (ret == KRB5_KDC_UNREACH)
|
||||
krb5_set_error_string(context,
|
||||
"unable to reach any KDC in realm %s", realm);
|
||||
if (ret)
|
||||
krb5_data_free(receive);
|
||||
if (freectx)
|
||||
krb5_sendto_ctx_free(context, ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
_krb5_kdc_retry(krb5_context context, krb5_sendto_ctx ctx, void *data,
|
||||
const krb5_data *reply, int *action)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
KRB_ERROR error;
|
||||
|
||||
if(krb5_rd_error(context, reply, &error))
|
||||
return 0;
|
||||
|
||||
ret = krb5_error_from_rd_error(context, &error, NULL);
|
||||
krb5_free_error_contents(context, &error);
|
||||
|
||||
switch(ret) {
|
||||
case KRB5KRB_ERR_RESPONSE_TOO_BIG: {
|
||||
if (krb5_sendto_ctx_get_flags(ctx) & KRB5_KRBHST_FLAGS_LARGE_MSG)
|
||||
break;
|
||||
krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG);
|
||||
*action = KRB5_SENDTO_RESTART;
|
||||
break;
|
||||
}
|
||||
case KRB5KDC_ERR_SVC_UNAVAILABLE:
|
||||
*action = KRB5_SENDTO_CONTINUE;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -33,6 +33,14 @@ heim_ntlm_calculate_ntlm2 (
|
||||
unsigned char ntlmv2[16],
|
||||
struct ntlm_buf */*answer*/);
|
||||
|
||||
int
|
||||
heim_ntlm_calculate_ntlm2_sess (
|
||||
const unsigned char clnt_nonce[8],
|
||||
const unsigned char svr_chal[8],
|
||||
const unsigned char ntlm_hash[16],
|
||||
struct ntlm_buf */*lm*/,
|
||||
struct ntlm_buf */*ntlm*/);
|
||||
|
||||
int
|
||||
heim_ntlm_decode_targetinfo (
|
||||
struct ntlm_buf */*data*/,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Kungliga Tekniska Högskolan
|
||||
* Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
RCSID("$Id: ntlm.c 20816 2007-06-03 04:36:31Z lha $");
|
||||
RCSID("$Id: ntlm.c 21317 2007-06-25 19:22:02Z lha $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -52,6 +52,12 @@ RCSID("$Id: ntlm.c 20816 2007-06-03 04:36:31Z lha $");
|
||||
#include <heimntlm.h>
|
||||
|
||||
|
||||
/*
|
||||
* Source of NTLM information:
|
||||
* http://davenport.sourceforge.net/ntlm.html
|
||||
*/
|
||||
|
||||
|
||||
struct sec_buffer {
|
||||
uint16_t length;
|
||||
uint16_t allocated;
|
||||
@ -760,6 +766,10 @@ splitandenc(unsigned char *hash,
|
||||
memset(key, 0, sizeof(key));
|
||||
}
|
||||
|
||||
/*
|
||||
* String-to-key function for NTLM
|
||||
*/
|
||||
|
||||
int
|
||||
heim_ntlm_nt_key(const char *password, struct ntlm_buf *key)
|
||||
{
|
||||
@ -784,6 +794,10 @@ heim_ntlm_nt_key(const char *password, struct ntlm_buf *key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate NTLMv1 response hash
|
||||
*/
|
||||
|
||||
int
|
||||
heim_ntlm_calculate_ntlm1(void *key, size_t len,
|
||||
unsigned char challange[8],
|
||||
@ -809,6 +823,10 @@ heim_ntlm_calculate_ntlm1(void *key, size_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate NTLMv1 master key
|
||||
*/
|
||||
|
||||
int
|
||||
heim_ntlm_build_ntlm1_master(void *key, size_t len,
|
||||
struct ntlm_buf *session,
|
||||
@ -880,8 +898,8 @@ heim_ntlm_ntlmv2_key(const void *key, size_t len,
|
||||
ascii2ucs2le(username, 1, &buf);
|
||||
HMAC_Update(&c, buf.data, buf.length);
|
||||
free(buf.data);
|
||||
/* turn target into ucs2-le */
|
||||
ascii2ucs2le(target, 0, &buf);
|
||||
/* uppercase target and turn into ucs2-le */
|
||||
ascii2ucs2le(target, 1, &buf);
|
||||
HMAC_Update(&c, buf.data, buf.length);
|
||||
free(buf.data);
|
||||
}
|
||||
@ -914,6 +932,10 @@ nt2unixtime(uint64_t t)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate NTLMv2 response
|
||||
*/
|
||||
|
||||
int
|
||||
heim_ntlm_calculate_ntlm2(const void *key, size_t len,
|
||||
const char *username,
|
||||
@ -948,25 +970,27 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len,
|
||||
return ENOMEM;
|
||||
krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
|
||||
|
||||
CHECK(krb5_store_uint32(sp, 0x01010000), 0);
|
||||
CHECK(krb5_store_uint32(sp, 0x00000101), 0);
|
||||
CHECK(krb5_store_uint32(sp, 0), 0);
|
||||
/* timestamp le 64 bit ts */
|
||||
CHECK(krb5_store_uint32(sp, t & 0xffffffff), 0);
|
||||
CHECK(krb5_store_uint32(sp, t >> 32), 0);
|
||||
|
||||
CHECK(krb5_storage_write(sp, clientchallange, 8), 8);
|
||||
|
||||
CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */
|
||||
CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length),
|
||||
infotarget->length);
|
||||
/* unknown */
|
||||
/* CHECK(krb5_store_uint32(sp, 0), 0); */
|
||||
CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */
|
||||
|
||||
CHECK(krb5_storage_to_data(sp, &data), 0);
|
||||
krb5_storage_free(sp);
|
||||
sp = NULL;
|
||||
|
||||
HMAC_CTX_init(&c);
|
||||
HMAC_Init_ex(&c, ntlmv2, sizeof(ntlmv2), EVP_md5(), NULL);
|
||||
HMAC_Update(&c, data.data, data.length);
|
||||
HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
|
||||
HMAC_Update(&c, serverchallange, 8);
|
||||
HMAC_Update(&c, data.data, data.length);
|
||||
HMAC_Final(&c, ntlmv2answer, &hmaclen);
|
||||
HMAC_CTX_cleanup(&c);
|
||||
|
||||
@ -996,6 +1020,10 @@ out:
|
||||
|
||||
static const int authtimediff = 3600 * 2; /* 2 hours */
|
||||
|
||||
/*
|
||||
* Verify NTLMv2 response.
|
||||
*/
|
||||
|
||||
int
|
||||
heim_ntlm_verify_ntlm2(const void *key, size_t len,
|
||||
const char *username,
|
||||
@ -1009,6 +1037,7 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
|
||||
krb5_error_code ret;
|
||||
unsigned int hmaclen;
|
||||
unsigned char clientanswer[16];
|
||||
unsigned char clientnonce[8];
|
||||
unsigned char serveranswer[16];
|
||||
krb5_storage *sp;
|
||||
HMAC_CTX c;
|
||||
@ -1039,7 +1068,7 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
|
||||
CHECK(krb5_storage_read(sp, clientanswer, 16), 16);
|
||||
|
||||
CHECK(krb5_ret_uint32(sp, &temp), 0);
|
||||
CHECK(temp, 0x01010000);
|
||||
CHECK(temp, 0x00000101);
|
||||
CHECK(krb5_ret_uint32(sp, &temp), 0);
|
||||
CHECK(temp, 0);
|
||||
/* timestamp le 64 bit ts */
|
||||
@ -1056,9 +1085,12 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
|
||||
}
|
||||
|
||||
/* client challange */
|
||||
CHECK(krb5_storage_read(sp, serveranswer, 8), 8);
|
||||
CHECK(krb5_storage_read(sp, clientnonce, 8), 8);
|
||||
|
||||
infotarget->length = answer->length - 40;
|
||||
CHECK(krb5_ret_uint32(sp, &temp), 0); /* unknown */
|
||||
|
||||
/* should really unparse the infotarget, but lets pick up everything */
|
||||
infotarget->length = answer->length - krb5_storage_seek(sp, 0, SEEK_CUR);
|
||||
infotarget->data = malloc(infotarget->length);
|
||||
if (infotarget->data == NULL) {
|
||||
ret = ENOMEM;
|
||||
@ -1066,14 +1098,14 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
|
||||
}
|
||||
CHECK(krb5_storage_read(sp, infotarget->data, infotarget->length),
|
||||
infotarget->length);
|
||||
/* XXX remove the unknown uint32_t */
|
||||
/* XXX remove the unknown ?? */
|
||||
krb5_storage_free(sp);
|
||||
sp = NULL;
|
||||
|
||||
HMAC_CTX_init(&c);
|
||||
HMAC_Init_ex(&c, ntlmv2, sizeof(ntlmv2), EVP_md5(), NULL);
|
||||
HMAC_Update(&c, ((char *)answer->data) + 16, answer->length - 16);
|
||||
HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
|
||||
HMAC_Update(&c, serverchallange, 8);
|
||||
HMAC_Update(&c, ((char *)answer->data) + 16, answer->length - 16);
|
||||
HMAC_Final(&c, serveranswer, &hmaclen);
|
||||
HMAC_CTX_cleanup(&c);
|
||||
|
||||
@ -1089,3 +1121,52 @@ out:
|
||||
krb5_storage_free(sp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the NTLM2 Session Response
|
||||
*/
|
||||
|
||||
int
|
||||
heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8],
|
||||
const unsigned char svr_chal[8],
|
||||
const unsigned char ntlm_hash[16],
|
||||
struct ntlm_buf *lm,
|
||||
struct ntlm_buf *ntlm)
|
||||
{
|
||||
unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
|
||||
unsigned char res[21], *resp;
|
||||
MD5_CTX md5;
|
||||
|
||||
lm->data = malloc(24);
|
||||
if (lm->data == NULL)
|
||||
return ENOMEM;
|
||||
lm->length = 24;
|
||||
|
||||
ntlm->data = malloc(24);
|
||||
if (ntlm->data == NULL) {
|
||||
free(lm->data);
|
||||
lm->data = NULL;
|
||||
return ENOMEM;
|
||||
}
|
||||
ntlm->length = 24;
|
||||
|
||||
/* first setup the lm resp */
|
||||
memset(lm->data, 0, 24);
|
||||
memcpy(lm->data, clnt_nonce, 8);
|
||||
|
||||
MD5_Init(&md5);
|
||||
MD5_Update(&md5, svr_chal, 8); /* session nonce part 1 */
|
||||
MD5_Update(&md5, clnt_nonce, 8); /* session nonce part 2 */
|
||||
MD5_Final(ntlm2_sess_hash, &md5); /* will only use first 8 bytes */
|
||||
|
||||
memset(res, 0, sizeof(res));
|
||||
memcpy(res, ntlm_hash, 16);
|
||||
|
||||
resp = ntlm->data;
|
||||
splitandenc(&res[0], ntlm2_sess_hash, resp + 0);
|
||||
splitandenc(&res[7], ntlm2_sess_hash, resp + 8);
|
||||
splitandenc(&res[14], ntlm2_sess_hash, resp + 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
RCSID("$Id: roken_gethostby.c 21005 2007-06-08 01:54:35Z lha $");
|
||||
RCSID("$Id: roken_gethostby.c 21157 2007-06-18 22:03:13Z lha $");
|
||||
#endif
|
||||
|
||||
#include <roken.h>
|
||||
@ -111,7 +111,7 @@ int ROKEN_LIB_FUNCTION
|
||||
roken_gethostby_setup(const char *proxy_spec, const char *dns_spec)
|
||||
{
|
||||
char *proxy_host = NULL;
|
||||
int proxy_port;
|
||||
int proxy_port = 0;
|
||||
char *dns_host, *dns_path;
|
||||
int dns_port;
|
||||
|
||||
|
@ -325,6 +325,7 @@ OBJ_FILES = \
|
||||
../heimdal/lib/hcrypto/rand-egd.o \
|
||||
../heimdal/lib/hcrypto/rand-unix.o \
|
||||
../heimdal/lib/hcrypto/rand-fortuna.o \
|
||||
../heimdal/lib/hcrypto/rand-timer.o \
|
||||
../heimdal/lib/hcrypto/hmac.o
|
||||
# End SUBSYSTEM HEIMDAL_HCRYPTO
|
||||
#######################
|
||||
|
Loading…
Reference in New Issue
Block a user