static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, X509_OBJECT *ret) { BY_DIR *ctx; union { struct { X509 st_x509; X509_CINF st_x509_cinf; } x509; struct { X509_CRL st_crl; X509_CRL_INFO st_crl_info; } crl; } data; int ok=0; int i,j,k; unsigned long h; BUF_MEM *b=NULL; struct stat st; X509_OBJECT stmp,*tmp; const char *postfix=""; if (name == NULL) return(0); stmp.type=type; if (type == X509_LU_X509) { data.x509.st_x509.cert_info= &data.x509.st_x509_cinf; data.x509.st_x509_cinf.subject=name; stmp.data.x509= &data.x509.st_x509; postfix=""; } else if (type == X509_LU_CRL) { data.crl.st_crl.crl= &data.crl.st_crl_info; data.crl.st_crl_info.issuer=name; stmp.data.crl= &data.crl.st_crl; postfix="r"; } else { X509err(X509_F_GET_CERT_BY_SUBJECT,X509_R_WRONG_LOOKUP_TYPE); goto finish; } if ((b=BUF_MEM_new()) == NULL) { X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_BUF_LIB); goto finish; } ctx=(BY_DIR *)xl->method_data; h=X509_NAME_hash(name); for (i=0; i<ctx->num_dirs; i++) { j=strlen(ctx->dirs[i])+1+8+6+1+1; if (!BUF_MEM_grow(b,j)) { X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_MALLOC_FAILURE); goto finish; } k=0; for (;;) { char c = '/'; #ifdef OPENSSL_SYS_VMS c = ctx->dirs[i][strlen(ctx->dirs[i])-1]; if (c != ':' && c != '>' && c != ']') { /* If no separator is present, we assume the directory specifier is a logical name, and add a colon. We really should use better VMS routines for merging things like this, but this will do for now... -- Richard Levitte */ c = ':'; } else { c = '\0'; } #endif if (c == '\0') { /* This is special. When c == '\0', no directory separator should be added. */ BIO_snprintf(b->data,b->max, "%s%08lx.%s%d",ctx->dirs[i],h, postfix,k); } else { BIO_snprintf(b->data,b->max, "%s%c%08lx.%s%d",ctx->dirs[i],c,h, postfix,k); } k++; if (stat(b->data,&st) < 0) break; /* found one. */ if (type == X509_LU_X509) { if ((X509_load_cert_file(xl,b->data, ctx->dirs_type[i])) == 0) break; } else if (type == X509_LU_CRL) { if ((X509_load_crl_file(xl,b->data, ctx->dirs_type[i])) == 0) break; } /* else case will caught higher up */ } /* we have added it to the cache so now pull * it out again */ CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); j = sk_X509_OBJECT_find(xl->store_ctx->objs,&stmp); if(j != -1) tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,j); else tmp = NULL; CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); if (tmp != NULL) { ok=1; ret->type=tmp->type; memcpy(&ret->data,&tmp->data,sizeof(ret->data)); /* If we were going to up the reference count, * we would need to do it on a perl 'type' * basis */ /* CRYPTO_add(&tmp->data.x509->references,1, CRYPTO_LOCK_X509);*/ goto finish; } } finish: if (b != NULL) BUF_MEM_free(b); return(ok); }
static int ldaplookup_by_subject( X509_LOOKUP *ctx, int type, X509_NAME *name, X509_OBJECT *ret ) { int count = 0; ldaphost *lh; const char *attrs[2]; char *filter = NULL; if (ctx == NULL) return(0); if (name == NULL) return(0); lh = (ldaphost*) ctx->method_data; if (lh == NULL) return(0); switch(type) { case X509_LU_X509: { attrs[0] = ATTR_CACERT; } break; case X509_LU_CRL: { attrs[0] = ATTR_CACRL; } break; default: { X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_WRONG_LOOKUP_TYPE); goto done; } } attrs[1] = NULL; filter = ldaplookup_filter(name, attrs[0]); if (filter == NULL) { X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_GET_FILTER); goto done; } #ifdef TRACE_BY_LDAP fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: filter=%s\n", filter); #endif for (; lh != NULL; lh = lh->next) { LDAPMessage *res = NULL; int result; #ifdef TRACE_BY_LDAP { int version = -1; ldap_get_option(lh->ld, LDAP_OPT_PROTOCOL_VERSION, &version); fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject:" " bind to \"%s://%s:%d\"" " using ldap v%d protocol\n" , lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port , version ); } #endif result = ldaplookup_bind_s(lh->ld); if (result != LDAP_SUCCESS) { X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_BIND); { char buf[1024]; snprintf(buf, sizeof(buf), " url=\"%s://%s:%d\"" " ldaperror=0x%x(%.256s)" , lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port , result, ldap_err2string(result) ); ERR_add_error_data(1, buf); } continue; } result = ldaplookup_search_s(lh->ld, lh->ldapurl->lud_dn, LDAP_SCOPE_SUBTREE, filter, (char**)attrs, 0, &res); if (result != LDAP_SUCCESS) { X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_SEARCH_FAIL); ldap_msgfree(res); continue; } result = ldaplookup_result2store(type, name, lh->ld, res, ctx->store_ctx); if (result > 0) count += result; ldap_msgfree(res); /*do not call ldap_unbind_s*/ } #ifdef TRACE_BY_LDAP fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: count=%d\n", count); #endif if (count > 0) { /* * we have added at least one to the cache so now pull one out again */ union { struct { X509_CINF st_x509_cinf; X509 st_x509; } x509; struct { X509_CRL_INFO st_crl_info; X509_CRL st_crl; } crl; } data; X509_OBJECT stmp, *tmp; int k; memset(&data, 0, sizeof(data)); stmp.type = type; switch(type) { case X509_LU_X509: { data.x509.st_x509_cinf.subject = name; data.x509.st_x509.cert_info = &data.x509.st_x509_cinf; stmp.data.x509 = &data.x509.st_x509; } break; case X509_LU_CRL: { data.crl.st_crl_info.issuer = name; data.crl.st_crl.crl = &data.crl.st_crl_info; stmp.data.crl = &data.crl.st_crl; } break; default: count = 0; goto done; } CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); k = sk_X509_OBJECT_find(ctx->store_ctx->objs, &stmp); if (k >= 0) tmp = sk_X509_OBJECT_value(ctx->store_ctx->objs, k); else tmp = NULL; CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); #ifdef TRACE_BY_LDAP fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: k=%d, tmp=%p\n", k, (void*)tmp); #endif if (tmp == NULL) { count = 0; goto done; } ret->type = tmp->type; memcpy(&ret->data, &tmp->data, sizeof(ret->data)); } done: if (filter != NULL) OPENSSL_free(filter); return(count > 0); }