On Mon, 2014-06-16 at 09:53 +0200, Petr Viktorin wrote: > On 06/13/2014 10:20 PM, Simo Sorce wrote: > [...] > > 2) and I think this is a MUCH bigger issue, the Admin users are > > unbounded and pass any Access Control Check and this means they can now > > retrieve any key for users or machines. > > It is already bad enough that admins can unconditionally set any key, > > but this at least leaves back a pretty big trail (the original client > > password/key fails to work), and is a necessary evil (password resets, > > hosts creation/recovery). > > But I am not very comfortable with the idea an admin can retrieve any > > key without actually ending up changing it. Petr do we have any short > > term plan to address the Admin's super ACI ? > > No, nothing in the short term.
Ok, then I think attached is the patch 0003 we want. This changes admins superpowers to not allow ipaProtectedOperation by default and instead adds a specific right in cn=accounts so admin can keep fetching keytabs for any principal. We may want to turn this into a permission with a future patch. Simo. -- Simo Sorce * Red Hat, Inc * New York
>From e57e6286e2b8bd3764ca9501117526554d3f416b Mon Sep 17 00:00:00 2001 From: Simo Sorce <[email protected]> Date: Tue, 17 Sep 2013 00:30:14 -0400 Subject: [PATCH 3/6] keytab: Add new extended operation to get a keytab. This new extended operation allow to create new keys or retrieve existing ones. The new set of keys is returned as a ASN.1 structure similar to the one that is passed in by the 'set keytab' extended operation. Access to the operation is regulated through a new special ACI that allows 'retrieval' only if the user has access to an attribute named ipaProtectedOperation postfixed by the subtypes 'read_keys' and 'write_keys' to distinguish between creation and retrieval operation. For example for allowing retrieval by a specific user the following ACI is set on cn=accounts: (targetattr="ipaProtectedOperation;read_keys") ... ... userattr=ipaAllowedToPerform;read_keys#USERDN) This ACI matches only if the service object hosts a new attribute named ipaAllowedToPerform that holds the DN of the user attempting the operation. Resolves: https://fedorahosted.org/freeipa/ticket/3859 --- .../ipa-pwd-extop/ipa_pwd_extop.c | 571 +++++++++++++++++++++ install/share/60basev3.ldif | 3 + install/share/default-aci.ldif | 7 + install/updates/20-aci.update | 13 +- util/ipa_krb5.h | 1 + 5 files changed, 594 insertions(+), 1 deletion(-) diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c index c0bb9fda26172699e9ae7628f61b763c746188fe..e0f90832400dd470b18e21177c135f2855b6f239 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c @@ -1268,6 +1268,571 @@ free_and_return: return SLAPI_PLUGIN_EXTENDED_SENT_RESULT; } +/* Format of getkeytab request + * + * KeytabGetRequest ::= CHOICE { + * request [0] Request, + * reply [1] Reply + * } + * + * Request ::= SEQUENCE { + * serviceIdentity [0] OCTET STRING, + * getNew [1] Boolean, + * password [2] OCTET STRING OPTIONAL, + * enctypes [3] SEQUENCE OF Int16 OPTIONAL + * } + */ + +#define GKREQ_PASSWORD_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2) +#define GKREQ_ENCTYPES_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 3) + +static int decode_getkeytab_request(struct berval *extop, bool *wantold, + char **_svcname, char **_password, + krb5_key_salt_tuple **kenctypes, + int *num_kenctypes, char **_err_msg) +{ + int rc = LDAP_OPERATIONS_ERROR; + char *err_msg = NULL; + BerElement *ber = NULL; + ber_len_t tlen; + ber_tag_t rtag; + ber_tag_t ctag; + ber_int_t getnew = 0; + char *svcname = NULL; + char *password = NULL; + ber_int_t enctype; + krb5_key_salt_tuple *enctypes = NULL; + int num = 0; + + ber = ber_init(extop); + if (ber == NULL) { + err_msg = "KeytabGet Request decode failed.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto done; + } + + /* check this is a request */ + rtag = ber_peek_tag(ber, &tlen); + if (rtag != (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)) { + LOG_FATAL("ber_peek_tag failed\n"); + err_msg = "Invalid payload.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto done; + } + + /* ber parse code */ + rtag = ber_scanf(ber, "t[{t[a]", &ctag, &ctag, &svcname); + if (rtag == LBER_ERROR) { + LOG_FATAL("ber_scanf failed to decode service name\n"); + err_msg = "Invalid payload.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto done; + } + + rtag = ber_scanf(ber, "t[b]", &ctag, &getnew); + if (rtag == LBER_ERROR) { + LOG_FATAL("ber_scanf failed to decode request type\n"); + err_msg = "Invalid payload.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto done; + } + + rtag = ber_peek_tag(ber, &tlen); + if (rtag == GKREQ_PASSWORD_TAG) { + /* optional password present */ + rtag = ber_scanf(ber, "[a]", &password); + if (rtag == LBER_ERROR) { + LOG_FATAL("ber_scanf failed to decode password\n"); + err_msg = "Invalid payload.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto done; + } + rtag = ber_peek_tag(ber, &tlen); + } + + if (rtag == GKREQ_ENCTYPES_TAG) { + rtag = ber_scanf(ber, "[{"); + if (rtag == LBER_ERROR) { + LOG_FATAL("ber_scanf failed to decode enctypes\n"); + err_msg = "Invalid payload.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto done; + } + + rtag = ber_peek_tag(ber, &tlen); + for (num = 0; rtag == LBER_INTEGER; num++) { + if ((num % 10) == 0) { + /* allocate space for at least 10 more enctypes */ + enctypes = realloc(enctypes, + (num + 10) * sizeof(krb5_key_salt_tuple)); + if (!enctypes) { + LOG_FATAL("allocation failed\n"); + err_msg = "Internal error\n"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + } + + rtag = ber_scanf(ber, "i", &enctype); + if (rtag == LBER_ERROR) { + LOG_FATAL("ber_scanf failed to decode enctype\n"); + err_msg = "Invalid payload.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto done; + } + + enctypes[num].ks_enctype = enctype; + enctypes[num].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL; + rtag = ber_peek_tag(ber, &tlen); + } + } + + rc = LDAP_SUCCESS; + +done: + if (rc != LDAP_SUCCESS) { + free(password); + free(svcname); + *_err_msg = err_msg; + } else { + *_password = password; + *_svcname = svcname; + *wantold = (getnew == 0); + *kenctypes = enctypes; + *num_kenctypes = num; + } + if (ber) ber_free(ber, 1); + return rc; +} + +/* Format of getkeytab reply + * + * Reply ::= SEQUENCE { + * new_kvno Int32 + * keys SEQUENCE OF KrbKey, + * } + * + * KrbKey ::= SEQUENCE { + * key [0] EncryptionKey, + * salt [1] KrbSalt OPTIONAL, + * s2kparams [2] OCTET STRING OPTIONAL, + * } + * + * EncryptionKey ::= SEQUENCE { + * keytype [0] Int32, + * keyvalue [1] OCTET STRING + * } + * + * KrbSalt ::= SEQUENCE { + * type [0] Int32, + * salt [1] OCTET STRING + * } + */ + +#define GKREP_KVNO_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1) +#define GKREP_KEY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0) +#define GKREP_SALT_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1) +#define GKREP_S2KPARAMS_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2) +#define GKREP_KEYTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0) +#define GKREP_KEYVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1) +#define GKREP_SALTTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0) +#define GKREP_SALTVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1) + +static int encode_getkeytab_reply(krb5_context krbctx, + krb5_keyblock *kmkey, int mkvno, + krb5_key_data *keys, int num_keys, + struct berval **_bvp) +{ + int rc = LDAP_OPERATIONS_ERROR; + struct berval *bvp = NULL; + BerElement *ber = NULL; + ber_int_t kvno; + krb5_data plain = { 0 }; + + ber = ber_alloc(); + if (!ber) { + LOG_OOM(); + goto done; + } + + /* uses last key kvno */ + kvno = keys[num_keys-1].key_data_kvno; + + rc = ber_printf(ber, "t[{i{", GKREP_KVNO_TAG, kvno); + if (rc == -1) { + rc = LDAP_OPERATIONS_ERROR; + LOG_FATAL("Failed to initiate key buffer\n"); + goto done; + } + + for (int i = 0; i < num_keys; i++) { + krb5_enc_data cipher = { 0 }; + krb5_int16 plen; + void *p; + + /* retrieve plain key */ + memcpy(&plen, keys[i].key_data_contents[0], 2); + cipher.ciphertext.data = (char *)keys[i].key_data_contents[0] + 2; + cipher.ciphertext.length = keys[i].key_data_length[0] - 2; + cipher.enctype = kmkey->enctype; + cipher.kvno = mkvno; + + plain.length = le16toh(plen); + p = realloc(plain.data, plain.length); + if (!p) { + LOG_FATAL("Failed to allocate plain buffer\n"); + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + plain.data = p; + + rc = krb5_c_decrypt(krbctx, kmkey, 0, 0, &cipher, &plain); + if (rc) { + LOG_FATAL("Failed to decrypt keys\n"); + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + rc = ber_printf(ber, + "{t[{t[i]t[o]}]", + GKREP_KEY_TAG, + GKREP_KEYTYPE_TAG, + (ber_int_t)keys[i].key_data_type[0], + GKREP_KEYVALUE_TAG, + plain.data, (ber_len_t)plain.length); + if (rc == -1) { + LOG_FATAL("Failed to encode key data\n"); + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + /* if salt available, add it */ + if (keys[i].key_data_length[1] != 0) { + rc = ber_printf(ber, + "t[{t[i]t[o]}]", + GKREP_SALT_TAG, + GKREP_SALTTYPE_TAG, + (ber_int_t)keys[i].key_data_type[1], + GKREP_SALTVALUE_TAG, + keys[i].key_data_contents[1], + (ber_len_t)keys[i].key_data_length[1]); + if (rc == -1) { + LOG_FATAL("Failed to encode salt data\n"); + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + } + + rc = ber_printf(ber, "}"); + if (rc == -1) { + LOG_FATAL("Failed to encode data\n"); + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + } + + rc = ber_printf(ber, "}}]"); + if (rc == -1) { + LOG_FATAL("Failed to terminate key buffer\n"); + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + rc = ber_flatten(ber, &bvp); + if (rc == -1) { + LOG_FATAL("Failed to encode key buffer\n"); + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + rc = LDAP_SUCCESS; + +done: + if (rc != LDAP_SUCCESS) { + if (bvp) ber_bvfree(bvp); + } else { + *_bvp = bvp; + } + if (ber) ber_free(ber, 1); + free(plain.data); + return rc; +} + +static int get_decoded_key_data(char *svcname, + krb5_key_data **_keys, int *_num_keys, + int *_mkvno, char **_err_msg) +{ + int rc = LDAP_OPERATIONS_ERROR; + char *err_msg = NULL; + krb5_key_data *keys = NULL; + int num_keys = 0; + int mkvno = 0; + Slapi_Entry *target = NULL; + Slapi_Attr *attr; + Slapi_Value *keys_value; + const struct berval *encoded_keys; + + target = get_entry_by_principal(svcname); + if (!target) { + err_msg = "PrincipalName disappeared while processing.\n"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + rc = slapi_entry_attr_find(target, "krbPrincipalKey", &attr); + if (rc) { + err_msg = "krbPrincipalKey not found\n"; + rc = LDAP_NO_SUCH_ATTRIBUTE; + goto done; + } + rc = slapi_attr_first_value(attr, &keys_value); + if (rc) { + err_msg = "Error retrieving krbPrincipalKey\n"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + encoded_keys = slapi_value_get_berval(keys_value); + if (!encoded_keys) { + err_msg = "Error retrieving encoded krbPrincipalKey\n"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + rc = ber_decode_krb5_key_data(discard_const(encoded_keys), + &mkvno, &num_keys, &keys); + if (rc) { + err_msg = "Error retrieving decoded krbPrincipalKey\n"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + if (num_keys <= 0) { + err_msg = "No krbPrincipalKeys available\n"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + rc = LDAP_SUCCESS; + +done: + if (rc != LDAP_SUCCESS) { + if (keys) ipa_krb5_free_key_data(keys, num_keys); + *_err_msg = err_msg; + } else { + *_mkvno = mkvno; + *_keys = keys; + *_num_keys = num_keys; + } + if (target) slapi_entry_free(target); + return rc; +} + +#define WRITEKEYS_OP_CHECK "ipaProtectedOperation;write_keys" +#define READKEYS_OP_CHECK "ipaProtectedOperation;read_keys" + +/* Password Modify Extended operation plugin function */ +static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) +{ + char *bind_dn = NULL; + char *err_msg = NULL; + int rc = 0; + krb5_context krbctx = NULL; + krb5_error_code krberr; + struct berval *extop_value = NULL; + BerElement *ber = NULL; + char *service_name = NULL; + char *svcname; + Slapi_Entry *target_entry = NULL; + bool acl_ok = false; + char *password = NULL; + int num_kenctypes = 0; + krb5_key_salt_tuple *kenctypes = NULL; + int mkvno = 0; + int num_keys = 0; + krb5_key_data *keys = NULL; + struct ipapwd_data data = { 0 }; + Slapi_Value **svals = NULL; + struct berval *bvp = NULL; + LDAPControl new_ctrl; + bool wantold = false; + + /* Get Bind DN */ + slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn); + + /* If the connection is bound anonymously, we must refuse to process + * this operation. */ + if (bind_dn == NULL || *bind_dn == '\0') { + /* Refuse the operation because they're bound anonymously */ + err_msg = "Anonymous Binds are not allowed.\n"; + rc = LDAP_INSUFFICIENT_ACCESS; + goto free_and_return; + } + + krberr = krb5_init_context(&krbctx); + if (krberr) { + LOG_FATAL("krb5_init_context failed\n"); + rc = LDAP_OPERATIONS_ERROR; + goto free_and_return; + } + + /* Get the ber value of the extended operation */ + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); + if (!extop_value) { + LOG_FATAL("Failed to retrieve extended op value from pblock\n"); + err_msg = "Failed to retrieve extended operation value\n"; + rc = LDAP_OPERATIONS_ERROR; + goto free_and_return; + } + + rc = decode_getkeytab_request(extop_value, &wantold, &service_name, + &password, &kenctypes, &num_kenctypes, + &err_msg); + if (rc != LDAP_SUCCESS) { + goto free_and_return; + } + + /* make sure it is a valid name */ + svcname = check_service_name(krbctx, service_name); + if (!svcname) { + rc = LDAP_OPERATIONS_ERROR; + goto free_and_return; + } + slapi_ch_free_string(&service_name); + service_name = svcname; + + /* check entry */ + + /* get Entry by krbPrincipalName */ + target_entry = get_entry_by_principal(service_name); + if (!target_entry) { + err_msg = "PrincipalName not found.\n"; + rc = LDAP_NO_SUCH_OBJECT; + goto free_and_return; + } + + /* ok access allowed */ + /* do we need to create new keys ? */ + if (wantold) { /* requesting to retrieve existing ones */ + + /* check if we are allowed to *read* keys */ + acl_ok = is_allowed_to_access_attr(pb, bind_dn, target_entry, + READKEYS_OP_CHECK, NULL, + SLAPI_ACL_READ); + if (!acl_ok) { + LOG_FATAL("Not allowed to retrieve keytab on [%s]!\n", + service_name); + err_msg = "Insufficient access rights\n"; + rc = LDAP_INSUFFICIENT_ACCESS; + goto free_and_return; + } + + } else { + + /* check if we are allowed to *write* keys */ + acl_ok = is_allowed_to_access_attr(pb, bind_dn, target_entry, + WRITEKEYS_OP_CHECK, NULL, + SLAPI_ACL_WRITE); + if (!acl_ok) { + LOG_FATAL("Not allowed to set keytab on [%s]!\n", + service_name); + err_msg = "Insufficient access rights\n"; + rc = LDAP_INSUFFICIENT_ACCESS; + goto free_and_return; + } + + for (int i = 0; i < num_kenctypes; i++) { + + /* Check if supported */ + for (int j = 0; j < krbcfg->num_supp_encsalts; j++) { + if (kenctypes[i].ks_enctype == + krbcfg->supp_encsalts[j].ks_enctype) { + continue; + } + } + /* Unsupported, filter out */ + for (int j = i; j + 1 < num_kenctypes; j++) { + kenctypes[j].ks_enctype = kenctypes[j + 1].ks_enctype; + kenctypes[j].ks_salttype = kenctypes[j + 1].ks_salttype; + } + num_kenctypes--; + i--; + } + + /* check if we have any left */ + if (num_kenctypes == 0 && kenctypes != NULL) { + LOG_FATAL("keyset filtering rejected all proposed keys\n"); + err_msg = "All enctypes provided are unsupported"; + rc = LDAP_UNWILLING_TO_PERFORM; + goto free_and_return; + } + + /* only target is used, leave everything else NULL, + * if password is not provided we want to generate a random key */ + data.target = target_entry; + data.password = password; + + svals = ipapwd_encrypt_encode_key(krbcfg, &data, + kenctypes ? num_kenctypes : + krbcfg->num_pref_encsalts, + kenctypes ? kenctypes : + krbcfg->pref_encsalts, + &err_msg); + if (!svals) { + rc = LDAP_OPERATIONS_ERROR; + LOG_FATAL("encrypt_encode_keys failed!\n"); + err_msg = "Internal error while encrypting keys\n"; + goto free_and_return; + } + + rc = store_new_keys(target_entry, service_name, bind_dn, svals, + &err_msg); + if (rc != LDAP_SUCCESS) { + goto free_and_return; + } + } + + rc = get_decoded_key_data(service_name, + &keys, &num_keys, &mkvno, &err_msg); + if (rc != LDAP_SUCCESS) { + goto free_and_return; + } + + rc = encode_getkeytab_reply(krbctx, krbcfg->kmkey, mkvno, + keys, num_keys, &bvp); + if (rc != LDAP_SUCCESS) { + err_msg = "Internal Error.\n"; + goto free_and_return; + } + + new_ctrl.ldctl_oid = KEYTAB_GET_OID; + new_ctrl.ldctl_value = *bvp; + new_ctrl.ldctl_iscritical = 0; + rc = slapi_pblock_set(pb, SLAPI_ADD_RESCONTROL, &new_ctrl); + +free_and_return: + if (rc == LDAP_SUCCESS) err_msg = NULL; + LOG("%s", err_msg ? err_msg : "success"); + slapi_send_ldap_result(pb, rc, NULL, err_msg, 0, NULL); + + /* Free anything that we allocated above */ + if (krbctx) krb5_free_context(krbctx); + free(kenctypes); + free(service_name); + free(password); + if (target_entry) slapi_entry_free(target_entry); + if (keys) ipa_krb5_free_key_data(keys, num_keys); + if (svals) { + for (int i = 0; svals[i]; i++) { + slapi_value_free(&svals[i]); + } + free(svals); + } + if (ber) ber_free(ber, 1); + if (bvp) ber_bvfree(bvp); + + return SLAPI_PLUGIN_EXTENDED_SENT_RESULT; +} + static int ipapwd_extop(Slapi_PBlock *pb) { struct ipapwd_krbcfg *krbcfg = NULL; @@ -1305,6 +1870,11 @@ static int ipapwd_extop(Slapi_PBlock *pb) free_ipapwd_krbcfg(&krbcfg); return ret; } + if (strcasecmp(oid, KEYTAB_GET_OID) == 0) { + ret = ipapwd_getkeytab(pb, krbcfg); + free_ipapwd_krbcfg(&krbcfg); + return ret; + } errMesg = "Request OID does not match supported OIDs.\n"; rc = LDAP_OPERATIONS_ERROR; @@ -1438,6 +2008,7 @@ done: static char *ipapwd_oid_list[] = { EXOP_PASSWD_OID, KEYTAB_SET_OID, + KEYTAB_GET_OID, NULL }; diff --git a/install/share/60basev3.ldif b/install/share/60basev3.ldif index 552045b63d9485ccd3685942b10c3f0e5b6105b6..ff148e97c879d5652b1ce3c9b41443d84d49fe40 100644 --- a/install/share/60basev3.ldif +++ b/install/share/60basev3.ldif @@ -46,6 +46,8 @@ attributeTypes: (2.16.840.1.113730.3.8.11.46 NAME 'ipaPermLocation' DESC 'Locati attributeTypes: (2.16.840.1.113730.3.8.11.47 NAME 'ipaPermRight' DESC 'IPA permission rights' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v3' ) attributeTypes: (2.16.840.1.113730.3.8.11.48 NAME 'ipaPermTargetFilter' DESC 'IPA permission target filter' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v3' ) attributeTypes: (2.16.840.1.113730.3.8.11.49 NAME 'ipaPermTarget' DESC 'IPA permission target' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'IPA v3' ) +attributeTypes: (2.16.840.1.113730.3.8.11.51 NAME 'ipaAllowedToPerform' DESC 'DNs allowed to perform an operation' SUP distinguishedName X-ORIGIN 'IPA-v3') +attributeTypes: (2.16.840.1.113730.3.8.11.52 NAME 'ipaProtectedOperation' DESC 'Operation to be protected' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) objectClasses: (2.16.840.1.113730.3.8.12.1 NAME 'ipaExternalGroup' SUP top STRUCTURAL MUST ( cn ) MAY ( ipaExternalMember $ memberOf $ description $ owner) X-ORIGIN 'IPA v3' ) objectClasses: (2.16.840.1.113730.3.8.12.2 NAME 'ipaNTUserAttrs' SUP top AUXILIARY MUST ( ipaNTSecurityIdentifier ) MAY ( ipaNTHash $ ipaNTLogonScript $ ipaNTProfilePath $ ipaNTHomeDirectory $ ipaNTHomeDirectoryDrive ) X-ORIGIN 'IPA v3' ) objectClasses: (2.16.840.1.113730.3.8.12.3 NAME 'ipaNTGroupAttrs' SUP top AUXILIARY MUST ( ipaNTSecurityIdentifier ) X-ORIGIN 'IPA v3' ) @@ -64,4 +66,5 @@ objectClasses: (2.16.840.1.113730.3.8.12.17 NAME 'ipaTrustedADDomainRange' SUP i objectClasses: (2.16.840.1.113730.3.8.12.19 NAME 'ipaUserAuthTypeClass' SUP top AUXILIARY DESC 'Class for authentication methods definition' MAY ipaUserAuthType X-ORIGIN 'IPA v3') objectClasses: (2.16.840.1.113730.3.8.12.20 NAME 'ipaUser' AUXILIARY MUST ( uid ) MAY ( userClass ) X-ORIGIN 'IPA v3' ) objectClasses: (2.16.840.1.113730.3.8.12.21 NAME 'ipaPermissionV2' DESC 'IPA Permission objectclass, version 2' SUP ipaPermission AUXILIARY MUST ( ipaPermBindRuleType $ ipaPermLocation ) MAY ( ipaPermDefaultAttr $ ipaPermIncludedAttr $ ipaPermExcludedAttr $ ipaPermRight $ ipaPermTargetFilter $ ipaPermTarget ) X-ORIGIN 'IPA v3' ) +objectclasses: (2.16.840.1.113730.3.8.12.22 NAME 'ipaAllowedOperations' SUP top AUXILIARY DESC 'Class to apply access controls to arbitrary operations' MAY ( ipaAllowedToPerform $ ipaProtectedOperation ) X-ORIGIN 'IPA v3') objectClasses: (2.16.840.1.113730.3.8.12.23 NAME 'ipaVirtualOperation' DESC 'IPA Virtual operation objectclass' SUP top AUXILIARY MUST ( cn ) X-ORIGIN 'IPA v3' ) diff --git a/install/share/default-aci.ldif b/install/share/default-aci.ldif index 04fc185f785ee71246c6cc4f958c754158f16302..9219ae945f7e014b4a207d6e82ac7c2cbf007b85 100644 --- a/install/share/default-aci.ldif +++ b/install/share/default-aci.ldif @@ -26,6 +26,13 @@ changetype: modify add: aci aci: (targetattr = "krbMaxPwdLife || krbMinPwdLife || krbPwdMinDiffChars || krbPwdMinLength || krbPwdHistoryLength")(version 3.0;acl "Admins can write password policy"; allow (write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) aci: (targetattr = "aci")(version 3.0;acl "Admins can manage delegations"; allow (write, delete) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) +aci: (targetattr="ipaProtectedOperation;read_keys")(version 3.0; acl "Users allowed to retrieve keytab keys"; allow(read) userattr="ipaAllowedToPerform;read_keys#USERDN";) +aci: (targetattr="ipaProtectedOperation;read_keys")(version 3.0; acl "Groups allowed to retrieve keytab keys"; allow(read) userattr="ipaAllowedToPerform;read_keys#GROUPDN";) +aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Users allowed to create keytab keys"; allow(write) userattr="ipaAllowedToPerform;write_keys#USERDN";) +aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Groups allowed to create keytab keys"; allow(write) userattr="ipaAllowedToPerform;write_keys#GROUPDN";) +aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Entities are allowed to rekey themselves"; allow(write) userdn="ldap:///self";) +aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Admins are allowed to rekey any entity"; allow(write) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,dc=ipa,dc=dev,dc=lan";) +aci: (targetfilter="(|(objectclass=ipaHost)(objectclass=ipaService))")(targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Entities are allowed to rekey managed entries"; allow(write) userattr="managedby#USERDN";) dn: cn=services,cn=accounts,$SUFFIX changetype: modify diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update index 6af800111f30d26d37ceb0849f8730a3e15dad0b..77b0352c0805b1485f6a99c8a9fdf3c0228725e8 100644 --- a/install/updates/20-aci.update +++ b/install/updates/20-aci.update @@ -39,7 +39,8 @@ remove:aci:'(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword | remove:aci:'(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || krbPrincipalName || krbCanonicalName || krbUPEnabled || krbTicketPolicyReference || krbPrincipalExpiration || krbPasswordExpiration || krbPwdPolicyReference || krbPrincipalType || krbPwdHistory || krbLastPwdChange || krbPrincipalAliases || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount || krbTicketFlags || ipaUniqueId || memberOf || serverHostName || enrolledBy || ipaNTHash")(version 3.0; acl "Admin can manage any entry"; allow (all) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' remove:aci:'(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || krbPrincipalName || krbCanonicalName || krbUPEnabled || krbTicketPolicyReference || krbPrincipalExpiration || krbPasswordExpiration || krbPwdPolicyReference || krbPrincipalType || krbPwdHistory || krbLastPwdChange || krbPrincipalAliases || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount || ipaUniqueId || memberOf || serverHostName || enrolledBy || ipaNTHash")(version 3.0; acl "Admin can manage any entry"; allow (all) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' remove:aci:'(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || krbPrincipalName || krbCanonicalName || krbUPEnabled || krbTicketPolicyReference || krbPasswordExpiration || krbPwdPolicyReference || krbPrincipalType || krbPwdHistory || krbLastPwdChange || krbPrincipalAliases || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount || ipaUniqueId || memberOf || serverHostName || enrolledBy || ipaNTHash")(version 3.0; acl "Admin can manage any entry"; allow (all) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' -add:aci:'(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || krbPrincipalName || krbCanonicalName || krbPasswordExpiration || krbPwdHistory || krbLastPwdChange || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount || ipaUniqueId || memberOf || enrolledBy || ipaNTHash")(version 3.0; acl "Admin can manage any entry"; allow (all) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' +remove:aci:'(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || krbPrincipalName || krbCanonicalName || krbPasswordExpiration || krbPwdHistory || krbLastPwdChange || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount || ipaUniqueId || memberOf || enrolledBy || ipaNTHash")(version 3.0; acl "Admin can manage any entry"; allow (all) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' +add:aci:'(targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || krbPrincipalName || krbCanonicalName || krbPasswordExpiration || krbPwdHistory || krbLastPwdChange || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount || ipaUniqueId || memberOf || enrolledBy || ipaNTHash || ipaProtectedOperation")(version 3.0; acl "Admin can manage any entry"; allow (all) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' # Write-only remove:aci:'(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Admins can write passwords"; allow (add,delete,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' add:aci:'(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || ipaNTHash")(version 3.0; acl "Admins can write passwords"; allow (add,delete,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)' @@ -65,3 +66,13 @@ remove:aci: '(targetattr = "*")(version 3.0; acl "No anonymous access to hbac"; dn: cn=sudo,$SUFFIX remove:aci: '(targetattr = "*")(version 3.0; acl "No anonymous access to sudo"; deny (read,search,compare) userdn != "ldap:///all";)' + +# Get Keytab operation Access Control +dn: cn=accounts,$SUFFIX +add:aci: (targetattr="ipaProtectedOperation;read_keys")(version 3.0; acl "Users allowed to retrieve keytab keys"; allow(read) userattr="ipaAllowedToPerform;read_keys#USERDN";) +add:aci: (targetattr="ipaProtectedOperation;read_keys")(version 3.0; acl "Groups allowed to retrieve keytab keys"; allow(read) userattr="ipaAllowedToPerform;read_keys#GROUPDN";) +add:aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Users allowed to create keytab keys"; allow(write) userattr="ipaAllowedToPerform;write_keys#USERDN";) +add:aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Groups allowed to create keytab keys"; allow(write) userattr="ipaAllowedToPerform;write_keys#GROUPDN";) +add:aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Entities are allowed to rekey themselves"; allow(write) userdn="ldap:///self";) +add:aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Admins are allowed to rekey any entity"; allow(write) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,dc=ipa,dc=dev,dc=lan";) +add:aci: (targetfilter="(|(objectclass=ipaHost)(objectclass=ipaService))")(targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Entities are allowed to rekey managed entries"; allow(write) userattr="managedby#USERDN";) diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h index 7fb0355724e3c4f522097df417d2686b85619319..2431fd70b01b86266700e0d30a9cbd2b8f7c7ded 100644 --- a/util/ipa_krb5.h +++ b/util/ipa_krb5.h @@ -27,6 +27,7 @@ struct keys_container { #define KEYTAB_SET_OID "2.16.840.1.113730.3.8.10.1" #define KEYTAB_RET_OID "2.16.840.1.113730.3.8.10.2" +#define KEYTAB_GET_OID "2.16.840.1.113730.3.8.10.5" void ipa_krb5_free_ktypes(krb5_context context, krb5_enctype *val); -- 1.9.3
_______________________________________________ Freeipa-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/freeipa-devel
