]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/crlTool/crlNetwork.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / crlTool / crlNetwork.cpp
1 /*
2 * crlNetwork.cpp - Network support for crlTool
3 */
4
5 #include "crlNetwork.h"
6 #include <CoreFoundation/CoreFoundation.h>
7 #include <CoreServices/CoreServices.h>
8 #include <security_cdsa_utils/cuEnc64.h>
9 #include <stdlib.h>
10 #include <Security/cssmapple.h>
11 #include <LDAP/ldap.h>
12
13 #define ocspdErrorLog(args...) printf(args)
14
15 #pragma mark ----- LDAP fetch -----
16
17 /*
18 * LDAP attribute names, used if not present in URI.
19 */
20 #define LDAP_ATTR_CERT "cacertificate;binary"
21 #define LDAP_ATTR_CRL "certificaterevocationlist;binary"
22
23 /*
24 * Default LDAP options.
25 */
26 #define LDAP_REFERRAL_DEFAULT LDAP_OPT_ON
27
28 static CSSM_RETURN ldapRtnToCssm(
29 int rtn)
30 {
31 switch(rtn) {
32 case LDAP_SERVER_DOWN:
33 case LDAP_TIMEOUT:
34 case LDAP_CONNECT_ERROR:
35 return CSSMERR_APPLETP_CRL_SERVER_DOWN;
36 case LDAP_PARAM_ERROR:
37 case LDAP_FILTER_ERROR:
38 return CSSMERR_APPLETP_CRL_BAD_URI;
39 default:
40 return CSSMERR_APPLETP_CRL_NOT_FOUND;
41 }
42 }
43
44 static CSSM_RETURN ldapFetch(
45 const CSSM_DATA &url,
46 LF_Type lfType,
47 CSSM_DATA &fetched) // mallocd and RETURNED
48 {
49 BerValue **value = NULL;
50 LDAPURLDesc *urlDesc = NULL;
51 int rtn;
52 LDAPMessage *msg = NULL;
53 LDAP *ldap = NULL;
54 LDAPMessage *entry = NULL;
55 bool mallocdString = false;
56 char *urlStr;
57 int numEntries;
58 CSSM_RETURN ourRtn = CSSM_OK;
59 /* attr input to ldap_search_s() */
60 char *attrArray[2];
61 char **attrArrayP = NULL;
62
63 /* don't assume URL string is NULL terminated */
64 if(url.Data[url.Length - 1] == '\0') {
65 urlStr = (char *)url.Data;
66 }
67 else {
68 urlStr = (char *)malloc(url.Length + 1);
69 memmove(urlStr, url.Data, url.Length);
70 urlStr[url.Length] = '\0';
71 mallocdString = true;
72 }
73
74 /* break up the URL into something usable */
75 rtn = ldap_url_parse(urlStr, &urlDesc);
76 if(rtn) {
77 ocspdErrorLog("ldap_url_parse returned %d", rtn);
78 return CSSMERR_APPLETP_CRL_BAD_URI;
79 }
80
81 /*
82 * Determine what attr we're looking for.
83 */
84 if((urlDesc->lud_attrs != NULL) && // attrs present in URL
85 (urlDesc->lud_attrs[0] != NULL) && // at least one attr present
86 (urlDesc->lud_attrs[1] == NULL)) {
87 /*
88 * Exactly one attr present in the caller-specified URL;
89 * assume that this is exactly what we want.
90 */
91 attrArrayP = &urlDesc->lud_attrs[0];
92 }
93 else {
94 /* use caller-specified attr */
95 switch(lfType) {
96 case LT_Crl:
97 attrArray[0] = (char *)LDAP_ATTR_CRL;
98 break;
99 case LT_Cert:
100 attrArray[0] = (char *)LDAP_ATTR_CERT;
101 break;
102 default:
103 printf("***ldapFetch screwup: bogus lfType (%d)\n",
104 (int)lfType);
105 return CSSMERR_CSSM_INTERNAL_ERROR;
106 }
107 attrArray[1] = NULL;
108 attrArrayP = &attrArray[0];
109 }
110
111 /* establish connection */
112 rtn = ldap_initialize(&ldap, urlStr);
113 if(rtn) {
114 ocspdErrorLog("ldap_initialize returned %d\n", rtn);
115 return ldapRtnToCssm(rtn);
116 }
117 /* subsequent errors to cleanup: */
118 rtn = ldap_simple_bind_s(ldap, NULL, NULL);
119 if(rtn) {
120 ocspdErrorLog("ldap_simple_bind_s returned %d\n", rtn);
121 ourRtn = ldapRtnToCssm(rtn);
122 goto cleanup;
123 }
124
125 rtn = ldap_set_option(ldap, LDAP_OPT_REFERRALS, LDAP_REFERRAL_DEFAULT);
126 if(rtn) {
127 ocspdErrorLog("ldap_set_option(referrals) returned %d\n", rtn);
128 ourRtn = ldapRtnToCssm(rtn);
129 goto cleanup;
130 }
131
132 rtn = ldap_search_s(
133 ldap,
134 urlDesc->lud_dn,
135 LDAP_SCOPE_SUBTREE,
136 urlDesc->lud_filter,
137 urlDesc->lud_attrs,
138 0, // attrsonly
139 &msg);
140 if(rtn) {
141 ocspdErrorLog("ldap_search_s returned %d\n", rtn);
142 ourRtn = ldapRtnToCssm(rtn);
143 goto cleanup;
144 }
145
146 /*
147 * We require exactly one entry (for now).
148 */
149 numEntries = ldap_count_entries(ldap, msg);
150 if(numEntries != 1) {
151 ocspdErrorLog("tpCrlViaLdap: numEntries %d\n", numEntries);
152 ourRtn = CSSMERR_APPLETP_CRL_NOT_FOUND;
153 goto cleanup;
154 }
155
156 entry = ldap_first_entry(ldap, msg);
157 value = ldap_get_values_len(ldap, msg, attrArrayP[0]);
158 if(value == NULL) {
159 ocspdErrorLog("Error on ldap_get_values_len\n");
160 ourRtn = CSSMERR_APPLETP_CRL_NOT_FOUND;
161 goto cleanup;
162 }
163
164 fetched.Length = value[0]->bv_len;
165 fetched.Data = (uint8 *)malloc(fetched.Length);
166 memmove(fetched.Data, value[0]->bv_val, fetched.Length);
167
168 ldap_value_free_len(value);
169 ourRtn = CSSM_OK;
170 cleanup:
171 if(msg) {
172 ldap_msgfree(msg);
173 }
174 if(mallocdString) {
175 free(urlStr);
176 }
177 ldap_free_urldesc(urlDesc);
178 rtn = ldap_unbind(ldap);
179 if(rtn) {
180 ocspdErrorLog("Error %d on ldap_unbind\n", rtn);
181 /* oh well */
182 }
183 return ourRtn;
184 }
185
186 #pragma mark ----- HTTP fetch via GET -----
187
188 /* fetch via HTTP */
189 static CSSM_RETURN httpFetch(
190 const CSSM_DATA &url,
191 CSSM_DATA &fetched) // mallocd in alloc space and RETURNED
192 {
193 /* trim off possible NULL terminator */
194 CSSM_DATA theUrl = url;
195 if(theUrl.Data[theUrl.Length - 1] == '\0') {
196 theUrl.Length--;
197 }
198 CFURLRef cfUrl = CFURLCreateWithBytes(NULL,
199 theUrl.Data, theUrl.Length,
200 kCFStringEncodingUTF8, // right?
201 //kCFStringEncodingASCII, // right?
202 NULL); // this is absolute path
203 if(cfUrl == NULL) {
204 ocspdErrorLog("CFURLCreateWithBytes returned NULL\n");
205 return CSSMERR_APPLETP_CRL_BAD_URI;
206 }
207 CFDataRef urlData = NULL;
208 SInt32 errorCode;
209 Boolean brtn = CFURLCreateDataAndPropertiesFromResource(NULL,
210 cfUrl,
211 &urlData,
212 NULL, // no properties
213 NULL,
214 &errorCode);
215 CFRelease(cfUrl);
216 if(!brtn) {
217 ocspdErrorLog("CFURLCreateDataAndPropertiesFromResource err: %d\n",
218 (int)errorCode);
219 if(urlData) {
220 return CSSMERR_APPLETP_NETWORK_FAILURE;
221 }
222 }
223 if(urlData == NULL) {
224 ocspdErrorLog("CFURLCreateDataAndPropertiesFromResource: no data\n");
225 return CSSMERR_APPLETP_NETWORK_FAILURE;
226 }
227 CFIndex len = CFDataGetLength(urlData);
228 fetched.Data = (uint8 *)malloc(len);
229 fetched.Length = len;
230 memmove(fetched.Data, CFDataGetBytePtr(urlData), len);
231 CFRelease(urlData);
232 return CSSM_OK;
233 }
234
235 /* Fetch cert or CRL from net, we figure out the schema */
236 CSSM_RETURN crlNetFetch(
237 const CSSM_DATA *url,
238 LF_Type lfType,
239 CSSM_DATA *fetched) // mallocd in alloc space and RETURNED
240 {
241 if(url->Length < 5) {
242 return CSSMERR_APPLETP_CRL_BAD_URI;
243 }
244 if(!strncmp((char *)url->Data, "ldap:", 5)) {
245 return ldapFetch(*url, lfType, *fetched);
246 }
247 if(!strncmp((char *)url->Data, "http:", 5) ||
248 !strncmp((char *)url->Data, "https:", 6)) {
249 return httpFetch(*url, *fetched);
250 }
251 return CSSMERR_APPLETP_CRL_BAD_URI;
252 }
253