| 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 | } | |
|
||||||||||