1 /* 2 * COPYRIGHT (C) 2006,2007 3 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN 4 * ALL RIGHTS RESERVED 5 * 6 * Permission is granted to use, copy, create derivative works 7 * and redistribute this software and such derivative works 8 * for any purpose, so long as the name of The University of 9 * Michigan is not used in any advertising or publicity 10 * pertaining to the use of distribution of this software 11 * without specific, written prior authorization. If the 12 * above copyright notice or any other identification of the 13 * University of Michigan is included in any copy of any 14 * portion of this software, then the disclaimer below must 15 * also be included. 16 * 17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGES. 29 */ 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <errno.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <ctype.h> 37 #include <assert.h> 38 39 #include "pkinit.h" 40 41 #define FAKECERT 42 43 const krb5_octet_data 44 dh_oid = { 0, 7, (unsigned char *)"\x2A\x86\x48\xce\x3e\x02\x01" }; 45 46 47 krb5_error_code 48 pkinit_init_req_opts(pkinit_req_opts **reqopts) 49 { 50 krb5_error_code retval = ENOMEM; 51 pkinit_req_opts *opts = NULL; 52 53 *reqopts = NULL; 54 opts = (pkinit_req_opts *) calloc(1, sizeof(pkinit_req_opts)); 55 if (opts == NULL) 56 return retval; 57 58 opts->require_eku = 1; 59 opts->accept_secondary_eku = 0; 60 opts->allow_upn = 0; 61 opts->dh_or_rsa = DH_PROTOCOL; 62 opts->require_crl_checking = 0; 63 opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS; 64 opts->win2k_target = 0; 65 opts->win2k_require_cksum = 0; 66 67 *reqopts = opts; 68 69 return 0; 70 } 71 72 void 73 pkinit_fini_req_opts(pkinit_req_opts *opts) 74 { 75 if (opts != NULL) 76 free(opts); 77 return; 78 } 79 80 krb5_error_code 81 pkinit_init_plg_opts(pkinit_plg_opts **plgopts) 82 { 83 krb5_error_code retval = ENOMEM; 84 pkinit_plg_opts *opts = NULL; 85 86 *plgopts = NULL; 87 opts = (pkinit_plg_opts *) calloc(1, sizeof(pkinit_plg_opts)); 88 if (opts == NULL) 89 return retval; 90 91 opts->require_eku = 1; 92 opts->accept_secondary_eku = 0; 93 opts->dh_or_rsa = DH_PROTOCOL; 94 opts->allow_upn = 0; 95 opts->require_crl_checking = 0; 96 97 opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS; 98 99 *plgopts = opts; 100 101 return 0; 102 } 103 104 void 105 pkinit_fini_plg_opts(pkinit_plg_opts *opts) 106 { 107 if (opts != NULL) 108 free(opts); 109 return; 110 } 111 112 void 113 free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) 114 { 115 if (*in == NULL) return; 116 if ((*in)->signedAuthPack.data != NULL) 117 free((*in)->signedAuthPack.data); 118 if ((*in)->trustedCertifiers != NULL) 119 free_krb5_external_principal_identifier(&(*in)->trustedCertifiers); 120 if ((*in)->kdcPkId.data != NULL) 121 free((*in)->kdcPkId.data); 122 free(*in); 123 } 124 125 void 126 free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in) 127 { 128 if (*in == NULL) return; 129 if ((*in)->signedAuthPack.data != NULL) 130 free((*in)->signedAuthPack.data); 131 if ((*in)->kdcCert.data != NULL) 132 free((*in)->kdcCert.data); 133 if ((*in)->encryptionCert.data != NULL) 134 free((*in)->encryptionCert.data); 135 if ((*in)->trustedCertifiers != NULL) 136 free_krb5_trusted_ca(&(*in)->trustedCertifiers); 137 free(*in); 138 } 139 140 void 141 free_krb5_reply_key_pack(krb5_reply_key_pack **in) 142 { 143 if (*in == NULL) return; 144 if ((*in)->replyKey.contents != NULL) 145 free((*in)->replyKey.contents); 146 if ((*in)->asChecksum.contents != NULL) 147 free((*in)->asChecksum.contents); 148 free(*in); 149 } 150 151 void 152 free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in) 153 { 154 if (*in == NULL) return; 155 if ((*in)->replyKey.contents != NULL) 156 free((*in)->replyKey.contents); 157 free(*in); 158 } 159 160 void 161 free_krb5_auth_pack(krb5_auth_pack **in) 162 { 163 if ((*in) == NULL) return; 164 if ((*in)->clientPublicValue != NULL) { 165 if ((*in)->clientPublicValue->algorithm.algorithm.data != NULL) 166 free((*in)->clientPublicValue->algorithm.algorithm.data); 167 if ((*in)->clientPublicValue->algorithm.parameters.data != NULL) 168 free((*in)->clientPublicValue->algorithm.parameters.data); 169 if ((*in)->clientPublicValue->subjectPublicKey.data != NULL) 170 free((*in)->clientPublicValue->subjectPublicKey.data); 171 free((*in)->clientPublicValue); 172 } 173 if ((*in)->pkAuthenticator.paChecksum.contents != NULL) 174 free((*in)->pkAuthenticator.paChecksum.contents); 175 if ((*in)->supportedCMSTypes != NULL) 176 free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes)); 177 free(*in); 178 } 179 180 void 181 free_krb5_auth_pack_draft9(krb5_context context, 182 krb5_auth_pack_draft9 **in) 183 { 184 if ((*in) == NULL) return; 185 krb5_free_principal(context, (*in)->pkAuthenticator.kdcName); 186 free(*in); 187 } 188 189 void 190 free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) 191 { 192 if (*in == NULL) return; 193 switch ((*in)->choice) { 194 case choice_pa_pk_as_rep_dhInfo: 195 if ((*in)->u.dh_Info.dhSignedData.data != NULL) 196 free((*in)->u.dh_Info.dhSignedData.data); 197 break; 198 case choice_pa_pk_as_rep_encKeyPack: 199 if ((*in)->u.encKeyPack.data != NULL) 200 free((*in)->u.encKeyPack.data); 201 break; 202 default: 203 break; 204 } 205 free(*in); 206 } 207 208 void 209 free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in) 210 { 211 if (*in == NULL) return; 212 if ((*in)->u.encKeyPack.data != NULL) 213 free((*in)->u.encKeyPack.data); 214 free(*in); 215 } 216 217 void 218 free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in) 219 { 220 int i = 0; 221 if (*in == NULL) return; 222 while ((*in)[i] != NULL) { 223 if ((*in)[i]->subjectName.data != NULL) 224 free((*in)[i]->subjectName.data); 225 if ((*in)[i]->issuerAndSerialNumber.data != NULL) 226 free((*in)[i]->issuerAndSerialNumber.data); 227 if ((*in)[i]->subjectKeyIdentifier.data != NULL) 228 free((*in)[i]->subjectKeyIdentifier.data); 229 free((*in)[i]); 230 i++; 231 } 232 free(*in); 233 } 234 235 void 236 free_krb5_trusted_ca(krb5_trusted_ca ***in) 237 { 238 int i = 0; 239 if (*in == NULL) return; 240 while ((*in)[i] != NULL) { 241 switch((*in)[i]->choice) { 242 case choice_trusted_cas_principalName: 243 break; 244 case choice_trusted_cas_caName: 245 if ((*in)[i]->u.caName.data != NULL) 246 free((*in)[i]->u.caName.data); 247 break; 248 case choice_trusted_cas_issuerAndSerial: 249 if ((*in)[i]->u.issuerAndSerial.data != NULL) 250 free((*in)[i]->u.issuerAndSerial.data); 251 break; 252 case choice_trusted_cas_UNKNOWN: 253 break; 254 } 255 free((*in)[i]); 256 i++; 257 } 258 free(*in); 259 } 260 261 void 262 free_krb5_typed_data(krb5_typed_data ***in) 263 { 264 int i = 0; 265 if (*in == NULL) return; 266 while ((*in)[i] != NULL) { 267 if ((*in)[i]->data != NULL) 268 free((*in)[i]->data); 269 free((*in)[i]); 270 i++; 271 } 272 free(*in); 273 } 274 275 void 276 free_krb5_algorithm_identifier(krb5_algorithm_identifier *in) 277 { 278 if (in == NULL) 279 return; 280 if (in->algorithm.data != NULL) 281 free(in->algorithm.data); 282 if (in->parameters.data != NULL) 283 free(in->parameters.data); 284 free(in); 285 } 286 287 void 288 free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in) 289 { 290 int i; 291 if (in == NULL || *in == NULL) 292 return; 293 for (i = 0; (*in)[i] != NULL; i++) { 294 free_krb5_algorithm_identifier((*in)[i]); 295 } 296 free(*in); 297 } 298 299 void 300 free_krb5_subject_pk_info(krb5_subject_pk_info **in) 301 { 302 if ((*in) == NULL) return; 303 if ((*in)->algorithm.parameters.data != NULL) 304 free((*in)->algorithm.parameters.data); 305 if ((*in)->subjectPublicKey.data != NULL) 306 free((*in)->subjectPublicKey.data); 307 free(*in); 308 } 309 310 void 311 free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in) 312 { 313 if (*in == NULL) return; 314 if ((*in)->subjectPublicKey.data != NULL) 315 free((*in)->subjectPublicKey.data); 316 free(*in); 317 } 318 319 void 320 init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) 321 { 322 (*in) = malloc(sizeof(krb5_pa_pk_as_req)); 323 if ((*in) == NULL) return; 324 (*in)->signedAuthPack.data = NULL; 325 (*in)->signedAuthPack.length = 0; 326 (*in)->trustedCertifiers = NULL; 327 (*in)->kdcPkId.data = NULL; 328 (*in)->kdcPkId.length = 0; 329 } 330 331 void 332 init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in) 333 { 334 (*in) = malloc(sizeof(krb5_pa_pk_as_req_draft9)); 335 if ((*in) == NULL) return; 336 (*in)->signedAuthPack.data = NULL; 337 (*in)->signedAuthPack.length = 0; 338 (*in)->trustedCertifiers = NULL; 339 (*in)->kdcCert.data = NULL; 340 (*in)->kdcCert.length = 0; 341 (*in)->encryptionCert.data = NULL; 342 (*in)->encryptionCert.length = 0; 343 } 344 345 void 346 init_krb5_reply_key_pack(krb5_reply_key_pack **in) 347 { 348 (*in) = malloc(sizeof(krb5_reply_key_pack)); 349 if ((*in) == NULL) return; 350 (*in)->replyKey.contents = NULL; 351 (*in)->replyKey.length = 0; 352 (*in)->asChecksum.contents = NULL; 353 (*in)->asChecksum.length = 0; 354 } 355 356 void 357 init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in) 358 { 359 (*in) = malloc(sizeof(krb5_reply_key_pack_draft9)); 360 if ((*in) == NULL) return; 361 (*in)->replyKey.contents = NULL; 362 (*in)->replyKey.length = 0; 363 } 364 365 void 366 init_krb5_auth_pack(krb5_auth_pack **in) 367 { 368 (*in) = malloc(sizeof(krb5_auth_pack)); 369 if ((*in) == NULL) return; 370 (*in)->clientPublicValue = NULL; 371 (*in)->supportedCMSTypes = NULL; 372 (*in)->clientDHNonce.length = 0; 373 (*in)->clientDHNonce.data = NULL; 374 (*in)->pkAuthenticator.paChecksum.contents = NULL; 375 } 376 377 void 378 init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in) 379 { 380 (*in) = malloc(sizeof(krb5_auth_pack_draft9)); 381 if ((*in) == NULL) return; 382 (*in)->clientPublicValue = NULL; 383 } 384 385 void 386 init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) 387 { 388 (*in) = malloc(sizeof(krb5_pa_pk_as_rep)); 389 if ((*in) == NULL) return; 390 (*in)->u.dh_Info.serverDHNonce.length = 0; 391 (*in)->u.dh_Info.serverDHNonce.data = NULL; 392 (*in)->u.dh_Info.dhSignedData.length = 0; 393 (*in)->u.dh_Info.dhSignedData.data = NULL; 394 (*in)->u.encKeyPack.length = 0; 395 (*in)->u.encKeyPack.data = NULL; 396 } 397 398 void 399 init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in) 400 { 401 (*in) = malloc(sizeof(krb5_pa_pk_as_rep_draft9)); 402 if ((*in) == NULL) return; 403 (*in)->u.dhSignedData.length = 0; 404 (*in)->u.dhSignedData.data = NULL; 405 (*in)->u.encKeyPack.length = 0; 406 (*in)->u.encKeyPack.data = NULL; 407 } 408 409 void 410 init_krb5_typed_data(krb5_typed_data **in) 411 { 412 (*in) = malloc(sizeof(krb5_typed_data)); 413 if ((*in) == NULL) return; 414 (*in)->type = 0; 415 (*in)->length = 0; 416 (*in)->data = NULL; 417 } 418 419 void 420 init_krb5_subject_pk_info(krb5_subject_pk_info **in) 421 { 422 (*in) = malloc(sizeof(krb5_subject_pk_info)); 423 if ((*in) == NULL) return; 424 (*in)->algorithm.parameters.data = NULL; 425 (*in)->algorithm.parameters.length = 0; 426 (*in)->subjectPublicKey.data = NULL; 427 (*in)->subjectPublicKey.length = 0; 428 } 429 430 krb5_error_code 431 pkinit_copy_krb5_octet_data(krb5_octet_data *dst, const krb5_octet_data *src) 432 { 433 if (dst == NULL || src == NULL) 434 return EINVAL; 435 if (src->data == NULL) { 436 dst->data = NULL; 437 dst->length = 0; 438 return 0; 439 } 440 dst->data = malloc(src->length); 441 if (dst->data == NULL) 442 return ENOMEM; 443 (void) memcpy(dst->data, src->data, src->length); 444 dst->length = src->length; 445 return 0; 446 } 447 448 /* debugging functions */ 449 void 450 print_buffer(unsigned char *buf, unsigned int len) 451 { 452 int i = 0; 453 /* Solaris Kerberos: len is unsigned (lint) */ 454 if (len == 0) 455 return; 456 457 for (i = 0; i < len; i++) 458 pkiDebug("%02x ", buf[i]); 459 pkiDebug("\n"); 460 } 461 462 void 463 print_buffer_bin(unsigned char *buf, unsigned int len, char *filename) 464 { 465 FILE *f = NULL; 466 int i = 0; 467 468 /* Solaris Kerberos: len is unsigned (lint) */ 469 if (len == 0 || filename == NULL) 470 return; 471 472 if ((f = fopen(filename, "w")) == NULL) 473 return; 474 475 for (i = 0; i < len; i++) 476 (void) fputc(buf[i], f); 477 478 (void) fclose(f); 479 } 480