Line data Source code
1 : // Copyright (C) 2009 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.auth.ldap; 16 : 17 : import com.google.gerrit.common.Nullable; 18 : import com.google.gerrit.common.data.ParameterizedString; 19 : import com.google.gerrit.metrics.Timer0; 20 : import java.util.ArrayList; 21 : import java.util.Collections; 22 : import java.util.HashMap; 23 : import java.util.List; 24 : import java.util.Map; 25 : import java.util.Set; 26 : import javax.naming.NamingEnumeration; 27 : import javax.naming.NamingException; 28 : import javax.naming.PartialResultException; 29 : import javax.naming.directory.Attribute; 30 : import javax.naming.directory.BasicAttribute; 31 : import javax.naming.directory.DirContext; 32 : import javax.naming.directory.SearchControls; 33 : import javax.naming.directory.SearchResult; 34 : 35 : /** Supports issuing parameterized queries against an LDAP data source. */ 36 : class LdapQuery { 37 0 : static final Set<String> ALL_ATTRIBUTES = null; 38 : 39 : private final String base; 40 : private final SearchScope searchScope; 41 : private final ParameterizedString pattern; 42 : private final String[] returnAttributes; 43 : 44 : LdapQuery( 45 : final String base, 46 : final SearchScope searchScope, 47 : final ParameterizedString pattern, 48 0 : final Set<String> returnAttributes) { 49 0 : this.base = base; 50 0 : this.searchScope = searchScope; 51 : 52 0 : this.pattern = pattern; 53 : 54 0 : if (returnAttributes != null) { 55 0 : this.returnAttributes = new String[returnAttributes.size()]; 56 0 : returnAttributes.toArray(this.returnAttributes); 57 : } else { 58 0 : this.returnAttributes = null; 59 : } 60 0 : } 61 : 62 : List<String> getParameters() { 63 0 : return pattern.getParameterNames(); 64 : } 65 : 66 : List<Result> query(DirContext ctx, Map<String, String> params, Timer0 queryTimer) 67 : throws NamingException { 68 0 : final SearchControls sc = new SearchControls(); 69 : final NamingEnumeration<SearchResult> res; 70 : 71 0 : sc.setSearchScope(searchScope.scope()); 72 0 : sc.setReturningAttributes(returnAttributes); 73 0 : try (Timer0.Context ignored = queryTimer.start()) { 74 0 : res = ctx.search(base, pattern.getRawPattern(), pattern.bind(params), sc); 75 : } 76 : try { 77 0 : final List<Result> r = new ArrayList<>(); 78 : try { 79 0 : while (res.hasMore()) { 80 0 : r.add(new Result(res.next())); 81 : } 82 0 : } catch (PartialResultException e) { 83 : // Ignored 84 0 : } 85 0 : return r; 86 : } finally { 87 0 : res.close(); 88 : } 89 : } 90 : 91 : class Result { 92 0 : private final Map<String, Attribute> atts = new HashMap<>(); 93 : 94 0 : Result(SearchResult sr) { 95 0 : if (returnAttributes != null) { 96 0 : for (String attName : returnAttributes) { 97 0 : final Attribute a = sr.getAttributes().get(attName); 98 0 : if (a != null && a.size() > 0) { 99 0 : atts.put(attName, a); 100 : } 101 : } 102 : 103 : } else { 104 0 : NamingEnumeration<? extends Attribute> e = sr.getAttributes().getAll(); 105 0 : while (e.hasMoreElements()) { 106 0 : final Attribute a = e.nextElement(); 107 0 : atts.put(a.getID(), a); 108 0 : } 109 : } 110 : 111 0 : atts.put("dn", new BasicAttribute("dn", sr.getNameInNamespace())); 112 0 : } 113 : 114 : String getDN() throws NamingException { 115 0 : return get("dn"); 116 : } 117 : 118 : @Nullable 119 : String get(String attName) throws NamingException { 120 0 : final Attribute att = getAll(attName); 121 0 : return att != null && 0 < att.size() ? String.valueOf(att.get(0)) : null; 122 : } 123 : 124 : Attribute getAll(String attName) { 125 0 : return atts.get(attName); 126 : } 127 : 128 : Set<String> attributes() { 129 0 : return Collections.unmodifiableSet(atts.keySet()); 130 : } 131 : 132 : @Override 133 : public String toString() { 134 : try { 135 0 : return getDN(); 136 0 : } catch (NamingException e) { 137 0 : return ""; 138 : } 139 : } 140 : } 141 : }