X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/crlTool/crlNetwork.cpp?ds=inline diff --git a/SecurityTests/clxutils/crlTool/crlNetwork.cpp b/SecurityTests/clxutils/crlTool/crlNetwork.cpp new file mode 100644 index 00000000..240824cd --- /dev/null +++ b/SecurityTests/clxutils/crlTool/crlNetwork.cpp @@ -0,0 +1,253 @@ +/* + * crlNetwork.cpp - Network support for crlTool + */ + +#include "crlNetwork.h" +#include +#include +#include +#include +#include +#include + +#define ocspdErrorLog(args...) printf(args) + +#pragma mark ----- LDAP fetch ----- + +/* + * LDAP attribute names, used if not present in URI. + */ +#define LDAP_ATTR_CERT "cacertificate;binary" +#define LDAP_ATTR_CRL "certificaterevocationlist;binary" + +/* + * Default LDAP options. + */ +#define LDAP_REFERRAL_DEFAULT LDAP_OPT_ON + +static CSSM_RETURN ldapRtnToCssm( + int rtn) +{ + switch(rtn) { + case LDAP_SERVER_DOWN: + case LDAP_TIMEOUT: + case LDAP_CONNECT_ERROR: + return CSSMERR_APPLETP_CRL_SERVER_DOWN; + case LDAP_PARAM_ERROR: + case LDAP_FILTER_ERROR: + return CSSMERR_APPLETP_CRL_BAD_URI; + default: + return CSSMERR_APPLETP_CRL_NOT_FOUND; + } +} + +static CSSM_RETURN ldapFetch( + const CSSM_DATA &url, + LF_Type lfType, + CSSM_DATA &fetched) // mallocd and RETURNED +{ + BerValue **value = NULL; + LDAPURLDesc *urlDesc = NULL; + int rtn; + LDAPMessage *msg = NULL; + LDAP *ldap = NULL; + LDAPMessage *entry = NULL; + bool mallocdString = false; + char *urlStr; + int numEntries; + CSSM_RETURN ourRtn = CSSM_OK; + /* attr input to ldap_search_s() */ + char *attrArray[2]; + char **attrArrayP = NULL; + + /* don't assume URL string is NULL terminated */ + if(url.Data[url.Length - 1] == '\0') { + urlStr = (char *)url.Data; + } + else { + urlStr = (char *)malloc(url.Length + 1); + memmove(urlStr, url.Data, url.Length); + urlStr[url.Length] = '\0'; + mallocdString = true; + } + + /* break up the URL into something usable */ + rtn = ldap_url_parse(urlStr, &urlDesc); + if(rtn) { + ocspdErrorLog("ldap_url_parse returned %d", rtn); + return CSSMERR_APPLETP_CRL_BAD_URI; + } + + /* + * Determine what attr we're looking for. + */ + if((urlDesc->lud_attrs != NULL) && // attrs present in URL + (urlDesc->lud_attrs[0] != NULL) && // at least one attr present + (urlDesc->lud_attrs[1] == NULL)) { + /* + * Exactly one attr present in the caller-specified URL; + * assume that this is exactly what we want. + */ + attrArrayP = &urlDesc->lud_attrs[0]; + } + else { + /* use caller-specified attr */ + switch(lfType) { + case LT_Crl: + attrArray[0] = (char *)LDAP_ATTR_CRL; + break; + case LT_Cert: + attrArray[0] = (char *)LDAP_ATTR_CERT; + break; + default: + printf("***ldapFetch screwup: bogus lfType (%d)\n", + (int)lfType); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + attrArray[1] = NULL; + attrArrayP = &attrArray[0]; + } + + /* establish connection */ + rtn = ldap_initialize(&ldap, urlStr); + if(rtn) { + ocspdErrorLog("ldap_initialize returned %d\n", rtn); + return ldapRtnToCssm(rtn); + } + /* subsequent errors to cleanup: */ + rtn = ldap_simple_bind_s(ldap, NULL, NULL); + if(rtn) { + ocspdErrorLog("ldap_simple_bind_s returned %d\n", rtn); + ourRtn = ldapRtnToCssm(rtn); + goto cleanup; + } + + rtn = ldap_set_option(ldap, LDAP_OPT_REFERRALS, LDAP_REFERRAL_DEFAULT); + if(rtn) { + ocspdErrorLog("ldap_set_option(referrals) returned %d\n", rtn); + ourRtn = ldapRtnToCssm(rtn); + goto cleanup; + } + + rtn = ldap_search_s( + ldap, + urlDesc->lud_dn, + LDAP_SCOPE_SUBTREE, + urlDesc->lud_filter, + urlDesc->lud_attrs, + 0, // attrsonly + &msg); + if(rtn) { + ocspdErrorLog("ldap_search_s returned %d\n", rtn); + ourRtn = ldapRtnToCssm(rtn); + goto cleanup; + } + + /* + * We require exactly one entry (for now). + */ + numEntries = ldap_count_entries(ldap, msg); + if(numEntries != 1) { + ocspdErrorLog("tpCrlViaLdap: numEntries %d\n", numEntries); + ourRtn = CSSMERR_APPLETP_CRL_NOT_FOUND; + goto cleanup; + } + + entry = ldap_first_entry(ldap, msg); + value = ldap_get_values_len(ldap, msg, attrArrayP[0]); + if(value == NULL) { + ocspdErrorLog("Error on ldap_get_values_len\n"); + ourRtn = CSSMERR_APPLETP_CRL_NOT_FOUND; + goto cleanup; + } + + fetched.Length = value[0]->bv_len; + fetched.Data = (uint8 *)malloc(fetched.Length); + memmove(fetched.Data, value[0]->bv_val, fetched.Length); + + ldap_value_free_len(value); + ourRtn = CSSM_OK; +cleanup: + if(msg) { + ldap_msgfree(msg); + } + if(mallocdString) { + free(urlStr); + } + ldap_free_urldesc(urlDesc); + rtn = ldap_unbind(ldap); + if(rtn) { + ocspdErrorLog("Error %d on ldap_unbind\n", rtn); + /* oh well */ + } + return ourRtn; +} + +#pragma mark ----- HTTP fetch via GET ----- + +/* fetch via HTTP */ +static CSSM_RETURN httpFetch( + const CSSM_DATA &url, + CSSM_DATA &fetched) // mallocd in alloc space and RETURNED +{ + /* trim off possible NULL terminator */ + CSSM_DATA theUrl = url; + if(theUrl.Data[theUrl.Length - 1] == '\0') { + theUrl.Length--; + } + CFURLRef cfUrl = CFURLCreateWithBytes(NULL, + theUrl.Data, theUrl.Length, + kCFStringEncodingUTF8, // right? + //kCFStringEncodingASCII, // right? + NULL); // this is absolute path + if(cfUrl == NULL) { + ocspdErrorLog("CFURLCreateWithBytes returned NULL\n"); + return CSSMERR_APPLETP_CRL_BAD_URI; + } + CFDataRef urlData = NULL; + SInt32 errorCode; + Boolean brtn = CFURLCreateDataAndPropertiesFromResource(NULL, + cfUrl, + &urlData, + NULL, // no properties + NULL, + &errorCode); + CFRelease(cfUrl); + if(!brtn) { + ocspdErrorLog("CFURLCreateDataAndPropertiesFromResource err: %d\n", + (int)errorCode); + if(urlData) { + return CSSMERR_APPLETP_NETWORK_FAILURE; + } + } + if(urlData == NULL) { + ocspdErrorLog("CFURLCreateDataAndPropertiesFromResource: no data\n"); + return CSSMERR_APPLETP_NETWORK_FAILURE; + } + CFIndex len = CFDataGetLength(urlData); + fetched.Data = (uint8 *)malloc(len); + fetched.Length = len; + memmove(fetched.Data, CFDataGetBytePtr(urlData), len); + CFRelease(urlData); + return CSSM_OK; +} + +/* Fetch cert or CRL from net, we figure out the schema */ +CSSM_RETURN crlNetFetch( + const CSSM_DATA *url, + LF_Type lfType, + CSSM_DATA *fetched) // mallocd in alloc space and RETURNED +{ + if(url->Length < 5) { + return CSSMERR_APPLETP_CRL_BAD_URI; + } + if(!strncmp((char *)url->Data, "ldap:", 5)) { + return ldapFetch(*url, lfType, *fetched); + } + if(!strncmp((char *)url->Data, "http:", 5) || + !strncmp((char *)url->Data, "https:", 6)) { + return httpFetch(*url, *fetched); + } + return CSSMERR_APPLETP_CRL_BAD_URI; +} +