]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
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 |