]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - useradmin/UserAdminConf.java
1 package org
.argeo
.osgi
.useradmin
;
3 import java
.io
.IOException
;
4 import java
.net
.InetAddress
;
6 import java
.net
.URISyntaxException
;
7 import java
.util
.Dictionary
;
8 import java
.util
.Enumeration
;
9 import java
.util
.Hashtable
;
10 import java
.util
.List
;
13 import javax
.naming
.Context
;
14 import javax
.naming
.NamingException
;
16 import org
.apache
.commons
.logging
.Log
;
17 import org
.apache
.commons
.logging
.LogFactory
;
18 import org
.argeo
.naming
.DnsBrowser
;
19 import org
.argeo
.naming
.NamingUtils
;
20 import org
.osgi
.framework
.Constants
;
22 /** Properties used to configure user admins. */
23 public enum UserAdminConf
{
24 /** Base DN (cannot be configured externally) */
25 baseDn("dc=example,dc=com"),
27 /** URI of the underlying resource (cannot be configured externally) */
28 uri("ldap://localhost:10389"),
30 /** User objectClass */
31 userObjectClass("inetOrgPerson"),
33 /** Relative base DN for users */
34 userBase("ou=People"),
36 /** Groups objectClass */
37 groupObjectClass("groupOfNames"),
39 /** Relative base DN for users */
40 groupBase("ou=Groups"),
42 /** Read-only source */
45 /** Authentication realm */
48 public final static String FACTORY_PID
= "org.argeo.osgi.useradmin.config";
49 private final static Log log
= LogFactory
.getLog(UserAdminConf
.class);
51 /** The default value. */
54 UserAdminConf(Object def
) {
58 public Object
getDefault() {
63 * For use as Java property.
65 * @deprecated use {@link #name()} instead
68 public String
property() {
72 public String
getValue(Dictionary
<String
, ?
> properties
) {
73 Object res
= getRawValue(properties
);
76 return res
.toString();
79 @SuppressWarnings("unchecked")
80 public <T
> T
getRawValue(Dictionary
<String
, ?
> properties
) {
81 Object res
= properties
.get(name());
87 /** @deprecated use {@link #valueOf(String)} instead */
89 public static UserAdminConf
local(String property
) {
90 return UserAdminConf
.valueOf(property
);
93 /** Hides host and credentials. */
94 public static URI
propertiesAsUri(Dictionary
<String
, ?
> properties
) {
95 StringBuilder query
= new StringBuilder();
98 for (Enumeration
<String
> keys
= properties
.keys(); keys
.hasMoreElements();) {
99 String key
= keys
.nextElement();
100 // TODO clarify which keys are relevant (list only the enum?)
101 if (!key
.equals("service.factoryPid") && !key
.equals("cn") && !key
.equals("dn")
102 && !key
.equals(Constants
.SERVICE_PID
) && !key
.startsWith("java") && !key
.equals(baseDn
.name())
103 && !key
.equals(uri
.name())) {
108 query
.append(valueOf(key
).name());
109 query
.append('=').append(properties
.get(key
).toString());
113 String bDn
= (String
) properties
.get(baseDn
.name());
115 return new URI(null, null, bDn
!= null ?
'/' + bDn
: null, query
.length() != 0 ? query
.toString() : null,
117 } catch (URISyntaxException e
) {
118 throw new UserDirectoryException("Cannot create URI from properties", e
);
122 public static Dictionary
<String
, Object
> uriAsProperties(String uriStr
) {
124 Hashtable
<String
, Object
> res
= new Hashtable
<String
, Object
>();
125 URI u
= new URI(uriStr
);
126 String scheme
= u
.getScheme();
127 if (scheme
!= null && scheme
.equals("ipa")) {
128 u
= convertIpaConfig(u
);
129 scheme
= u
.getScheme();
131 String path
= u
.getPath();
133 String bDn
= path
.substring(path
.lastIndexOf('/') + 1, path
.length());
134 if (bDn
.endsWith(".ldif"))
135 bDn
= bDn
.substring(0, bDn
.length() - ".ldif".length());
137 String principal
= null;
138 String credentials
= null;
140 if (scheme
.equals("ldap") || scheme
.equals("ldaps")) {
141 // TODO additional checks
142 if (u
.getUserInfo() != null) {
143 String
[] userInfo
= u
.getUserInfo().split(":");
144 principal
= userInfo
.length
> 0 ? userInfo
[0] : null;
145 credentials
= userInfo
.length
> 1 ? userInfo
[1] : null;
147 } else if (scheme
.equals("file")) {
148 } else if (scheme
.equals("ipa")) {
150 throw new UserDirectoryException("Unsupported scheme " + scheme
);
151 Map
<String
, List
<String
>> query
= NamingUtils
.queryToMap(u
);
152 for (String key
: query
.keySet()) {
153 UserAdminConf ldapProp
= UserAdminConf
.valueOf(key
);
154 List
<String
> values
= query
.get(key
);
155 if (values
.size() == 1) {
156 res
.put(ldapProp
.name(), values
.get(0));
158 throw new UserDirectoryException("Only single values are supported");
161 res
.put(baseDn
.name(), bDn
);
162 if (principal
!= null)
163 res
.put(Context
.SECURITY_PRINCIPAL
, principal
);
164 if (credentials
!= null)
165 res
.put(Context
.SECURITY_CREDENTIALS
, credentials
);
166 if (scheme
!= null) {// relative URIs are dealt with externally
167 URI bareUri
= new URI(scheme
, null, u
.getHost(), u
.getPort(),
168 scheme
.equals("file") ? u
.getPath() : null, null, null);
169 res
.put(uri
.name(), bareUri
.toString());
172 } catch (Exception e
) {
173 throw new UserDirectoryException("Cannot convert " + uri
+ " to properties", e
);
177 private static URI
convertIpaConfig(URI uri
) {
178 String path
= uri
.getPath();
179 String kerberosRealm
;
180 if (path
== null || path
.length() <= 1) {
181 kerberosRealm
= kerberosDomainFromDns();
183 kerberosRealm
= path
.substring(1);
186 if (kerberosRealm
== null)
187 throw new UserDirectoryException("No Kerberos domain available for " + uri
);
188 try (DnsBrowser dnsBrowser
= new DnsBrowser()) {
189 String ldapHostsStr
= uri
.getHost();
190 if (ldapHostsStr
== null || ldapHostsStr
.trim().equals("")) {
191 List
<String
> ldapHosts
= dnsBrowser
.getSrvRecordsAsHosts("_ldap._tcp." + kerberosRealm
.toLowerCase());
192 if (ldapHosts
== null || ldapHosts
.size() == 0) {
193 throw new UserDirectoryException("Cannot configure LDAP for IPA " + uri
);
195 ldapHostsStr
= ldapHosts
.get(0);
198 URI convertedUri
= new URI(
199 "ldap://" + ldapHostsStr
+ "/" + IpaUtils
.domainToUserDirectoryConfigPath(kerberosRealm
));
200 if (log
.isDebugEnabled())
201 log
.debug("Converted " + uri
+ " to " + convertedUri
);
203 } catch (NamingException
| IOException
| URISyntaxException e
) {
204 throw new UserDirectoryException("cannot convert IPA uri " + uri
, e
);
208 private static String
kerberosDomainFromDns() {
209 String kerberosDomain
;
210 try (DnsBrowser dnsBrowser
= new DnsBrowser()) {
211 InetAddress localhost
= InetAddress
.getLocalHost();
212 String hostname
= localhost
.getHostName();
213 String dnsZone
= hostname
.substring(hostname
.indexOf('.') + 1);
214 kerberosDomain
= dnsBrowser
.getRecord("_kerberos." + dnsZone
, "TXT");
215 return kerberosDomain
;
216 } catch (Exception e
) {
217 throw new UserDirectoryException("Cannot determine Kerberos domain from DNS", e
);
222 // private static Map<String, List<String>> splitQuery(String query) throws
223 // UnsupportedEncodingException {
224 // final Map<String, List<String>> query_pairs = new LinkedHashMap<String,
226 // if (query == null)
227 // return query_pairs;
228 // final String[] pairs = query.split("&");
229 // for (String pair : pairs) {
230 // final int idx = pair.indexOf("=");
231 // final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx),
233 // if (!query_pairs.containsKey(key)) {
234 // query_pairs.put(key, new LinkedList<String>());
236 // final String value = idx > 0 && pair.length() > idx + 1
237 // ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null;
238 // query_pairs.get(key).add(value);
240 // return query_pairs;
243 public static void main(String
[] args
) {
244 Dictionary
<String
, ?
> props
= uriAsProperties("ldap://" + "uid=admin,ou=system:secret@localhost:10389"
245 + "/dc=example,dc=com" + "?readOnly=false&userObjectClass=person");
246 System
.out
.println(props
);
247 System
.out
.println(propertiesAsUri(props
));
249 System
.out
.println(uriAsProperties("file://some/dir/dc=example,dc=com.ldif"));
251 props
= uriAsProperties(
252 "/dc=example,dc=com.ldif?readOnly=true" + "&userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles");
253 System
.out
.println(props
);
254 System
.out
.println(propertiesAsUri(props
));