]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.util/src/org/argeo/util/directory/ldap/IpaUtils.java
Refactor deploy properties and move legacy CMS exception.
[lgpl/argeo-commons.git] / org.argeo.util / src / org / argeo / util / directory / ldap / IpaUtils.java
1 package org.argeo.util.directory.ldap;
2
3 import java.io.IOException;
4 import java.net.InetAddress;
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.util.ArrayList;
8 import java.util.Dictionary;
9 import java.util.Hashtable;
10 import java.util.List;
11
12 import javax.naming.InvalidNameException;
13 import javax.naming.NamingException;
14 import javax.naming.ldap.LdapName;
15 import javax.naming.ldap.Rdn;
16
17 import org.argeo.util.directory.DirectoryConf;
18 import org.argeo.util.naming.LdapAttrs;
19 import org.argeo.util.naming.dns.DnsBrowser;
20
21 /** Free IPA specific conventions. */
22 public class IpaUtils {
23 public final static String IPA_USER_BASE = "cn=users";
24 public final static String IPA_GROUP_BASE = "cn=groups";
25 public final static String IPA_ROLE_BASE = "cn=roles";
26 public final static String IPA_SERVICE_BASE = "cn=services,cn=accounts";
27
28 public final static Rdn IPA_ACCOUNTS_RDN;
29 static {
30 try {
31 IPA_ACCOUNTS_RDN = new Rdn(LdapAttrs.cn.name(), "accounts");
32 } catch (InvalidNameException e) {
33 // should not happen
34 throw new IllegalStateException(e);
35 }
36 }
37
38 private final static String KRB_PRINCIPAL_NAME = LdapAttrs.krbPrincipalName.name().toLowerCase();
39
40 public final static String IPA_USER_DIRECTORY_CONFIG = DirectoryConf.userBase + "=" + IPA_USER_BASE + "&"
41 + DirectoryConf.groupBase + "=" + IPA_GROUP_BASE + "&" + DirectoryConf.systemRoleBase + "=" + IPA_ROLE_BASE
42 + "&" + DirectoryConf.readOnly + "=true";
43
44 @Deprecated
45 static String domainToUserDirectoryConfigPath(String realm) {
46 return domainToBaseDn(realm) + "?" + IPA_USER_DIRECTORY_CONFIG + "&" + DirectoryConf.realm.name() + "=" + realm;
47 }
48
49 public static void addIpaConfig(String realm, Dictionary<String, Object> properties) {
50 properties.put(DirectoryConf.baseDn.name(), domainToBaseDn(realm));
51 properties.put(DirectoryConf.realm.name(), realm);
52 properties.put(DirectoryConf.userBase.name(), IPA_USER_BASE);
53 properties.put(DirectoryConf.groupBase.name(), IPA_GROUP_BASE);
54 properties.put(DirectoryConf.systemRoleBase.name(), IPA_ROLE_BASE);
55 properties.put(DirectoryConf.readOnly.name(), Boolean.TRUE.toString());
56 }
57
58 public static String domainToBaseDn(String domain) {
59 String[] dcs = domain.split("\\.");
60 StringBuilder sb = new StringBuilder();
61 for (int i = 0; i < dcs.length; i++) {
62 if (i != 0)
63 sb.append(',');
64 String dc = dcs[i];
65 sb.append(LdapAttrs.dc.name()).append('=').append(dc.toLowerCase());
66 }
67 return sb.toString();
68 }
69
70 public static LdapName kerberosToDn(String kerberosName) {
71 String[] kname = kerberosName.split("@");
72 String username = kname[0];
73 String baseDn = domainToBaseDn(kname[1]);
74 String dn;
75 if (!username.contains("/"))
76 dn = LdapAttrs.uid + "=" + username + "," + IPA_USER_BASE + "," + IPA_ACCOUNTS_RDN + "," + baseDn;
77 else
78 dn = KRB_PRINCIPAL_NAME + "=" + kerberosName + "," + IPA_SERVICE_BASE + "," + baseDn;
79 try {
80 return new LdapName(dn);
81 } catch (InvalidNameException e) {
82 throw new IllegalArgumentException("Badly formatted name for " + kerberosName + ": " + dn);
83 }
84 }
85
86 private IpaUtils() {
87
88 }
89
90 public static String kerberosDomainFromDns() {
91 String kerberosDomain;
92 try (DnsBrowser dnsBrowser = new DnsBrowser()) {
93 InetAddress localhost = InetAddress.getLocalHost();
94 String hostname = localhost.getHostName();
95 String dnsZone = hostname.substring(hostname.indexOf('.') + 1);
96 kerberosDomain = dnsBrowser.getRecord("_kerberos." + dnsZone, "TXT");
97 return kerberosDomain;
98 } catch (NamingException | IOException e) {
99 throw new IllegalStateException("Cannot determine Kerberos domain from DNS", e);
100 }
101
102 }
103
104 public static Dictionary<String, Object> convertIpaUri(URI uri) {
105 String path = uri.getPath();
106 String kerberosRealm;
107 if (path == null || path.length() <= 1) {
108 kerberosRealm = kerberosDomainFromDns();
109 } else {
110 kerberosRealm = path.substring(1);
111 }
112
113 if (kerberosRealm == null)
114 throw new IllegalStateException("No Kerberos domain available for " + uri);
115 // TODO intergrate CA certificate in truststore
116 // String schemeToUse = SCHEME_LDAPS;
117 String schemeToUse = DirectoryConf.SCHEME_LDAP;
118 List<String> ldapHosts;
119 String ldapHostsStr = uri.getHost();
120 if (ldapHostsStr == null || ldapHostsStr.trim().equals("")) {
121 try (DnsBrowser dnsBrowser = new DnsBrowser()) {
122 ldapHosts = dnsBrowser.getSrvRecordsAsHosts("_ldap._tcp." + kerberosRealm.toLowerCase(),
123 schemeToUse.equals(DirectoryConf.SCHEME_LDAP) ? true : false);
124 if (ldapHosts == null || ldapHosts.size() == 0) {
125 throw new IllegalStateException("Cannot configure LDAP for IPA " + uri);
126 } else {
127 ldapHostsStr = ldapHosts.get(0);
128 }
129 } catch (NamingException | IOException e) {
130 throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
131 }
132 } else {
133 ldapHosts = new ArrayList<>();
134 ldapHosts.add(ldapHostsStr);
135 }
136
137 StringBuilder uriStr = new StringBuilder();
138 try {
139 for (String host : ldapHosts) {
140 URI convertedUri = new URI(schemeToUse + "://" + host + "/");
141 uriStr.append(convertedUri).append(' ');
142 }
143 } catch (URISyntaxException e) {
144 throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
145 }
146
147 Hashtable<String, Object> res = new Hashtable<>();
148 res.put(DirectoryConf.uri.name(), uriStr.toString());
149 addIpaConfig(kerberosRealm, res);
150 return res;
151 }
152 }