Skip to content

Commit

Permalink
ipa-kdb: Always allow services to get PAC if needed
Browse files Browse the repository at this point in the history
Previously, FreeIPA only allowed to issue PAC record in a ticket
for the following principal types:
   - for IPA users
   - for a host principal of one of IPA masters
   - for a cifs/ or HTTP/ service on one of IPA masters

To allow S4U2Self operations over trust to AD, an impersonating service
must have PAC record in its TGT to be able to ask AD DCs for a S4U2Self
ticket. It means any IPA service performing S4U2Self would need to have
PAC record and the constraints above prevent it from doing so.

However, depending on whether the service or host principal belongs to
one of IPA masters, we need to set proper primary RID to 516 (domain
controllers) or 515 (domain computers).

Fixes: https://pagure.io/freeipa/issue/8319

Signed-off-by: Alexander Bokovoy <[email protected]>
Reviewed-By: Isaac Boukris <[email protected]>
Reviewed-By: Florence Blanc-Renaud <[email protected]>
  • Loading branch information
abbra committed May 27, 2020
1 parent 015ae27 commit 3e20a96
Showing 1 changed file with 19 additions and 58 deletions.
77 changes: 19 additions & 58 deletions daemons/ipa-kdb/ipa_kdb_mspac.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,6 @@ static char *memberof_pac_attrs[] = {
NULL
};


static struct {
char *service;
int length;
} supported_services[] = {
{"cifs", sizeof("cifs")},
{"HTTP", sizeof("HTTP")},
{NULL, 0}
};


#define SID_ID_AUTHS 6
#define SID_SUB_AUTHS 15
#define MAX(a,b) (((a)>(b))?(a):(b))
Expand Down Expand Up @@ -435,7 +424,6 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
char *strres;
int intres;
int ret;
int i;
char **objectclasses = NULL;
size_t c;
bool is_host = false;
Expand All @@ -444,7 +432,6 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
bool is_ipauser = false;
bool is_idobject = false;
krb5_principal princ;
krb5_data *data;

ret = ipadb_ldap_attr_to_strlist(lcontext, lentry, "objectClass",
&objectclasses);
Expand Down Expand Up @@ -488,17 +475,10 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
/* fqdn is mandatory for hosts */
return ret;
}

/* Currently we only add a PAC to TGTs for IPA servers to allow SSSD in
* ipa_server_mode to access the AD LDAP server */
if (!is_master_host(ipactx, strres)) {
free(strres);
return ENOENT;
}
} else if (is_service) {
ret = ipadb_ldap_attr_to_str(lcontext, lentry, "krbPrincipalName", &strres);
ret = ipadb_ldap_attr_to_str(lcontext, lentry, "krbCanonicalName", &strres);
if (ret) {
/* krbPrincipalName is mandatory for services */
/* krbCanonicalName is mandatory for services */
return ret;
}

Expand All @@ -509,39 +489,10 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
return ENOENT;
}

if (krb5_princ_size(ipactx->kcontext, princ) != 2) {
krb5_free_principal(ipactx->kcontext, princ);
return ENOENT;
}

data = krb5_princ_component(ipactx->context, princ, 0);
for (i = 0; supported_services[i].service; i++) {
if (0 == memcmp(data->data, supported_services[i].service,
MIN(supported_services[i].length, data->length))) {
break;
}
}

if (supported_services[i].service == NULL) {
krb5_free_principal(ipactx->kcontext, princ);
return ENOENT;
}

data = krb5_princ_component(ipactx->context, princ, 1);
strres = malloc(data->length+1);
if (strres == NULL) {
krb5_free_principal(ipactx->kcontext, princ);
return ENOENT;
}

memcpy(strres, data->data, data->length);
strres[data->length] = '\0';
krb5_free_principal(ipactx->kcontext, princ);

/* Only add PAC to TGT to services on IPA masters to allow querying
* AD LDAP server */
if (!is_master_host(ipactx, strres)) {
free(strres);
ret = krb5_unparse_name_flags(ipactx->kcontext,
princ, KRB5_PRINCIPAL_UNPARSE_SHORT,
&strres);
if (ret) {
return ENOENT;
}
} else {
Expand Down Expand Up @@ -678,9 +629,19 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
info3->base.logon_count = 0; /* we do not have this info yet */
info3->base.bad_password_count = 0; /* we do not have this info yet */

if (is_host || is_service) {
/* Well know RID of domain controllers group */
info3->base.rid = 516;
if ((is_host || is_service)) {
/* it is either host or service, so get the hostname first */
char *sep = strchr(info3->base.account_name.string, '/');
bool is_master = is_master_host(
ipactx,
sep ? sep + 1 : info3->base.account_name.string);
if (is_master) {
/* Well know RID of domain controllers group */
info3->base.rid = 516;
} else {
/* Well know RID of domain computers group */
info3->base.rid = 515;
}
} else {
ret = ipadb_ldap_attr_to_str(lcontext, lentry,
"ipaNTSecurityIdentifier", &strres);
Expand Down

0 comments on commit 3e20a96

Please sign in to comment.