1178825Sdfr/* 2233294Sstas * Copyright (c) 2004 - 2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825Sdfr 36178825Sdfr/** 37178825Sdfr * @page page_print Hx509 printing functions 38178825Sdfr * 39178825Sdfr * See the library functions here: @ref hx509_print 40178825Sdfr */ 41178825Sdfr 42178825Sdfrstruct hx509_validate_ctx_data { 43178825Sdfr int flags; 44178825Sdfr hx509_vprint_func vprint_func; 45178825Sdfr void *ctx; 46178825Sdfr}; 47178825Sdfr 48178825Sdfrstruct cert_status { 49178825Sdfr unsigned int selfsigned:1; 50178825Sdfr unsigned int isca:1; 51178825Sdfr unsigned int isproxy:1; 52178825Sdfr unsigned int haveSAN:1; 53178825Sdfr unsigned int haveIAN:1; 54178825Sdfr unsigned int haveSKI:1; 55178825Sdfr unsigned int haveAKI:1; 56178825Sdfr unsigned int haveCRLDP:1; 57178825Sdfr}; 58178825Sdfr 59178825Sdfr 60178825Sdfr/* 61178825Sdfr * 62178825Sdfr */ 63178825Sdfr 64178825Sdfrstatic int 65178825SdfrTime2string(const Time *T, char **str) 66178825Sdfr{ 67178825Sdfr time_t t; 68178825Sdfr char *s; 69178825Sdfr struct tm *tm; 70178825Sdfr 71178825Sdfr *str = NULL; 72178825Sdfr t = _hx509_Time2time_t(T); 73178825Sdfr tm = gmtime (&t); 74178825Sdfr s = malloc(30); 75178825Sdfr if (s == NULL) 76178825Sdfr return ENOMEM; 77178825Sdfr strftime(s, 30, "%Y-%m-%d %H:%M:%S", tm); 78178825Sdfr *str = s; 79178825Sdfr return 0; 80178825Sdfr} 81178825Sdfr 82178825Sdfr/** 83178825Sdfr * Helper function to print on stdout for: 84178825Sdfr * - hx509_oid_print(), 85178825Sdfr * - hx509_bitstring_print(), 86178825Sdfr * - hx509_validate_ctx_set_print(). 87178825Sdfr * 88178825Sdfr * @param ctx the context to the print function. If the ctx is NULL, 89178825Sdfr * stdout is used. 90178825Sdfr * @param fmt the printing format. 91178825Sdfr * @param va the argumet list. 92178825Sdfr * 93178825Sdfr * @ingroup hx509_print 94178825Sdfr */ 95178825Sdfr 96178825Sdfrvoid 97178825Sdfrhx509_print_stdout(void *ctx, const char *fmt, va_list va) 98178825Sdfr{ 99178825Sdfr FILE *f = ctx; 100178825Sdfr if (f == NULL) 101178825Sdfr f = stdout; 102178825Sdfr vfprintf(f, fmt, va); 103178825Sdfr} 104178825Sdfr 105178825Sdfrstatic void 106178825Sdfrprint_func(hx509_vprint_func func, void *ctx, const char *fmt, ...) 107178825Sdfr{ 108178825Sdfr va_list va; 109178825Sdfr va_start(va, fmt); 110178825Sdfr (*func)(ctx, fmt, va); 111178825Sdfr va_end(va); 112178825Sdfr} 113178825Sdfr 114178825Sdfr/** 115178825Sdfr * Print a oid to a string. 116233294Sstas * 117178825Sdfr * @param oid oid to print 118178825Sdfr * @param str allocated string, free with hx509_xfree(). 119178825Sdfr * 120178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 121178825Sdfr * 122178825Sdfr * @ingroup hx509_print 123178825Sdfr */ 124178825Sdfr 125178825Sdfrint 126178825Sdfrhx509_oid_sprint(const heim_oid *oid, char **str) 127178825Sdfr{ 128178825Sdfr return der_print_heim_oid(oid, '.', str); 129178825Sdfr} 130178825Sdfr 131178825Sdfr/** 132178825Sdfr * Print a oid using a hx509_vprint_func function. To print to stdout 133178825Sdfr * use hx509_print_stdout(). 134233294Sstas * 135178825Sdfr * @param oid oid to print 136178825Sdfr * @param func hx509_vprint_func to print with. 137178825Sdfr * @param ctx context variable to hx509_vprint_func function. 138178825Sdfr * 139178825Sdfr * @ingroup hx509_print 140178825Sdfr */ 141178825Sdfr 142178825Sdfrvoid 143178825Sdfrhx509_oid_print(const heim_oid *oid, hx509_vprint_func func, void *ctx) 144178825Sdfr{ 145178825Sdfr char *str; 146178825Sdfr hx509_oid_sprint(oid, &str); 147178825Sdfr print_func(func, ctx, "%s", str); 148178825Sdfr free(str); 149178825Sdfr} 150178825Sdfr 151178825Sdfr/** 152178825Sdfr * Print a bitstring using a hx509_vprint_func function. To print to 153178825Sdfr * stdout use hx509_print_stdout(). 154233294Sstas * 155178825Sdfr * @param b bit string to print. 156178825Sdfr * @param func hx509_vprint_func to print with. 157178825Sdfr * @param ctx context variable to hx509_vprint_func function. 158178825Sdfr * 159178825Sdfr * @ingroup hx509_print 160178825Sdfr */ 161178825Sdfr 162178825Sdfrvoid 163178825Sdfrhx509_bitstring_print(const heim_bit_string *b, 164178825Sdfr hx509_vprint_func func, void *ctx) 165178825Sdfr{ 166233294Sstas size_t i; 167178825Sdfr print_func(func, ctx, "\tlength: %d\n\t", b->length); 168178825Sdfr for (i = 0; i < (b->length + 7) / 8; i++) 169178825Sdfr print_func(func, ctx, "%02x%s%s", 170233294Sstas ((unsigned char *)b->data)[i], 171178825Sdfr i < (b->length - 7) / 8 172178825Sdfr && (i == 0 || (i % 16) != 15) ? ":" : "", 173178825Sdfr i != 0 && (i % 16) == 15 ? 174178825Sdfr (i <= ((b->length + 7) / 8 - 2) ? "\n\t" : "\n"):""); 175178825Sdfr} 176178825Sdfr 177178825Sdfr/** 178178825Sdfr * Print certificate usage for a certificate to a string. 179233294Sstas * 180178825Sdfr * @param context A hx509 context. 181178825Sdfr * @param c a certificate print the keyusage for. 182178825Sdfr * @param s the return string with the keysage printed in to, free 183178825Sdfr * with hx509_xfree(). 184178825Sdfr * 185178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 186178825Sdfr * 187178825Sdfr * @ingroup hx509_print 188178825Sdfr */ 189178825Sdfr 190178825Sdfrint 191178825Sdfrhx509_cert_keyusage_print(hx509_context context, hx509_cert c, char **s) 192178825Sdfr{ 193178825Sdfr KeyUsage ku; 194178825Sdfr char buf[256]; 195178825Sdfr int ret; 196178825Sdfr 197178825Sdfr *s = NULL; 198178825Sdfr 199178825Sdfr ret = _hx509_cert_get_keyusage(context, c, &ku); 200178825Sdfr if (ret) 201178825Sdfr return ret; 202178825Sdfr unparse_flags(KeyUsage2int(ku), asn1_KeyUsage_units(), buf, sizeof(buf)); 203178825Sdfr *s = strdup(buf); 204178825Sdfr if (*s == NULL) { 205178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 206178825Sdfr return ENOMEM; 207178825Sdfr } 208178825Sdfr 209178825Sdfr return 0; 210178825Sdfr} 211178825Sdfr 212178825Sdfr/* 213178825Sdfr * 214178825Sdfr */ 215178825Sdfr 216178825Sdfrstatic void 217178825Sdfrvalidate_vprint(void *c, const char *fmt, va_list va) 218178825Sdfr{ 219178825Sdfr hx509_validate_ctx ctx = c; 220178825Sdfr if (ctx->vprint_func == NULL) 221178825Sdfr return; 222178825Sdfr (ctx->vprint_func)(ctx->ctx, fmt, va); 223178825Sdfr} 224178825Sdfr 225178825Sdfrstatic void 226178825Sdfrvalidate_print(hx509_validate_ctx ctx, int flags, const char *fmt, ...) 227178825Sdfr{ 228178825Sdfr va_list va; 229178825Sdfr if ((ctx->flags & flags) == 0) 230178825Sdfr return; 231178825Sdfr va_start(va, fmt); 232178825Sdfr validate_vprint(ctx, fmt, va); 233178825Sdfr va_end(va); 234178825Sdfr} 235178825Sdfr 236233294Sstas/* 237178825Sdfr * Dont Care, SHOULD critical, SHOULD NOT critical, MUST critical, 238178825Sdfr * MUST NOT critical 239178825Sdfr */ 240178825Sdfrenum critical_flag { D_C = 0, S_C, S_N_C, M_C, M_N_C }; 241178825Sdfr 242178825Sdfrstatic int 243178825Sdfrcheck_Null(hx509_validate_ctx ctx, 244178825Sdfr struct cert_status *status, 245178825Sdfr enum critical_flag cf, const Extension *e) 246178825Sdfr{ 247178825Sdfr switch(cf) { 248178825Sdfr case D_C: 249178825Sdfr break; 250178825Sdfr case S_C: 251178825Sdfr if (!e->critical) 252178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 253178825Sdfr "\tCritical not set on SHOULD\n"); 254178825Sdfr break; 255178825Sdfr case S_N_C: 256178825Sdfr if (e->critical) 257178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 258178825Sdfr "\tCritical set on SHOULD NOT\n"); 259178825Sdfr break; 260178825Sdfr case M_C: 261178825Sdfr if (!e->critical) 262178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 263178825Sdfr "\tCritical not set on MUST\n"); 264178825Sdfr break; 265178825Sdfr case M_N_C: 266178825Sdfr if (e->critical) 267178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 268178825Sdfr "\tCritical set on MUST NOT\n"); 269178825Sdfr break; 270178825Sdfr default: 271178825Sdfr _hx509_abort("internal check_Null state error"); 272178825Sdfr } 273178825Sdfr return 0; 274178825Sdfr} 275178825Sdfr 276178825Sdfrstatic int 277233294Sstascheck_subjectKeyIdentifier(hx509_validate_ctx ctx, 278178825Sdfr struct cert_status *status, 279178825Sdfr enum critical_flag cf, 280178825Sdfr const Extension *e) 281178825Sdfr{ 282178825Sdfr SubjectKeyIdentifier si; 283178825Sdfr size_t size; 284178825Sdfr int ret; 285178825Sdfr 286178825Sdfr status->haveSKI = 1; 287178825Sdfr check_Null(ctx, status, cf, e); 288178825Sdfr 289233294Sstas ret = decode_SubjectKeyIdentifier(e->extnValue.data, 290178825Sdfr e->extnValue.length, 291178825Sdfr &si, &size); 292178825Sdfr if (ret) { 293178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 294178825Sdfr "Decoding SubjectKeyIdentifier failed: %d", ret); 295178825Sdfr return 1; 296178825Sdfr } 297178825Sdfr if (size != e->extnValue.length) { 298178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 299178825Sdfr "Decoding SKI ahve extra bits on the end"); 300178825Sdfr return 1; 301178825Sdfr } 302178825Sdfr if (si.length == 0) 303178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 304178825Sdfr "SKI is too short (0 bytes)"); 305178825Sdfr if (si.length > 20) 306178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 307178825Sdfr "SKI is too long"); 308178825Sdfr 309178825Sdfr { 310178825Sdfr char *id; 311178825Sdfr hex_encode(si.data, si.length, &id); 312178825Sdfr if (id) { 313178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 314178825Sdfr "\tsubject key id: %s\n", id); 315178825Sdfr free(id); 316178825Sdfr } 317178825Sdfr } 318178825Sdfr 319178825Sdfr free_SubjectKeyIdentifier(&si); 320178825Sdfr 321178825Sdfr return 0; 322178825Sdfr} 323178825Sdfr 324178825Sdfrstatic int 325233294Sstascheck_authorityKeyIdentifier(hx509_validate_ctx ctx, 326178825Sdfr struct cert_status *status, 327178825Sdfr enum critical_flag cf, 328178825Sdfr const Extension *e) 329178825Sdfr{ 330178825Sdfr AuthorityKeyIdentifier ai; 331178825Sdfr size_t size; 332178825Sdfr int ret; 333178825Sdfr 334178825Sdfr status->haveAKI = 1; 335178825Sdfr check_Null(ctx, status, cf, e); 336178825Sdfr 337233294Sstas ret = decode_AuthorityKeyIdentifier(e->extnValue.data, 338178825Sdfr e->extnValue.length, 339178825Sdfr &ai, &size); 340178825Sdfr if (ret) { 341178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 342178825Sdfr "Decoding AuthorityKeyIdentifier failed: %d", ret); 343178825Sdfr return 1; 344178825Sdfr } 345178825Sdfr if (size != e->extnValue.length) { 346178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 347178825Sdfr "Decoding SKI ahve extra bits on the end"); 348178825Sdfr return 1; 349178825Sdfr } 350178825Sdfr 351178825Sdfr if (ai.keyIdentifier) { 352178825Sdfr char *id; 353178825Sdfr hex_encode(ai.keyIdentifier->data, ai.keyIdentifier->length, &id); 354178825Sdfr if (id) { 355178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 356178825Sdfr "\tauthority key id: %s\n", id); 357178825Sdfr free(id); 358178825Sdfr } 359178825Sdfr } 360178825Sdfr 361178825Sdfr return 0; 362178825Sdfr} 363178825Sdfr 364233294Sstasstatic int 365233294Sstascheck_extKeyUsage(hx509_validate_ctx ctx, 366233294Sstas struct cert_status *status, 367233294Sstas enum critical_flag cf, 368233294Sstas const Extension *e) 369233294Sstas{ 370233294Sstas ExtKeyUsage eku; 371233294Sstas size_t size, i; 372233294Sstas int ret; 373178825Sdfr 374233294Sstas check_Null(ctx, status, cf, e); 375233294Sstas 376233294Sstas ret = decode_ExtKeyUsage(e->extnValue.data, 377233294Sstas e->extnValue.length, 378233294Sstas &eku, &size); 379233294Sstas if (ret) { 380233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 381233294Sstas "Decoding ExtKeyUsage failed: %d", ret); 382233294Sstas return 1; 383233294Sstas } 384233294Sstas if (size != e->extnValue.length) { 385233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 386233294Sstas "Padding data in EKU"); 387233294Sstas free_ExtKeyUsage(&eku); 388233294Sstas return 1; 389233294Sstas } 390233294Sstas if (eku.len == 0) { 391233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 392233294Sstas "ExtKeyUsage length is 0"); 393233294Sstas return 1; 394233294Sstas } 395233294Sstas 396233294Sstas for (i = 0; i < eku.len; i++) { 397233294Sstas char *str; 398233294Sstas ret = der_print_heim_oid (&eku.val[i], '.', &str); 399233294Sstas if (ret) { 400233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 401233294Sstas "\tEKU: failed to print oid %d", i); 402233294Sstas free_ExtKeyUsage(&eku); 403233294Sstas return 1; 404233294Sstas } 405233294Sstas validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 406233294Sstas "\teku-%d: %s\n", i, str);; 407233294Sstas free(str); 408233294Sstas } 409233294Sstas 410233294Sstas free_ExtKeyUsage(&eku); 411233294Sstas 412233294Sstas return 0; 413233294Sstas} 414233294Sstas 415178825Sdfrstatic int 416178825Sdfrcheck_pkinit_san(hx509_validate_ctx ctx, heim_any *a) 417178825Sdfr{ 418178825Sdfr KRB5PrincipalName kn; 419178825Sdfr unsigned i; 420178825Sdfr size_t size; 421178825Sdfr int ret; 422178825Sdfr 423178825Sdfr ret = decode_KRB5PrincipalName(a->data, a->length, &kn, &size); 424178825Sdfr if (ret) { 425178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 426178825Sdfr "Decoding kerberos name in SAN failed: %d", ret); 427178825Sdfr return 1; 428178825Sdfr } 429178825Sdfr 430178825Sdfr if (size != a->length) { 431178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 432178825Sdfr "Decoding kerberos name have extra bits on the end"); 433178825Sdfr return 1; 434178825Sdfr } 435178825Sdfr 436178825Sdfr /* print kerberos principal, add code to quote / within components */ 437178825Sdfr for (i = 0; i < kn.principalName.name_string.len; i++) { 438233294Sstas validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", 439178825Sdfr kn.principalName.name_string.val[i]); 440178825Sdfr if (i + 1 < kn.principalName.name_string.len) 441178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "/"); 442178825Sdfr } 443178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "@"); 444178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", kn.realm); 445178825Sdfr 446178825Sdfr free_KRB5PrincipalName(&kn); 447178825Sdfr return 0; 448178825Sdfr} 449178825Sdfr 450178825Sdfrstatic int 451178825Sdfrcheck_utf8_string_san(hx509_validate_ctx ctx, heim_any *a) 452178825Sdfr{ 453178825Sdfr PKIXXmppAddr jid; 454178825Sdfr size_t size; 455178825Sdfr int ret; 456178825Sdfr 457178825Sdfr ret = decode_PKIXXmppAddr(a->data, a->length, &jid, &size); 458178825Sdfr if (ret) { 459178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 460178825Sdfr "Decoding JID in SAN failed: %d", ret); 461178825Sdfr return 1; 462178825Sdfr } 463178825Sdfr 464178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", jid); 465178825Sdfr free_PKIXXmppAddr(&jid); 466178825Sdfr 467178825Sdfr return 0; 468178825Sdfr} 469178825Sdfr 470178825Sdfrstatic int 471178825Sdfrcheck_altnull(hx509_validate_ctx ctx, heim_any *a) 472178825Sdfr{ 473178825Sdfr return 0; 474178825Sdfr} 475178825Sdfr 476178825Sdfrstatic int 477233294Sstascheck_CRLDistributionPoints(hx509_validate_ctx ctx, 478178825Sdfr struct cert_status *status, 479178825Sdfr enum critical_flag cf, 480178825Sdfr const Extension *e) 481178825Sdfr{ 482178825Sdfr CRLDistributionPoints dp; 483178825Sdfr size_t size; 484233294Sstas int ret; 485233294Sstas size_t i; 486178825Sdfr 487178825Sdfr check_Null(ctx, status, cf, e); 488178825Sdfr 489233294Sstas ret = decode_CRLDistributionPoints(e->extnValue.data, 490178825Sdfr e->extnValue.length, 491178825Sdfr &dp, &size); 492178825Sdfr if (ret) { 493178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 494178825Sdfr "Decoding CRL Distribution Points failed: %d\n", ret); 495178825Sdfr return 1; 496178825Sdfr } 497178825Sdfr 498178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "CRL Distribution Points:\n"); 499178825Sdfr for (i = 0 ; i < dp.len; i++) { 500178825Sdfr if (dp.val[i].distributionPoint) { 501178825Sdfr DistributionPointName dpname; 502178825Sdfr heim_any *data = dp.val[i].distributionPoint; 503233294Sstas size_t j; 504233294Sstas 505178825Sdfr ret = decode_DistributionPointName(data->data, data->length, 506178825Sdfr &dpname, NULL); 507178825Sdfr if (ret) { 508233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 509178825Sdfr "Failed to parse CRL Distribution Point Name: %d\n", ret); 510178825Sdfr continue; 511178825Sdfr } 512178825Sdfr 513178825Sdfr switch (dpname.element) { 514178825Sdfr case choice_DistributionPointName_fullName: 515178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "Fullname:\n"); 516233294Sstas 517178825Sdfr for (j = 0 ; j < dpname.u.fullName.len; j++) { 518178825Sdfr char *s; 519178825Sdfr GeneralName *name = &dpname.u.fullName.val[j]; 520178825Sdfr 521178825Sdfr ret = hx509_general_name_unparse(name, &s); 522178825Sdfr if (ret == 0 && s != NULL) { 523178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " %s\n", s); 524178825Sdfr free(s); 525178825Sdfr } 526178825Sdfr } 527178825Sdfr break; 528178825Sdfr case choice_DistributionPointName_nameRelativeToCRLIssuer: 529178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 530178825Sdfr "Unknown nameRelativeToCRLIssuer"); 531178825Sdfr break; 532178825Sdfr default: 533178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 534178825Sdfr "Unknown DistributionPointName"); 535178825Sdfr break; 536178825Sdfr } 537178825Sdfr free_DistributionPointName(&dpname); 538178825Sdfr } 539178825Sdfr } 540178825Sdfr free_CRLDistributionPoints(&dp); 541178825Sdfr 542178825Sdfr status->haveCRLDP = 1; 543178825Sdfr 544178825Sdfr return 0; 545178825Sdfr} 546178825Sdfr 547178825Sdfr 548178825Sdfrstruct { 549178825Sdfr const char *name; 550233294Sstas const heim_oid *oid; 551178825Sdfr int (*func)(hx509_validate_ctx, heim_any *); 552233294Sstas} altname_types[] = { 553233294Sstas { "pk-init", &asn1_oid_id_pkinit_san, check_pkinit_san }, 554233294Sstas { "jabber", &asn1_oid_id_pkix_on_xmppAddr, check_utf8_string_san }, 555233294Sstas { "dns-srv", &asn1_oid_id_pkix_on_dnsSRV, check_altnull }, 556233294Sstas { "card-id", &asn1_oid_id_uspkicommon_card_id, check_altnull }, 557233294Sstas { "Microsoft NT-PRINCIPAL-NAME", &asn1_oid_id_pkinit_ms_san, check_utf8_string_san } 558178825Sdfr}; 559178825Sdfr 560178825Sdfrstatic int 561178825Sdfrcheck_altName(hx509_validate_ctx ctx, 562178825Sdfr struct cert_status *status, 563178825Sdfr const char *name, 564178825Sdfr enum critical_flag cf, 565178825Sdfr const Extension *e) 566178825Sdfr{ 567178825Sdfr GeneralNames gn; 568178825Sdfr size_t size; 569233294Sstas int ret; 570233294Sstas size_t i; 571178825Sdfr 572178825Sdfr check_Null(ctx, status, cf, e); 573178825Sdfr 574178825Sdfr if (e->extnValue.length == 0) { 575178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 576178825Sdfr "%sAltName empty, not allowed", name); 577178825Sdfr return 1; 578178825Sdfr } 579178825Sdfr ret = decode_GeneralNames(e->extnValue.data, e->extnValue.length, 580178825Sdfr &gn, &size); 581178825Sdfr if (ret) { 582178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 583233294Sstas "\tret = %d while decoding %s GeneralNames\n", 584178825Sdfr ret, name); 585178825Sdfr return 1; 586178825Sdfr } 587178825Sdfr if (gn.len == 0) { 588178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 589178825Sdfr "%sAltName generalName empty, not allowed\n", name); 590178825Sdfr return 1; 591178825Sdfr } 592178825Sdfr 593178825Sdfr for (i = 0; i < gn.len; i++) { 594178825Sdfr switch (gn.val[i].element) { 595178825Sdfr case choice_GeneralName_otherName: { 596178825Sdfr unsigned j; 597178825Sdfr 598178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 599178825Sdfr "%sAltName otherName ", name); 600178825Sdfr 601233294Sstas for (j = 0; j < sizeof(altname_types)/sizeof(altname_types[0]); j++) { 602233294Sstas if (der_heim_oid_cmp(altname_types[j].oid, 603178825Sdfr &gn.val[i].u.otherName.type_id) != 0) 604178825Sdfr continue; 605233294Sstas 606233294Sstas validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s: ", 607233294Sstas altname_types[j].name); 608233294Sstas (*altname_types[j].func)(ctx, &gn.val[i].u.otherName.value); 609178825Sdfr break; 610178825Sdfr } 611233294Sstas if (j == sizeof(altname_types)/sizeof(altname_types[0])) { 612178825Sdfr hx509_oid_print(&gn.val[i].u.otherName.type_id, 613178825Sdfr validate_vprint, ctx); 614178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " unknown"); 615178825Sdfr } 616178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\n"); 617178825Sdfr break; 618178825Sdfr } 619178825Sdfr default: { 620178825Sdfr char *s; 621178825Sdfr ret = hx509_general_name_unparse(&gn.val[i], &s); 622178825Sdfr if (ret) { 623178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 624178825Sdfr "ret = %d unparsing GeneralName\n", ret); 625178825Sdfr return 1; 626178825Sdfr } 627178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s\n", s); 628178825Sdfr free(s); 629178825Sdfr break; 630178825Sdfr } 631178825Sdfr } 632178825Sdfr } 633178825Sdfr 634178825Sdfr free_GeneralNames(&gn); 635178825Sdfr 636178825Sdfr return 0; 637178825Sdfr} 638178825Sdfr 639178825Sdfrstatic int 640178825Sdfrcheck_subjectAltName(hx509_validate_ctx ctx, 641178825Sdfr struct cert_status *status, 642178825Sdfr enum critical_flag cf, 643178825Sdfr const Extension *e) 644178825Sdfr{ 645178825Sdfr status->haveSAN = 1; 646178825Sdfr return check_altName(ctx, status, "subject", cf, e); 647178825Sdfr} 648178825Sdfr 649178825Sdfrstatic int 650178825Sdfrcheck_issuerAltName(hx509_validate_ctx ctx, 651178825Sdfr struct cert_status *status, 652178825Sdfr enum critical_flag cf, 653178825Sdfr const Extension *e) 654178825Sdfr{ 655178825Sdfr status->haveIAN = 1; 656178825Sdfr return check_altName(ctx, status, "issuer", cf, e); 657178825Sdfr} 658178825Sdfr 659178825Sdfr 660178825Sdfrstatic int 661233294Sstascheck_basicConstraints(hx509_validate_ctx ctx, 662178825Sdfr struct cert_status *status, 663233294Sstas enum critical_flag cf, 664178825Sdfr const Extension *e) 665178825Sdfr{ 666178825Sdfr BasicConstraints b; 667178825Sdfr size_t size; 668178825Sdfr int ret; 669178825Sdfr 670178825Sdfr check_Null(ctx, status, cf, e); 671233294Sstas 672178825Sdfr ret = decode_BasicConstraints(e->extnValue.data, e->extnValue.length, 673178825Sdfr &b, &size); 674178825Sdfr if (ret) { 675178825Sdfr printf("\tret = %d while decoding BasicConstraints\n", ret); 676178825Sdfr return 0; 677178825Sdfr } 678178825Sdfr if (size != e->extnValue.length) 679178825Sdfr printf("\tlength of der data isn't same as extension\n"); 680178825Sdfr 681178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 682178825Sdfr "\tis %sa CA\n", b.cA && *b.cA ? "" : "NOT "); 683178825Sdfr if (b.pathLenConstraint) 684178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 685178825Sdfr "\tpathLenConstraint: %d\n", *b.pathLenConstraint); 686178825Sdfr 687178825Sdfr if (b.cA) { 688178825Sdfr if (*b.cA) { 689178825Sdfr if (!e->critical) 690178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 691178825Sdfr "Is a CA and not BasicConstraints CRITICAL\n"); 692178825Sdfr status->isca = 1; 693178825Sdfr } 694178825Sdfr else 695178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 696178825Sdfr "cA is FALSE, not allowed to be\n"); 697178825Sdfr } 698178825Sdfr free_BasicConstraints(&b); 699178825Sdfr 700178825Sdfr return 0; 701178825Sdfr} 702178825Sdfr 703178825Sdfrstatic int 704233294Sstascheck_proxyCertInfo(hx509_validate_ctx ctx, 705178825Sdfr struct cert_status *status, 706233294Sstas enum critical_flag cf, 707178825Sdfr const Extension *e) 708178825Sdfr{ 709178825Sdfr check_Null(ctx, status, cf, e); 710178825Sdfr status->isproxy = 1; 711178825Sdfr return 0; 712178825Sdfr} 713178825Sdfr 714178825Sdfrstatic int 715233294Sstascheck_authorityInfoAccess(hx509_validate_ctx ctx, 716178825Sdfr struct cert_status *status, 717233294Sstas enum critical_flag cf, 718178825Sdfr const Extension *e) 719178825Sdfr{ 720178825Sdfr AuthorityInfoAccessSyntax aia; 721178825Sdfr size_t size; 722233294Sstas int ret; 723233294Sstas size_t i; 724178825Sdfr 725178825Sdfr check_Null(ctx, status, cf, e); 726178825Sdfr 727233294Sstas ret = decode_AuthorityInfoAccessSyntax(e->extnValue.data, 728178825Sdfr e->extnValue.length, 729178825Sdfr &aia, &size); 730178825Sdfr if (ret) { 731178825Sdfr printf("\tret = %d while decoding AuthorityInfoAccessSyntax\n", ret); 732178825Sdfr return 0; 733178825Sdfr } 734178825Sdfr 735178825Sdfr for (i = 0; i < aia.len; i++) { 736178825Sdfr char *str; 737178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 738178825Sdfr "\ttype: "); 739178825Sdfr hx509_oid_print(&aia.val[i].accessMethod, validate_vprint, ctx); 740178825Sdfr hx509_general_name_unparse(&aia.val[i].accessLocation, &str); 741178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 742178825Sdfr "\n\tdirname: %s\n", str); 743178825Sdfr free(str); 744178825Sdfr } 745178825Sdfr free_AuthorityInfoAccessSyntax(&aia); 746178825Sdfr 747178825Sdfr return 0; 748178825Sdfr} 749178825Sdfr 750178825Sdfr/* 751178825Sdfr * 752178825Sdfr */ 753178825Sdfr 754178825Sdfrstruct { 755178825Sdfr const char *name; 756233294Sstas const heim_oid *oid; 757233294Sstas int (*func)(hx509_validate_ctx ctx, 758178825Sdfr struct cert_status *status, 759233294Sstas enum critical_flag cf, 760178825Sdfr const Extension *); 761178825Sdfr enum critical_flag cf; 762178825Sdfr} check_extension[] = { 763233294Sstas#define ext(name, checkname) #name, &asn1_oid_id_x509_ce_##name, check_##checkname 764178825Sdfr { ext(subjectDirectoryAttributes, Null), M_N_C }, 765178825Sdfr { ext(subjectKeyIdentifier, subjectKeyIdentifier), M_N_C }, 766178825Sdfr { ext(keyUsage, Null), S_C }, 767178825Sdfr { ext(subjectAltName, subjectAltName), M_N_C }, 768178825Sdfr { ext(issuerAltName, issuerAltName), S_N_C }, 769178825Sdfr { ext(basicConstraints, basicConstraints), D_C }, 770178825Sdfr { ext(cRLNumber, Null), M_N_C }, 771178825Sdfr { ext(cRLReason, Null), M_N_C }, 772178825Sdfr { ext(holdInstructionCode, Null), M_N_C }, 773178825Sdfr { ext(invalidityDate, Null), M_N_C }, 774178825Sdfr { ext(deltaCRLIndicator, Null), M_C }, 775178825Sdfr { ext(issuingDistributionPoint, Null), M_C }, 776178825Sdfr { ext(certificateIssuer, Null), M_C }, 777178825Sdfr { ext(nameConstraints, Null), M_C }, 778178825Sdfr { ext(cRLDistributionPoints, CRLDistributionPoints), S_N_C }, 779233294Sstas { ext(certificatePolicies, Null), 0 }, 780178825Sdfr { ext(policyMappings, Null), M_N_C }, 781178825Sdfr { ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C }, 782178825Sdfr { ext(policyConstraints, Null), D_C }, 783233294Sstas { ext(extKeyUsage, extKeyUsage), D_C }, 784178825Sdfr { ext(freshestCRL, Null), M_N_C }, 785178825Sdfr { ext(inhibitAnyPolicy, Null), M_C }, 786178825Sdfr#undef ext 787233294Sstas#define ext(name, checkname) #name, &asn1_oid_id_pkix_pe_##name, check_##checkname 788178825Sdfr { ext(proxyCertInfo, proxyCertInfo), M_C }, 789178825Sdfr { ext(authorityInfoAccess, authorityInfoAccess), M_C }, 790178825Sdfr#undef ext 791233294Sstas { "US Fed PKI - PIV Interim", &asn1_oid_id_uspkicommon_piv_interim, 792178825Sdfr check_Null, D_C }, 793233294Sstas { "Netscape cert comment", &asn1_oid_id_netscape_cert_comment, 794178825Sdfr check_Null, D_C }, 795233294Sstas { NULL, NULL, NULL, 0 } 796178825Sdfr}; 797178825Sdfr 798178825Sdfr/** 799178825Sdfr * Allocate a hx509 validation/printing context. 800233294Sstas * 801178825Sdfr * @param context A hx509 context. 802178825Sdfr * @param ctx a new allocated hx509 validation context, free with 803178825Sdfr * hx509_validate_ctx_free(). 804178825Sdfr 805178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 806178825Sdfr * 807178825Sdfr * @ingroup hx509_print 808178825Sdfr */ 809178825Sdfr 810178825Sdfrint 811178825Sdfrhx509_validate_ctx_init(hx509_context context, hx509_validate_ctx *ctx) 812178825Sdfr{ 813178825Sdfr *ctx = malloc(sizeof(**ctx)); 814178825Sdfr if (*ctx == NULL) 815178825Sdfr return ENOMEM; 816178825Sdfr memset(*ctx, 0, sizeof(**ctx)); 817178825Sdfr return 0; 818178825Sdfr} 819178825Sdfr 820178825Sdfr/** 821178825Sdfr * Set the printing functions for the validation context. 822233294Sstas * 823178825Sdfr * @param ctx a hx509 valication context. 824178825Sdfr * @param func the printing function to usea. 825178825Sdfr * @param c the context variable to the printing function. 826178825Sdfr * 827178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 828178825Sdfr * 829178825Sdfr * @ingroup hx509_print 830178825Sdfr */ 831178825Sdfr 832178825Sdfrvoid 833233294Sstashx509_validate_ctx_set_print(hx509_validate_ctx ctx, 834178825Sdfr hx509_vprint_func func, 835178825Sdfr void *c) 836178825Sdfr{ 837178825Sdfr ctx->vprint_func = func; 838178825Sdfr ctx->ctx = c; 839178825Sdfr} 840178825Sdfr 841178825Sdfr/** 842178825Sdfr * Add flags to control the behaivor of the hx509_validate_cert() 843178825Sdfr * function. 844233294Sstas * 845178825Sdfr * @param ctx A hx509 validation context. 846178825Sdfr * @param flags flags to add to the validation context. 847178825Sdfr * 848178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 849178825Sdfr * 850178825Sdfr * @ingroup hx509_print 851178825Sdfr */ 852178825Sdfr 853178825Sdfrvoid 854178825Sdfrhx509_validate_ctx_add_flags(hx509_validate_ctx ctx, int flags) 855178825Sdfr{ 856178825Sdfr ctx->flags |= flags; 857178825Sdfr} 858178825Sdfr 859178825Sdfr/** 860178825Sdfr * Free an hx509 validate context. 861233294Sstas * 862178825Sdfr * @param ctx the hx509 validate context to free. 863178825Sdfr * 864178825Sdfr * @ingroup hx509_print 865178825Sdfr */ 866178825Sdfr 867178825Sdfrvoid 868178825Sdfrhx509_validate_ctx_free(hx509_validate_ctx ctx) 869178825Sdfr{ 870178825Sdfr free(ctx); 871178825Sdfr} 872178825Sdfr 873178825Sdfr/** 874178825Sdfr * Validate/Print the status of the certificate. 875233294Sstas * 876178825Sdfr * @param context A hx509 context. 877178825Sdfr * @param ctx A hx509 validation context. 878178825Sdfr * @param cert the cerificate to validate/print. 879178825Sdfr 880178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 881178825Sdfr * 882178825Sdfr * @ingroup hx509_print 883178825Sdfr */ 884178825Sdfr 885178825Sdfrint 886178825Sdfrhx509_validate_cert(hx509_context context, 887178825Sdfr hx509_validate_ctx ctx, 888178825Sdfr hx509_cert cert) 889178825Sdfr{ 890178825Sdfr Certificate *c = _hx509_get_cert(cert); 891178825Sdfr TBSCertificate *t = &c->tbsCertificate; 892178825Sdfr hx509_name issuer, subject; 893178825Sdfr char *str; 894178825Sdfr struct cert_status status; 895178825Sdfr int ret; 896178825Sdfr 897178825Sdfr memset(&status, 0, sizeof(status)); 898178825Sdfr 899178825Sdfr if (_hx509_cert_get_version(c) != 3) 900178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 901178825Sdfr "Not version 3 certificate\n"); 902233294Sstas 903178825Sdfr if ((t->version == NULL || *t->version < 2) && t->extensions) 904178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 905178825Sdfr "Not version 3 certificate with extensions\n"); 906233294Sstas 907178825Sdfr if (_hx509_cert_get_version(c) >= 3 && t->extensions == NULL) 908178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 909178825Sdfr "Version 3 certificate without extensions\n"); 910178825Sdfr 911178825Sdfr ret = hx509_cert_get_subject(cert, &subject); 912178825Sdfr if (ret) abort(); 913178825Sdfr hx509_name_to_string(subject, &str); 914178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 915178825Sdfr "subject name: %s\n", str); 916178825Sdfr free(str); 917178825Sdfr 918178825Sdfr ret = hx509_cert_get_issuer(cert, &issuer); 919178825Sdfr if (ret) abort(); 920178825Sdfr hx509_name_to_string(issuer, &str); 921178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 922178825Sdfr "issuer name: %s\n", str); 923178825Sdfr free(str); 924178825Sdfr 925178825Sdfr if (hx509_name_cmp(subject, issuer) == 0) { 926178825Sdfr status.selfsigned = 1; 927178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 928178825Sdfr "\tis a self-signed certificate\n"); 929178825Sdfr } 930178825Sdfr 931178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 932178825Sdfr "Validity:\n"); 933178825Sdfr 934178825Sdfr Time2string(&t->validity.notBefore, &str); 935178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotBefore %s\n", str); 936178825Sdfr free(str); 937178825Sdfr Time2string(&t->validity.notAfter, &str); 938178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotAfter %s\n", str); 939178825Sdfr free(str); 940178825Sdfr 941178825Sdfr if (t->extensions) { 942233294Sstas size_t i, j; 943178825Sdfr 944178825Sdfr if (t->extensions->len == 0) { 945178825Sdfr validate_print(ctx, 946178825Sdfr HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE, 947178825Sdfr "The empty extensions list is not " 948178825Sdfr "allowed by PKIX\n"); 949178825Sdfr } 950178825Sdfr 951178825Sdfr for (i = 0; i < t->extensions->len; i++) { 952178825Sdfr 953178825Sdfr for (j = 0; check_extension[j].name; j++) 954233294Sstas if (der_heim_oid_cmp(check_extension[j].oid, 955178825Sdfr &t->extensions->val[i].extnID) == 0) 956178825Sdfr break; 957178825Sdfr if (check_extension[j].name == NULL) { 958178825Sdfr int flags = HX509_VALIDATE_F_VERBOSE; 959178825Sdfr if (t->extensions->val[i].critical) 960178825Sdfr flags |= HX509_VALIDATE_F_VALIDATE; 961178825Sdfr validate_print(ctx, flags, "don't know what "); 962178825Sdfr if (t->extensions->val[i].critical) 963178825Sdfr validate_print(ctx, flags, "and is CRITICAL "); 964178825Sdfr if (ctx->flags & flags) 965233294Sstas hx509_oid_print(&t->extensions->val[i].extnID, 966178825Sdfr validate_vprint, ctx); 967178825Sdfr validate_print(ctx, flags, " is\n"); 968178825Sdfr continue; 969178825Sdfr } 970178825Sdfr validate_print(ctx, 971178825Sdfr HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE, 972178825Sdfr "checking extention: %s\n", 973178825Sdfr check_extension[j].name); 974178825Sdfr (*check_extension[j].func)(ctx, 975178825Sdfr &status, 976178825Sdfr check_extension[j].cf, 977178825Sdfr &t->extensions->val[i]); 978178825Sdfr } 979178825Sdfr } else 980178825Sdfr validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "no extentions\n"); 981233294Sstas 982178825Sdfr if (status.isca) { 983178825Sdfr if (!status.haveSKI) 984233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 985178825Sdfr "CA certificate have no SubjectKeyIdentifier\n"); 986178825Sdfr 987178825Sdfr } else { 988178825Sdfr if (!status.haveAKI) 989233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 990178825Sdfr "Is not CA and doesn't have " 991178825Sdfr "AuthorityKeyIdentifier\n"); 992178825Sdfr } 993178825Sdfr 994233294Sstas 995178825Sdfr if (!status.haveSKI) 996233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 997178825Sdfr "Doesn't have SubjectKeyIdentifier\n"); 998178825Sdfr 999178825Sdfr if (status.isproxy && status.isca) 1000233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 1001178825Sdfr "Proxy and CA at the same time!\n"); 1002178825Sdfr 1003178825Sdfr if (status.isproxy) { 1004178825Sdfr if (status.haveSAN) 1005233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 1006178825Sdfr "Proxy and have SAN\n"); 1007178825Sdfr if (status.haveIAN) 1008233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 1009178825Sdfr "Proxy and have IAN\n"); 1010178825Sdfr } 1011178825Sdfr 1012178825Sdfr if (hx509_name_is_null_p(subject) && !status.haveSAN) 1013233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 1014178825Sdfr "NULL subject DN and doesn't have a SAN\n"); 1015178825Sdfr 1016178825Sdfr if (!status.selfsigned && !status.haveCRLDP) 1017233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 1018178825Sdfr "Not a CA nor PROXY and doesn't have" 1019178825Sdfr "CRL Dist Point\n"); 1020178825Sdfr 1021178825Sdfr if (status.selfsigned) { 1022178825Sdfr ret = _hx509_verify_signature_bitstring(context, 1023233294Sstas cert, 1024178825Sdfr &c->signatureAlgorithm, 1025178825Sdfr &c->tbsCertificate._save, 1026178825Sdfr &c->signatureValue); 1027178825Sdfr if (ret == 0) 1028233294Sstas validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 1029178825Sdfr "Self-signed certificate was self-signed\n"); 1030178825Sdfr else 1031233294Sstas validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 1032178825Sdfr "Self-signed certificate NOT really self-signed!\n"); 1033178825Sdfr } 1034178825Sdfr 1035178825Sdfr hx509_name_free(&subject); 1036178825Sdfr hx509_name_free(&issuer); 1037178825Sdfr 1038178825Sdfr return 0; 1039178825Sdfr} 1040