static int certificate_verify_callback(int preverify_ok, X509_STORE_CTX * ctx) { char fnm[FILE_PATH_SIZE]; DIR * dir = NULL; int err = 0; int found = 0; snprintf(fnm, sizeof(fnm), "%s/ssl", tcf_dir); if (!err && (dir = opendir(fnm)) == NULL) err = errno; while (!err && !found) { int l = 0; X509 * cert = NULL; FILE * fp = NULL; struct dirent * ent = readdir(dir); if (ent == NULL) break; l = strlen(ent->d_name); if (l < 5 || strcmp(ent->d_name + l -5 , ".cert") != 0) continue; snprintf(fnm, sizeof(fnm), "%s/ssl/%s", tcf_dir, ent->d_name); if (!err && (fp = fopen(fnm, "r")) == NULL) err = errno; if (!err && (cert = PEM_read_X509(fp, NULL, NULL, NULL)) == NULL) err = set_ssl_errno(); if (!err && fclose(fp) != 0) err = errno; if (!err && X509_cmp(X509_STORE_CTX_get_current_cert(ctx), cert) == 0) found = 1; } if (dir != NULL && closedir(dir) < 0 && !err) err = errno; if (err) trace(LOG_ALWAYS, "Cannot read certificate %s: %s", fnm, errno_to_str(err)); else if (!found) trace(LOG_ALWAYS, "Authentication failure: invalid certificate"); return err == 0 && found; }
int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) { CMS_CertificateChoices *cch; STACK_OF(CMS_CertificateChoices) **pcerts; int i; pcerts = cms_get0_certificate_choices(cms); if (!pcerts) return 0; for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { cch = sk_CMS_CertificateChoices_value(*pcerts, i); if (cch->type == CMS_CERTCHOICE_CERT) { if (!X509_cmp(cch->d.certificate, cert)) { CMSerr(CMS_F_CMS_ADD0_CERT, CMS_R_CERTIFICATE_ALREADY_PRESENT); return 0; } } } cch = CMS_add0_CertificateChoices(cms); if (!cch) return 0; cch->type = CMS_CERTCHOICE_CERT; cch->d.certificate = cert; return 1; }
/* * Returns: 0 if successfully matching certificate to TLSA record bytes * -1 if there was no match */ int ca_constraint(const SSL *con, const X509 *tlsa_cert, int usage) { STACK_OF(X509) *cert_chain = NULL; cert_chain = SSL_get_peer_cert_chain(con); BIO_printf(b_err, "DANE ca_constraint() chain of %d length\n", sk_X509_num(cert_chain)); int ret_val; ret_val = 0; if (cert_chain != NULL) { int i; for (i = 0; i < sk_X509_num(cert_chain); i++) { BIO_printf(b_err, "DANE ca_constraint() cert %d of %d.\n", i, sk_X509_num(cert_chain)); /* BIO_printf(b_err, "DANE CXN Certificate\n"); PEM_write_bio_X509(b_err, sk_X509_value(cert_chain, i)); BIO_printf(b_err, "DANE TLSA Certificate\n"); PEM_write_bio_X509(b_err, tlsa_cert); */ if (X509_cmp(tlsa_cert, sk_X509_value(cert_chain, i)) < 0) { ret_val = -1; BIO_printf(b_err, "DANE ca_constraint() certificates didn't match\n"); } else { BIO_printf(b_err, "DANE ca_constraint() certificates matches\n"); if (usage == 0) return 0; /* For this to be a trust anchor, the following characteristics applies: * 1. Issuer name is the same as Subject name * 2. Either or both * a) the Key Usage field is set to keyCertSign (KU_KEY_CERT_SIGN) * b) the basicConstraints field has the attribute cA set to True (EXFLAG_CA) */ X509_NAME *issuer_name, *subject_name; issuer_name = X509_get_issuer_name(tlsa_cert); subject_name = X509_get_subject_name(tlsa_cert); if (X509_name_cmp(issuer_name, subject_name) == 0) { BIO_printf(b_err, "DANE issuer == subject\n"); if (tlsa_cert->ex_flags & EXFLAG_CA) { BIO_printf(b_err, "DANE ca_constraint() EXFLAG_CA set\n"); return 0; } /* Left unimplemented since I don't have a CA certificate to work with.*/ int ext_count, j; ext_count = X509_get_ext_count(tlsa_cert); BIO_printf(b_err, "DANE ca_constraint() %d certificate extensions\n"); } else { return 0; } } } } return ret_val; }
static int test_resp_signer(void) { OCSP_BASICRESP *bs = NULL; X509 *signer = NULL, *tmp; EVP_PKEY *key = NULL; STACK_OF(X509) *extra_certs = NULL; int ret = 0; /* * Test a response with no certs at all; get the signer from the * extra certs given to OCSP_resp_get0_signer(). */ bs = make_dummy_resp(); extra_certs = sk_X509_new_null(); if (!TEST_ptr(bs) || !TEST_ptr(extra_certs) || !TEST_true(get_cert_and_key(&signer, &key)) || !TEST_true(sk_X509_push(extra_certs, signer)) || !TEST_true(OCSP_basic_sign(bs, signer, key, EVP_sha1(), NULL, OCSP_NOCERTS))) goto err; if (!TEST_true(OCSP_resp_get0_signer(bs, &tmp, extra_certs)) || !TEST_int_eq(X509_cmp(tmp, signer), 0)) goto err; OCSP_BASICRESP_free(bs); /* Do it again but include the signer cert */ bs = make_dummy_resp(); tmp = NULL; if (!TEST_ptr(bs) || !TEST_true(OCSP_basic_sign(bs, signer, key, EVP_sha1(), NULL, 0))) goto err; if (!TEST_true(OCSP_resp_get0_signer(bs, &tmp, NULL)) || !TEST_int_eq(X509_cmp(tmp, signer), 0)) goto err; ret = 1; err: OCSP_BASICRESP_free(bs); sk_X509_free(extra_certs); X509_free(signer); EVP_PKEY_free(key); return ret; }
static int ssl_certificate_compare(SSLCertificate *cert_a, SSLCertificate *cert_b) { if (cert_a == NULL || cert_b == NULL) return FALSE; else if (!X509_cmp(cert_a->x509_cert, cert_b->x509_cert)) return TRUE; else return FALSE; }
bool SSLConnection::checkCertCache() { unsigned char peermd[EVP_MAX_MD_SIZE]; unsigned int peermdlen; size_t i; if (!X509_digest (cert, EVP_sha1(), peermd, &peermdlen)) return false; for (i=0; i<Certs.size(); i++) { if (X509_cmp(Certs[i],peermd,peermdlen)) { DEBUGPRINT(D_SOCKET,("found cached cert at %d",i)); return true; } } return false; }
bool SSLConnection::checkCertDigest() { unsigned char peermd[EVP_MAX_MD_SIZE]; unsigned int peermdlen; X509 *c = NULL; bool pass = false; FILE *fp; buffer_t msg; buffer_init(&msg); /* expiration check */ if (X509_cmp_current_time (X509_get_notBefore (cert)) >= 0) { buffer_shrink(&msg,0); buffer_add_str(&msg,_("Server certificate is not yet valid."),-1); displayError.emit(&msg); buffer_free(&msg); return 0; } if (X509_cmp_current_time (X509_get_notAfter (cert)) <= 0) { buffer_shrink(&msg,0); buffer_add_str(&msg,_("Server certificate has expired."),-1); displayError.emit(&msg); buffer_free(&msg); return 0; } buffer_free(&msg); if ((fp = fopen (SSLCertFile, "rt")) == NULL) return false; if (!X509_digest (cert, EVP_sha1 (), peermd, &peermdlen)) { fclose (fp); return false; } while ((c = READ_X509_KEY (fp, &c)) != NULL) { pass = X509_cmp (c, peermd, peermdlen); if (pass) break; } X509_free(c); fclose (fp); return pass; }
//int service_cert_constraint(const SSL *con, const unsigned char *tlsa_bytes, int tlsa_len) { int service_cert_constraint(const X509 *con_cert, const X509 *tlsa_cert) { int ret_val; ret_val = 0; if (con_cert != NULL) { if (X509_cmp(tlsa_cert, con_cert) != 0) { ret_val = -1; BIO_printf(b_err, "DANE server_cert_constraint() certificates didn't match\n"); } else { BIO_printf(b_err, "DANE server_cert_constraint() certificates matches\n"); // Must return immediately in case there are non-matching certificates return 0; } } else BIO_printf(b_err,"DANE:no peer certificate available\n"); return ret_val; }
/* * Compare two X509 certificates. * return: * 1 - certificates are not NULL and equal * 0 - certificates are not NULL and differ * -1 - both certificates are NULL * -2 - x509_cert1 is NULL, x509_cert2 is not NULL * -3 - x509_cert1 in not NULL, x509_cert2 is NULL */ static int ssl_X509_cmp(X509 *x509_cert1, X509 *x509_cert2) { /* X509_cmp() will crash if any of its args are NULL */ if (x509_cert1 != NULL) { if (x509_cert2 == NULL) { return -3; /* x509_cert1 in not NULL, x509_cert2 is NULL */ } else { if (X509_cmp(x509_cert1, x509_cert2)) { return 0; /* certificates are differ */ } else { return 1; /* certificates are equal */ } } } else { if (x509_cert2 == NULL) { return -1; /* both certificates are NULL */ } else { return -2; /* x509_cert1 is NULL, x509_cert2 is not NULL */ } } }
int X509_verify_cert(X509_STORE_CTX *ctx) { X509 *x,*xtmp,*chain_ss=NULL; X509_NAME *xn; int depth,i,ok=0; int num; int (*cb)(); STACK_OF(X509) *sktmp=NULL; if (ctx->cert == NULL) { X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); return -1; } cb=ctx->verify_cb; /* first we make sure the chain we are going to build is * present and that the first entry is in place */ if (ctx->chain == NULL) { if ( ((ctx->chain=sk_X509_new_null()) == NULL) || (!sk_X509_push(ctx->chain,ctx->cert))) { X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); goto end; } CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509); ctx->last_untrusted=1; } /* We use a temporary STACK so we can chop and hack at it */ if (ctx->untrusted != NULL && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL) { X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); goto end; } num=sk_X509_num(ctx->chain); x=sk_X509_value(ctx->chain,num-1); depth=ctx->depth; for (;;) { /* If we have enough, we break */ if (depth < num) break; /* FIXME: If this happens, we should take * note of it and, if appropriate, use the * X509_V_ERR_CERT_CHAIN_TOO_LONG error * code later. */ /* If we are self signed, we break */ xn=X509_get_issuer_name(x); if (ctx->check_issued(ctx, x,x)) break; /* If we were passed a cert chain, use it first */ if (ctx->untrusted != NULL) { xtmp=find_issuer(ctx, sktmp,x); if (xtmp != NULL) { if (!sk_X509_push(ctx->chain,xtmp)) { X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); goto end; } CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509); sk_X509_delete_ptr(sktmp,xtmp); ctx->last_untrusted++; x=xtmp; num++; /* reparse the full chain for * the next one */ continue; } } break; } /* at this point, chain should contain a list of untrusted * certificates. We now need to add at least one trusted one, * if possible, otherwise we complain. */ /* Examine last certificate in chain and see if it * is self signed. */ i=sk_X509_num(ctx->chain); x=sk_X509_value(ctx->chain,i-1); xn = X509_get_subject_name(x); if (ctx->check_issued(ctx, x, x)) { /* we have a self signed certificate */ if (sk_X509_num(ctx->chain) == 1) { /* We have a single self signed certificate: see if * we can find it in the store. We must have an exact * match to avoid possible impersonation. */ ok = ctx->get_issuer(&xtmp, ctx, x); if ((ok <= 0) || X509_cmp(x, xtmp)) { ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; ctx->current_cert=x; ctx->error_depth=i-1; if (ok == 1) X509_free(xtmp); ok=cb(0,ctx); if (!ok) goto end; } else { /* We have a match: replace certificate with store version * so we get any trust settings. */ X509_free(x); x = xtmp; sk_X509_set(ctx->chain, i - 1, x); ctx->last_untrusted=0; } } else { /* extract and save self signed certificate for later use */ chain_ss=sk_X509_pop(ctx->chain); ctx->last_untrusted--; num--; x=sk_X509_value(ctx->chain,num-1); } } /* We now lookup certs from the certificate store */ for (;;) { /* If we have enough, we break */ if (depth < num) break; /* If we are self signed, we break */ xn=X509_get_issuer_name(x); if (ctx->check_issued(ctx,x,x)) break; ok = ctx->get_issuer(&xtmp, ctx, x); if (ok < 0) return ok; if (ok == 0) break; x = xtmp; if (!sk_X509_push(ctx->chain,x)) { X509_free(xtmp); X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); return 0; } num++; } /* we now have our chain, lets check it... */ xn=X509_get_issuer_name(x); /* Is last certificate looked up self signed? */ if (!ctx->check_issued(ctx,x,x)) { if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { if (ctx->last_untrusted >= num) ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; else ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; ctx->current_cert=x; } else { sk_X509_push(ctx->chain,chain_ss); num++; ctx->last_untrusted=num; ctx->current_cert=chain_ss; ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; chain_ss=NULL; } ctx->error_depth=num-1; ok=cb(0,ctx); if (!ok) goto end; } /* We have the chain complete: now we need to check its purpose */ ok = check_chain_extensions(ctx); if (!ok) goto end; /* The chain extensions are OK: check trust */ if (ctx->trust > 0) ok = check_trust(ctx); if (!ok) goto end; /* We may as well copy down any DSA parameters that are required */ X509_get_pubkey_parameters(NULL,ctx->chain); /* Check revocation status: we do this after copying parameters * because they may be needed for CRL signature verification. */ ok = ctx->check_revocation(ctx); if(!ok) goto end; /* At this point, we have a chain and just need to verify it */ if (ctx->verify != NULL) ok=ctx->verify(ctx); else ok=internal_verify(ctx); if (0) { end: X509_get_pubkey_parameters(NULL,ctx->chain); } if (sktmp != NULL) sk_X509_free(sktmp); if (chain_ss != NULL) X509_free(chain_ss); return ok; }
/*============================================================================ * OpcUa_P_OpenSSL_PKI_ValidateCertificate *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ValidateCertificate( OpcUa_PKIProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_Void* a_pCertificateStore, OpcUa_Int* a_pValidationCode /* Validation return codes from OpenSSL */ ) { OpcUa_P_OpenSSL_CertificateStore_Config* pCertificateStoreCfg; const unsigned char* p; X509* pX509Certificate = OpcUa_Null; STACK_OF(X509)* pX509Chain = OpcUa_Null; X509_STORE_CTX* verify_ctx = OpcUa_Null; /* holds data used during verification process */ char CertFile[MAX_PATH]; struct dirent **dirlist = NULL; int numCertificates = 0, i; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ValidateCertificate"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore); OpcUa_ReturnErrorIfArgumentNull(a_pValidationCode); pCertificateStoreCfg = (OpcUa_P_OpenSSL_CertificateStore_Config*)a_pProvider->Handle; /* convert DER encoded bytestring certificate to openssl X509 certificate */ p = a_pCertificate->Data; if(!(pX509Certificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } while(p < a_pCertificate->Data + a_pCertificate->Length) { X509* pX509AddCertificate; if(!(pX509AddCertificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Data + a_pCertificate->Length - p))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if(pX509Chain == NULL) { pX509Chain = sk_X509_new_null(); OpcUa_GotoErrorIfAllocFailed(pX509Chain); } if(!sk_X509_push(pX509Chain, pX509AddCertificate)) { X509_free(pX509AddCertificate); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } /* create verification context and initialize it */ if(!(verify_ctx = X509_STORE_CTX_new())) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } #if (OPENSSL_VERSION_NUMBER > 0x00907000L) if(X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } #else X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain); #endif if(X509_STORE_CTX_set_app_data(verify_ctx, pCertificateStoreCfg) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if((pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) == OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL_EXCEPT_SELF_SIGNED && !verify_ctx->check_issued(verify_ctx, pX509Certificate, pX509Certificate)) { /* set the flags of the store so that CRLs are consulted */ X509_STORE_CTX_set_flags(verify_ctx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* verify the certificate */ *a_pValidationCode = X509_V_OK; if(X509_verify_cert(verify_ctx) <= 0) { *a_pValidationCode = verify_ctx->error; switch(verify_ctx->error) { case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_CRL_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: { uStatus = OpcUa_BadCertificateTimeInvalid; break; } case X509_V_ERR_CERT_REVOKED: { uStatus = OpcUa_BadCertificateRevoked; break; } case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: { uStatus = OpcUa_BadCertificateUntrusted; break; } case X509_V_ERR_CERT_SIGNATURE_FAILURE: { uStatus = OpcUa_BadSecurityChecksFailed; break; } default: { uStatus = OpcUa_BadCertificateInvalid; } } OpcUa_GotoErrorIfBad(uStatus); } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REQUIRE_CHAIN_CERTIFICATE_IN_TRUST_LIST) { FILE* pCertificateFile; X509* pTrustCert; STACK_OF(X509)* chain; int trusted, n; chain = X509_STORE_CTX_get_chain(verify_ctx); trusted = 0; if(pCertificateStoreCfg->CertificateTrustListLocation == NULL || pCertificateStoreCfg->CertificateTrustListLocation[0] == '\0') { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } numCertificates = scandir(pCertificateStoreCfg->CertificateTrustListLocation, &dirlist, certificate_filter_der, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateTrustListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); /* read DER certificates */ pCertificateFile = fopen(CertFile, "r"); if(pCertificateFile == OpcUa_Null) { continue; /* ignore access errors */ } pTrustCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null); fclose(pCertificateFile); if(pTrustCert == OpcUa_Null) { continue; /* ignore parse errors */ } for(n = 0; n < sk_X509_num(chain); n++) { if (X509_cmp(sk_X509_value(chain, n), pTrustCert) == 0) break; } X509_free(pTrustCert); if(n < sk_X509_num(chain)) { trusted = 1; break; } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; if(!trusted) { uStatus = OpcUa_BadCertificateUntrusted; OpcUa_GotoErrorIfBad(uStatus); } } X509_STORE_CTX_free(verify_ctx); X509_free(pX509Certificate); if(pX509Chain != OpcUa_Null) { sk_X509_pop_free(pX509Chain, X509_free); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(dirlist != NULL) { for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); } if(verify_ctx != OpcUa_Null) { X509_STORE_CTX_free(verify_ctx); } if(pX509Certificate != OpcUa_Null) { X509_free(pX509Certificate); } if(pX509Chain != OpcUa_Null) { sk_X509_pop_free(pX509Chain, X509_free); } OpcUa_FinishErrorHandling; }
static int ldap_mapper_match_user(X509 *x509, const char *login, void *context) { int match_found = 0; int i=0; if ( 1 != ldap_get_certificate(login)){ DBG("ldap_get_certificate() failed"); match_found = 0; } else { /* TODO: maybe compare public keys instead of hashes */ while( i<certcnt && !match_found ) { #ifdef HAVE_NSS if ( x509 == ldap_x509[i]) { #else if ( 0 == X509_cmp(x509, ldap_x509[i])) { #endif DBG1("Certificate %d is matching", i); match_found = 1; } else { DBG1("Certificate %d is NOT matching", i); } i++; } if (certcnt) { #ifdef HAVE_NSS int rv; for (rv=0; rv<certcnt; rv++) if (ldap_x509[rv]) CERT_DestroyCertificate(ldap_x509[rv]); #endif free(ldap_x509); } certcnt=0; } return match_found; } static char * ldap_mapper_find_user(X509 *x509, void *context, int *match) { struct passwd *pw = NULL; char *found=NULL; setpwent(); while( (pw=getpwent()) !=NULL) { int res; DBG1("Trying to match certificate with user: '******'",pw->pw_name); res= ldap_mapper_match_user(x509,pw->pw_name,context); if (res) { DBG1("Certificate maps to user '%s'",pw->pw_name); found= clone_str(pw->pw_name); *match = 1; break; } else { DBG1("Certificate map to user '%s' failed",pw->pw_name); } } endpwent(); #ifdef false int res; res= ldap_mapper_match_user(x509,"wefel",context); if (res) { DBG("Certificate maps to user wefel"); found= clone_str("wefel"); } else { DBG("Certificate map to user wefel failed"); } #endif return found; } static mapper_module * init_mapper_st(scconf_block *blk, const char *name) { mapper_module *pt= malloc(sizeof(mapper_module)); if (!pt) return NULL; pt->name = name; pt->block = blk; pt->context = NULL; pt->entries = ldap_mapper_find_entries; pt->finder = ldap_mapper_find_user; pt->matcher = ldap_mapper_match_user; pt->deinit = mapper_module_end; return pt; }
/* * -1 if authentication failed * 1 if authentication succeeded * 2 if authentication succeeded, using parameter * -2 if authentication is delayed, don't error * No AuthStruct = everyone allowed */ int Auth_Check(aClient *cptr, anAuthStruct *as, char *para) { #ifdef AUTHENABLE_UNIXCRYPT extern char *crypt(); #endif #ifdef AUTHENABLE_SSL_CLIENTCERT X509 *x509_clientcert = NULL; X509 *x509_filecert = NULL; FILE *x509_f = NULL; #endif if (!as) return 1; switch (as->type) { case AUTHTYPE_PLAINTEXT: if (!para) return -1; /* plain text compare */ if (!strcmp(para, as->data)) return 2; else return -1; break; #ifdef AUTHENABLE_UNIXCRYPT case AUTHTYPE_UNIXCRYPT: if (!para) return -1; /* If our data is like 1 or none, we just let em through .. */ if (!(as->data[0] && as->data[1])) return 1; if (!strcmp(crypt(para, as->data), as->data)) return 2; else return -1; break; #endif case AUTHTYPE_MD5: return authcheck_md5(cptr, as, para); break; #ifdef AUTHENABLE_SHA1 case AUTHTYPE_SHA1: return authcheck_sha1(cptr, as, para); break; #endif #ifdef AUTHENABLE_RIPEMD160 case AUTHTYPE_RIPEMD160: return authcheck_ripemd160(cptr, as, para); #endif #ifdef AUTHENABLE_SSL_CLIENTCERT case AUTHTYPE_SSL_CLIENTCERT: if (!para) return -1; if (!cptr->ssl) return -1; x509_clientcert = SSL_get_peer_certificate((SSL *)cptr->ssl); if (!x509_clientcert) return -1; if (!(x509_f = fopen(as->data, "r"))) { X509_free(x509_clientcert); return -1; } x509_filecert = PEM_read_X509(x509_f, NULL, NULL, NULL); fclose(x509_f); if (!x509_filecert) { X509_free(x509_clientcert); return -1; } if (X509_cmp(x509_filecert, x509_clientcert) != 0) { X509_free(x509_clientcert); X509_free(x509_filecert); break; } X509_free(x509_clientcert); X509_free(x509_filecert); return 2; #endif } return -1; }
bool operator==(const Certificate& c1, const Certificate& c2) { return (X509_cmp(c1.x, c2.x) == 0 && c1.subject == c2.subject && /* c1.validity == c2.validity && */ c1.issuer == c2.issuer); }
static int test_cert_reparse(const uint8_t *der_bytes, size_t der_len) { CBS pkcs7; CBB cbb; STACK_OF(X509) *certs = sk_X509_new_null(); STACK_OF(X509) *certs2 = sk_X509_new_null(); uint8_t *result_data, *result2_data; size_t result_len, result2_len, i; CBS_init(&pkcs7, der_bytes, der_len); if (!PKCS7_get_certificates(certs, &pkcs7)) { fprintf(stderr, "PKCS7_get_certificates failed.\n"); return 0; } CBB_init(&cbb, der_len); if (!PKCS7_bundle_certificates(&cbb, certs) || !CBB_finish(&cbb, &result_data, &result_len)) { fprintf(stderr, "PKCS7_bundle_certificates failed.\n"); return 0; } CBS_init(&pkcs7, result_data, result_len); if (!PKCS7_get_certificates(certs2, &pkcs7)) { fprintf(stderr, "PKCS7_get_certificates reparse failed.\n"); return 0; } if (sk_X509_num(certs) != sk_X509_num(certs2)) { fprintf(stderr, "Number of certs in results differ.\n"); return 0; } for (i = 0; i < sk_X509_num(certs); i++) { X509 *a = sk_X509_value(certs, i); X509 *b = sk_X509_value(certs2, i); if (X509_cmp(a, b) != 0) { fprintf(stderr, "Certificate %u differs.\n", (unsigned) i); return 0; } } CBB_init(&cbb, der_len); if (!PKCS7_bundle_certificates(&cbb, certs2) || !CBB_finish(&cbb, &result2_data, &result2_len)) { fprintf(stderr, "PKCS7_bundle_certificates failed the second time.\n"); return 0; } if (result_len != result2_len || memcmp(result_data, result2_data, result_len) != 0) { fprintf(stderr, "Serialisation is not stable.\n"); return 0; } OPENSSL_free(result_data); OPENSSL_free(result2_data); sk_X509_pop_free(certs, X509_free); sk_X509_pop_free(certs2, X509_free); return 1; }
/* This function is called on a socket file descriptor once the connection has been * established and we're ready to negotiate SSL. If the SSL handshake fails for some * reason (such as the host on the other end not using SSL), it will return 0 for * failure. Success returns 1. */ static int FinishConnection(TCLinkCon *c, int sd) { int ssl_connected, is_error, errcode, res; X509 *server_cert; time_t start, remaining; fd_set in, out, err; struct timeval tv; /* check if socket has connected successfully */ int val; int /*socklen_t*/ size = 4; getsockopt(sd, SOL_SOCKET, SO_ERROR, (char*)&val, &size); if (val != 0) return 0; c->ssl = SSL_new(c->ctx); if (!c->ssl) return 0; FD_ZERO(&in); FD_SET((unsigned)sd, &in); FD_ZERO(&out); FD_SET((unsigned)sd, &out); FD_ZERO(&err); FD_SET((unsigned)sd, &err); SSL_set_fd(c->ssl, sd); ssl_connected = 0; is_error = 0; start = time(0); while (!ssl_connected && !is_error) { remaining = 5 - (time(0) - start); if (remaining <= 0) { is_error = 1; break; } res = SSL_connect(c->ssl); ssl_connected = ((res == 1) && SSL_is_init_finished(c->ssl)); if (!ssl_connected) { errcode = SSL_get_error(c->ssl, res); switch (errcode) { case SSL_ERROR_NONE: /* no error, we should have a connection, check again */ break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: /* no error, just wait for more data */ tv.tv_sec = remaining; tv.tv_usec = 0; if (select(sd+1, &in, &out, &err, &tv) < 0) is_error = 1; break; case SSL_ERROR_ZERO_RETURN: /* peer closed the connection */ case SSL_ERROR_SSL: /* error in SSL handshake */ default: is_error = 1; } } } if (is_error) { SSL_free(c->ssl); return 0; } #ifdef WIN32 u_long param = 0; ioctlsocket(sd, FIONBIO, ¶m); // make the socket blocking again #else fcntl(sd, F_SETFL, 0); /* make the socket blocking again */ #endif /* verify that server certificate is authentic */ server_cert = SSL_get_peer_certificate(c->ssl); if (!server_cert || (X509_cmp(server_cert, c->tc_cert) != 0)) { SSL_free(c->ssl); return 0; } X509_free(server_cert); return 1; }
/* * -1 if authentication failed * 1 if authentication succeeded * 2 if authentication succeeded, using parameter * -2 if authentication is delayed, don't error * No AuthStruct = everyone allowed */ int Auth_Check(aClient *cptr, anAuthStruct *as, char *para) { #ifdef AUTHENABLE_UNIXCRYPT extern char *crypt(); #endif #if defined(AUTHENABLE_SSL_CLIENTCERT) || defined(AUTHENABLE_SSL_CLIENTCERTFP) X509 *x509_clientcert = NULL; #endif #ifdef AUTHENABLE_SSL_CLIENTCERT X509 *x509_filecert = NULL; FILE *x509_f = NULL; #endif #ifdef AUTHENABLE_SSL_CLIENTCERTFP unsigned int n; unsigned int i; unsigned int j; unsigned int k; unsigned char md[EVP_MAX_MD_SIZE]; char hex[EVP_MAX_MD_SIZE * 2 + 1]; char hexc[EVP_MAX_MD_SIZE * 3 + 1]; char hexchars[16] = "0123456789abcdef"; const EVP_MD *digest = EVP_sha256(); #endif if (!as) return 1; switch (as->type) { case AUTHTYPE_PLAINTEXT: if (!para) return -1; /* plain text compare */ if (!strcmp(para, as->data)) return 2; else return -1; break; #ifdef AUTHENABLE_UNIXCRYPT case AUTHTYPE_UNIXCRYPT: if (!para) return -1; /* If our data is like 1 or none, we just let em through .. */ if (!(as->data[0] && as->data[1])) return 1; if (!strcmp(crypt(para, as->data), as->data)) return 2; else return -1; break; #endif case AUTHTYPE_MD5: return authcheck_md5(cptr, as, para); break; #ifdef AUTHENABLE_SHA1 case AUTHTYPE_SHA1: return authcheck_sha1(cptr, as, para); break; #endif #ifdef AUTHENABLE_RIPEMD160 case AUTHTYPE_RIPEMD160: return authcheck_ripemd160(cptr, as, para); #endif #ifdef AUTHENABLE_SSL_CLIENTCERT case AUTHTYPE_SSL_CLIENTCERT: if (!para) return -1; if (!cptr->ssl) return -1; x509_clientcert = SSL_get_peer_certificate((SSL *)cptr->ssl); if (!x509_clientcert) return -1; if (!(x509_f = fopen(as->data, "r"))) { X509_free(x509_clientcert); return -1; } x509_filecert = PEM_read_X509(x509_f, NULL, NULL, NULL); fclose(x509_f); if (!x509_filecert) { X509_free(x509_clientcert); return -1; } if (X509_cmp(x509_filecert, x509_clientcert) != 0) { X509_free(x509_clientcert); X509_free(x509_filecert); break; } X509_free(x509_clientcert); X509_free(x509_filecert); return 2; #endif #ifdef AUTHENABLE_SSL_CLIENTCERTFP case AUTHTYPE_SSL_CLIENTCERTFP: if (!para) return -1; if (!cptr->ssl) return -1; x509_clientcert = SSL_get_peer_certificate((SSL *)cptr->ssl); if (!x509_clientcert) return -1; if (!X509_digest(x509_clientcert, digest, md, &n)) { X509_free(x509_clientcert); return -1; } j = 0; k = 0; for (i=0; i<n; i++) { hex[j++] = hexchars[(md[i] >> 4) & 0xF]; hex[j++] = hexchars[md[i] & 0xF]; hexc[k++] = hexchars[(md[i] >> 4) & 0xF]; hexc[k++] = hexchars[md[i] & 0xF]; hexc[k++] = ':'; } hex[j] = '\0'; hexc[--k] = '\0'; if (strcasecmp(as->data, hex) && strcasecmp(as->data, hexc)) { X509_free(x509_clientcert); return -1; } X509_free(x509_clientcert); return 2; #endif } return -1; }