2 Unix SMB/CIFS implementation.
3 IPA helper functions for SAMBA
4 Copyright (C) Sumit Bose <sbose@redhat.com> 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/security/dom_sid.h"
24 #include "../librpc/ndr/libndr.h"
25 #include "librpc/gen_ndr/samr.h"
29 #include "passdb/pdb_ldap.h"
31 #define IPA_KEYTAB_SET_OID "2.16.840.1.113730.3.8.3.1"
32 #define IPA_MAGIC_ID_STR "999"
34 #define LDAP_TRUST_CONTAINER "ou=system"
35 #define LDAP_ATTRIBUTE_CN "cn"
36 #define LDAP_ATTRIBUTE_TRUST_TYPE "sambaTrustType"
37 #define LDAP_ATTRIBUTE_TRUST_ATTRIBUTES "sambaTrustAttributes"
38 #define LDAP_ATTRIBUTE_TRUST_DIRECTION "sambaTrustDirection"
39 #define LDAP_ATTRIBUTE_TRUST_POSIX_OFFSET "sambaTrustPosixOffset"
40 #define LDAP_ATTRIBUTE_SUPPORTED_ENC_TYPE "sambaSupportedEncryptionTypes"
41 #define LDAP_ATTRIBUTE_TRUST_PARTNER "sambaTrustPartner"
42 #define LDAP_ATTRIBUTE_FLAT_NAME "sambaFlatName"
43 #define LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING "sambaTrustAuthOutgoing"
44 #define LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING "sambaTrustAuthIncoming"
45 #define LDAP_ATTRIBUTE_SECURITY_IDENTIFIER "sambaSecurityIdentifier"
46 #define LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO "sambaTrustForestTrustInfo"
47 #define LDAP_ATTRIBUTE_OBJECTCLASS "objectClass"
49 #define LDAP_OBJ_KRB_PRINCIPAL "krbPrincipal"
50 #define LDAP_OBJ_KRB_PRINCIPAL_AUX "krbPrincipalAux"
51 #define LDAP_ATTRIBUTE_KRB_PRINCIPAL "krbPrincipalName"
53 #define LDAP_OBJ_IPAOBJECT "ipaObject"
54 #define LDAP_OBJ_IPAHOST "ipaHost"
55 #define LDAP_OBJ_POSIXACCOUNT "posixAccount"
57 #define LDAP_OBJ_GROUPOFNAMES "groupOfNames"
58 #define LDAP_OBJ_NESTEDGROUP "nestedGroup"
59 #define LDAP_OBJ_IPAUSERGROUP "ipaUserGroup"
60 #define LDAP_OBJ_POSIXGROUP "posixGroup"
62 #define HAS_KRB_PRINCIPAL (1<<0)
63 #define HAS_KRB_PRINCIPAL_AUX (1<<1)
64 #define HAS_IPAOBJECT (1<<2)
65 #define HAS_IPAHOST (1<<3)
66 #define HAS_POSIXACCOUNT (1<<4)
67 #define HAS_GROUPOFNAMES (1<<5)
68 #define HAS_NESTEDGROUP (1<<6)
69 #define HAS_IPAUSERGROUP (1<<7)
70 #define HAS_POSIXGROUP (1<<8)
72 struct ipasam_privates {
74 NTSTATUS (*ldapsam_add_sam_account)(struct pdb_methods *,
75 struct samu *sampass);
76 NTSTATUS (*ldapsam_update_sam_account)(struct pdb_methods *,
77 struct samu *sampass);
78 NTSTATUS (*ldapsam_create_user)(struct pdb_methods *my_methods,
79 TALLOC_CTX *tmp_ctx, const char *name,
80 uint32_t acb_info, uint32_t *rid);
81 NTSTATUS (*ldapsam_create_dom_group)(struct pdb_methods *my_methods,
87 static bool ipasam_get_trusteddom_pw(struct pdb_methods *methods,
91 time_t *pass_last_set_time)
96 static bool ipasam_set_trusteddom_pw(struct pdb_methods *methods,
99 const struct dom_sid *sid)
104 static bool ipasam_del_trusteddom_pw(struct pdb_methods *methods,
110 static char *get_account_dn(const char *name)
115 escape_name = escape_rdn_val_string_alloc(name);
120 if (name[strlen(name)-1] == '$') {
121 dn = talloc_asprintf(talloc_tos(), "uid=%s,%s", escape_name,
122 lp_ldap_machine_suffix());
124 dn = talloc_asprintf(talloc_tos(), "uid=%s,%s", escape_name,
125 lp_ldap_user_suffix());
128 SAFE_FREE(escape_name);
133 static char *trusted_domain_dn(struct ldapsam_privates *ldap_state,
136 return talloc_asprintf(talloc_tos(), "%s=%s,%s,%s",
137 LDAP_ATTRIBUTE_CN, domain,
138 LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
141 static char *trusted_domain_base_dn(struct ldapsam_privates *ldap_state)
143 return talloc_asprintf(talloc_tos(), "%s,%s",
144 LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
147 static bool get_trusted_domain_int(struct ldapsam_privates *ldap_state,
149 const char *filter, LDAPMessage **entry)
152 char *base_dn = NULL;
153 LDAPMessage *result = NULL;
156 base_dn = trusted_domain_base_dn(ldap_state);
157 if (base_dn == NULL) {
161 rc = smbldap_search(ldap_state->smbldap_state, base_dn,
162 LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
163 TALLOC_FREE(base_dn);
165 if (result != NULL) {
166 talloc_autofree_ldapmsg(mem_ctx, result);
169 if (rc == LDAP_NO_SUCH_OBJECT) {
174 if (rc != LDAP_SUCCESS) {
178 num_result = ldap_count_entries(priv2ld(ldap_state), result);
180 if (num_result > 1) {
181 DEBUG(1, ("get_trusted_domain_int: more than one "
182 "%s object with filter '%s'?!\n",
183 LDAP_OBJ_TRUSTED_DOMAIN, filter));
187 if (num_result == 0) {
188 DEBUG(1, ("get_trusted_domain_int: no "
189 "%s object with filter '%s'.\n",
190 LDAP_OBJ_TRUSTED_DOMAIN, filter));
193 *entry = ldap_first_entry(priv2ld(ldap_state), result);
199 static bool get_trusted_domain_by_name_int(struct ldapsam_privates *ldap_state,
206 filter = talloc_asprintf(talloc_tos(),
207 "(&(objectClass=%s)(|(%s=%s)(%s=%s)(cn=%s)))",
208 LDAP_OBJ_TRUSTED_DOMAIN,
209 LDAP_ATTRIBUTE_FLAT_NAME, domain,
210 LDAP_ATTRIBUTE_TRUST_PARTNER, domain, domain);
211 if (filter == NULL) {
215 return get_trusted_domain_int(ldap_state, mem_ctx, filter, entry);
218 static bool get_trusted_domain_by_sid_int(struct ldapsam_privates *ldap_state,
220 const char *sid, LDAPMessage **entry)
224 filter = talloc_asprintf(talloc_tos(), "(&(objectClass=%s)(%s=%s))",
225 LDAP_OBJ_TRUSTED_DOMAIN,
226 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER, sid);
227 if (filter == NULL) {
231 return get_trusted_domain_int(ldap_state, mem_ctx, filter, entry);
234 static bool get_uint32_t_from_ldap_msg(struct ldapsam_privates *ldap_state,
243 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
246 DEBUG(9, ("Attribute %s not present.\n", attr));
251 l = strtoul(dummy, &endptr, 10);
254 if (l < 0 || l > UINT32_MAX || *endptr != '\0') {
263 static void get_data_blob_from_ldap_msg(TALLOC_CTX *mem_ctx,
264 struct ldapsam_privates *ldap_state,
265 LDAPMessage *entry, const char *attr,
271 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, attr,
274 DEBUG(9, ("Attribute %s not present.\n", attr));
277 blob = base64_decode_data_blob(dummy);
278 if (blob.length == 0) {
281 _blob->length = blob.length;
282 _blob->data = talloc_steal(mem_ctx, blob.data);
288 static bool fill_pdb_trusted_domain(TALLOC_CTX *mem_ctx,
289 struct ldapsam_privates *ldap_state,
291 struct pdb_trusted_domain **_td)
295 struct pdb_trusted_domain *td;
301 td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
306 /* All attributes are MAY */
308 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
309 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
312 DEBUG(9, ("Attribute %s not present.\n",
313 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER));
314 ZERO_STRUCT(td->security_identifier);
316 res = string_to_sid(&td->security_identifier, dummy);
323 get_data_blob_from_ldap_msg(td, ldap_state, entry,
324 LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
325 &td->trust_auth_incoming);
327 get_data_blob_from_ldap_msg(td, ldap_state, entry,
328 LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
329 &td->trust_auth_outgoing);
331 td->netbios_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
333 LDAP_ATTRIBUTE_FLAT_NAME,
335 if (td->netbios_name == NULL) {
336 DEBUG(9, ("Attribute %s not present.\n",
337 LDAP_ATTRIBUTE_FLAT_NAME));
340 td->domain_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
342 LDAP_ATTRIBUTE_TRUST_PARTNER,
344 if (td->domain_name == NULL) {
345 DEBUG(9, ("Attribute %s not present.\n",
346 LDAP_ATTRIBUTE_TRUST_PARTNER));
349 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
350 LDAP_ATTRIBUTE_TRUST_DIRECTION,
351 &td->trust_direction);
356 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
357 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
358 &td->trust_attributes);
363 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
364 LDAP_ATTRIBUTE_TRUST_TYPE,
370 td->trust_posix_offset = talloc(td, uint32_t);
371 if (td->trust_posix_offset == NULL) {
374 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
375 LDAP_ATTRIBUTE_TRUST_POSIX_OFFSET,
376 td->trust_posix_offset);
381 td->supported_enc_type = talloc(td, uint32_t);
382 if (td->supported_enc_type == NULL) {
385 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
386 LDAP_ATTRIBUTE_SUPPORTED_ENC_TYPE,
387 td->supported_enc_type);
393 get_data_blob_from_ldap_msg(td, ldap_state, entry,
394 LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO,
395 &td->trust_forest_trust_info);
402 static NTSTATUS ipasam_get_trusted_domain(struct pdb_methods *methods,
405 struct pdb_trusted_domain **td)
407 struct ldapsam_privates *ldap_state =
408 (struct ldapsam_privates *)methods->private_data;
409 LDAPMessage *entry = NULL;
411 DEBUG(10, ("ipasam_get_trusted_domain called for domain %s\n", domain));
413 if (!get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
415 return NT_STATUS_UNSUCCESSFUL;
418 DEBUG(5, ("ipasam_get_trusted_domain: no such trusted domain: "
420 return NT_STATUS_NO_SUCH_DOMAIN;
423 if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
424 return NT_STATUS_UNSUCCESSFUL;
430 static NTSTATUS ipasam_get_trusted_domain_by_sid(struct pdb_methods *methods,
433 struct pdb_trusted_domain **td)
435 struct ldapsam_privates *ldap_state =
436 (struct ldapsam_privates *)methods->private_data;
437 LDAPMessage *entry = NULL;
440 sid_str = sid_string_tos(sid);
442 DEBUG(10, ("ipasam_get_trusted_domain_by_sid called for sid %s\n",
445 if (!get_trusted_domain_by_sid_int(ldap_state, talloc_tos(), sid_str,
447 return NT_STATUS_UNSUCCESSFUL;
450 DEBUG(5, ("ipasam_get_trusted_domain_by_sid: no trusted domain "
451 "with sid: %s\n", sid_str));
452 return NT_STATUS_NO_SUCH_DOMAIN;
455 if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
456 return NT_STATUS_UNSUCCESSFUL;
462 static bool smbldap_make_mod_uint32_t(LDAP *ldap_struct, LDAPMessage *entry,
463 LDAPMod ***mods, const char *attribute,
468 dummy = talloc_asprintf(talloc_tos(), "%lu", (unsigned long) val);
472 smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
478 static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
480 const struct pdb_trusted_domain *td)
482 struct ldapsam_privates *ldap_state =
483 (struct ldapsam_privates *)methods->private_data;
484 LDAPMessage *entry = NULL;
487 char *trusted_dn = NULL;
490 DEBUG(10, ("ipasam_set_trusted_domain called for domain %s\n", domain));
492 res = get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
495 return NT_STATUS_UNSUCCESSFUL;
499 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
500 LDAP_OBJ_TRUSTED_DOMAIN);
502 if (td->netbios_name != NULL) {
503 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
504 LDAP_ATTRIBUTE_FLAT_NAME,
508 if (td->domain_name != NULL) {
509 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
510 LDAP_ATTRIBUTE_TRUST_PARTNER,
514 if (!is_null_sid(&td->security_identifier)) {
515 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
516 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
517 sid_string_tos(&td->security_identifier));
520 if (td->trust_type != 0) {
521 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
522 &mods, LDAP_ATTRIBUTE_TRUST_TYPE,
525 return NT_STATUS_UNSUCCESSFUL;
529 if (td->trust_attributes != 0) {
530 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
532 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
533 td->trust_attributes);
535 return NT_STATUS_UNSUCCESSFUL;
539 if (td->trust_direction != 0) {
540 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
542 LDAP_ATTRIBUTE_TRUST_DIRECTION,
543 td->trust_direction);
545 return NT_STATUS_UNSUCCESSFUL;
549 if (td->trust_posix_offset != NULL) {
550 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
552 LDAP_ATTRIBUTE_TRUST_POSIX_OFFSET,
553 *td->trust_posix_offset);
555 return NT_STATUS_UNSUCCESSFUL;
559 if (td->supported_enc_type != NULL) {
560 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
562 LDAP_ATTRIBUTE_SUPPORTED_ENC_TYPE,
563 *td->supported_enc_type);
565 return NT_STATUS_UNSUCCESSFUL;
569 if (td->trust_auth_outgoing.data != NULL) {
570 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
571 LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
572 &td->trust_auth_outgoing);
575 if (td->trust_auth_incoming.data != NULL) {
576 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
577 LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
578 &td->trust_auth_incoming);
581 if (td->trust_forest_trust_info.data != NULL) {
582 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
583 LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO,
584 &td->trust_forest_trust_info);
587 talloc_autofree_ldapmod(talloc_tos(), mods);
589 trusted_dn = trusted_domain_dn(ldap_state, domain);
590 if (trusted_dn == NULL) {
591 return NT_STATUS_NO_MEMORY;
594 ret = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
596 ret = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
599 if (ret != LDAP_SUCCESS) {
600 DEBUG(1, ("error writing trusted domain data!\n"));
601 return NT_STATUS_UNSUCCESSFUL;
606 static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
610 struct ldapsam_privates *ldap_state =
611 (struct ldapsam_privates *)methods->private_data;
612 LDAPMessage *entry = NULL;
615 if (!get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
617 return NT_STATUS_UNSUCCESSFUL;
621 DEBUG(5, ("ipasam_del_trusted_domain: no such trusted domain: "
623 return NT_STATUS_NO_SUCH_DOMAIN;
626 dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
628 DEBUG(0,("ipasam_del_trusted_domain: Out of memory!\n"));
629 return NT_STATUS_NO_MEMORY;
632 ret = smbldap_delete(ldap_state->smbldap_state, dn);
633 if (ret != LDAP_SUCCESS) {
634 return NT_STATUS_UNSUCCESSFUL;
640 static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods,
642 uint32_t *num_domains,
643 struct pdb_trusted_domain ***domains)
646 struct ldapsam_privates *ldap_state =
647 (struct ldapsam_privates *)methods->private_data;
648 char *base_dn = NULL;
650 int scope = LDAP_SCOPE_SUBTREE;
651 LDAPMessage *result = NULL;
652 LDAPMessage *entry = NULL;
654 filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
655 LDAP_OBJ_TRUSTED_DOMAIN);
656 if (filter == NULL) {
657 return NT_STATUS_NO_MEMORY;
660 base_dn = trusted_domain_base_dn(ldap_state);
661 if (base_dn == NULL) {
663 return NT_STATUS_NO_MEMORY;
666 rc = smbldap_search(ldap_state->smbldap_state, base_dn, scope, filter,
669 TALLOC_FREE(base_dn);
671 if (result != NULL) {
672 talloc_autofree_ldapmsg(mem_ctx, result);
675 if (rc == LDAP_NO_SUCH_OBJECT) {
681 if (rc != LDAP_SUCCESS) {
682 return NT_STATUS_UNSUCCESSFUL;
686 if (!(*domains = talloc_array(mem_ctx, struct pdb_trusted_domain *, 1))) {
687 DEBUG(1, ("talloc failed\n"));
688 return NT_STATUS_NO_MEMORY;
691 for (entry = ldap_first_entry(priv2ld(ldap_state), result);
693 entry = ldap_next_entry(priv2ld(ldap_state), entry))
695 struct pdb_trusted_domain *dom_info;
697 if (!fill_pdb_trusted_domain(*domains, ldap_state, entry,
699 return NT_STATUS_UNSUCCESSFUL;
702 ADD_TO_ARRAY(*domains, struct pdb_trusted_domain *, dom_info,
703 domains, num_domains);
705 if (*domains == NULL) {
706 DEBUG(1, ("talloc failed\n"));
707 return NT_STATUS_NO_MEMORY;
711 DEBUG(5, ("ipasam_enum_trusted_domains: got %d domains\n", *num_domains));
715 static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
717 uint32_t *num_domains,
718 struct trustdom_info ***domains)
721 struct pdb_trusted_domain **td;
724 status = ipasam_enum_trusted_domains(methods, talloc_tos(),
726 if (!NT_STATUS_IS_OK(status)) {
730 if (*num_domains == 0) {
734 if (!(*domains = talloc_array(mem_ctx, struct trustdom_info *,
736 DEBUG(1, ("talloc failed\n"));
737 return NT_STATUS_NO_MEMORY;
740 for (i = 0; i < *num_domains; i++) {
741 struct trustdom_info *dom_info;
743 dom_info = talloc(*domains, struct trustdom_info);
744 if (dom_info == NULL) {
745 DEBUG(1, ("talloc failed\n"));
746 return NT_STATUS_NO_MEMORY;
749 dom_info->name = talloc_steal(mem_ctx, td[i]->netbios_name);
750 sid_copy(&dom_info->sid, &td[i]->security_identifier);
752 (*domains)[i] = dom_info;
758 static uint32_t pdb_ipasam_capabilities(struct pdb_methods *methods)
760 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
763 static struct pdb_domain_info *pdb_ipasam_get_domain_info(struct pdb_methods *pdb_methods,
766 struct pdb_domain_info *info;
767 struct ldapsam_privates *ldap_state =
768 (struct ldapsam_privates *)pdb_methods->private_data;
773 info = talloc(mem_ctx, struct pdb_domain_info);
778 info->name = talloc_strdup(info, ldap_state->domain_name);
779 if (info->name == NULL) {
783 /* TODO: read dns_domain, dns_forest and guid from LDAP */
784 info->dns_domain = talloc_strdup(info, lp_realm());
785 if (info->dns_domain == NULL) {
788 strlower_m(info->dns_domain);
789 info->dns_forest = talloc_strdup(info, info->dns_domain);
791 /* we expect a domain SID to have 4 sub IDs */
792 if (ldap_state->domain_sid.num_auths != 4) {
796 sid_copy(&info->sid, &ldap_state->domain_sid);
798 if (!sid_linearize(sid_buf, sizeof(sid_buf), &info->sid)) {
802 /* the first 8 bytes of the linearized SID are not random,
804 sid_blob.data = (uint8_t *) sid_buf + 8 ;
805 sid_blob.length = 16;
807 status = GUID_from_ndr_blob(&sid_blob, &info->guid);
808 if (!NT_STATUS_IS_OK(status)) {
819 static NTSTATUS modify_ipa_password_exop(struct ldapsam_privates *ldap_state,
820 struct samu *sampass)
823 BerElement *ber = NULL;
824 struct berval *bv = NULL;
826 struct berval *retdata = NULL;
827 const char *password;
830 password = pdb_get_plaintext_passwd(sampass);
831 if (password == NULL || *password == '\0') {
832 return NT_STATUS_INVALID_PARAMETER;
835 dn = get_account_dn(pdb_get_username(sampass));
837 return NT_STATUS_INVALID_PARAMETER;
840 ber = ber_alloc_t( LBER_USE_DER );
842 DEBUG(7, ("ber_alloc_t failed.\n"));
843 return NT_STATUS_NO_MEMORY;
846 ret = ber_printf(ber, "{tsts}", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, dn,
847 LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, password);
849 DEBUG(7, ("ber_printf failed.\n"));
851 return NT_STATUS_UNSUCCESSFUL;
854 ret = ber_flatten(ber, &bv);
857 DEBUG(1, ("ber_flatten failed.\n"));
858 return NT_STATUS_UNSUCCESSFUL;
861 ret = smbldap_extended_operation(ldap_state->smbldap_state,
862 LDAP_EXOP_MODIFY_PASSWD, bv, NULL,
863 NULL, &retoid, &retdata);
869 ldap_memfree(retoid);
871 if (ret != LDAP_SUCCESS) {
872 DEBUG(1, ("smbldap_extended_operation LDAP_EXOP_MODIFY_PASSWD failed.\n"));
873 return NT_STATUS_UNSUCCESSFUL;
879 static NTSTATUS ipasam_get_objectclasses(struct ldapsam_privates *ldap_state,
880 const char *dn, LDAPMessage *entry,
881 uint32_t *has_objectclass)
883 char **objectclasses;
886 objectclasses = ldap_get_values(priv2ld(ldap_state), entry,
887 LDAP_ATTRIBUTE_OBJECTCLASS);
888 if (objectclasses == NULL) {
889 DEBUG(0, ("Entry [%s] does not have any objectclasses.\n", dn));
890 return NT_STATUS_INTERNAL_DB_CORRUPTION;
893 *has_objectclass = 0;
894 for (c = 0; objectclasses[c] != NULL; c++) {
895 if (strequal(objectclasses[c], LDAP_OBJ_KRB_PRINCIPAL)) {
896 *has_objectclass |= HAS_KRB_PRINCIPAL;
897 } else if (strequal(objectclasses[c],
898 LDAP_OBJ_KRB_PRINCIPAL_AUX)) {
899 *has_objectclass |= HAS_KRB_PRINCIPAL_AUX;
900 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAOBJECT)) {
901 *has_objectclass |= HAS_IPAOBJECT;
902 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAHOST)) {
903 *has_objectclass |= HAS_IPAHOST;
904 } else if (strequal(objectclasses[c], LDAP_OBJ_POSIXACCOUNT)) {
905 *has_objectclass |= HAS_POSIXACCOUNT;
906 } else if (strequal(objectclasses[c], LDAP_OBJ_GROUPOFNAMES)) {
907 *has_objectclass |= HAS_GROUPOFNAMES;
908 } else if (strequal(objectclasses[c], LDAP_OBJ_NESTEDGROUP)) {
909 *has_objectclass |= HAS_NESTEDGROUP;
910 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAUSERGROUP)) {
911 *has_objectclass |= HAS_IPAUSERGROUP;
912 } else if (strequal(objectclasses[c], LDAP_OBJ_POSIXGROUP)) {
913 *has_objectclass |= HAS_POSIXGROUP;
916 ldap_value_free(objectclasses);
927 static NTSTATUS find_obj(struct ldapsam_privates *ldap_state, const char *name,
928 enum obj_type type, char **_dn,
929 uint32_t *_has_objectclass)
934 LDAPMessage *result = NULL;
935 LDAPMessage *entry = NULL;
938 uint32_t has_objectclass;
940 const char *obj_class = NULL;
944 obj_class = LDAP_OBJ_POSIXACCOUNT;
947 obj_class = LDAP_OBJ_POSIXGROUP;
950 DEBUG(0, ("Unsupported IPA object.\n"));
951 return NT_STATUS_INVALID_PARAMETER;
954 username = escape_ldap_string(talloc_tos(), name);
955 if (username == NULL) {
956 return NT_STATUS_NO_MEMORY;
958 filter = talloc_asprintf(talloc_tos(), "(&(uid=%s)(objectClass=%s))",
959 username, obj_class);
960 if (filter == NULL) {
961 return NT_STATUS_NO_MEMORY;
963 TALLOC_FREE(username);
965 ret = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL,
967 if (ret != LDAP_SUCCESS) {
968 DEBUG(0, ("smbldap_search_suffix failed.\n"));
969 return NT_STATUS_ACCESS_DENIED;
972 num_result = ldap_count_entries(priv2ld(ldap_state), result);
974 if (num_result != 1) {
975 if (num_result == 0) {
978 status = NT_STATUS_NO_SUCH_USER;
981 status = NT_STATUS_NO_SUCH_GROUP;
984 status = NT_STATUS_INVALID_PARAMETER;
987 DEBUG (0, ("find_user: More than one object with name [%s] ?!\n",
989 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
994 entry = ldap_first_entry(priv2ld(ldap_state), result);
996 DEBUG(0,("find_user: Out of memory!\n"));
997 status = NT_STATUS_UNSUCCESSFUL;
1001 dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
1003 DEBUG(0,("find_user: Out of memory!\n"));
1004 status = NT_STATUS_NO_MEMORY;
1008 status = ipasam_get_objectclasses(ldap_state, dn, entry, &has_objectclass);
1009 if (!NT_STATUS_IS_OK(status)) {
1014 *_has_objectclass = has_objectclass;
1016 status = NT_STATUS_OK;
1019 ldap_msgfree(result);
1024 static NTSTATUS find_user(struct ldapsam_privates *ldap_state, const char *name,
1025 char **_dn, uint32_t *_has_objectclass)
1027 return find_obj(ldap_state, name, IPA_USER_OBJ, _dn, _has_objectclass);
1030 static NTSTATUS find_group(struct ldapsam_privates *ldap_state, const char *name,
1031 char **_dn, uint32_t *_has_objectclass)
1033 return find_obj(ldap_state, name, IPA_GROUP_OBJ, _dn, _has_objectclass);
1036 static NTSTATUS ipasam_add_posix_account_objectclass(struct ldapsam_privates *ldap_state,
1039 const char *username)
1042 LDAPMod **mods = NULL;
1044 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1045 "objectclass", "posixAccount");
1046 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1048 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1049 "uidNumber", IPA_MAGIC_ID_STR);
1050 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1051 "gidNumber", "12345");
1052 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1053 "homeDirectory", "/dev/null");
1055 if (ldap_op == LDAP_MOD_ADD) {
1056 ret = smbldap_add(ldap_state->smbldap_state, dn, mods);
1058 ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1060 ldap_mods_free(mods, 1);
1061 if (ret != LDAP_SUCCESS) {
1062 DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
1064 return NT_STATUS_LDAP(ret);
1067 return NT_STATUS_OK;
1070 static NTSTATUS ipasam_add_ipa_group_objectclasses(struct ldapsam_privates *ldap_state,
1073 uint32_t has_objectclass)
1075 LDAPMod **mods = NULL;
1078 if (!(has_objectclass & HAS_GROUPOFNAMES)) {
1079 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1080 LDAP_ATTRIBUTE_OBJECTCLASS,
1081 LDAP_OBJ_GROUPOFNAMES);
1084 if (!(has_objectclass & HAS_NESTEDGROUP)) {
1085 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1086 LDAP_ATTRIBUTE_OBJECTCLASS,
1087 LDAP_OBJ_NESTEDGROUP);
1090 if (!(has_objectclass & HAS_IPAUSERGROUP)) {
1091 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1092 LDAP_ATTRIBUTE_OBJECTCLASS,
1093 LDAP_OBJ_IPAUSERGROUP);
1096 if (!(has_objectclass & HAS_IPAOBJECT)) {
1097 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1098 LDAP_ATTRIBUTE_OBJECTCLASS,
1099 LDAP_OBJ_IPAOBJECT);
1102 if (!(has_objectclass & HAS_POSIXGROUP)) {
1103 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1104 LDAP_ATTRIBUTE_OBJECTCLASS,
1105 LDAP_OBJ_POSIXGROUP);
1106 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1109 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1110 LDAP_ATTRIBUTE_GIDNUMBER,
1114 ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1115 ldap_mods_free(mods, 1);
1116 if (ret != LDAP_SUCCESS) {
1117 DEBUG(1, ("failed to modify/add group %s (dn = %s)\n",
1119 return NT_STATUS_LDAP(ret);
1122 return NT_STATUS_OK;
1125 static NTSTATUS ipasam_add_ipa_objectclasses(struct ldapsam_privates *ldap_state,
1126 const char *dn, const char *name,
1128 uint32_t acct_flags,
1129 uint32_t has_objectclass)
1131 LDAPMod **mods = NULL;
1135 if (!(has_objectclass & HAS_KRB_PRINCIPAL)) {
1136 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1137 LDAP_ATTRIBUTE_OBJECTCLASS,
1138 LDAP_OBJ_KRB_PRINCIPAL);
1140 princ = talloc_asprintf(talloc_tos(), "%s@%s", name, lp_realm());
1141 if (princ == NULL) {
1142 return NT_STATUS_NO_MEMORY;
1145 smbldap_set_mod(&mods, LDAP_MOD_ADD, LDAP_ATTRIBUTE_KRB_PRINCIPAL, princ);
1148 if (!(has_objectclass & HAS_KRB_PRINCIPAL_AUX)) {
1149 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1150 LDAP_ATTRIBUTE_OBJECTCLASS,
1151 LDAP_OBJ_KRB_PRINCIPAL_AUX);
1154 if (!(has_objectclass & HAS_IPAOBJECT)) {
1155 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1156 LDAP_ATTRIBUTE_OBJECTCLASS, LDAP_OBJ_IPAOBJECT);
1159 if ((acct_flags != 0) &&
1160 (((acct_flags & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
1161 ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))) {
1163 if (!(has_objectclass & HAS_IPAHOST)) {
1164 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1165 LDAP_ATTRIBUTE_OBJECTCLASS,
1168 if (domain == NULL) {
1169 return NT_STATUS_INVALID_PARAMETER;
1172 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1177 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1178 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1179 "objectclass", "posixAccount");
1180 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
1181 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1182 "uidNumber", IPA_MAGIC_ID_STR);
1183 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1184 "gidNumber", "12345");
1185 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1186 "homeDirectory", "/dev/null");
1190 ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1191 ldap_mods_free(mods, 1);
1192 if (ret != LDAP_SUCCESS) {
1193 DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
1195 return NT_STATUS_LDAP(ret);
1199 return NT_STATUS_OK;
1202 static NTSTATUS pdb_ipasam_add_sam_account(struct pdb_methods *pdb_methods,
1203 struct samu *sampass)
1206 struct ldapsam_privates *ldap_state;
1209 uint32_t has_objectclass;
1211 struct dom_sid user_sid;
1213 ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1215 if (IS_SAM_SET(sampass, PDB_USERSID) ||
1216 IS_SAM_CHANGED(sampass, PDB_USERSID)) {
1217 if (!pdb_new_rid(&rid)) {
1218 return NT_STATUS_DS_NO_MORE_RIDS;
1220 sid_compose(&user_sid, get_global_sam_sid(), rid);
1221 if (!pdb_set_user_sid(sampass, &user_sid, PDB_SET)) {
1222 return NT_STATUS_UNSUCCESSFUL;
1226 status = ldap_state->ipasam_privates->ldapsam_add_sam_account(pdb_methods,
1228 if (!NT_STATUS_IS_OK(status)) {
1232 if (ldap_state->ipasam_privates->server_is_ipa) {
1233 name = pdb_get_username(sampass);
1234 if (name == NULL || *name == '\0') {
1235 return NT_STATUS_INVALID_PARAMETER;
1238 status = find_user(ldap_state, name, &dn, &has_objectclass);
1239 if (!NT_STATUS_IS_OK(status)) {
1243 status = ipasam_add_ipa_objectclasses(ldap_state, dn, name,
1244 pdb_get_domain(sampass),
1245 pdb_get_acct_ctrl(sampass),
1247 if (!NT_STATUS_IS_OK(status)) {
1251 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1252 status = ipasam_add_posix_account_objectclass(ldap_state,
1255 if (!NT_STATUS_IS_OK(status)) {
1260 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1261 status = modify_ipa_password_exop(ldap_state, sampass);
1262 if (!NT_STATUS_IS_OK(status)) {
1268 return NT_STATUS_OK;
1271 static NTSTATUS pdb_ipasam_update_sam_account(struct pdb_methods *pdb_methods,
1272 struct samu *sampass)
1275 struct ldapsam_privates *ldap_state;
1276 ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1278 status = ldap_state->ipasam_privates->ldapsam_update_sam_account(pdb_methods,
1280 if (!NT_STATUS_IS_OK(status)) {
1284 if (ldap_state->ipasam_privates->server_is_ipa) {
1285 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1286 status = modify_ipa_password_exop(ldap_state, sampass);
1287 if (!NT_STATUS_IS_OK(status)) {
1293 return NT_STATUS_OK;
1296 static NTSTATUS ipasam_create_dom_group(struct pdb_methods *pdb_methods,
1297 TALLOC_CTX *tmp_ctx, const char *name,
1301 struct ldapsam_privates *ldap_state;
1302 int ldap_op = LDAP_MOD_REPLACE;
1304 uint32_t has_objectclass = 0;
1306 ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1308 if (name == NULL || *name == '\0') {
1309 return NT_STATUS_INVALID_PARAMETER;
1312 status = find_group(ldap_state, name, &dn, &has_objectclass);
1313 if (NT_STATUS_IS_OK(status)) {
1314 ldap_op = LDAP_MOD_REPLACE;
1315 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1316 ldap_op = LDAP_MOD_ADD;
1321 if (!(has_objectclass & HAS_POSIXGROUP)) {
1322 status = ipasam_add_ipa_group_objectclasses(ldap_state, dn,
1325 if (!NT_STATUS_IS_OK(status)) {
1330 status = ldap_state->ipasam_privates->ldapsam_create_dom_group(pdb_methods,
1334 if (!NT_STATUS_IS_OK(status)) {
1338 return NT_STATUS_OK;
1340 static NTSTATUS ipasam_create_user(struct pdb_methods *pdb_methods,
1341 TALLOC_CTX *tmp_ctx, const char *name,
1342 uint32_t acb_info, uint32_t *rid)
1345 struct ldapsam_privates *ldap_state;
1346 int ldap_op = LDAP_MOD_REPLACE;
1348 uint32_t has_objectclass = 0;
1350 ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1352 if (name == NULL || *name == '\0') {
1353 return NT_STATUS_INVALID_PARAMETER;
1356 status = find_user(ldap_state, name, &dn, &has_objectclass);
1357 if (NT_STATUS_IS_OK(status)) {
1358 ldap_op = LDAP_MOD_REPLACE;
1359 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1360 char *escape_username;
1361 ldap_op = LDAP_MOD_ADD;
1362 escape_username = escape_rdn_val_string_alloc(name);
1363 if (!escape_username) {
1364 return NT_STATUS_NO_MEMORY;
1366 if (name[strlen(name)-1] == '$') {
1367 dn = talloc_asprintf(tmp_ctx, "uid=%s,%s",
1369 lp_ldap_machine_suffix());
1371 dn = talloc_asprintf(tmp_ctx, "uid=%s,%s",
1373 lp_ldap_user_suffix());
1375 SAFE_FREE(escape_username);
1377 return NT_STATUS_NO_MEMORY;
1383 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1384 status = ipasam_add_posix_account_objectclass(ldap_state, ldap_op,
1386 if (!NT_STATUS_IS_OK(status)) {
1389 has_objectclass |= HAS_POSIXACCOUNT;
1392 status = ldap_state->ipasam_privates->ldapsam_create_user(pdb_methods,
1395 if (!NT_STATUS_IS_OK(status)) {
1399 status = ipasam_add_ipa_objectclasses(ldap_state, dn, name, lp_realm(),
1400 acb_info, has_objectclass);
1401 if (!NT_STATUS_IS_OK(status)) {
1405 return NT_STATUS_OK;
1408 static NTSTATUS pdb_init_IPA_ldapsam(struct pdb_methods **pdb_method, const char *location)
1410 struct ldapsam_privates *ldap_state;
1413 status = pdb_init_ldapsam(pdb_method, location);
1414 if (!NT_STATUS_IS_OK(status)) {
1418 (*pdb_method)->name = "IPA_ldapsam";
1420 ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
1421 ldap_state->ipasam_privates = talloc_zero(ldap_state,
1422 struct ipasam_privates);
1423 if (ldap_state->ipasam_privates == NULL) {
1424 return NT_STATUS_NO_MEMORY;
1426 ldap_state->is_ipa_ldap = True;
1428 ldap_state->ipasam_privates->server_is_ipa = smbldap_has_extension(
1429 priv2ld(ldap_state), IPA_KEYTAB_SET_OID);
1430 ldap_state->ipasam_privates->ldapsam_add_sam_account = (*pdb_method)->add_sam_account;
1431 ldap_state->ipasam_privates->ldapsam_update_sam_account = (*pdb_method)->update_sam_account;
1432 ldap_state->ipasam_privates->ldapsam_create_user = (*pdb_method)->create_user;
1433 ldap_state->ipasam_privates->ldapsam_create_dom_group = (*pdb_method)->create_dom_group;
1435 (*pdb_method)->add_sam_account = pdb_ipasam_add_sam_account;
1436 (*pdb_method)->update_sam_account = pdb_ipasam_update_sam_account;
1438 if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
1439 if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
1440 (*pdb_method)->create_user = ipasam_create_user;
1441 (*pdb_method)->create_dom_group = ipasam_create_dom_group;
1445 (*pdb_method)->capabilities = pdb_ipasam_capabilities;
1446 (*pdb_method)->get_domain_info = pdb_ipasam_get_domain_info;
1448 (*pdb_method)->get_trusteddom_pw = ipasam_get_trusteddom_pw;
1449 (*pdb_method)->set_trusteddom_pw = ipasam_set_trusteddom_pw;
1450 (*pdb_method)->del_trusteddom_pw = ipasam_del_trusteddom_pw;
1451 (*pdb_method)->enum_trusteddoms = ipasam_enum_trusteddoms;
1453 (*pdb_method)->get_trusted_domain = ipasam_get_trusted_domain;
1454 (*pdb_method)->get_trusted_domain_by_sid = ipasam_get_trusted_domain_by_sid;
1455 (*pdb_method)->set_trusted_domain = ipasam_set_trusted_domain;
1456 (*pdb_method)->del_trusted_domain = ipasam_del_trusted_domain;
1457 (*pdb_method)->enum_trusted_domains = ipasam_enum_trusted_domains;
1459 return NT_STATUS_OK;
1462 NTSTATUS pdb_ipa_init(void)
1466 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "IPA_ldapsam", pdb_init_IPA_ldapsam)))
1469 return NT_STATUS_OK;