1
0
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:
Andrew Bartlett 2007-07-03 08:00:08 +00:00 committed by Gerald (Jerry) Carter
parent d2fba8faf0
commit 14a4ddb131
67 changed files with 2173 additions and 890 deletions

View File

@ -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 =

View File

@ -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;

View File

@ -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*/);

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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),

View File

@ -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.

View File

@ -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),
...
}

View File

@ -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.

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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];

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View 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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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) {

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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*/,

View File

@ -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*/,

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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*/,

View File

@ -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*/,

View File

@ -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;

View File

@ -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"

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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*/,

View File

@ -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;
}

View File

@ -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;

View File

@ -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
#######################