1 1.4 christos /* $NetBSD: pkinit.c,v 1.6 2023/06/19 21:41:42 christos Exp $ */ 2 1.1 elric 3 1.1 elric /* 4 1.2 christos * Copyright (c) 2003 - 2016 Kungliga Tekniska Hgskolan 5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden). 6 1.1 elric * All rights reserved. 7 1.1 elric * 8 1.1 elric * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 9 1.1 elric * 10 1.1 elric * Redistribution and use in source and binary forms, with or without 11 1.1 elric * modification, are permitted provided that the following conditions 12 1.1 elric * are met: 13 1.1 elric * 14 1.1 elric * 1. Redistributions of source code must retain the above copyright 15 1.1 elric * notice, this list of conditions and the following disclaimer. 16 1.1 elric * 17 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright 18 1.1 elric * notice, this list of conditions and the following disclaimer in the 19 1.1 elric * documentation and/or other materials provided with the distribution. 20 1.1 elric * 21 1.1 elric * 3. Neither the name of the Institute nor the names of its contributors 22 1.1 elric * may be used to endorse or promote products derived from this software 23 1.1 elric * without specific prior written permission. 24 1.1 elric * 25 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 26 1.1 elric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 1.1 elric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 29 1.1 elric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 1.1 elric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 1.1 elric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 1.1 elric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 1.1 elric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 1.1 elric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 1.1 elric * SUCH DAMAGE. 36 1.1 elric */ 37 1.1 elric 38 1.1 elric #include "kdc_locl.h" 39 1.1 elric 40 1.1 elric #ifdef PKINIT 41 1.1 elric 42 1.1 elric #include <krb5/heim_asn1.h> 43 1.1 elric #include <krb5/rfc2459_asn1.h> 44 1.1 elric #include <krb5/cms_asn1.h> 45 1.1 elric #include <krb5/pkinit_asn1.h> 46 1.1 elric 47 1.1 elric #include <krb5/hx509.h> 48 1.1 elric #include "crypto-headers.h" 49 1.1 elric 50 1.1 elric struct pk_client_params { 51 1.1 elric enum krb5_pk_type type; 52 1.2 christos enum keyex_enum keyex; 53 1.1 elric union { 54 1.1 elric struct { 55 1.1 elric BIGNUM *public_key; 56 1.1 elric DH *key; 57 1.1 elric } dh; 58 1.1 elric struct { 59 1.2 christos void *public_key; 60 1.2 christos void *key; 61 1.1 elric } ecdh; 62 1.1 elric } u; 63 1.1 elric hx509_cert cert; 64 1.1 elric unsigned nonce; 65 1.1 elric EncryptionKey reply_key; 66 1.1 elric char *dh_group_name; 67 1.1 elric hx509_peer_info peer; 68 1.1 elric hx509_certs client_anchors; 69 1.1 elric hx509_verify_ctx verify_ctx; 70 1.1 elric }; 71 1.1 elric 72 1.1 elric struct pk_principal_mapping { 73 1.1 elric unsigned int len; 74 1.1 elric struct pk_allowed_princ { 75 1.1 elric krb5_principal principal; 76 1.1 elric char *subject; 77 1.1 elric } *val; 78 1.1 elric }; 79 1.1 elric 80 1.1 elric static struct krb5_pk_identity *kdc_identity; 81 1.1 elric static struct pk_principal_mapping principal_mappings; 82 1.1 elric static struct krb5_dh_moduli **moduli; 83 1.1 elric 84 1.1 elric static struct { 85 1.1 elric krb5_data data; 86 1.1 elric time_t expire; 87 1.1 elric time_t next_update; 88 1.1 elric } ocsp; 89 1.1 elric 90 1.1 elric /* 91 1.1 elric * 92 1.1 elric */ 93 1.1 elric 94 1.1 elric static krb5_error_code 95 1.1 elric pk_check_pkauthenticator_win2k(krb5_context context, 96 1.1 elric PKAuthenticator_Win2k *a, 97 1.1 elric const KDC_REQ *req) 98 1.1 elric { 99 1.1 elric krb5_timestamp now; 100 1.1 elric 101 1.1 elric krb5_timeofday (context, &now); 102 1.1 elric 103 1.1 elric /* XXX cusec */ 104 1.2 christos if (a->ctime == 0 || labs(a->ctime - now) > context->max_skew) { 105 1.1 elric krb5_clear_error_message(context); 106 1.1 elric return KRB5KRB_AP_ERR_SKEW; 107 1.1 elric } 108 1.1 elric return 0; 109 1.1 elric } 110 1.1 elric 111 1.1 elric static krb5_error_code 112 1.1 elric pk_check_pkauthenticator(krb5_context context, 113 1.1 elric PKAuthenticator *a, 114 1.1 elric const KDC_REQ *req) 115 1.1 elric { 116 1.1 elric u_char *buf = NULL; 117 1.1 elric size_t buf_size; 118 1.1 elric krb5_error_code ret; 119 1.2 christos size_t len = 0; 120 1.1 elric krb5_timestamp now; 121 1.1 elric Checksum checksum; 122 1.1 elric 123 1.1 elric krb5_timeofday (context, &now); 124 1.1 elric 125 1.1 elric /* XXX cusec */ 126 1.2 christos if (a->ctime == 0 || labs(a->ctime - now) > context->max_skew) { 127 1.1 elric krb5_clear_error_message(context); 128 1.1 elric return KRB5KRB_AP_ERR_SKEW; 129 1.1 elric } 130 1.1 elric 131 1.1 elric ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret); 132 1.1 elric if (ret) { 133 1.1 elric krb5_clear_error_message(context); 134 1.1 elric return ret; 135 1.1 elric } 136 1.1 elric if (buf_size != len) 137 1.1 elric krb5_abortx(context, "Internal error in ASN.1 encoder"); 138 1.1 elric 139 1.1 elric ret = krb5_create_checksum(context, 140 1.1 elric NULL, 141 1.1 elric 0, 142 1.1 elric CKSUMTYPE_SHA1, 143 1.1 elric buf, 144 1.1 elric len, 145 1.1 elric &checksum); 146 1.1 elric free(buf); 147 1.1 elric if (ret) { 148 1.1 elric krb5_clear_error_message(context); 149 1.1 elric return ret; 150 1.1 elric } 151 1.2 christos 152 1.1 elric if (a->paChecksum == NULL) { 153 1.1 elric krb5_clear_error_message(context); 154 1.1 elric ret = KRB5_KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED; 155 1.1 elric goto out; 156 1.1 elric } 157 1.1 elric 158 1.1 elric if (der_heim_octet_string_cmp(a->paChecksum, &checksum.checksum) != 0) { 159 1.1 elric krb5_clear_error_message(context); 160 1.1 elric ret = KRB5KRB_ERR_GENERIC; 161 1.1 elric } 162 1.1 elric 163 1.1 elric out: 164 1.1 elric free_Checksum(&checksum); 165 1.1 elric 166 1.1 elric return ret; 167 1.1 elric } 168 1.1 elric 169 1.1 elric void 170 1.1 elric _kdc_pk_free_client_param(krb5_context context, pk_client_params *cp) 171 1.1 elric { 172 1.1 elric if (cp == NULL) 173 1.1 elric return; 174 1.1 elric if (cp->cert) 175 1.1 elric hx509_cert_free(cp->cert); 176 1.1 elric if (cp->verify_ctx) 177 1.1 elric hx509_verify_destroy_ctx(cp->verify_ctx); 178 1.1 elric if (cp->keyex == USE_DH) { 179 1.1 elric if (cp->u.dh.key) 180 1.1 elric DH_free(cp->u.dh.key); 181 1.1 elric if (cp->u.dh.public_key) 182 1.1 elric BN_free(cp->u.dh.public_key); 183 1.1 elric } 184 1.2 christos if (cp->keyex == USE_ECDH) 185 1.2 christos _kdc_pk_free_client_ec_param(context, cp->u.ecdh.key, 186 1.2 christos cp->u.ecdh.public_key); 187 1.1 elric krb5_free_keyblock_contents(context, &cp->reply_key); 188 1.1 elric if (cp->dh_group_name) 189 1.1 elric free(cp->dh_group_name); 190 1.1 elric if (cp->peer) 191 1.1 elric hx509_peer_info_free(cp->peer); 192 1.1 elric if (cp->client_anchors) 193 1.1 elric hx509_certs_free(&cp->client_anchors); 194 1.1 elric memset(cp, 0, sizeof(*cp)); 195 1.1 elric free(cp); 196 1.1 elric } 197 1.1 elric 198 1.1 elric static krb5_error_code 199 1.1 elric generate_dh_keyblock(krb5_context context, 200 1.1 elric pk_client_params *client_params, 201 1.1 elric krb5_enctype enctype) 202 1.1 elric { 203 1.1 elric unsigned char *dh_gen_key = NULL; 204 1.1 elric krb5_keyblock key; 205 1.1 elric krb5_error_code ret; 206 1.1 elric size_t dh_gen_keylen, size; 207 1.1 elric 208 1.1 elric memset(&key, 0, sizeof(key)); 209 1.1 elric 210 1.1 elric if (client_params->keyex == USE_DH) { 211 1.1 elric 212 1.1 elric if (client_params->u.dh.public_key == NULL) { 213 1.1 elric ret = KRB5KRB_ERR_GENERIC; 214 1.2 christos krb5_set_error_message(context, ret, "missing DH public_key"); 215 1.1 elric goto out; 216 1.1 elric } 217 1.1 elric 218 1.1 elric if (!DH_generate_key(client_params->u.dh.key)) { 219 1.1 elric ret = KRB5KRB_ERR_GENERIC; 220 1.2 christos krb5_set_error_message(context, ret, 221 1.1 elric "Can't generate Diffie-Hellman keys"); 222 1.1 elric goto out; 223 1.1 elric } 224 1.1 elric 225 1.1 elric size = DH_size(client_params->u.dh.key); 226 1.1 elric 227 1.1 elric dh_gen_key = malloc(size); 228 1.1 elric if (dh_gen_key == NULL) { 229 1.1 elric ret = ENOMEM; 230 1.1 elric krb5_set_error_message(context, ret, "malloc: out of memory"); 231 1.1 elric goto out; 232 1.1 elric } 233 1.1 elric 234 1.1 elric dh_gen_keylen = DH_compute_key(dh_gen_key,client_params->u.dh.public_key, client_params->u.dh.key); 235 1.2 christos if (dh_gen_keylen == (size_t)-1) { 236 1.1 elric ret = KRB5KRB_ERR_GENERIC; 237 1.1 elric krb5_set_error_message(context, ret, 238 1.1 elric "Can't compute Diffie-Hellman key"); 239 1.1 elric goto out; 240 1.1 elric } 241 1.1 elric if (dh_gen_keylen < size) { 242 1.1 elric size -= dh_gen_keylen; 243 1.1 elric memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen); 244 1.1 elric memset(dh_gen_key, 0, size); 245 1.1 elric } 246 1.1 elric } else if (client_params->keyex == USE_ECDH) { 247 1.1 elric if (client_params->u.ecdh.public_key == NULL) { 248 1.1 elric ret = KRB5KRB_ERR_GENERIC; 249 1.2 christos krb5_set_error_message(context, ret, "missing ECDH public_key"); 250 1.1 elric goto out; 251 1.1 elric } 252 1.2 christos ret = _kdc_generate_ecdh_keyblock(context, 253 1.2 christos client_params->u.ecdh.public_key, 254 1.2 christos &client_params->u.ecdh.key, 255 1.2 christos &dh_gen_key, &dh_gen_keylen); 256 1.2 christos if (ret) 257 1.2 christos goto out; 258 1.1 elric } else { 259 1.1 elric ret = KRB5KRB_ERR_GENERIC; 260 1.2 christos krb5_set_error_message(context, ret, 261 1.1 elric "Diffie-Hellman not selected keys"); 262 1.1 elric goto out; 263 1.1 elric } 264 1.1 elric 265 1.1 elric ret = _krb5_pk_octetstring2key(context, 266 1.1 elric enctype, 267 1.1 elric dh_gen_key, dh_gen_keylen, 268 1.1 elric NULL, NULL, 269 1.1 elric &client_params->reply_key); 270 1.1 elric 271 1.1 elric out: 272 1.1 elric if (dh_gen_key) 273 1.1 elric free(dh_gen_key); 274 1.1 elric if (key.keyvalue.data) 275 1.1 elric krb5_free_keyblock_contents(context, &key); 276 1.1 elric 277 1.1 elric return ret; 278 1.1 elric } 279 1.1 elric 280 1.1 elric static BIGNUM * 281 1.1 elric integer_to_BN(krb5_context context, const char *field, heim_integer *f) 282 1.1 elric { 283 1.1 elric BIGNUM *bn; 284 1.1 elric 285 1.1 elric bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); 286 1.1 elric if (bn == NULL) { 287 1.1 elric krb5_set_error_message(context, KRB5_BADMSGTYPE, 288 1.1 elric "PKINIT: parsing BN failed %s", field); 289 1.1 elric return NULL; 290 1.1 elric } 291 1.1 elric BN_set_negative(bn, f->negative); 292 1.1 elric return bn; 293 1.1 elric } 294 1.1 elric 295 1.1 elric static krb5_error_code 296 1.1 elric get_dh_param(krb5_context context, 297 1.1 elric krb5_kdc_configuration *config, 298 1.1 elric SubjectPublicKeyInfo *dh_key_info, 299 1.1 elric pk_client_params *client_params) 300 1.1 elric { 301 1.1 elric DomainParameters dhparam; 302 1.1 elric DH *dh = NULL; 303 1.1 elric krb5_error_code ret; 304 1.1 elric 305 1.1 elric memset(&dhparam, 0, sizeof(dhparam)); 306 1.1 elric 307 1.1 elric if ((dh_key_info->subjectPublicKey.length % 8) != 0) { 308 1.1 elric ret = KRB5_BADMSGTYPE; 309 1.1 elric krb5_set_error_message(context, ret, 310 1.1 elric "PKINIT: subjectPublicKey not aligned " 311 1.1 elric "to 8 bit boundary"); 312 1.1 elric goto out; 313 1.1 elric } 314 1.1 elric 315 1.1 elric if (dh_key_info->algorithm.parameters == NULL) { 316 1.1 elric krb5_set_error_message(context, KRB5_BADMSGTYPE, 317 1.1 elric "PKINIT missing algorithm parameter " 318 1.1 elric "in clientPublicValue"); 319 1.1 elric return KRB5_BADMSGTYPE; 320 1.1 elric } 321 1.1 elric 322 1.1 elric ret = decode_DomainParameters(dh_key_info->algorithm.parameters->data, 323 1.1 elric dh_key_info->algorithm.parameters->length, 324 1.1 elric &dhparam, 325 1.1 elric NULL); 326 1.1 elric if (ret) { 327 1.1 elric krb5_set_error_message(context, ret, "Can't decode algorithm " 328 1.1 elric "parameters in clientPublicValue"); 329 1.1 elric goto out; 330 1.1 elric } 331 1.1 elric 332 1.1 elric ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits, 333 1.2 christos &dhparam.p, &dhparam.g, dhparam.q, moduli, 334 1.1 elric &client_params->dh_group_name); 335 1.1 elric if (ret) { 336 1.1 elric /* XXX send back proposal of better group */ 337 1.1 elric goto out; 338 1.1 elric } 339 1.1 elric 340 1.1 elric dh = DH_new(); 341 1.1 elric if (dh == NULL) { 342 1.1 elric ret = ENOMEM; 343 1.1 elric krb5_set_error_message(context, ret, "Cannot create DH structure"); 344 1.1 elric goto out; 345 1.1 elric } 346 1.1 elric ret = KRB5_BADMSGTYPE; 347 1.3 christos BIGNUM *p, *q, *g; 348 1.3 christos p = integer_to_BN(context, "DH prime", &dhparam.p); 349 1.3 christos if (p == NULL) 350 1.1 elric goto out; 351 1.3 christos g = integer_to_BN(context, "DH base", &dhparam.g); 352 1.3 christos if (g == NULL) 353 1.1 elric goto out; 354 1.2 christos 355 1.2 christos if (dhparam.q) { 356 1.3 christos q = integer_to_BN(context, "DH p-1 factor", dhparam.q); 357 1.3 christos if (q == NULL) 358 1.2 christos goto out; 359 1.3 christos } else 360 1.3 christos q = NULL; 361 1.1 elric 362 1.3 christos #if OPENSSL_VERSION_NUMBER < 0x10100000UL 363 1.3 christos dh->p = p; 364 1.3 christos if (q) 365 1.3 christos dh->q = q; 366 1.3 christos dh->g = g; 367 1.3 christos #else 368 1.3 christos DH_set0_pqg(dh, p, q, g); 369 1.3 christos #endif 370 1.1 elric { 371 1.1 elric heim_integer glue; 372 1.1 elric size_t size; 373 1.1 elric 374 1.1 elric ret = decode_DHPublicKey(dh_key_info->subjectPublicKey.data, 375 1.1 elric dh_key_info->subjectPublicKey.length / 8, 376 1.1 elric &glue, 377 1.1 elric &size); 378 1.1 elric if (ret) { 379 1.1 elric krb5_clear_error_message(context); 380 1.1 elric return ret; 381 1.1 elric } 382 1.1 elric 383 1.1 elric client_params->u.dh.public_key = integer_to_BN(context, 384 1.1 elric "subjectPublicKey", 385 1.1 elric &glue); 386 1.1 elric der_free_heim_integer(&glue); 387 1.1 elric if (client_params->u.dh.public_key == NULL) { 388 1.1 elric ret = KRB5_BADMSGTYPE; 389 1.1 elric goto out; 390 1.1 elric } 391 1.1 elric } 392 1.1 elric 393 1.1 elric client_params->u.dh.key = dh; 394 1.1 elric dh = NULL; 395 1.1 elric ret = 0; 396 1.1 elric 397 1.1 elric out: 398 1.1 elric if (dh) 399 1.1 elric DH_free(dh); 400 1.1 elric free_DomainParameters(&dhparam); 401 1.1 elric return ret; 402 1.1 elric } 403 1.1 elric 404 1.1 elric krb5_error_code 405 1.1 elric _kdc_pk_rd_padata(krb5_context context, 406 1.1 elric krb5_kdc_configuration *config, 407 1.1 elric const KDC_REQ *req, 408 1.1 elric const PA_DATA *pa, 409 1.1 elric hdb_entry_ex *client, 410 1.1 elric pk_client_params **ret_params) 411 1.1 elric { 412 1.1 elric pk_client_params *cp; 413 1.1 elric krb5_error_code ret; 414 1.1 elric heim_oid eContentType = { 0, NULL }, contentInfoOid = { 0, NULL }; 415 1.1 elric krb5_data eContent = { 0, NULL }; 416 1.1 elric krb5_data signed_content = { 0, NULL }; 417 1.1 elric const char *type = "unknown type"; 418 1.1 elric hx509_certs trust_anchors; 419 1.1 elric int have_data = 0; 420 1.1 elric const HDB_Ext_PKINIT_cert *pc; 421 1.1 elric 422 1.1 elric *ret_params = NULL; 423 1.1 elric 424 1.1 elric if (!config->enable_pkinit) { 425 1.1 elric kdc_log(context, config, 0, "PK-INIT request but PK-INIT not enabled"); 426 1.1 elric krb5_clear_error_message(context); 427 1.1 elric return 0; 428 1.1 elric } 429 1.1 elric 430 1.1 elric cp = calloc(1, sizeof(*cp)); 431 1.1 elric if (cp == NULL) { 432 1.1 elric krb5_clear_error_message(context); 433 1.1 elric ret = ENOMEM; 434 1.1 elric goto out; 435 1.1 elric } 436 1.1 elric 437 1.1 elric ret = hx509_certs_init(context->hx509ctx, 438 1.1 elric "MEMORY:trust-anchors", 439 1.1 elric 0, NULL, &trust_anchors); 440 1.1 elric if (ret) { 441 1.1 elric krb5_set_error_message(context, ret, "failed to create trust anchors"); 442 1.1 elric goto out; 443 1.1 elric } 444 1.1 elric 445 1.2 christos ret = hx509_certs_merge(context->hx509ctx, trust_anchors, 446 1.1 elric kdc_identity->anchors); 447 1.1 elric if (ret) { 448 1.1 elric hx509_certs_free(&trust_anchors); 449 1.1 elric krb5_set_error_message(context, ret, "failed to create verify context"); 450 1.1 elric goto out; 451 1.1 elric } 452 1.1 elric 453 1.1 elric /* Add any registered certificates for this client as trust anchors */ 454 1.1 elric ret = hdb_entry_get_pkinit_cert(&client->entry, &pc); 455 1.1 elric if (ret == 0 && pc != NULL) { 456 1.1 elric hx509_cert cert; 457 1.1 elric unsigned int i; 458 1.2 christos 459 1.1 elric for (i = 0; i < pc->len; i++) { 460 1.2 christos cert = hx509_cert_init_data(context->hx509ctx, 461 1.2 christos pc->val[i].cert.data, 462 1.2 christos pc->val[i].cert.length, 463 1.2 christos NULL); 464 1.2 christos if (cert == NULL) 465 1.1 elric continue; 466 1.1 elric hx509_certs_add(context->hx509ctx, trust_anchors, cert); 467 1.1 elric hx509_cert_free(cert); 468 1.1 elric } 469 1.1 elric } 470 1.1 elric 471 1.1 elric ret = hx509_verify_init_ctx(context->hx509ctx, &cp->verify_ctx); 472 1.1 elric if (ret) { 473 1.1 elric hx509_certs_free(&trust_anchors); 474 1.1 elric krb5_set_error_message(context, ret, "failed to create verify context"); 475 1.1 elric goto out; 476 1.1 elric } 477 1.1 elric 478 1.1 elric hx509_verify_set_time(cp->verify_ctx, kdc_time); 479 1.1 elric hx509_verify_attach_anchors(cp->verify_ctx, trust_anchors); 480 1.1 elric hx509_certs_free(&trust_anchors); 481 1.1 elric 482 1.1 elric if (config->pkinit_allow_proxy_certs) 483 1.1 elric hx509_verify_set_proxy_certificate(cp->verify_ctx, 1); 484 1.1 elric 485 1.1 elric if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) { 486 1.1 elric PA_PK_AS_REQ_Win2k r; 487 1.1 elric 488 1.1 elric type = "PK-INIT-Win2k"; 489 1.1 elric 490 1.5 christos if (_kdc_is_anonymous(context, client->entry.principal)) { 491 1.1 elric ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; 492 1.2 christos krb5_set_error_message(context, ret, 493 1.1 elric "Anon not supported in RSA mode"); 494 1.1 elric goto out; 495 1.1 elric } 496 1.1 elric 497 1.1 elric ret = decode_PA_PK_AS_REQ_Win2k(pa->padata_value.data, 498 1.1 elric pa->padata_value.length, 499 1.1 elric &r, 500 1.1 elric NULL); 501 1.1 elric if (ret) { 502 1.1 elric krb5_set_error_message(context, ret, "Can't decode " 503 1.1 elric "PK-AS-REQ-Win2k: %d", ret); 504 1.1 elric goto out; 505 1.1 elric } 506 1.2 christos 507 1.1 elric ret = hx509_cms_unwrap_ContentInfo(&r.signed_auth_pack, 508 1.1 elric &contentInfoOid, 509 1.1 elric &signed_content, 510 1.1 elric &have_data); 511 1.1 elric free_PA_PK_AS_REQ_Win2k(&r); 512 1.1 elric if (ret) { 513 1.1 elric krb5_set_error_message(context, ret, 514 1.1 elric "Can't unwrap ContentInfo(win): %d", ret); 515 1.1 elric goto out; 516 1.1 elric } 517 1.1 elric 518 1.1 elric } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) { 519 1.1 elric PA_PK_AS_REQ r; 520 1.1 elric 521 1.1 elric type = "PK-INIT-IETF"; 522 1.1 elric 523 1.1 elric ret = decode_PA_PK_AS_REQ(pa->padata_value.data, 524 1.1 elric pa->padata_value.length, 525 1.1 elric &r, 526 1.1 elric NULL); 527 1.1 elric if (ret) { 528 1.1 elric krb5_set_error_message(context, ret, 529 1.1 elric "Can't decode PK-AS-REQ: %d", ret); 530 1.1 elric goto out; 531 1.1 elric } 532 1.2 christos 533 1.1 elric /* XXX look at r.kdcPkId */ 534 1.1 elric if (r.trustedCertifiers) { 535 1.1 elric ExternalPrincipalIdentifiers *edi = r.trustedCertifiers; 536 1.1 elric unsigned int i, maxedi; 537 1.1 elric 538 1.1 elric ret = hx509_certs_init(context->hx509ctx, 539 1.1 elric "MEMORY:client-anchors", 540 1.1 elric 0, NULL, 541 1.1 elric &cp->client_anchors); 542 1.1 elric if (ret) { 543 1.1 elric krb5_set_error_message(context, ret, 544 1.2 christos "Can't allocate client anchors: %d", 545 1.1 elric ret); 546 1.1 elric goto out; 547 1.1 elric 548 1.1 elric } 549 1.2 christos /* 550 1.1 elric * If the client sent more then 10 EDI, don't bother 551 1.1 elric * looking more then 10 of performance reasons. 552 1.1 elric */ 553 1.1 elric maxedi = edi->len; 554 1.1 elric if (maxedi > 10) 555 1.1 elric maxedi = 10; 556 1.1 elric for (i = 0; i < maxedi; i++) { 557 1.1 elric IssuerAndSerialNumber iasn; 558 1.1 elric hx509_query *q; 559 1.1 elric hx509_cert cert; 560 1.1 elric size_t size; 561 1.1 elric 562 1.1 elric if (edi->val[i].issuerAndSerialNumber == NULL) 563 1.1 elric continue; 564 1.1 elric 565 1.1 elric ret = hx509_query_alloc(context->hx509ctx, &q); 566 1.1 elric if (ret) { 567 1.1 elric krb5_set_error_message(context, ret, 568 1.1 elric "Failed to allocate hx509_query"); 569 1.1 elric goto out; 570 1.1 elric } 571 1.2 christos 572 1.1 elric ret = decode_IssuerAndSerialNumber(edi->val[i].issuerAndSerialNumber->data, 573 1.1 elric edi->val[i].issuerAndSerialNumber->length, 574 1.1 elric &iasn, 575 1.1 elric &size); 576 1.1 elric if (ret) { 577 1.1 elric hx509_query_free(context->hx509ctx, q); 578 1.1 elric continue; 579 1.1 elric } 580 1.1 elric ret = hx509_query_match_issuer_serial(q, &iasn.issuer, &iasn.serialNumber); 581 1.1 elric free_IssuerAndSerialNumber(&iasn); 582 1.1 elric if (ret) { 583 1.1 elric hx509_query_free(context->hx509ctx, q); 584 1.1 elric continue; 585 1.1 elric } 586 1.1 elric 587 1.1 elric ret = hx509_certs_find(context->hx509ctx, 588 1.1 elric kdc_identity->certs, 589 1.1 elric q, 590 1.1 elric &cert); 591 1.1 elric hx509_query_free(context->hx509ctx, q); 592 1.1 elric if (ret) 593 1.1 elric continue; 594 1.1 elric hx509_certs_add(context->hx509ctx, 595 1.1 elric cp->client_anchors, cert); 596 1.1 elric hx509_cert_free(cert); 597 1.1 elric } 598 1.1 elric } 599 1.1 elric 600 1.1 elric ret = hx509_cms_unwrap_ContentInfo(&r.signedAuthPack, 601 1.1 elric &contentInfoOid, 602 1.1 elric &signed_content, 603 1.1 elric &have_data); 604 1.1 elric free_PA_PK_AS_REQ(&r); 605 1.1 elric if (ret) { 606 1.1 elric krb5_set_error_message(context, ret, 607 1.1 elric "Can't unwrap ContentInfo: %d", ret); 608 1.1 elric goto out; 609 1.1 elric } 610 1.1 elric 611 1.1 elric } else { 612 1.1 elric krb5_clear_error_message(context); 613 1.1 elric ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; 614 1.1 elric goto out; 615 1.1 elric } 616 1.1 elric 617 1.1 elric ret = der_heim_oid_cmp(&contentInfoOid, &asn1_oid_id_pkcs7_signedData); 618 1.1 elric if (ret != 0) { 619 1.1 elric ret = KRB5KRB_ERR_GENERIC; 620 1.1 elric krb5_set_error_message(context, ret, 621 1.1 elric "PK-AS-REQ-Win2k invalid content type oid"); 622 1.1 elric goto out; 623 1.1 elric } 624 1.2 christos 625 1.1 elric if (!have_data) { 626 1.1 elric ret = KRB5KRB_ERR_GENERIC; 627 1.1 elric krb5_set_error_message(context, ret, 628 1.1 elric "PK-AS-REQ-Win2k no signed auth pack"); 629 1.1 elric goto out; 630 1.1 elric } 631 1.1 elric 632 1.1 elric { 633 1.1 elric hx509_certs signer_certs; 634 1.1 elric int flags = HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; /* BTMM */ 635 1.1 elric 636 1.6 christos if (_kdc_is_anonymous(context, client->entry.principal) 637 1.6 christos || (config->historical_anon_realm && _kdc_is_anon_request(req))) 638 1.1 elric flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER; 639 1.1 elric 640 1.1 elric ret = hx509_cms_verify_signed(context->hx509ctx, 641 1.1 elric cp->verify_ctx, 642 1.1 elric flags, 643 1.1 elric signed_content.data, 644 1.1 elric signed_content.length, 645 1.1 elric NULL, 646 1.1 elric kdc_identity->certpool, 647 1.1 elric &eContentType, 648 1.1 elric &eContent, 649 1.1 elric &signer_certs); 650 1.1 elric if (ret) { 651 1.1 elric char *s = hx509_get_error_string(context->hx509ctx, ret); 652 1.1 elric krb5_warnx(context, "PKINIT: failed to verify signature: %s: %d", 653 1.1 elric s, ret); 654 1.1 elric free(s); 655 1.1 elric goto out; 656 1.1 elric } 657 1.1 elric 658 1.1 elric if (signer_certs) { 659 1.1 elric ret = hx509_get_one_cert(context->hx509ctx, signer_certs, 660 1.1 elric &cp->cert); 661 1.1 elric hx509_certs_free(&signer_certs); 662 1.1 elric } 663 1.1 elric if (ret) 664 1.1 elric goto out; 665 1.1 elric } 666 1.1 elric 667 1.1 elric /* Signature is correct, now verify the signed message */ 668 1.1 elric if (der_heim_oid_cmp(&eContentType, &asn1_oid_id_pkcs7_data) != 0 && 669 1.1 elric der_heim_oid_cmp(&eContentType, &asn1_oid_id_pkauthdata) != 0) 670 1.1 elric { 671 1.1 elric ret = KRB5_BADMSGTYPE; 672 1.1 elric krb5_set_error_message(context, ret, "got wrong oid for pkauthdata"); 673 1.1 elric goto out; 674 1.1 elric } 675 1.1 elric 676 1.1 elric if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) { 677 1.1 elric AuthPack_Win2k ap; 678 1.1 elric 679 1.1 elric ret = decode_AuthPack_Win2k(eContent.data, 680 1.1 elric eContent.length, 681 1.1 elric &ap, 682 1.1 elric NULL); 683 1.1 elric if (ret) { 684 1.1 elric krb5_set_error_message(context, ret, 685 1.1 elric "Can't decode AuthPack: %d", ret); 686 1.1 elric goto out; 687 1.1 elric } 688 1.1 elric 689 1.1 elric ret = pk_check_pkauthenticator_win2k(context, 690 1.1 elric &ap.pkAuthenticator, 691 1.1 elric req); 692 1.1 elric if (ret) { 693 1.1 elric free_AuthPack_Win2k(&ap); 694 1.1 elric goto out; 695 1.1 elric } 696 1.1 elric 697 1.1 elric cp->type = PKINIT_WIN2K; 698 1.1 elric cp->nonce = ap.pkAuthenticator.nonce; 699 1.1 elric 700 1.1 elric if (ap.clientPublicValue) { 701 1.1 elric ret = KRB5KRB_ERR_GENERIC; 702 1.1 elric krb5_set_error_message(context, ret, 703 1.1 elric "DH not supported for windows"); 704 1.1 elric goto out; 705 1.1 elric } 706 1.1 elric free_AuthPack_Win2k(&ap); 707 1.1 elric 708 1.1 elric } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) { 709 1.1 elric AuthPack ap; 710 1.1 elric 711 1.1 elric ret = decode_AuthPack(eContent.data, 712 1.1 elric eContent.length, 713 1.1 elric &ap, 714 1.1 elric NULL); 715 1.1 elric if (ret) { 716 1.1 elric krb5_set_error_message(context, ret, 717 1.1 elric "Can't decode AuthPack: %d", ret); 718 1.1 elric free_AuthPack(&ap); 719 1.1 elric goto out; 720 1.1 elric } 721 1.1 elric 722 1.5 christos if (_kdc_is_anonymous(context, client->entry.principal) && 723 1.1 elric ap.clientPublicValue == NULL) { 724 1.1 elric free_AuthPack(&ap); 725 1.1 elric ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; 726 1.2 christos krb5_set_error_message(context, ret, 727 1.1 elric "Anon not supported in RSA mode"); 728 1.1 elric goto out; 729 1.1 elric } 730 1.1 elric 731 1.1 elric ret = pk_check_pkauthenticator(context, 732 1.1 elric &ap.pkAuthenticator, 733 1.1 elric req); 734 1.1 elric if (ret) { 735 1.1 elric free_AuthPack(&ap); 736 1.1 elric goto out; 737 1.1 elric } 738 1.1 elric 739 1.1 elric cp->type = PKINIT_27; 740 1.1 elric cp->nonce = ap.pkAuthenticator.nonce; 741 1.1 elric 742 1.1 elric if (ap.clientPublicValue) { 743 1.1 elric if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_dhpublicnumber) == 0) { 744 1.1 elric cp->keyex = USE_DH; 745 1.1 elric ret = get_dh_param(context, config, 746 1.1 elric ap.clientPublicValue, cp); 747 1.1 elric } else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) { 748 1.1 elric cp->keyex = USE_ECDH; 749 1.2 christos ret = _kdc_get_ecdh_param(context, config, 750 1.2 christos ap.clientPublicValue, 751 1.2 christos &cp->u.ecdh.public_key); 752 1.1 elric } else { 753 1.1 elric ret = KRB5_BADMSGTYPE; 754 1.1 elric krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism"); 755 1.1 elric } 756 1.1 elric if (ret) { 757 1.1 elric free_AuthPack(&ap); 758 1.1 elric goto out; 759 1.1 elric } 760 1.1 elric } else 761 1.1 elric cp->keyex = USE_RSA; 762 1.1 elric 763 1.1 elric ret = hx509_peer_info_alloc(context->hx509ctx, 764 1.1 elric &cp->peer); 765 1.1 elric if (ret) { 766 1.1 elric free_AuthPack(&ap); 767 1.1 elric goto out; 768 1.1 elric } 769 1.2 christos 770 1.1 elric if (ap.supportedCMSTypes) { 771 1.1 elric ret = hx509_peer_info_set_cms_algs(context->hx509ctx, 772 1.1 elric cp->peer, 773 1.1 elric ap.supportedCMSTypes->val, 774 1.1 elric ap.supportedCMSTypes->len); 775 1.1 elric if (ret) { 776 1.1 elric free_AuthPack(&ap); 777 1.1 elric goto out; 778 1.1 elric } 779 1.1 elric } else { 780 1.1 elric /* assume old client */ 781 1.1 elric hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, 782 1.1 elric hx509_crypto_des_rsdi_ede3_cbc()); 783 1.1 elric hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, 784 1.1 elric hx509_signature_rsa_with_sha1()); 785 1.1 elric hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, 786 1.1 elric hx509_signature_sha1()); 787 1.1 elric } 788 1.1 elric free_AuthPack(&ap); 789 1.1 elric } else 790 1.1 elric krb5_abortx(context, "internal pkinit error"); 791 1.1 elric 792 1.1 elric kdc_log(context, config, 0, "PK-INIT request of type %s", type); 793 1.1 elric 794 1.1 elric out: 795 1.1 elric if (ret) 796 1.1 elric krb5_warn(context, ret, "PKINIT"); 797 1.1 elric 798 1.1 elric if (signed_content.data) 799 1.1 elric free(signed_content.data); 800 1.1 elric krb5_data_free(&eContent); 801 1.1 elric der_free_oid(&eContentType); 802 1.1 elric der_free_oid(&contentInfoOid); 803 1.1 elric if (ret) { 804 1.1 elric _kdc_pk_free_client_param(context, cp); 805 1.2 christos } else 806 1.1 elric *ret_params = cp; 807 1.1 elric return ret; 808 1.1 elric } 809 1.1 elric 810 1.1 elric /* 811 1.1 elric * 812 1.1 elric */ 813 1.1 elric 814 1.1 elric static krb5_error_code 815 1.4 christos BN_to_integer(krb5_context context, const BIGNUM *bn, heim_integer *integer) 816 1.1 elric { 817 1.1 elric integer->length = BN_num_bytes(bn); 818 1.1 elric integer->data = malloc(integer->length); 819 1.1 elric if (integer->data == NULL) { 820 1.1 elric krb5_clear_error_message(context); 821 1.1 elric return ENOMEM; 822 1.1 elric } 823 1.1 elric BN_bn2bin(bn, integer->data); 824 1.1 elric integer->negative = BN_is_negative(bn); 825 1.1 elric return 0; 826 1.1 elric } 827 1.1 elric 828 1.1 elric static krb5_error_code 829 1.1 elric pk_mk_pa_reply_enckey(krb5_context context, 830 1.1 elric krb5_kdc_configuration *config, 831 1.1 elric pk_client_params *cp, 832 1.1 elric const KDC_REQ *req, 833 1.1 elric const krb5_data *req_buffer, 834 1.1 elric krb5_keyblock *reply_key, 835 1.1 elric ContentInfo *content_info, 836 1.1 elric hx509_cert *kdc_cert) 837 1.1 elric { 838 1.1 elric const heim_oid *envelopedAlg = NULL, *sdAlg = NULL, *evAlg = NULL; 839 1.1 elric krb5_error_code ret; 840 1.1 elric krb5_data buf, signed_data; 841 1.2 christos size_t size = 0; 842 1.1 elric int do_win2k = 0; 843 1.1 elric 844 1.1 elric krb5_data_zero(&buf); 845 1.1 elric krb5_data_zero(&signed_data); 846 1.1 elric 847 1.1 elric *kdc_cert = NULL; 848 1.1 elric 849 1.1 elric /* 850 1.1 elric * If the message client is a win2k-type but it send pa data 851 1.1 elric * 09-binding it expects a IETF (checksum) reply so there can be 852 1.1 elric * no replay attacks. 853 1.1 elric */ 854 1.1 elric 855 1.1 elric switch (cp->type) { 856 1.1 elric case PKINIT_WIN2K: { 857 1.1 elric int i = 0; 858 1.1 elric if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL 859 1.1 elric && config->pkinit_require_binding == 0) 860 1.1 elric { 861 1.1 elric do_win2k = 1; 862 1.1 elric } 863 1.1 elric sdAlg = &asn1_oid_id_pkcs7_data; 864 1.1 elric evAlg = &asn1_oid_id_pkcs7_data; 865 1.1 elric envelopedAlg = &asn1_oid_id_rsadsi_des_ede3_cbc; 866 1.1 elric break; 867 1.1 elric } 868 1.1 elric case PKINIT_27: 869 1.1 elric sdAlg = &asn1_oid_id_pkrkeydata; 870 1.1 elric evAlg = &asn1_oid_id_pkcs7_signedData; 871 1.1 elric break; 872 1.1 elric default: 873 1.1 elric krb5_abortx(context, "internal pkinit error"); 874 1.2 christos } 875 1.1 elric 876 1.1 elric if (do_win2k) { 877 1.1 elric ReplyKeyPack_Win2k kp; 878 1.1 elric memset(&kp, 0, sizeof(kp)); 879 1.1 elric 880 1.1 elric ret = copy_EncryptionKey(reply_key, &kp.replyKey); 881 1.1 elric if (ret) { 882 1.1 elric krb5_clear_error_message(context); 883 1.1 elric goto out; 884 1.1 elric } 885 1.1 elric kp.nonce = cp->nonce; 886 1.2 christos 887 1.1 elric ASN1_MALLOC_ENCODE(ReplyKeyPack_Win2k, 888 1.1 elric buf.data, buf.length, 889 1.1 elric &kp, &size,ret); 890 1.1 elric free_ReplyKeyPack_Win2k(&kp); 891 1.1 elric } else { 892 1.1 elric krb5_crypto ascrypto; 893 1.1 elric ReplyKeyPack kp; 894 1.1 elric memset(&kp, 0, sizeof(kp)); 895 1.1 elric 896 1.1 elric ret = copy_EncryptionKey(reply_key, &kp.replyKey); 897 1.1 elric if (ret) { 898 1.1 elric krb5_clear_error_message(context); 899 1.1 elric goto out; 900 1.1 elric } 901 1.1 elric 902 1.1 elric ret = krb5_crypto_init(context, reply_key, 0, &ascrypto); 903 1.1 elric if (ret) { 904 1.1 elric krb5_clear_error_message(context); 905 1.1 elric goto out; 906 1.1 elric } 907 1.1 elric 908 1.1 elric ret = krb5_create_checksum(context, ascrypto, 6, 0, 909 1.1 elric req_buffer->data, req_buffer->length, 910 1.1 elric &kp.asChecksum); 911 1.1 elric if (ret) { 912 1.1 elric krb5_clear_error_message(context); 913 1.1 elric goto out; 914 1.1 elric } 915 1.2 christos 916 1.1 elric ret = krb5_crypto_destroy(context, ascrypto); 917 1.1 elric if (ret) { 918 1.1 elric krb5_clear_error_message(context); 919 1.1 elric goto out; 920 1.1 elric } 921 1.1 elric ASN1_MALLOC_ENCODE(ReplyKeyPack, buf.data, buf.length, &kp, &size,ret); 922 1.1 elric free_ReplyKeyPack(&kp); 923 1.1 elric } 924 1.1 elric if (ret) { 925 1.1 elric krb5_set_error_message(context, ret, "ASN.1 encoding of ReplyKeyPack " 926 1.1 elric "failed (%d)", ret); 927 1.1 elric goto out; 928 1.1 elric } 929 1.1 elric if (buf.length != size) 930 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 931 1.1 elric 932 1.1 elric { 933 1.1 elric hx509_query *q; 934 1.1 elric hx509_cert cert; 935 1.2 christos 936 1.1 elric ret = hx509_query_alloc(context->hx509ctx, &q); 937 1.1 elric if (ret) 938 1.1 elric goto out; 939 1.2 christos 940 1.1 elric hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 941 1.1 elric if (config->pkinit_kdc_friendly_name) 942 1.1 elric hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); 943 1.2 christos 944 1.1 elric ret = hx509_certs_find(context->hx509ctx, 945 1.1 elric kdc_identity->certs, 946 1.1 elric q, 947 1.1 elric &cert); 948 1.1 elric hx509_query_free(context->hx509ctx, q); 949 1.1 elric if (ret) 950 1.1 elric goto out; 951 1.2 christos 952 1.1 elric ret = hx509_cms_create_signed_1(context->hx509ctx, 953 1.1 elric 0, 954 1.1 elric sdAlg, 955 1.1 elric buf.data, 956 1.1 elric buf.length, 957 1.1 elric NULL, 958 1.1 elric cert, 959 1.1 elric cp->peer, 960 1.1 elric cp->client_anchors, 961 1.1 elric kdc_identity->certpool, 962 1.1 elric &signed_data); 963 1.1 elric *kdc_cert = cert; 964 1.1 elric } 965 1.1 elric 966 1.1 elric krb5_data_free(&buf); 967 1.1 elric if (ret) 968 1.1 elric goto out; 969 1.1 elric 970 1.1 elric if (cp->type == PKINIT_WIN2K) { 971 1.1 elric ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, 972 1.1 elric &signed_data, 973 1.1 elric &buf); 974 1.1 elric if (ret) 975 1.1 elric goto out; 976 1.1 elric krb5_data_free(&signed_data); 977 1.1 elric signed_data = buf; 978 1.1 elric } 979 1.1 elric 980 1.1 elric ret = hx509_cms_envelope_1(context->hx509ctx, 981 1.1 elric HX509_CMS_EV_NO_KU_CHECK, 982 1.1 elric cp->cert, 983 1.1 elric signed_data.data, signed_data.length, 984 1.1 elric envelopedAlg, 985 1.1 elric evAlg, &buf); 986 1.1 elric if (ret) 987 1.1 elric goto out; 988 1.1 elric 989 1.1 elric ret = _krb5_pk_mk_ContentInfo(context, 990 1.1 elric &buf, 991 1.1 elric &asn1_oid_id_pkcs7_envelopedData, 992 1.1 elric content_info); 993 1.1 elric out: 994 1.1 elric if (ret && *kdc_cert) { 995 1.1 elric hx509_cert_free(*kdc_cert); 996 1.1 elric *kdc_cert = NULL; 997 1.1 elric } 998 1.2 christos 999 1.1 elric krb5_data_free(&buf); 1000 1.1 elric krb5_data_free(&signed_data); 1001 1.1 elric return ret; 1002 1.1 elric } 1003 1.1 elric 1004 1.1 elric /* 1005 1.1 elric * 1006 1.1 elric */ 1007 1.1 elric 1008 1.1 elric static krb5_error_code 1009 1.1 elric pk_mk_pa_reply_dh(krb5_context context, 1010 1.1 elric krb5_kdc_configuration *config, 1011 1.1 elric pk_client_params *cp, 1012 1.1 elric ContentInfo *content_info, 1013 1.1 elric hx509_cert *kdc_cert) 1014 1.1 elric { 1015 1.1 elric KDCDHKeyInfo dh_info; 1016 1.1 elric krb5_data signed_data, buf; 1017 1.1 elric ContentInfo contentinfo; 1018 1.1 elric krb5_error_code ret; 1019 1.1 elric hx509_cert cert; 1020 1.1 elric hx509_query *q; 1021 1.2 christos size_t size = 0; 1022 1.1 elric 1023 1.1 elric memset(&contentinfo, 0, sizeof(contentinfo)); 1024 1.1 elric memset(&dh_info, 0, sizeof(dh_info)); 1025 1.1 elric krb5_data_zero(&signed_data); 1026 1.1 elric krb5_data_zero(&buf); 1027 1.1 elric 1028 1.1 elric *kdc_cert = NULL; 1029 1.1 elric 1030 1.1 elric if (cp->keyex == USE_DH) { 1031 1.1 elric DH *kdc_dh = cp->u.dh.key; 1032 1.1 elric heim_integer i; 1033 1.1 elric 1034 1.3 christos const BIGNUM *pub_key; 1035 1.3 christos #if OPENSSL_VERSION_NUMBER < 0x10100000UL 1036 1.3 christos pub_key = kdc_dh->pub_key; 1037 1.3 christos #else 1038 1.3 christos DH_get0_key(kdc_dh, &pub_key, NULL); 1039 1.3 christos #endif 1040 1.4 christos ret = BN_to_integer(context, pub_key, &i); 1041 1.1 elric if (ret) 1042 1.1 elric return ret; 1043 1.2 christos 1044 1.1 elric ASN1_MALLOC_ENCODE(DHPublicKey, buf.data, buf.length, &i, &size, ret); 1045 1.1 elric der_free_heim_integer(&i); 1046 1.1 elric if (ret) { 1047 1.1 elric krb5_set_error_message(context, ret, "ASN.1 encoding of " 1048 1.1 elric "DHPublicKey failed (%d)", ret); 1049 1.1 elric return ret; 1050 1.1 elric } 1051 1.1 elric if (buf.length != size) 1052 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 1053 1.2 christos 1054 1.1 elric dh_info.subjectPublicKey.length = buf.length * 8; 1055 1.1 elric dh_info.subjectPublicKey.data = buf.data; 1056 1.1 elric krb5_data_zero(&buf); 1057 1.1 elric } else if (cp->keyex == USE_ECDH) { 1058 1.2 christos unsigned char *p; 1059 1.2 christos ret = _kdc_serialize_ecdh_key(context, cp->u.ecdh.key, &p, 1060 1.2 christos &dh_info.subjectPublicKey.length); 1061 1.2 christos dh_info.subjectPublicKey.data = p; 1062 1.2 christos if (ret) 1063 1.2 christos goto out; 1064 1.1 elric } else 1065 1.1 elric krb5_abortx(context, "no keyex selected ?"); 1066 1.1 elric 1067 1.2 christos 1068 1.1 elric dh_info.nonce = cp->nonce; 1069 1.1 elric 1070 1.1 elric ASN1_MALLOC_ENCODE(KDCDHKeyInfo, buf.data, buf.length, &dh_info, &size, 1071 1.1 elric ret); 1072 1.1 elric if (ret) { 1073 1.1 elric krb5_set_error_message(context, ret, "ASN.1 encoding of " 1074 1.1 elric "KdcDHKeyInfo failed (%d)", ret); 1075 1.1 elric goto out; 1076 1.1 elric } 1077 1.1 elric if (buf.length != size) 1078 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 1079 1.1 elric 1080 1.1 elric /* 1081 1.1 elric * Create the SignedData structure and sign the KdcDHKeyInfo 1082 1.1 elric * filled in above 1083 1.1 elric */ 1084 1.1 elric 1085 1.1 elric ret = hx509_query_alloc(context->hx509ctx, &q); 1086 1.1 elric if (ret) 1087 1.1 elric goto out; 1088 1.2 christos 1089 1.1 elric hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 1090 1.1 elric if (config->pkinit_kdc_friendly_name) 1091 1.1 elric hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); 1092 1.2 christos 1093 1.1 elric ret = hx509_certs_find(context->hx509ctx, 1094 1.1 elric kdc_identity->certs, 1095 1.1 elric q, 1096 1.1 elric &cert); 1097 1.1 elric hx509_query_free(context->hx509ctx, q); 1098 1.1 elric if (ret) 1099 1.1 elric goto out; 1100 1.2 christos 1101 1.1 elric ret = hx509_cms_create_signed_1(context->hx509ctx, 1102 1.1 elric 0, 1103 1.1 elric &asn1_oid_id_pkdhkeydata, 1104 1.1 elric buf.data, 1105 1.1 elric buf.length, 1106 1.1 elric NULL, 1107 1.1 elric cert, 1108 1.1 elric cp->peer, 1109 1.1 elric cp->client_anchors, 1110 1.1 elric kdc_identity->certpool, 1111 1.1 elric &signed_data); 1112 1.1 elric if (ret) { 1113 1.1 elric kdc_log(context, config, 0, "Failed signing the DH* reply: %d", ret); 1114 1.1 elric goto out; 1115 1.1 elric } 1116 1.1 elric *kdc_cert = cert; 1117 1.1 elric 1118 1.1 elric ret = _krb5_pk_mk_ContentInfo(context, 1119 1.1 elric &signed_data, 1120 1.1 elric &asn1_oid_id_pkcs7_signedData, 1121 1.1 elric content_info); 1122 1.1 elric if (ret) 1123 1.1 elric goto out; 1124 1.1 elric 1125 1.1 elric out: 1126 1.1 elric if (ret && *kdc_cert) { 1127 1.1 elric hx509_cert_free(*kdc_cert); 1128 1.1 elric *kdc_cert = NULL; 1129 1.1 elric } 1130 1.1 elric 1131 1.1 elric krb5_data_free(&buf); 1132 1.1 elric krb5_data_free(&signed_data); 1133 1.1 elric free_KDCDHKeyInfo(&dh_info); 1134 1.1 elric 1135 1.1 elric return ret; 1136 1.1 elric } 1137 1.1 elric 1138 1.1 elric /* 1139 1.1 elric * 1140 1.1 elric */ 1141 1.1 elric 1142 1.1 elric krb5_error_code 1143 1.1 elric _kdc_pk_mk_pa_reply(krb5_context context, 1144 1.1 elric krb5_kdc_configuration *config, 1145 1.1 elric pk_client_params *cp, 1146 1.1 elric const hdb_entry_ex *client, 1147 1.1 elric krb5_enctype sessionetype, 1148 1.1 elric const KDC_REQ *req, 1149 1.1 elric const krb5_data *req_buffer, 1150 1.2 christos krb5_keyblock *reply_key, 1151 1.1 elric krb5_keyblock *sessionkey, 1152 1.1 elric METHOD_DATA *md) 1153 1.1 elric { 1154 1.1 elric krb5_error_code ret; 1155 1.2 christos void *buf = NULL; 1156 1.2 christos size_t len = 0, size = 0; 1157 1.1 elric krb5_enctype enctype; 1158 1.1 elric int pa_type; 1159 1.1 elric hx509_cert kdc_cert = NULL; 1160 1.2 christos size_t i; 1161 1.1 elric 1162 1.1 elric if (!config->enable_pkinit) { 1163 1.1 elric krb5_clear_error_message(context); 1164 1.1 elric return 0; 1165 1.1 elric } 1166 1.1 elric 1167 1.1 elric if (req->req_body.etype.len > 0) { 1168 1.1 elric for (i = 0; i < req->req_body.etype.len; i++) 1169 1.1 elric if (krb5_enctype_valid(context, req->req_body.etype.val[i]) == 0) 1170 1.1 elric break; 1171 1.1 elric if (req->req_body.etype.len <= i) { 1172 1.1 elric ret = KRB5KRB_ERR_GENERIC; 1173 1.1 elric krb5_set_error_message(context, ret, 1174 1.1 elric "No valid enctype available from client"); 1175 1.1 elric goto out; 1176 1.2 christos } 1177 1.1 elric enctype = req->req_body.etype.val[i]; 1178 1.1 elric } else 1179 1.1 elric enctype = ETYPE_DES3_CBC_SHA1; 1180 1.1 elric 1181 1.1 elric if (cp->type == PKINIT_27) { 1182 1.1 elric PA_PK_AS_REP rep; 1183 1.1 elric const char *type, *other = ""; 1184 1.1 elric 1185 1.1 elric memset(&rep, 0, sizeof(rep)); 1186 1.1 elric 1187 1.1 elric pa_type = KRB5_PADATA_PK_AS_REP; 1188 1.1 elric 1189 1.1 elric if (cp->keyex == USE_RSA) { 1190 1.1 elric ContentInfo info; 1191 1.1 elric 1192 1.1 elric type = "enckey"; 1193 1.1 elric 1194 1.1 elric rep.element = choice_PA_PK_AS_REP_encKeyPack; 1195 1.1 elric 1196 1.1 elric ret = krb5_generate_random_keyblock(context, enctype, 1197 1.1 elric &cp->reply_key); 1198 1.1 elric if (ret) { 1199 1.1 elric free_PA_PK_AS_REP(&rep); 1200 1.1 elric goto out; 1201 1.1 elric } 1202 1.1 elric ret = pk_mk_pa_reply_enckey(context, 1203 1.1 elric config, 1204 1.1 elric cp, 1205 1.1 elric req, 1206 1.1 elric req_buffer, 1207 1.1 elric &cp->reply_key, 1208 1.1 elric &info, 1209 1.1 elric &kdc_cert); 1210 1.1 elric if (ret) { 1211 1.1 elric free_PA_PK_AS_REP(&rep); 1212 1.1 elric goto out; 1213 1.1 elric } 1214 1.1 elric ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data, 1215 1.1 elric rep.u.encKeyPack.length, &info, &size, 1216 1.1 elric ret); 1217 1.1 elric free_ContentInfo(&info); 1218 1.1 elric if (ret) { 1219 1.1 elric krb5_set_error_message(context, ret, "encoding of Key ContentInfo " 1220 1.1 elric "failed %d", ret); 1221 1.1 elric free_PA_PK_AS_REP(&rep); 1222 1.1 elric goto out; 1223 1.1 elric } 1224 1.1 elric if (rep.u.encKeyPack.length != size) 1225 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 1226 1.1 elric 1227 1.2 christos ret = krb5_generate_random_keyblock(context, sessionetype, 1228 1.1 elric sessionkey); 1229 1.1 elric if (ret) { 1230 1.1 elric free_PA_PK_AS_REP(&rep); 1231 1.1 elric goto out; 1232 1.1 elric } 1233 1.1 elric 1234 1.1 elric } else { 1235 1.1 elric ContentInfo info; 1236 1.1 elric 1237 1.1 elric switch (cp->keyex) { 1238 1.1 elric case USE_DH: type = "dh"; break; 1239 1.1 elric case USE_ECDH: type = "ecdh"; break; 1240 1.1 elric default: krb5_abortx(context, "unknown keyex"); break; 1241 1.1 elric } 1242 1.1 elric 1243 1.1 elric if (cp->dh_group_name) 1244 1.1 elric other = cp->dh_group_name; 1245 1.1 elric 1246 1.1 elric rep.element = choice_PA_PK_AS_REP_dhInfo; 1247 1.1 elric 1248 1.1 elric ret = generate_dh_keyblock(context, cp, enctype); 1249 1.1 elric if (ret) 1250 1.1 elric return ret; 1251 1.1 elric 1252 1.1 elric ret = pk_mk_pa_reply_dh(context, config, 1253 1.1 elric cp, 1254 1.1 elric &info, 1255 1.1 elric &kdc_cert); 1256 1.1 elric if (ret) { 1257 1.1 elric free_PA_PK_AS_REP(&rep); 1258 1.1 elric krb5_set_error_message(context, ret, 1259 1.1 elric "create pa-reply-dh " 1260 1.1 elric "failed %d", ret); 1261 1.1 elric goto out; 1262 1.1 elric } 1263 1.1 elric 1264 1.1 elric ASN1_MALLOC_ENCODE(ContentInfo, rep.u.dhInfo.dhSignedData.data, 1265 1.1 elric rep.u.dhInfo.dhSignedData.length, &info, &size, 1266 1.1 elric ret); 1267 1.1 elric free_ContentInfo(&info); 1268 1.1 elric if (ret) { 1269 1.1 elric krb5_set_error_message(context, ret, 1270 1.1 elric "encoding of Key ContentInfo " 1271 1.1 elric "failed %d", ret); 1272 1.1 elric free_PA_PK_AS_REP(&rep); 1273 1.1 elric goto out; 1274 1.1 elric } 1275 1.1 elric if (rep.u.encKeyPack.length != size) 1276 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 1277 1.1 elric 1278 1.2 christos /* generate the session key using the method from RFC6112 */ 1279 1.2 christos { 1280 1.2 christos krb5_keyblock kdc_contribution_key; 1281 1.2 christos krb5_crypto reply_crypto; 1282 1.2 christos krb5_crypto kdccont_crypto; 1283 1.2 christos krb5_data p1 = { strlen("PKINIT"), "PKINIT"}; 1284 1.2 christos krb5_data p2 = { strlen("KEYEXCHANGE"), "KEYEXCHANGE"}; 1285 1.2 christos void *kckdata; 1286 1.2 christos size_t kcklen; 1287 1.2 christos EncryptedData kx; 1288 1.2 christos void *kxdata; 1289 1.2 christos size_t kxlen; 1290 1.2 christos 1291 1.2 christos ret = krb5_generate_random_keyblock(context, sessionetype, 1292 1.2 christos &kdc_contribution_key); 1293 1.2 christos if (ret) { 1294 1.2 christos free_PA_PK_AS_REP(&rep); 1295 1.2 christos goto out; 1296 1.2 christos } 1297 1.2 christos ret = krb5_crypto_init(context, &cp->reply_key, enctype, &reply_crypto); 1298 1.2 christos if (ret) { 1299 1.2 christos krb5_free_keyblock_contents(context, &kdc_contribution_key); 1300 1.2 christos free_PA_PK_AS_REP(&rep); 1301 1.2 christos goto out; 1302 1.2 christos } 1303 1.2 christos ret = krb5_crypto_init(context, &kdc_contribution_key, sessionetype, &kdccont_crypto); 1304 1.2 christos if (ret) { 1305 1.2 christos krb5_crypto_destroy(context, reply_crypto); 1306 1.2 christos krb5_free_keyblock_contents(context, &kdc_contribution_key); 1307 1.2 christos free_PA_PK_AS_REP(&rep); 1308 1.2 christos goto out; 1309 1.2 christos } 1310 1.2 christos /* KRB-FX-CF2 */ 1311 1.2 christos ret = krb5_crypto_fx_cf2(context, kdccont_crypto, reply_crypto, 1312 1.2 christos &p1, &p2, sessionetype, sessionkey); 1313 1.2 christos krb5_crypto_destroy(context, kdccont_crypto); 1314 1.2 christos if (ret) { 1315 1.2 christos krb5_crypto_destroy(context, reply_crypto); 1316 1.2 christos krb5_free_keyblock_contents(context, &kdc_contribution_key); 1317 1.2 christos free_PA_PK_AS_REP(&rep); 1318 1.2 christos goto out; 1319 1.2 christos } 1320 1.2 christos ASN1_MALLOC_ENCODE(EncryptionKey, kckdata, kcklen, 1321 1.2 christos &kdc_contribution_key, &size, ret); 1322 1.2 christos krb5_free_keyblock_contents(context, &kdc_contribution_key); 1323 1.2 christos if (ret) { 1324 1.2 christos krb5_set_error_message(context, ret, "encoding of PKINIT-KX Key failed %d", ret); 1325 1.2 christos krb5_crypto_destroy(context, reply_crypto); 1326 1.2 christos free_PA_PK_AS_REP(&rep); 1327 1.2 christos goto out; 1328 1.2 christos } 1329 1.2 christos if (kcklen != size) 1330 1.2 christos krb5_abortx(context, "Internal ASN.1 encoder error"); 1331 1.2 christos ret = krb5_encrypt_EncryptedData(context, reply_crypto, KRB5_KU_PA_PKINIT_KX, 1332 1.2 christos kckdata, kcklen, 0, &kx); 1333 1.2 christos krb5_crypto_destroy(context, reply_crypto); 1334 1.2 christos free(kckdata); 1335 1.2 christos if (ret) { 1336 1.2 christos free_PA_PK_AS_REP(&rep); 1337 1.2 christos goto out; 1338 1.2 christos } 1339 1.2 christos ASN1_MALLOC_ENCODE(EncryptedData, kxdata, kxlen, 1340 1.2 christos &kx, &size, ret); 1341 1.2 christos free_EncryptedData(&kx); 1342 1.2 christos if (ret) { 1343 1.2 christos krb5_set_error_message(context, ret, "encoding of PKINIT-KX failed %d", ret); 1344 1.2 christos free_PA_PK_AS_REP(&rep); 1345 1.2 christos goto out; 1346 1.2 christos } 1347 1.2 christos if (kxlen != size) 1348 1.2 christos krb5_abortx(context, "Internal ASN.1 encoder error"); 1349 1.2 christos /* Add PA-PKINIT-KX */ 1350 1.2 christos ret = krb5_padata_add(context, md, KRB5_PADATA_PKINIT_KX, kxdata, kxlen); 1351 1.2 christos if (ret) { 1352 1.2 christos krb5_set_error_message(context, ret, 1353 1.2 christos "Failed adding PKINIT-KX %d", ret); 1354 1.2 christos free(buf); 1355 1.2 christos goto out; 1356 1.2 christos } 1357 1.1 elric } 1358 1.1 elric } 1359 1.1 elric 1360 1.1 elric #define use_btmm_with_enckey 0 1361 1.1 elric if (use_btmm_with_enckey && rep.element == choice_PA_PK_AS_REP_encKeyPack) { 1362 1.1 elric PA_PK_AS_REP_BTMM btmm; 1363 1.1 elric heim_any any; 1364 1.1 elric 1365 1.1 elric any.data = rep.u.encKeyPack.data; 1366 1.1 elric any.length = rep.u.encKeyPack.length; 1367 1.1 elric 1368 1.1 elric btmm.dhSignedData = NULL; 1369 1.1 elric btmm.encKeyPack = &any; 1370 1.1 elric 1371 1.1 elric ASN1_MALLOC_ENCODE(PA_PK_AS_REP_BTMM, buf, len, &btmm, &size, ret); 1372 1.1 elric } else { 1373 1.1 elric ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret); 1374 1.1 elric } 1375 1.1 elric 1376 1.1 elric free_PA_PK_AS_REP(&rep); 1377 1.1 elric if (ret) { 1378 1.1 elric krb5_set_error_message(context, ret, 1379 1.1 elric "encode PA-PK-AS-REP failed %d", ret); 1380 1.1 elric goto out; 1381 1.1 elric } 1382 1.1 elric if (len != size) 1383 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 1384 1.1 elric 1385 1.1 elric kdc_log(context, config, 0, "PK-INIT using %s %s", type, other); 1386 1.1 elric 1387 1.1 elric } else if (cp->type == PKINIT_WIN2K) { 1388 1.1 elric PA_PK_AS_REP_Win2k rep; 1389 1.1 elric ContentInfo info; 1390 1.1 elric 1391 1.1 elric if (cp->keyex != USE_RSA) { 1392 1.1 elric ret = KRB5KRB_ERR_GENERIC; 1393 1.1 elric krb5_set_error_message(context, ret, 1394 1.1 elric "Windows PK-INIT doesn't support DH"); 1395 1.1 elric goto out; 1396 1.1 elric } 1397 1.1 elric 1398 1.1 elric memset(&rep, 0, sizeof(rep)); 1399 1.1 elric 1400 1.1 elric pa_type = KRB5_PADATA_PK_AS_REP_19; 1401 1.2 christos rep.element = choice_PA_PK_AS_REP_Win2k_encKeyPack; 1402 1.1 elric 1403 1.1 elric ret = krb5_generate_random_keyblock(context, enctype, 1404 1.1 elric &cp->reply_key); 1405 1.1 elric if (ret) { 1406 1.1 elric free_PA_PK_AS_REP_Win2k(&rep); 1407 1.1 elric goto out; 1408 1.1 elric } 1409 1.1 elric ret = pk_mk_pa_reply_enckey(context, 1410 1.1 elric config, 1411 1.1 elric cp, 1412 1.1 elric req, 1413 1.1 elric req_buffer, 1414 1.1 elric &cp->reply_key, 1415 1.1 elric &info, 1416 1.1 elric &kdc_cert); 1417 1.1 elric if (ret) { 1418 1.1 elric free_PA_PK_AS_REP_Win2k(&rep); 1419 1.1 elric goto out; 1420 1.1 elric } 1421 1.1 elric ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data, 1422 1.1 elric rep.u.encKeyPack.length, &info, &size, 1423 1.1 elric ret); 1424 1.1 elric free_ContentInfo(&info); 1425 1.1 elric if (ret) { 1426 1.1 elric krb5_set_error_message(context, ret, "encoding of Key ContentInfo " 1427 1.1 elric "failed %d", ret); 1428 1.1 elric free_PA_PK_AS_REP_Win2k(&rep); 1429 1.1 elric goto out; 1430 1.1 elric } 1431 1.1 elric if (rep.u.encKeyPack.length != size) 1432 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 1433 1.1 elric 1434 1.1 elric ASN1_MALLOC_ENCODE(PA_PK_AS_REP_Win2k, buf, len, &rep, &size, ret); 1435 1.1 elric free_PA_PK_AS_REP_Win2k(&rep); 1436 1.1 elric if (ret) { 1437 1.1 elric krb5_set_error_message(context, ret, 1438 1.1 elric "encode PA-PK-AS-REP-Win2k failed %d", ret); 1439 1.1 elric goto out; 1440 1.1 elric } 1441 1.1 elric if (len != size) 1442 1.1 elric krb5_abortx(context, "Internal ASN.1 encoder error"); 1443 1.1 elric 1444 1.2 christos ret = krb5_generate_random_keyblock(context, sessionetype, 1445 1.1 elric sessionkey); 1446 1.1 elric if (ret) { 1447 1.1 elric free(buf); 1448 1.1 elric goto out; 1449 1.1 elric } 1450 1.1 elric 1451 1.1 elric } else 1452 1.1 elric krb5_abortx(context, "PK-INIT internal error"); 1453 1.1 elric 1454 1.1 elric 1455 1.1 elric ret = krb5_padata_add(context, md, pa_type, buf, len); 1456 1.1 elric if (ret) { 1457 1.1 elric krb5_set_error_message(context, ret, 1458 1.1 elric "Failed adding PA-PK-AS-REP %d", ret); 1459 1.1 elric free(buf); 1460 1.1 elric goto out; 1461 1.1 elric } 1462 1.1 elric 1463 1.1 elric if (config->pkinit_kdc_ocsp_file) { 1464 1.1 elric 1465 1.1 elric if (ocsp.expire == 0 && ocsp.next_update > kdc_time) { 1466 1.1 elric struct stat sb; 1467 1.1 elric int fd; 1468 1.1 elric 1469 1.1 elric krb5_data_free(&ocsp.data); 1470 1.1 elric 1471 1.1 elric ocsp.expire = 0; 1472 1.1 elric ocsp.next_update = kdc_time + 60 * 5; 1473 1.1 elric 1474 1.1 elric fd = open(config->pkinit_kdc_ocsp_file, O_RDONLY); 1475 1.1 elric if (fd < 0) { 1476 1.1 elric kdc_log(context, config, 0, 1477 1.1 elric "PK-INIT failed to open ocsp data file %d", errno); 1478 1.1 elric goto out_ocsp; 1479 1.1 elric } 1480 1.1 elric ret = fstat(fd, &sb); 1481 1.1 elric if (ret) { 1482 1.1 elric ret = errno; 1483 1.1 elric close(fd); 1484 1.1 elric kdc_log(context, config, 0, 1485 1.1 elric "PK-INIT failed to stat ocsp data %d", ret); 1486 1.1 elric goto out_ocsp; 1487 1.1 elric } 1488 1.2 christos 1489 1.1 elric ret = krb5_data_alloc(&ocsp.data, sb.st_size); 1490 1.1 elric if (ret) { 1491 1.1 elric close(fd); 1492 1.1 elric kdc_log(context, config, 0, 1493 1.1 elric "PK-INIT failed to stat ocsp data %d", ret); 1494 1.1 elric goto out_ocsp; 1495 1.1 elric } 1496 1.1 elric ocsp.data.length = sb.st_size; 1497 1.1 elric ret = read(fd, ocsp.data.data, sb.st_size); 1498 1.1 elric close(fd); 1499 1.1 elric if (ret != sb.st_size) { 1500 1.1 elric kdc_log(context, config, 0, 1501 1.1 elric "PK-INIT failed to read ocsp data %d", errno); 1502 1.1 elric goto out_ocsp; 1503 1.1 elric } 1504 1.1 elric 1505 1.1 elric ret = hx509_ocsp_verify(context->hx509ctx, 1506 1.1 elric kdc_time, 1507 1.1 elric kdc_cert, 1508 1.1 elric 0, 1509 1.1 elric ocsp.data.data, ocsp.data.length, 1510 1.1 elric &ocsp.expire); 1511 1.1 elric if (ret) { 1512 1.1 elric kdc_log(context, config, 0, 1513 1.1 elric "PK-INIT failed to verify ocsp data %d", ret); 1514 1.1 elric krb5_data_free(&ocsp.data); 1515 1.1 elric ocsp.expire = 0; 1516 1.1 elric } else if (ocsp.expire > 180) { 1517 1.1 elric ocsp.expire -= 180; /* refetch the ocsp before it expire */ 1518 1.1 elric ocsp.next_update = ocsp.expire; 1519 1.1 elric } else { 1520 1.1 elric ocsp.next_update = kdc_time; 1521 1.1 elric } 1522 1.1 elric out_ocsp: 1523 1.1 elric ret = 0; 1524 1.1 elric } 1525 1.1 elric 1526 1.1 elric if (ocsp.expire != 0 && ocsp.expire > kdc_time) { 1527 1.1 elric 1528 1.1 elric ret = krb5_padata_add(context, md, 1529 1.1 elric KRB5_PADATA_PA_PK_OCSP_RESPONSE, 1530 1.1 elric ocsp.data.data, ocsp.data.length); 1531 1.1 elric if (ret) { 1532 1.1 elric krb5_set_error_message(context, ret, 1533 1.1 elric "Failed adding OCSP response %d", ret); 1534 1.1 elric goto out; 1535 1.1 elric } 1536 1.1 elric } 1537 1.1 elric } 1538 1.1 elric 1539 1.1 elric out: 1540 1.1 elric if (kdc_cert) 1541 1.1 elric hx509_cert_free(kdc_cert); 1542 1.1 elric 1543 1.1 elric if (ret == 0) 1544 1.2 christos ret = krb5_copy_keyblock_contents(context, &cp->reply_key, reply_key); 1545 1.1 elric return ret; 1546 1.1 elric } 1547 1.1 elric 1548 1.1 elric static int 1549 1.1 elric match_rfc_san(krb5_context context, 1550 1.1 elric krb5_kdc_configuration *config, 1551 1.1 elric hx509_context hx509ctx, 1552 1.1 elric hx509_cert client_cert, 1553 1.1 elric krb5_const_principal match) 1554 1.1 elric { 1555 1.1 elric hx509_octet_string_list list; 1556 1.2 christos int ret, found = 0; 1557 1.2 christos size_t i; 1558 1.1 elric 1559 1.1 elric memset(&list, 0 , sizeof(list)); 1560 1.1 elric 1561 1.1 elric ret = hx509_cert_find_subjectAltName_otherName(hx509ctx, 1562 1.1 elric client_cert, 1563 1.1 elric &asn1_oid_id_pkinit_san, 1564 1.1 elric &list); 1565 1.1 elric if (ret) 1566 1.1 elric goto out; 1567 1.1 elric 1568 1.1 elric for (i = 0; !found && i < list.len; i++) { 1569 1.1 elric krb5_principal_data principal; 1570 1.1 elric KRB5PrincipalName kn; 1571 1.1 elric size_t size; 1572 1.1 elric 1573 1.1 elric ret = decode_KRB5PrincipalName(list.val[i].data, 1574 1.1 elric list.val[i].length, 1575 1.1 elric &kn, &size); 1576 1.1 elric if (ret) { 1577 1.1 elric const char *msg = krb5_get_error_message(context, ret); 1578 1.1 elric kdc_log(context, config, 0, 1579 1.1 elric "Decoding kerberos name in certificate failed: %s", msg); 1580 1.1 elric krb5_free_error_message(context, msg); 1581 1.1 elric break; 1582 1.1 elric } 1583 1.1 elric if (size != list.val[i].length) { 1584 1.1 elric kdc_log(context, config, 0, 1585 1.1 elric "Decoding kerberos name have extra bits on the end"); 1586 1.1 elric return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; 1587 1.1 elric } 1588 1.1 elric 1589 1.2 christos memset(&principal, 0, sizeof (principal)); 1590 1.1 elric principal.name = kn.principalName; 1591 1.1 elric principal.realm = kn.realm; 1592 1.1 elric 1593 1.1 elric if (krb5_principal_compare(context, &principal, match) == TRUE) 1594 1.1 elric found = 1; 1595 1.1 elric free_KRB5PrincipalName(&kn); 1596 1.1 elric } 1597 1.1 elric 1598 1.1 elric out: 1599 1.1 elric hx509_free_octet_string_list(&list); 1600 1.1 elric if (ret) 1601 1.1 elric return ret; 1602 1.1 elric 1603 1.1 elric if (!found) 1604 1.1 elric return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; 1605 1.1 elric 1606 1.1 elric return 0; 1607 1.1 elric } 1608 1.1 elric 1609 1.1 elric static int 1610 1.1 elric match_ms_upn_san(krb5_context context, 1611 1.1 elric krb5_kdc_configuration *config, 1612 1.1 elric hx509_context hx509ctx, 1613 1.1 elric hx509_cert client_cert, 1614 1.1 elric HDB *clientdb, 1615 1.1 elric hdb_entry_ex *client) 1616 1.1 elric { 1617 1.1 elric hx509_octet_string_list list; 1618 1.1 elric krb5_principal principal = NULL; 1619 1.1 elric int ret; 1620 1.1 elric MS_UPN_SAN upn; 1621 1.1 elric size_t size; 1622 1.1 elric 1623 1.1 elric memset(&list, 0 , sizeof(list)); 1624 1.1 elric 1625 1.1 elric ret = hx509_cert_find_subjectAltName_otherName(hx509ctx, 1626 1.1 elric client_cert, 1627 1.1 elric &asn1_oid_id_pkinit_ms_san, 1628 1.1 elric &list); 1629 1.1 elric if (ret) 1630 1.1 elric goto out; 1631 1.1 elric 1632 1.1 elric if (list.len != 1) { 1633 1.1 elric kdc_log(context, config, 0, 1634 1.1 elric "More then one PK-INIT MS UPN SAN"); 1635 1.2 christos ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; 1636 1.1 elric goto out; 1637 1.1 elric } 1638 1.1 elric 1639 1.1 elric ret = decode_MS_UPN_SAN(list.val[0].data, list.val[0].length, &upn, &size); 1640 1.1 elric if (ret) { 1641 1.1 elric kdc_log(context, config, 0, "Decode of MS-UPN-SAN failed"); 1642 1.1 elric goto out; 1643 1.1 elric } 1644 1.1 elric if (size != list.val[0].length) { 1645 1.1 elric free_MS_UPN_SAN(&upn); 1646 1.1 elric kdc_log(context, config, 0, "Trailing data in "); 1647 1.1 elric ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; 1648 1.1 elric goto out; 1649 1.1 elric } 1650 1.1 elric 1651 1.1 elric kdc_log(context, config, 0, "found MS UPN SAN: %s", upn); 1652 1.1 elric 1653 1.1 elric ret = krb5_parse_name(context, upn, &principal); 1654 1.1 elric free_MS_UPN_SAN(&upn); 1655 1.1 elric if (ret) { 1656 1.1 elric kdc_log(context, config, 0, "Failed to parse principal in MS UPN SAN"); 1657 1.1 elric goto out; 1658 1.1 elric } 1659 1.1 elric 1660 1.1 elric if (clientdb->hdb_check_pkinit_ms_upn_match) { 1661 1.1 elric ret = clientdb->hdb_check_pkinit_ms_upn_match(context, clientdb, client, principal); 1662 1.1 elric } else { 1663 1.2 christos 1664 1.1 elric /* 1665 1.1 elric * This is very wrong, but will do for a fallback 1666 1.1 elric */ 1667 1.1 elric strupr(principal->realm); 1668 1.2 christos 1669 1.1 elric if (krb5_principal_compare(context, principal, client->entry.principal) == FALSE) 1670 1.1 elric ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; 1671 1.1 elric } 1672 1.1 elric 1673 1.1 elric out: 1674 1.1 elric if (principal) 1675 1.1 elric krb5_free_principal(context, principal); 1676 1.1 elric hx509_free_octet_string_list(&list); 1677 1.1 elric 1678 1.1 elric return ret; 1679 1.1 elric } 1680 1.1 elric 1681 1.1 elric krb5_error_code 1682 1.1 elric _kdc_pk_check_client(krb5_context context, 1683 1.1 elric krb5_kdc_configuration *config, 1684 1.1 elric HDB *clientdb, 1685 1.1 elric hdb_entry_ex *client, 1686 1.1 elric pk_client_params *cp, 1687 1.1 elric char **subject_name) 1688 1.1 elric { 1689 1.1 elric const HDB_Ext_PKINIT_acl *acl; 1690 1.1 elric const HDB_Ext_PKINIT_cert *pc; 1691 1.1 elric krb5_error_code ret; 1692 1.1 elric hx509_name name; 1693 1.2 christos size_t i; 1694 1.1 elric 1695 1.1 elric if (cp->cert == NULL) { 1696 1.6 christos if (!_kdc_is_anonymous(context, client->entry.principal) 1697 1.6 christos && !config->historical_anon_realm) 1698 1.5 christos return KRB5KDC_ERR_BADOPTION; 1699 1.1 elric 1700 1.5 christos *subject_name = strdup("<unauthenticated anonymous client>"); 1701 1.1 elric if (*subject_name == NULL) 1702 1.1 elric return ENOMEM; 1703 1.1 elric return 0; 1704 1.1 elric } 1705 1.1 elric 1706 1.1 elric ret = hx509_cert_get_base_subject(context->hx509ctx, 1707 1.1 elric cp->cert, 1708 1.1 elric &name); 1709 1.1 elric if (ret) 1710 1.1 elric return ret; 1711 1.1 elric 1712 1.1 elric ret = hx509_name_to_string(name, subject_name); 1713 1.1 elric hx509_name_free(&name); 1714 1.1 elric if (ret) 1715 1.1 elric return ret; 1716 1.1 elric 1717 1.1 elric kdc_log(context, config, 0, 1718 1.1 elric "Trying to authorize PK-INIT subject DN %s", 1719 1.1 elric *subject_name); 1720 1.1 elric 1721 1.1 elric ret = hdb_entry_get_pkinit_cert(&client->entry, &pc); 1722 1.1 elric if (ret == 0 && pc) { 1723 1.1 elric hx509_cert cert; 1724 1.2 christos size_t j; 1725 1.2 christos 1726 1.2 christos for (j = 0; j < pc->len; j++) { 1727 1.2 christos cert = hx509_cert_init_data(context->hx509ctx, 1728 1.2 christos pc->val[j].cert.data, 1729 1.2 christos pc->val[j].cert.length, 1730 1.2 christos NULL); 1731 1.2 christos if (cert == NULL) 1732 1.1 elric continue; 1733 1.1 elric ret = hx509_cert_cmp(cert, cp->cert); 1734 1.1 elric hx509_cert_free(cert); 1735 1.1 elric if (ret == 0) { 1736 1.1 elric kdc_log(context, config, 5, 1737 1.1 elric "Found matching PK-INIT cert in hdb"); 1738 1.1 elric return 0; 1739 1.1 elric } 1740 1.1 elric } 1741 1.1 elric } 1742 1.1 elric 1743 1.1 elric 1744 1.1 elric if (config->pkinit_princ_in_cert) { 1745 1.1 elric ret = match_rfc_san(context, config, 1746 1.1 elric context->hx509ctx, 1747 1.1 elric cp->cert, 1748 1.1 elric client->entry.principal); 1749 1.1 elric if (ret == 0) { 1750 1.1 elric kdc_log(context, config, 5, 1751 1.1 elric "Found matching PK-INIT SAN in certificate"); 1752 1.1 elric return 0; 1753 1.1 elric } 1754 1.1 elric ret = match_ms_upn_san(context, config, 1755 1.1 elric context->hx509ctx, 1756 1.1 elric cp->cert, 1757 1.2 christos clientdb, 1758 1.1 elric client); 1759 1.1 elric if (ret == 0) { 1760 1.1 elric kdc_log(context, config, 5, 1761 1.1 elric "Found matching MS UPN SAN in certificate"); 1762 1.1 elric return 0; 1763 1.1 elric } 1764 1.1 elric } 1765 1.1 elric 1766 1.1 elric ret = hdb_entry_get_pkinit_acl(&client->entry, &acl); 1767 1.1 elric if (ret == 0 && acl != NULL) { 1768 1.1 elric /* 1769 1.1 elric * Cheat here and compare the generated name with the string 1770 1.1 elric * and not the reverse. 1771 1.1 elric */ 1772 1.1 elric for (i = 0; i < acl->len; i++) { 1773 1.1 elric if (strcmp(*subject_name, acl->val[0].subject) != 0) 1774 1.1 elric continue; 1775 1.1 elric 1776 1.1 elric /* Don't support isser and anchor checking right now */ 1777 1.1 elric if (acl->val[0].issuer) 1778 1.1 elric continue; 1779 1.1 elric if (acl->val[0].anchor) 1780 1.1 elric continue; 1781 1.1 elric 1782 1.1 elric kdc_log(context, config, 5, 1783 1.1 elric "Found matching PK-INIT database ACL"); 1784 1.1 elric return 0; 1785 1.1 elric } 1786 1.1 elric } 1787 1.1 elric 1788 1.1 elric for (i = 0; i < principal_mappings.len; i++) { 1789 1.1 elric krb5_boolean b; 1790 1.1 elric 1791 1.1 elric b = krb5_principal_compare(context, 1792 1.1 elric client->entry.principal, 1793 1.1 elric principal_mappings.val[i].principal); 1794 1.1 elric if (b == FALSE) 1795 1.1 elric continue; 1796 1.1 elric if (strcmp(principal_mappings.val[i].subject, *subject_name) != 0) 1797 1.1 elric continue; 1798 1.1 elric kdc_log(context, config, 5, 1799 1.1 elric "Found matching PK-INIT FILE ACL"); 1800 1.1 elric return 0; 1801 1.1 elric } 1802 1.1 elric 1803 1.1 elric ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; 1804 1.1 elric krb5_set_error_message(context, ret, 1805 1.1 elric "PKINIT no matching principals for %s", 1806 1.1 elric *subject_name); 1807 1.1 elric 1808 1.1 elric kdc_log(context, config, 5, 1809 1.1 elric "PKINIT no matching principals for %s", 1810 1.1 elric *subject_name); 1811 1.1 elric 1812 1.1 elric free(*subject_name); 1813 1.1 elric *subject_name = NULL; 1814 1.1 elric 1815 1.1 elric return ret; 1816 1.1 elric } 1817 1.1 elric 1818 1.1 elric static krb5_error_code 1819 1.1 elric add_principal_mapping(krb5_context context, 1820 1.1 elric const char *principal_name, 1821 1.1 elric const char * subject) 1822 1.1 elric { 1823 1.1 elric struct pk_allowed_princ *tmp; 1824 1.1 elric krb5_principal principal; 1825 1.1 elric krb5_error_code ret; 1826 1.1 elric 1827 1.1 elric tmp = realloc(principal_mappings.val, 1828 1.1 elric (principal_mappings.len + 1) * sizeof(*tmp)); 1829 1.1 elric if (tmp == NULL) 1830 1.1 elric return ENOMEM; 1831 1.1 elric principal_mappings.val = tmp; 1832 1.1 elric 1833 1.1 elric ret = krb5_parse_name(context, principal_name, &principal); 1834 1.1 elric if (ret) 1835 1.1 elric return ret; 1836 1.1 elric 1837 1.1 elric principal_mappings.val[principal_mappings.len].principal = principal; 1838 1.1 elric 1839 1.1 elric principal_mappings.val[principal_mappings.len].subject = strdup(subject); 1840 1.1 elric if (principal_mappings.val[principal_mappings.len].subject == NULL) { 1841 1.1 elric krb5_free_principal(context, principal); 1842 1.1 elric return ENOMEM; 1843 1.1 elric } 1844 1.1 elric principal_mappings.len++; 1845 1.1 elric 1846 1.1 elric return 0; 1847 1.1 elric } 1848 1.1 elric 1849 1.1 elric krb5_error_code 1850 1.1 elric _kdc_add_inital_verified_cas(krb5_context context, 1851 1.1 elric krb5_kdc_configuration *config, 1852 1.1 elric pk_client_params *cp, 1853 1.1 elric EncTicketPart *tkt) 1854 1.1 elric { 1855 1.1 elric AD_INITIAL_VERIFIED_CAS cas; 1856 1.1 elric krb5_error_code ret; 1857 1.1 elric krb5_data data; 1858 1.2 christos size_t size = 0; 1859 1.1 elric 1860 1.1 elric memset(&cas, 0, sizeof(cas)); 1861 1.1 elric 1862 1.1 elric /* XXX add CAs to cas here */ 1863 1.1 elric 1864 1.1 elric ASN1_MALLOC_ENCODE(AD_INITIAL_VERIFIED_CAS, data.data, data.length, 1865 1.1 elric &cas, &size, ret); 1866 1.1 elric if (ret) 1867 1.1 elric return ret; 1868 1.1 elric if (data.length != size) 1869 1.1 elric krb5_abortx(context, "internal asn.1 encoder error"); 1870 1.1 elric 1871 1.1 elric ret = _kdc_tkt_add_if_relevant_ad(context, tkt, 1872 1.1 elric KRB5_AUTHDATA_INITIAL_VERIFIED_CAS, 1873 1.1 elric &data); 1874 1.1 elric krb5_data_free(&data); 1875 1.1 elric return ret; 1876 1.1 elric } 1877 1.1 elric 1878 1.1 elric /* 1879 1.1 elric * 1880 1.1 elric */ 1881 1.1 elric 1882 1.1 elric static void 1883 1.1 elric load_mappings(krb5_context context, const char *fn) 1884 1.1 elric { 1885 1.1 elric krb5_error_code ret; 1886 1.1 elric char buf[1024]; 1887 1.1 elric unsigned long lineno = 0; 1888 1.1 elric FILE *f; 1889 1.1 elric 1890 1.1 elric f = fopen(fn, "r"); 1891 1.1 elric if (f == NULL) 1892 1.1 elric return; 1893 1.1 elric 1894 1.1 elric while (fgets(buf, sizeof(buf), f) != NULL) { 1895 1.1 elric char *subject_name, *p; 1896 1.1 elric 1897 1.1 elric buf[strcspn(buf, "\n")] = '\0'; 1898 1.1 elric lineno++; 1899 1.1 elric 1900 1.1 elric p = buf + strspn(buf, " \t"); 1901 1.1 elric 1902 1.1 elric if (*p == '#' || *p == '\0') 1903 1.1 elric continue; 1904 1.1 elric 1905 1.1 elric subject_name = strchr(p, ':'); 1906 1.1 elric if (subject_name == NULL) { 1907 1.1 elric krb5_warnx(context, "pkinit mapping file line %lu " 1908 1.1 elric "missing \":\" :%s", 1909 1.1 elric lineno, buf); 1910 1.1 elric continue; 1911 1.1 elric } 1912 1.1 elric *subject_name++ = '\0'; 1913 1.1 elric 1914 1.1 elric ret = add_principal_mapping(context, p, subject_name); 1915 1.1 elric if (ret) { 1916 1.1 elric krb5_warn(context, ret, "failed to add line %lu \":\" :%s\n", 1917 1.1 elric lineno, buf); 1918 1.1 elric continue; 1919 1.1 elric } 1920 1.1 elric } 1921 1.1 elric 1922 1.1 elric fclose(f); 1923 1.1 elric } 1924 1.2 christos 1925 1.1 elric /* 1926 1.1 elric * 1927 1.1 elric */ 1928 1.1 elric 1929 1.1 elric krb5_error_code 1930 1.1 elric krb5_kdc_pk_initialize(krb5_context context, 1931 1.1 elric krb5_kdc_configuration *config, 1932 1.1 elric const char *user_id, 1933 1.1 elric const char *anchors, 1934 1.1 elric char **pool, 1935 1.1 elric char **revoke_list) 1936 1.1 elric { 1937 1.1 elric const char *file; 1938 1.1 elric char *fn = NULL; 1939 1.1 elric krb5_error_code ret; 1940 1.1 elric 1941 1.1 elric file = krb5_config_get_string(context, NULL, 1942 1.1 elric "libdefaults", "moduli", NULL); 1943 1.1 elric 1944 1.1 elric ret = _krb5_parse_moduli(context, file, &moduli); 1945 1.1 elric if (ret) 1946 1.1 elric krb5_err(context, 1, ret, "PKINIT: failed to load modidi file"); 1947 1.1 elric 1948 1.1 elric principal_mappings.len = 0; 1949 1.1 elric principal_mappings.val = NULL; 1950 1.1 elric 1951 1.1 elric ret = _krb5_pk_load_id(context, 1952 1.1 elric &kdc_identity, 1953 1.1 elric user_id, 1954 1.1 elric anchors, 1955 1.1 elric pool, 1956 1.1 elric revoke_list, 1957 1.1 elric NULL, 1958 1.1 elric NULL, 1959 1.1 elric NULL); 1960 1.1 elric if (ret) { 1961 1.1 elric krb5_warn(context, ret, "PKINIT: "); 1962 1.1 elric config->enable_pkinit = 0; 1963 1.1 elric return ret; 1964 1.1 elric } 1965 1.1 elric 1966 1.1 elric { 1967 1.1 elric hx509_query *q; 1968 1.1 elric hx509_cert cert; 1969 1.2 christos 1970 1.1 elric ret = hx509_query_alloc(context->hx509ctx, &q); 1971 1.1 elric if (ret) { 1972 1.1 elric krb5_warnx(context, "PKINIT: out of memory"); 1973 1.1 elric return ENOMEM; 1974 1.1 elric } 1975 1.2 christos 1976 1.1 elric hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 1977 1.1 elric if (config->pkinit_kdc_friendly_name) 1978 1.1 elric hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); 1979 1.2 christos 1980 1.1 elric ret = hx509_certs_find(context->hx509ctx, 1981 1.1 elric kdc_identity->certs, 1982 1.1 elric q, 1983 1.1 elric &cert); 1984 1.1 elric hx509_query_free(context->hx509ctx, q); 1985 1.1 elric if (ret == 0) { 1986 1.1 elric if (hx509_cert_check_eku(context->hx509ctx, cert, 1987 1.1 elric &asn1_oid_id_pkkdcekuoid, 0)) { 1988 1.1 elric hx509_name name; 1989 1.1 elric char *str; 1990 1.1 elric ret = hx509_cert_get_subject(cert, &name); 1991 1.1 elric if (ret == 0) { 1992 1.1 elric hx509_name_to_string(name, &str); 1993 1.1 elric krb5_warnx(context, "WARNING Found KDC certificate (%s)" 1994 1.1 elric "is missing the PK-INIT KDC EKU, this is bad for " 1995 1.1 elric "interoperability.", str); 1996 1.1 elric hx509_name_free(&name); 1997 1.1 elric free(str); 1998 1.1 elric } 1999 1.1 elric } 2000 1.1 elric hx509_cert_free(cert); 2001 1.1 elric } else 2002 1.1 elric krb5_warnx(context, "PKINIT: failed to find a signing " 2003 1.1 elric "certifiate with a public key"); 2004 1.1 elric } 2005 1.1 elric 2006 1.1 elric if (krb5_config_get_bool_default(context, 2007 1.1 elric NULL, 2008 1.1 elric FALSE, 2009 1.1 elric "kdc", 2010 1.1 elric "pkinit_allow_proxy_certificate", 2011 1.1 elric NULL)) 2012 1.1 elric config->pkinit_allow_proxy_certs = 1; 2013 1.1 elric 2014 1.1 elric file = krb5_config_get_string(context, 2015 1.1 elric NULL, 2016 1.1 elric "kdc", 2017 1.1 elric "pkinit_mappings_file", 2018 1.1 elric NULL); 2019 1.1 elric if (file == NULL) { 2020 1.2 christos int aret; 2021 1.2 christos 2022 1.2 christos aret = asprintf(&fn, "%s/pki-mapping", hdb_db_dir(context)); 2023 1.2 christos if (aret == -1) { 2024 1.2 christos krb5_warnx(context, "PKINIT: out of memory"); 2025 1.2 christos return ENOMEM; 2026 1.2 christos } 2027 1.2 christos 2028 1.1 elric file = fn; 2029 1.1 elric } 2030 1.1 elric 2031 1.1 elric load_mappings(context, file); 2032 1.1 elric if (fn) 2033 1.1 elric free(fn); 2034 1.1 elric 2035 1.1 elric return 0; 2036 1.1 elric } 2037 1.1 elric 2038 1.1 elric #endif /* PKINIT */ 2039