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 43const krb5_octet_data 44 dh_oid = { 0, 7, (unsigned char *)"\x2A\x86\x48\xce\x3e\x02\x01" }; 45 46 47krb5_error_code 48pkinit_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 72void 73pkinit_fini_req_opts(pkinit_req_opts *opts) 74{ 75 if (opts != NULL) 76 free(opts); 77 return; 78} 79 80krb5_error_code 81pkinit_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 104void 105pkinit_fini_plg_opts(pkinit_plg_opts *opts) 106{ 107 if (opts != NULL) 108 free(opts); 109 return; 110} 111 112void 113free_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 125void 126free_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 140void 141free_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 151void 152free_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 160void 161free_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 180void 181free_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 189void 190free_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 208void 209free_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 217void 218free_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 235void 236free_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 261void 262free_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 275void 276free_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 287void 288free_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 299void 300free_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 310void 311free_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 319void 320init_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 331void 332init_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 345void 346init_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 356void 357init_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 365void 366init_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 377void 378init_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 385void 386init_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 398void 399init_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 409void 410init_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 419void 420init_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 430krb5_error_code 431pkinit_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 */ 449void 450print_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 462void 463print_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