001package org.apache.archiva.redback.common.ldap;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import javax.naming.CompositeName;
023import javax.naming.InvalidNameException;
024import javax.naming.NamingEnumeration;
025import javax.naming.NamingException;
026import javax.naming.directory.Attribute;
027import javax.naming.directory.Attributes;
028import javax.naming.ldap.LdapName;
029import javax.naming.ldap.Rdn;
030
031/**
032 * 
033 *
034 */
035public final class LdapUtils
036{
037
038    private static String[] FILTER_ESCAPE_TABLE = new String['\\' + 1];
039
040
041    // Characters that must be escaped in a user filter
042    static {
043
044        // Filter encoding table -------------------------------------
045        // fill with char itself
046        for (char c = 0; c < FILTER_ESCAPE_TABLE.length; c++) {
047            FILTER_ESCAPE_TABLE[c] = String.valueOf(c);
048        }
049
050        // escapes (RFC2254)
051        FILTER_ESCAPE_TABLE['*'] = "\\2a";
052        FILTER_ESCAPE_TABLE['('] = "\\28";
053        FILTER_ESCAPE_TABLE[')'] = "\\29";
054        FILTER_ESCAPE_TABLE['\\'] = "\\5c";
055        FILTER_ESCAPE_TABLE[0] = "\\00";
056    }
057
058
059    private LdapUtils()
060    {
061        // no op
062    }
063
064    @SuppressWarnings("unchecked")
065    public static String getLabeledUriValue( Attributes attributes, String attrName, String label,
066                                             String attributeDescription )
067        throws MappingException
068    {
069        if ( attrName == null )
070        {
071            return null;
072        }
073
074        Attribute attribute = attributes.get( attrName );
075        if ( attribute != null )
076        {
077            NamingEnumeration attrs;
078            try
079            {
080                attrs = attribute.getAll();
081            }
082            catch ( NamingException e )
083            {
084                throw new MappingException(
085                    "Failed to retrieve " + attributeDescription + " (attribute: \'" + attrName + "\').", e );
086            }
087
088            while ( attrs.hasMoreElements() )
089            {
090                Object value = attrs.nextElement();
091
092                String val = String.valueOf( value );
093
094                if ( val.endsWith( " " + label ) )
095                {
096                    return val.substring( 0, val.length() - ( label.length() + 1 ) );
097                }
098            }
099        }
100
101        return null;
102    }
103
104    public static String getAttributeValue( Attributes attributes, String attrName, String attributeDescription )
105        throws MappingException
106    {
107        if ( attrName == null )
108        {
109            return null;
110        }
111
112        Attribute attribute = attributes.get( attrName );
113        if ( attribute != null )
114        {
115            try
116            {
117                Object value = attribute.get();
118
119                return String.valueOf( value );
120            }
121            catch ( NamingException e )
122            {
123                throw new MappingException(
124                    "Failed to retrieve " + attributeDescription + " (attribute: \'" + attrName + "\').", e );
125            }
126        }
127
128        return null;
129    }
130
131    public static String getAttributeValueFromByteArray( Attributes attributes, String attrName,
132                                                         String attributeDescription )
133        throws MappingException
134    {
135        if ( attrName == null )
136        {
137            return null;
138        }
139
140        Attribute attribute = attributes.get( attrName );
141        if ( attribute != null )
142        {
143            try
144            {
145                byte[] value = (byte[]) attribute.get();
146
147                return new String( value );
148            }
149            catch ( NamingException e )
150            {
151                throw new MappingException(
152                    "Failed to retrieve " + attributeDescription + " (attribute: \'" + attrName + "\').", e );
153            }
154        }
155
156        return null;
157    }
158
159    /**
160     * Returns a LDAP name from a given RDN string. The  <code>name</code> parameter must be a string
161     * representation of a composite name (as returned by ldapsearch result getName())
162     * @param name The string of the RDN (may be escaped)
163     * @return The LdapName that corresponds to this string
164     * @throws InvalidNameException If the string cannot be parsed as LDAP name
165     */
166    public static LdapName getLdapNameFromString(final String name) throws InvalidNameException
167    {
168        CompositeName coName = new CompositeName( name );
169        LdapName ldapName = new LdapName( "" );
170        ldapName.addAll( coName );
171        return ldapName;
172    }
173
174    /**
175     * Returns the first RDN value that matches the given type.
176     * E.g. for the RDN ou=People,dc=test,dc=de, and type dc it will return 'test'.
177     *
178     * @param name the ldap name
179     * @param type the type of the RDN entry
180     * @return
181     */
182    public static String findFirstRdnValue(LdapName name, String type) {
183        for ( Rdn rdn : name.getRdns() )
184        {
185            if ( rdn.getType( ).equals( type ) )
186            {
187                Object val = rdn.getValue( );
188                if (val!=null) {
189                    return val.toString( );
190                } else {
191                    return "";
192                }
193            }
194        }
195        return "";
196    }
197
198    /**
199     * Escape a value for use in a filter.
200     * This method is copied from the spring framework class org.springframework.security.ldap.authentication.LdapEncoder
201     *
202     * @param value the value to escape.
203     * @return a properly escaped representation of the supplied value.
204     */
205    public static String encodeFilterValue(String value) {
206
207            if (value == null) {
208                return null;
209            }
210
211            // make buffer roomy
212            StringBuilder encodedValue = new StringBuilder(value.length() * 2);
213
214            int length = value.length();
215
216            for (int i = 0; i < length; i++) {
217
218                char c = value.charAt(i);
219
220                if (c < FILTER_ESCAPE_TABLE.length) {
221                    encodedValue.append(FILTER_ESCAPE_TABLE[c]);
222                }
223                else {
224                    // default: add the char
225                    encodedValue.append(c);
226                }
227            }
228
229            return encodedValue.toString();
230    }
231}