summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Bokovoy <abokovoy@redhat.com>2015-03-26 14:34:06 +0200
committerAlexander Bokovoy <abokovoy@redhat.com>2015-07-07 10:33:53 +0300
commitb7a3b206deb3257b3a78939f0d2a6a114e48b758 (patch)
treef1b2cd372d811eb35a9214e30bd04d62d86dbbe7
parent8ee975b276d0728130a148b01f9bfc0b77524ae0 (diff)
downloadfreeipa-b7a3b206deb3257b3a78939f0d2a6a114e48b758.tar.gz
freeipa-b7a3b206deb3257b3a78939f0d2a6a114e48b758.tar.xz
freeipa-b7a3b206deb3257b3a78939f0d2a6a114e48b758.zip
add one-way trust support to ipasam
When trust is established, ipasam module creates a number of objects in LDAP to represent the trust information. Among them, for one-way trust we create a principal named IPA$@AD where IPA is a NetBIOS (flat) name of the IPA forest and AD is a realm of the trusted Active Directory forest root domain. This principal is then used by SSSD on IPA masters to authenticate against trusted Active Directory domain controllers and retrieve information about user and group identities. FreeIPA also uses this principal's credentials to retrieve domain topology. The access to the keys of the principal should be well-protected. We only allow to retrieve the keytab for it for members of cn=adtrust agents group. This group is populated with host/ and cifs/ principals from IPA masters. Starting with FreeIPA 4.2 the group will also have host/ principals of IPA masters where no ipa-adtrust-install was run. To add them, run ipa-adtrust-install on the master which will be configured to be a domain controller (e.g. run Samba with ipasam), and specify --add-agents option to trigger activation of the interactive mode to specify which IPA masters to enable. Fixes https://fedorahosted.org/freeipa/ticket/4962 Part of fixes for https://fedorahosted.org/freeipa/ticket/4546
-rw-r--r--daemons/ipa-sam/ipa_sam.c106
1 files changed, 85 insertions, 21 deletions
diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
index 07249fd27..19d0a23ab 100644
--- a/daemons/ipa-sam/ipa_sam.c
+++ b/daemons/ipa-sam/ipa_sam.c
@@ -147,6 +147,8 @@ void idmap_cache_set_sid2unixid(const struct dom_sid *sid, struct unixid *unix_i
#define LDAP_OBJ_KRB_PRINCIPAL_AUX "krbPrincipalAux"
#define LDAP_OBJ_KRB_TICKET_POLICY_AUX "krbTicketPolicyAux"
#define LDAP_ATTRIBUTE_KRB_PRINCIPAL "krbPrincipalName"
+#define LDAP_ATTRIBUTE_KRB_TICKET_FLAGS "krbTicketFlags"
+#define LDAP_ATTRIBUTE_IPAOPALLOW "ipaAllowedToPerform;read_keys"
#define LDAP_OBJ_IPAOBJECT "ipaObject"
#define LDAP_OBJ_IPAHOST "ipaHost"
@@ -157,9 +159,13 @@ void idmap_cache_set_sid2unixid(const struct dom_sid *sid, struct unixid *unix_i
#define LDAP_OBJ_IPAUSERGROUP "ipaUserGroup"
#define LDAP_OBJ_POSIXGROUP "posixGroup"
#define LDAP_OBJ_DOMAINRELATED "domainRelatedObject"
+#define LDAP_OBJ_IPAOPALLOW "ipaAllowedOperations"
#define LDAP_CN_REALM_DOMAINS "cn=Realm Domains,cn=ipa,cn=etc"
+#define LDAP_CN_ADTRUST_AGENTS "cn=adtrust agents,cn=sysaccounts,cn=etc"
+#define LDAP_CN_ADTRUST_ADMINS "cn=trust admins,cn=groups,cn=accounts"
+
#define HAS_KRB_PRINCIPAL (1<<0)
#define HAS_KRB_PRINCIPAL_AUX (1<<1)
#define HAS_IPAOBJECT (1<<2)
@@ -171,6 +177,9 @@ void idmap_cache_set_sid2unixid(const struct dom_sid *sid, struct unixid *unix_i
#define HAS_POSIXGROUP (1<<8)
#define HAS_KRB_TICKET_POLICY_AUX (1<<9)
+/* krbTicketFlags flag to don't allow issuing any ticket, keep in decimal form for LDAP use*/
+#define IPASAM_DISALLOW_ALL_TIX 64
+
const struct dom_sid global_sid_Builtin = { 1, 1, {0,0,0,0,0,5},
{32,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
@@ -1677,11 +1686,16 @@ static bool search_krb_princ(struct ldapsam_privates *ldap_state,
return true;
}
+#define KRB_PRINC_DEFAULT_ENCTYPES "aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96,arcfour-hmac"
+
static int set_cross_realm_pw(struct ldapsam_privates *ldap_state,
TALLOC_CTX *mem_ctx,
- const char *princ, const char *pwd,
+ const char *princ,
+ const char *saltprinc,
+ const char *pwd,
const char *base_dn)
{
+
int ret;
krb5_error_code krberr;
krb5_context krbctx;
@@ -1699,14 +1713,14 @@ static int set_cross_realm_pw(struct ldapsam_privates *ldap_state,
goto done;
}
- krberr = krb5_parse_name(krbctx, princ, &service_princ);
+ krberr = krb5_parse_name(krbctx, (saltprinc != NULL) ? saltprinc : princ, &service_princ);
if (krberr != 0) {
DEBUG(1, ("Invalid Service Principal Name [%s]\n", princ));
ret = krberr;
goto done;
}
- ret = create_keys(krbctx, service_princ, discard_const(pwd), NULL,
+ ret = create_keys(krbctx, service_princ, discard_const(pwd), KRB_PRINC_DEFAULT_ENCTYPES,
&keys, &err_msg);
krb5_free_principal(krbctx, service_princ);
if (!ret) {
@@ -1748,10 +1762,16 @@ done:
return ret;
}
+#define KRB_PRINC_CREATE_DEFAULT 0x00000000
+#define KRB_PRINC_CREATE_DISABLED 0x00000001
+#define KRB_PRINC_CREATE_AGENT_PERMISSION 0x00000002
+
static bool set_krb_princ(struct ldapsam_privates *ldap_state,
TALLOC_CTX *mem_ctx,
- const char *princ, const char *pwd,
- const char *base_dn)
+ const char *princ, const char *saltprinc,
+ const char *pwd,
+ const char *base_dn,
+ uint32_t create_flags)
{
LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
@@ -1805,6 +1825,33 @@ static bool set_krb_princ(struct ldapsam_privates *ldap_state,
smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
LDAP_ATTRIBUTE_KRB_PRINCIPAL, princ);
+ if ((create_flags & KRB_PRINC_CREATE_DISABLED)) {
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+ LDAP_ATTRIBUTE_KRB_TICKET_FLAGS, __TALLOC_STRING_LINE2__(IPASAM_DISALLOW_ALL_TIX));
+ }
+
+ if ((create_flags & KRB_PRINC_CREATE_AGENT_PERMISSION)) {
+ char *agent_dn = NULL;
+ agent_dn = talloc_asprintf(mem_ctx, LDAP_CN_ADTRUST_AGENTS",%s", ldap_state->ipasam_privates->base_dn);
+ if (agent_dn == NULL) {
+ DEBUG(1, ("error configuring cross realm principal data!\n"));
+ return false;
+ }
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ LDAP_ATTRIBUTE_OBJECTCLASS,
+ LDAP_OBJ_IPAOPALLOW);
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+ LDAP_ATTRIBUTE_IPAOPALLOW, agent_dn);
+ agent_dn = talloc_asprintf(mem_ctx, LDAP_CN_ADTRUST_ADMINS",%s", ldap_state->ipasam_privates->base_dn);
+ if (agent_dn == NULL) {
+ DEBUG(1, ("error configuring cross realm principal data for trust admins!\n"));
+ return false;
+ }
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+ LDAP_ATTRIBUTE_IPAOPALLOW, agent_dn);
+ }
+
+
if (entry == NULL) {
ret = smbldap_add(ldap_state->smbldap_state, dn, mods);
} else {
@@ -1815,7 +1862,7 @@ static bool set_krb_princ(struct ldapsam_privates *ldap_state,
return false;
}
- ret = set_cross_realm_pw(ldap_state, mem_ctx, princ, pwd, base_dn);
+ ret = set_cross_realm_pw(ldap_state, mem_ctx, princ, saltprinc, pwd, base_dn);
if (ret != 0) {
DEBUG(1, ("set_cross_realm_pw failed.\n"));
return false;
@@ -1858,11 +1905,14 @@ enum princ_mod {
static bool handle_cross_realm_princs(struct ldapsam_privates *ldap_state,
const char *domain, const char *pwd,
+ uint32_t trust_direction,
enum princ_mod mod)
{
char *trusted_dn;
char *princ_l;
char *princ_r;
+ char *princ_tdo;
+ char *saltprinc_tdo;
char *remote_realm;
bool ok;
TALLOC_CTX *tmp_ctx;
@@ -1885,27 +1935,40 @@ static bool handle_cross_realm_princs(struct ldapsam_privates *ldap_state,
princ_r = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
ldap_state->ipasam_privates->realm, remote_realm);
- if (trusted_dn == NULL || princ_l == NULL || princ_r == NULL) {
+ princ_tdo = talloc_asprintf(tmp_ctx, "%s$@%s",
+ ldap_state->ipasam_privates->flat_name, remote_realm);
+
+ saltprinc_tdo = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
+ ldap_state->ipasam_privates->flat_name, remote_realm);
+
+ if (trusted_dn == NULL || princ_l == NULL ||
+ princ_r == NULL || princ_tdo == NULL || saltprinc_tdo == NULL) {
ok = false;
goto done;
}
switch (mod) {
case SET_PRINC:
- if (!set_krb_princ(ldap_state, tmp_ctx, princ_l, pwd,
- trusted_dn) ||
- !set_krb_princ(ldap_state, tmp_ctx, princ_r, pwd,
- trusted_dn)) {
- ok = false;
+ /* Create Kerberos principal for inbound trust, enabled by default */
+ ok = set_krb_princ(ldap_state, tmp_ctx, princ_r, NULL, pwd, trusted_dn, KRB_PRINC_CREATE_DEFAULT);
+ /* Create Kerberos principal corresponding to TDO in AD for SSSD usage, disabled by default */
+ ok |= set_krb_princ(ldap_state, tmp_ctx, princ_tdo, saltprinc_tdo, pwd, trusted_dn,
+ KRB_PRINC_CREATE_DISABLED | KRB_PRINC_CREATE_AGENT_PERMISSION);
+ if ((trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) != 0) {
+ /* Create Kerberos principal for outbound trust, enabled by default */
+ ok |= set_krb_princ(ldap_state, tmp_ctx, princ_l, NULL, pwd, trusted_dn, KRB_PRINC_CREATE_DEFAULT);
+ }
+ if (!ok) {
goto done;
}
break;
case DEL_PRINC:
- if (!del_krb_princ(ldap_state, tmp_ctx, princ_l,
- trusted_dn) ||
- !del_krb_princ(ldap_state, tmp_ctx, princ_r,
- trusted_dn)) {
- ok = false;
+ ok = del_krb_princ(ldap_state, tmp_ctx, princ_r, trusted_dn);
+ ok |= del_krb_princ(ldap_state, tmp_ctx, princ_tdo, trusted_dn);
+ if ((trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) != 0) {
+ ok |= del_krb_princ(ldap_state, tmp_ctx, princ_l, trusted_dn);
+ }
+ if (!ok) {
goto done;
}
break;
@@ -1922,15 +1985,16 @@ done:
}
static bool set_cross_realm_princs(struct ldapsam_privates *ldap_state,
- const char *domain, const char *pwd)
+ const char *domain, const char *pwd, uint32_t trust_direction)
{
- return handle_cross_realm_princs(ldap_state, domain, pwd, SET_PRINC);
+ return handle_cross_realm_princs(ldap_state, domain, pwd, trust_direction, SET_PRINC);
}
static bool del_cross_realm_princs(struct ldapsam_privates *ldap_state,
const char *domain)
{
- return handle_cross_realm_princs(ldap_state, domain, NULL, DEL_PRINC);
+ uint32_t trust_direction = LSA_TRUST_DIRECTION_INBOUND | LSA_TRUST_DIRECTION_OUTBOUND;
+ return handle_cross_realm_princs(ldap_state, domain, NULL, trust_direction, DEL_PRINC);
}
static bool get_trusted_domain_int(struct ldapsam_privates *ldap_state,
@@ -2518,7 +2582,7 @@ static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
goto done;
}
res = set_cross_realm_princs(ldap_state, td->domain_name,
- trustpw);
+ trustpw, td->trust_direction);
memset(trustpw, 0, strlen(trustpw));
if (!res) {
DEBUG(1, ("error writing cross realm principals!\n"));