LDAPRepository | Line # 112 | 67 | 23 | 40.4% |
0.40350878
|
No Tests | |||
1 | /* | |
2 | * Copyright (c) 2000-2005, University of Salford | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are met: | |
7 | * | |
8 | * Redistributions of source code must retain the above copyright notice, this | |
9 | * list of conditions and the following disclaimer. | |
10 | * | |
11 | * Redistributions in binary form must reproduce the above copyright notice, | |
12 | * this list of conditions and the following disclaimer in the documentation | |
13 | * and/or other materials provided with the distribution. | |
14 | * | |
15 | * Neither the name of the University of Salford nor the names of its | |
16 | * contributors may be used to endorse or promote products derived from this | |
17 | * software without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | |
31 | /* | |
32 | * Copyright (c) 2006, University of Kent | |
33 | * All rights reserved. | |
34 | * | |
35 | * Redistribution and use in source and binary forms, with or without | |
36 | * modification, are permitted provided that the following conditions are met: | |
37 | * | |
38 | * Redistributions of source code must retain the above copyright notice, this | |
39 | * list of conditions and the following disclaimer. | |
40 | * | |
41 | * Redistributions in binary form must reproduce the above copyright notice, | |
42 | * this list of conditions and the following disclaimer in the documentation | |
43 | * and/or other materials provided with the distribution. | |
44 | * | |
45 | * 1. Neither the name of the University of Kent nor the names of its | |
46 | * contributors may be used to endorse or promote products derived from this | |
47 | * software without specific prior written permission. | |
48 | * | |
49 | * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
50 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
51 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
52 | * PURPOSE ARE DISCLAIMED. | |
53 | * | |
54 | * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
55 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
56 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
57 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
58 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
59 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
60 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
61 | * POSSIBILITY OF SUCH DAMAGE. | |
62 | * | |
63 | * 4. YOU AGREE THAT THE EXCLUSIctx.getAttributes(dnONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE | |
64 | * IN THE CIRCUMSTANCES. IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS | |
65 | * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS | |
66 | * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH | |
67 | * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH | |
68 | * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY | |
69 | * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE | |
70 | * SERIOUS FAULTS, IN THIS SOFTWARE. | |
71 | * | |
72 | * 5. This license is governed, except to the extent that local laws | |
73 | * necessarily apply, by the laws of England and Wales. | |
74 | */ | |
75 | ||
76 | package issrg.utils.repository; | |
77 | ||
78 | import issrg.utils.ToRawCredential; | |
79 | import javax.naming.directory.DirContext; | |
80 | import javax.naming.directory.Attributes; | |
81 | import javax.naming.NamingException; | |
82 | import javax.naming.NamingEnumeration; | |
83 | import javax.naming.NameParser; | |
84 | import javax.naming.Name; | |
85 | import java.security.Principal; | |
86 | import java.util.Vector; | |
87 | ||
88 | import issrg.pba.rbac.CustomisePERMIS; | |
89 | ||
90 | import org.apache.log4j.*;// added for logging | |
91 | /** | |
92 | * This class is the implementation of the Attribute Repository for LDAP. | |
93 | * It can be built out of an array of DirContext. Each of these contexts | |
94 | * constitutes a root for LDAP searches. Each DirContext is obtained by | |
95 | * establishing an LDAP connection with the directory concerned. | |
96 | * | |
97 | * <p>The object can be used for retrieving similar information from multiple | |
98 | * directories simultaneously. For example, it is useful when retrieving X.509 | |
99 | * Attribute Certificates for PMI entities that possess ACs issued by different | |
100 | * issuers (therefore, stored in different directories available to these | |
101 | * issuers). | |
102 | * | |
103 | * <p>The object uses MultiRepository to create multiple threads, and acts as | |
104 | * a proxy object for backwards compatibility (earlier versions of this object | |
105 | * had a constructor with an array of DirContext). It is better to use | |
106 | * MultiRepository for multi-root clusters of LDAP repositories to be more | |
107 | * efficient. | |
108 | * | |
109 | * @author A Otenko | |
110 | * @version 0.2 | |
111 | */ | |
112 | public class LDAPRepository extends DefaultRepository{ | |
113 | private MultiRepository mr=null; | |
114 | private DirContext ctx=null; | |
115 | ||
116 | private int status; // status of the Repository | |
117 | private Throwable diagnosis; // the ultimate status: the stack frame in it, the error message to deliver, etc | |
118 | ||
119 | 0 | protected LDAPRepository(){} |
120 | ||
121 | static Logger logger = Logger.getLogger("issrg.utils.repository.LDAPRepository"); | |
122 | ||
123 | /** | |
124 | * This constructor builds the LDAPRepository with a number of roots. | |
125 | * | |
126 | * @param Contexts - An array of DirContexts to use as the roots of LDAP | |
127 | * searches | |
128 | */ | |
129 | 0 | public LDAPRepository(DirContext [] Contexts) { |
130 | ||
131 | 0 | LDAPRepository [] ldaps=new LDAPRepository[Contexts.length]; |
132 | 0 | for (int i=0; i<ldaps.length; i++){ |
133 | 0 | if (logger.isDebugEnabled()){ |
134 | 0 | try { |
135 | 0 | logger.debug("Base DN = " + Contexts[i].getNameInNamespace()) ; |
136 | } catch (NamingException e) { | |
137 | // TODO Auto-generated catch block | |
138 | 0 | e.printStackTrace(); |
139 | }} | |
140 | 0 | ldaps[i]=new LDAPRepository(Contexts[i]); |
141 | } | |
142 | ||
143 | 0 | mr=new MultiRepository(ldaps); |
144 | } | |
145 | ||
146 | /** | |
147 | * This creates an LDAPRepository with a single root context | |
148 | * | |
149 | * @param Context - A DirContext to be used as the root of LDAP searches | |
150 | */ | |
151 | 1 | public LDAPRepository(DirContext Context) { |
152 | 1 | ctx=Context; |
153 | 1 | if (logger.isDebugEnabled()){ |
154 | 0 | try { |
155 | 0 | logger.debug("Base DN = " + ctx.getNameInNamespace()); |
156 | } catch (NamingException e) { | |
157 | // TODO Auto-generated catch block | |
158 | 0 | e.printStackTrace(); |
159 | }} | |
160 | } | |
161 | ||
162 | /** | |
163 | * This method gets the set of named attributes from the entry with the DN. | |
164 | * It searches all ldap contexts simultaneously. If the DN and named attribute | |
165 | * exist in more than one of the named contexts, then multiple attribute | |
166 | * values will be returned. | |
167 | * | |
168 | * <p>Note that all attribute retrieval methods call this method, and they do | |
169 | * not update the status or diagnosis set by this method, and they propagate | |
170 | * the exceptions thrown by this method. | |
171 | * | |
172 | * <p>After calling the method the repository will be set into one of the | |
173 | * states: FAILURE_STATUS, SUCCESS_STATUS or PARTIAL_SUCCESS_STATUS. Failure | |
174 | * means there were no roots that succeeded. Success means that all of the | |
175 | * roots succeeded (the entries were found and some or no attributes were | |
176 | * retrieved). Partial success means that some of the roots failed, but some | |
177 | * have succeeded, which may be in case some of the roots do not contain | |
178 | * the required entry. The caller must find out himself what the cause is, and | |
179 | * decide if the results are sufficiently successful. | |
180 | * | |
181 | * @param DN The distinguished name of the entry from which the attributes | |
182 | * are requested | |
183 | * @param AttributeNames The array of LDAP names for the attributes; can be | |
184 | * null, if all available attributes and their values are to be retrieved | |
185 | * | |
186 | * @return the requested attributes; the Repository status reflects the status | |
187 | * of retrieval, the diagnosis contains exceptions the underlying objects | |
188 | * threw, if they failed | |
189 | * | |
190 | * @throws RepositoryException, if all of the repositories failed, in which | |
191 | * case the | |
192 | * embedded exception will be the Throwable returned by <code>getDiagnosis</code> | |
193 | * method; FAILURE_STATUS will also be set | |
194 | */ | |
195 | ||
196 | 3 | public Attributes getAttributes(java.security.Principal DN, String [] AttributeNames) throws RepositoryException{ |
197 | 3 | if (logger.isDebugEnabled()){ |
198 | 0 | logger.debug("retrieving attributes: " ); |
199 | ||
200 | //System.err.print("retrieving attributes: "); | |
201 | 0 | for(int i=0; i<AttributeNames.length; i++) |
202 | { | |
203 | 0 | if (i!=0) System.err.print(","); |
204 | 0 | logger.debug("Attribute type is " + AttributeNames[i]);} |
205 | ||
206 | } | |
207 | 3 | if (mr==null){ |
208 | 3 | try{ |
209 | 3 | diagnosis=null; |
210 | 3 | if (logger.isDebugEnabled()){ |
211 | ||
212 | 0 | String attrs=""; |
213 | ||
214 | 0 | for(int i=0; AttributeNames!=null && i<AttributeNames.length; i++){ |
215 | 0 | if (i==0) { |
216 | 0 | attrs=AttributeNames[i]; |
217 | 0 | } else {attrs+=", "+AttributeNames[i];} |
218 | } | |
219 | 0 | logger.debug("getting ["+attrs+"] attributes for "+DN.getName()); //************ |
220 | 0 | int i = 0; |
221 | 0 | Attributes f = ctx.getAttributes(dnWithoutBaseDN(ctx, DN.getName()), AttributeNames); |
222 | 0 | logger.debug(f.size() + " attributes were found"); |
223 | ||
224 | } | |
225 | 3 | if (DN.getName().equals("")) logger.debug("warning : an empty DN "); |
226 | 3 | Attributes atts = ctx.getAttributes(dnWithoutBaseDN(ctx, DN.getName()), AttributeNames); |
227 | 1 | ToRawCredential toRaw = new ToRawCredential(atts,this.getClass().getName()); |
228 | 1 | atts = toRaw.convert(); |
229 | 1 | return (Attributes)atts.clone(); |
230 | }catch(javax.naming.NameNotFoundException nnfe){ | |
231 | 0 | if (logger.isDebugEnabled())logger.debug(nnfe.getClass().getName()+" exception occured while retrieving attributes");//************* |
232 | //nnfe.printStackTrace(); //************* | |
233 | ||
234 | 2 | diagnosis=nnfe; // set this as a diagnosis, so partial success can be signalled |
235 | 0 | if (logger.isDebugEnabled())logger.debug("returning: null"); |
236 | 2 | return null; // return null, i.e. no attributes were found |
237 | }catch(Throwable th){ | |
238 | ||
239 | 0 | if (logger.isDebugEnabled())logger.debug(th.getClass().getName()+" exception occured while retrieving attributes");//************* |
240 | //th.printStackTrace(); //************* | |
241 | ||
242 | 0 | diagnosis=new RepositoryException("Failed to get attributes", th); |
243 | 0 | throw (RepositoryException)diagnosis; |
244 | ||
245 | }finally{ | |
246 | 3 | status=diagnosis==null?SUCCESS_STATUS:FAILURE_STATUS; |
247 | } | |
248 | } else { | |
249 | 0 | if (logger.isDebugEnabled()) logger.debug("using MultiRepository to retrieve the attributes"); //************ |
250 | 0 | Attributes atts = mr.getAttributes(DN, AttributeNames); |
251 | 0 | ToRawCredential toRaw = new ToRawCredential(atts,this.getClass().getName()); |
252 | 0 | atts = toRaw.convert(); |
253 | 0 | return (Attributes)atts.clone(); |
254 | } | |
255 | } | |
256 | ||
257 | /** | |
258 | * This method returns the status of the repository. It is set when returning | |
259 | * attributes. | |
260 | * | |
261 | * @return the integer value corresponding to the status | |
262 | * | |
263 | * @see getAttributes(java.security.Principal,String[]) | |
264 | */ | |
265 | 0 | public int getStatus(){ |
266 | 0 | return mr==null?status:mr.getStatus(); |
267 | } | |
268 | ||
269 | /** | |
270 | * This method returns the Throwable, representing the error, or null, if no | |
271 | * error has been encountered (only if the repository is in SUCCESS_STATUS). | |
272 | * The Throwable contains an error message and the stack trace of the error. | |
273 | * | |
274 | * @return Throwable object, representing the error, or null if there was no | |
275 | * error during the last call | |
276 | */ | |
277 | 3 | public Throwable getDiagnosis(){ |
278 | 3 | return mr==null?diagnosis:mr.getDiagnosis(); |
279 | } | |
280 | ||
281 | /** | |
282 | * This is a utility method that strips off the base DN from the DN, if it | |
283 | * is present there. Sometimes the DN is relative to the root, sometimes it is | |
284 | * an absolute DN and includes the DN of the root DirContext. It is important | |
285 | * to stranslate the DN into the DN without the base DN for successful | |
286 | * searches. | |
287 | * | |
288 | * @param root - the DirContext of the search root | |
289 | * @param dn - a DN with or without the base DN (the DN of the search root) | |
290 | * | |
291 | * @return a LDAP DN relative to the base DN (the DN of the search root) | |
292 | * | |
293 | * @throws NamingException, if the DN is not a valid DN | |
294 | */ | |
295 | 3 | public static String dnWithoutBaseDN(DirContext root, String dn) throws NamingException { |
296 | ||
297 | 3 | String baseDN = root.getNameInNamespace(); |
298 | 3 | NameParser np = root.getNameParser(""); |
299 | 3 | Name baseDNName = np.parse(baseDN); |
300 | 3 | Name dnName = np.parse(dn); |
301 | ||
302 | 3 | if (!dnName.isEmpty()) { |
303 | 2 | Name dnWithoutBaseDN = dnName.getSuffix(baseDNName.size()); |
304 | //System.out.println("DN w/o base DN: "+dnWithoutBaseDN);//**************** | |
305 | ||
306 | 2 | if (dnName.startsWith(baseDNName)){ |
307 | //System.out.println("DN starts with the Base DN");//************* | |
308 | 0 | dnName = dnName.getSuffix(baseDNName.size()); |
309 | ||
310 | //System.out.println("We've got "+dnName.toString());//************* | |
311 | }else{ | |
312 | // well... it should not come here! | |
313 | } | |
314 | } | |
315 | 3 | logger.debug("DN name = <"+dnName.toString()+">"); |
316 | 3 | return dnName.toString(); |
317 | } | |
318 | } |
|