2 * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please
7 * obtain a copy of the License at http://www.apple.com/publicsource and
8 * read it before using this file.
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
15 * Please see the License for the specific language governing rights and
16 * limitations under the License.
20 * ldapFetch.cpp - fetch an entity via LDAP
23 #include "ldapFetch.h"
24 #include <LDAP/ldap.h>
25 #include <Security/cssmapple.h>
29 #include <CoreFoundation/CoreFoundation.h>
33 #define dprintf(args...) printf(args)
35 #define dprintf(args...)
39 * LDAP attribute names, used if not present in URI.
41 #define LDAP_ATTR_CERT "cacertificate;binary"
42 #define LDAP_ATTR_CRL "certificaterevocationlist;binary"
45 * Default LDAP options.
47 #define LDAP_REFERRAL_DEFAULT LDAP_OPT_ON
49 static CSSM_RETURN
ldapRtnToCssm(
53 case LDAP_SERVER_DOWN
:
55 case LDAP_CONNECT_ERROR
:
56 return CSSMERR_APPLETP_CRL_SERVER_DOWN
;
57 case LDAP_PARAM_ERROR
:
58 case LDAP_FILTER_ERROR
:
59 return CSSMERR_APPLETP_CRL_BAD_URI
;
61 return CSSMERR_APPLETP_CRL_NOT_FOUND
;
65 CSSM_RETURN
ldapFetch(
68 CSSM_DATA
&fetched
) // mallocd and RETURNED
70 BerValue
**value
= NULL
;
71 LDAPURLDesc
*urlDesc
= NULL
;
73 LDAPMessage
*msg
= NULL
;
75 LDAPMessage
*entry
= NULL
;
76 bool mallocdString
= false;
79 CSSM_RETURN ourRtn
= CSSM_OK
;
80 /* attr input to ldap_search_s() */
82 char **attrArrayP
= NULL
;
84 /* don't assume URL string is NULL terminated */
85 if(url
.Data
[url
.Length
- 1] == '\0') {
86 urlStr
= (char *)url
.Data
;
89 urlStr
= (char *)malloc(url
.Length
+ 1);
90 memmove(urlStr
, url
.Data
, url
.Length
);
91 urlStr
[url
.Length
] = '\0';
95 /* break up the URL into something usable */
96 rtn
= ldap_url_parse(urlStr
, &urlDesc
);
98 dprintf("ldap_url_parse returned %d", rtn
);
99 return CSSMERR_APPLETP_CRL_BAD_URI
;
103 * Determine what attr we're looking for.
105 if((urlDesc
->lud_attrs
!= NULL
) && // attrs present in URL
106 (urlDesc
->lud_attrs
[0] != NULL
) && // at least one attr present
107 (urlDesc
->lud_attrs
[1] == NULL
)) {
109 * Exactly one attr present in the caller-specified URL;
110 * assume that this is exactly what we want.
112 attrArrayP
= &urlDesc
->lud_attrs
[0];
115 /* use caller-specified attr */
118 attrArray
[0] = (char *)LDAP_ATTR_CRL
;
121 attrArray
[0] = (char *)LDAP_ATTR_CERT
;
124 printf("***ldapFetch screwup: bogus lfType (%d)\n",
126 return CSSMERR_CSSM_INTERNAL_ERROR
;
129 attrArrayP
= &attrArray
[0];
132 /* establish connection */
133 rtn
= ldap_initialize(&ldap
, urlStr
);
135 dprintf("ldap_initialize returned %d\n", rtn
);
136 return ldapRtnToCssm(rtn
);
138 /* subsequent errors to cleanup: */
139 rtn
= ldap_simple_bind_s(ldap
, NULL
, NULL
);
141 dprintf("ldap_simple_bind_s returned %d\n", rtn
);
142 ourRtn
= ldapRtnToCssm(rtn
);
146 rtn
= ldap_set_option(ldap
, LDAP_OPT_REFERRALS
, LDAP_REFERRAL_DEFAULT
);
148 dprintf("ldap_set_option(referrals) returned %d\n", rtn
);
149 ourRtn
= ldapRtnToCssm(rtn
);
162 dprintf("ldap_search_s returned %d\n", rtn
);
163 ourRtn
= ldapRtnToCssm(rtn
);
168 * We require exactly one entry (for now).
170 numEntries
= ldap_count_entries(ldap
, msg
);
171 if(numEntries
!= 1) {
172 dprintf("tpCrlViaLdap: numEntries %d\n", numEntries
);
173 ourRtn
= CSSMERR_APPLETP_CRL_NOT_FOUND
;
177 entry
= ldap_first_entry(ldap
, msg
);
178 value
= ldap_get_values_len(ldap
, msg
, attrArrayP
[0]);
180 dprintf("Error on ldap_get_values_len\n");
181 ourRtn
= CSSMERR_APPLETP_CRL_NOT_FOUND
;
185 fetched
.Length
= value
[0]->bv_len
;
186 fetched
.Data
= (uint8
*)malloc(fetched
.Length
);
187 memmove(fetched
.Data
, value
[0]->bv_val
, fetched
.Length
);
189 ldap_value_free_len(value
);
198 ldap_free_urldesc(urlDesc
);
199 rtn
= ldap_unbind(ldap
);
201 dprintf("Error %d on ldap_unbind\n", rtn
);
208 CSSM_RETURN
httpFetch(
209 const CSSM_DATA
&url
,
210 CSSM_DATA
&fetched
) // mallocd and RETURNED
212 /* trim off possible NULL terminator */
213 CSSM_DATA theUrl
= url
;
214 if(theUrl
.Data
[theUrl
.Length
- 1] == '\0') {
217 CFURLRef cfUrl
= CFURLCreateWithBytes(NULL
,
218 theUrl
.Data
, theUrl
.Length
,
219 kCFStringEncodingUTF8
, // right?
220 //kCFStringEncodingASCII, // right?
221 NULL
); // this is absolute path
223 dprintf("CFURLCreateWithBytes returned NULL\n");
224 return CSSMERR_APPLETP_CRL_BAD_URI
;
226 CFDataRef urlData
= NULL
;
228 Boolean brtn
= CFURLCreateDataAndPropertiesFromResource(NULL
,
231 NULL
, // no properties
236 dprintf("CFURLCreateDataAndPropertiesFromResource err: %d\n",
239 return CSSMERR_APPLETP_CRL_BAD_URI
;
242 if(urlData
== NULL
) {
243 dprintf("CFURLCreateDataAndPropertiesFromResource: no data\n");
244 return CSSMERR_APPLETP_CRL_BAD_URI
;
246 CFIndex len
= CFDataGetLength(urlData
);
247 fetched
.Data
= (uint8
*)malloc(len
);
248 fetched
.Length
= len
;
249 memmove(fetched
.Data
, CFDataGetBytePtr(urlData
), len
);
254 /* Fetch from net, we figure out the schema */
255 CSSM_RETURN
netFetch(
256 const CSSM_DATA
&url
,
258 CSSM_DATA
&fetched
) // mallocd and RETURNED
261 return CSSMERR_APPLETP_CRL_BAD_URI
;
263 if(!strncmp((char *)url
.Data
, "ldap:", 5)) {
264 return ldapFetch(url
, lfType
, fetched
);
266 if(!strncmp((char *)url
.Data
, "http:", 5) ||
267 !strncmp((char *)url
.Data
, "https:", 6)) {
268 return httpFetch(url
, fetched
);
270 return CSSMERR_APPLETP_CRL_BAD_URI
;