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 #define IPA_KEYTAB_SET_OID "2.16.840.1.113730.3.8.3.1"
31 #define LDAP_TRUST_CONTAINER "ou=system"
32 #define LDAP_ATTRIBUTE_CN "cn"
33 #define LDAP_ATTRIBUTE_TRUST_TYPE "sambaTrustType"
34 #define LDAP_ATTRIBUTE_TRUST_ATTRIBUTES "sambaTrustAttributes"
35 #define LDAP_ATTRIBUTE_TRUST_DIRECTION "sambaTrustDirection"
36 #define LDAP_ATTRIBUTE_TRUST_PARTNER "sambaTrustPartner"
37 #define LDAP_ATTRIBUTE_FLAT_NAME "sambaFlatName"
38 #define LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING "sambaTrustAuthOutgoing"
39 #define LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING "sambaTrustAuthIncoming"
40 #define LDAP_ATTRIBUTE_SECURITY_IDENTIFIER "sambaSecurityIdentifier"
41 #define LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO "sambaTrustForestTrustInfo"
42 #define LDAP_ATTRIBUTE_OBJECTCLASS "objectClass"
44 #define LDAP_OBJ_KRB_PRINCIPAL "krbPrincipal"
45 #define LDAP_OBJ_KRB_PRINCIPAL_AUX "krbPrincipalAux"
46 #define LDAP_ATTRIBUTE_KRB_PRINCIPAL "krbPrincipalName"
48 #define LDAP_OBJ_IPAOBJECT "ipaObject"
49 #define LDAP_OBJ_IPAHOST "ipaHost"
50 #define LDAP_OBJ_POSIXACCOUNT "posixAccount"
52 #define HAS_KRB_PRINCIPAL (1<<0)
53 #define HAS_KRB_PRINCIPAL_AUX (1<<1)
54 #define HAS_IPAOBJECT (1<<2)
55 #define HAS_IPAHOST (1<<3)
56 #define HAS_POSIXACCOUNT (1<<4)
58 struct ipasam_privates {
60 NTSTATUS (*ldapsam_add_sam_account)(struct pdb_methods *,
61 struct samu *sampass);
62 NTSTATUS (*ldapsam_update_sam_account)(struct pdb_methods *,
63 struct samu *sampass);
64 NTSTATUS (*ldapsam_create_user)(struct pdb_methods *my_methods,
65 TALLOC_CTX *tmp_ctx, const char *name,
66 uint32_t acb_info, uint32_t *rid);
69 static bool ipasam_get_trusteddom_pw(struct pdb_methods *methods,
73 time_t *pass_last_set_time)
78 static bool ipasam_set_trusteddom_pw(struct pdb_methods *methods,
81 const struct dom_sid *sid)
86 static bool ipasam_del_trusteddom_pw(struct pdb_methods *methods,
92 static char *get_account_dn(const char *name)
97 escape_name = escape_rdn_val_string_alloc(name);
102 if (name[strlen(name)-1] == '$') {
103 dn = talloc_asprintf(talloc_tos(), "uid=%s,%s", escape_name,
104 lp_ldap_machine_suffix());
106 dn = talloc_asprintf(talloc_tos(), "uid=%s,%s", escape_name,
107 lp_ldap_user_suffix());
110 SAFE_FREE(escape_name);
115 static char *trusted_domain_dn(struct ldapsam_privates *ldap_state,
118 return talloc_asprintf(talloc_tos(), "%s=%s,%s,%s",
119 LDAP_ATTRIBUTE_CN, domain,
120 LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
123 static char *trusted_domain_base_dn(struct ldapsam_privates *ldap_state)
125 return talloc_asprintf(talloc_tos(), "%s,%s",
126 LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
129 static bool get_trusted_domain_int(struct ldapsam_privates *ldap_state,
131 const char *filter, LDAPMessage **entry)
134 char *base_dn = NULL;
135 LDAPMessage *result = NULL;
138 base_dn = trusted_domain_base_dn(ldap_state);
139 if (base_dn == NULL) {
143 rc = smbldap_search(ldap_state->smbldap_state, base_dn,
144 LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
145 TALLOC_FREE(base_dn);
147 if (result != NULL) {
148 talloc_autofree_ldapmsg(mem_ctx, result);
151 if (rc == LDAP_NO_SUCH_OBJECT) {
156 if (rc != LDAP_SUCCESS) {
160 num_result = ldap_count_entries(priv2ld(ldap_state), result);
162 if (num_result > 1) {
163 DEBUG(1, ("get_trusted_domain_int: more than one "
164 "%s object with filter '%s'?!\n",
165 LDAP_OBJ_TRUSTED_DOMAIN, filter));
169 if (num_result == 0) {
170 DEBUG(1, ("get_trusted_domain_int: no "
171 "%s object with filter '%s'.\n",
172 LDAP_OBJ_TRUSTED_DOMAIN, filter));
175 *entry = ldap_first_entry(priv2ld(ldap_state), result);
181 static bool get_trusted_domain_by_name_int(struct ldapsam_privates *ldap_state,
188 filter = talloc_asprintf(talloc_tos(),
189 "(&(objectClass=%s)(|(%s=%s)(%s=%s)(cn=%s)))",
190 LDAP_OBJ_TRUSTED_DOMAIN,
191 LDAP_ATTRIBUTE_FLAT_NAME, domain,
192 LDAP_ATTRIBUTE_TRUST_PARTNER, domain, domain);
193 if (filter == NULL) {
197 return get_trusted_domain_int(ldap_state, mem_ctx, filter, entry);
200 static bool get_trusted_domain_by_sid_int(struct ldapsam_privates *ldap_state,
202 const char *sid, LDAPMessage **entry)
206 filter = talloc_asprintf(talloc_tos(), "(&(objectClass=%s)(%s=%s))",
207 LDAP_OBJ_TRUSTED_DOMAIN,
208 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER, sid);
209 if (filter == NULL) {
213 return get_trusted_domain_int(ldap_state, mem_ctx, filter, entry);
216 static bool get_uint32_t_from_ldap_msg(struct ldapsam_privates *ldap_state,
225 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
228 DEBUG(9, ("Attribute %s not present.\n", attr));
233 l = strtoul(dummy, &endptr, 10);
236 if (l < 0 || l > UINT32_MAX || *endptr != '\0') {
245 static void get_data_blob_from_ldap_msg(TALLOC_CTX *mem_ctx,
246 struct ldapsam_privates *ldap_state,
247 LDAPMessage *entry, const char *attr,
253 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, attr,
256 DEBUG(9, ("Attribute %s not present.\n", attr));
259 blob = base64_decode_data_blob(dummy);
260 if (blob.length == 0) {
263 _blob->length = blob.length;
264 _blob->data = talloc_steal(mem_ctx, blob.data);
270 static bool fill_pdb_trusted_domain(TALLOC_CTX *mem_ctx,
271 struct ldapsam_privates *ldap_state,
273 struct pdb_trusted_domain **_td)
277 struct pdb_trusted_domain *td;
283 td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
288 /* All attributes are MAY */
290 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
291 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
294 DEBUG(9, ("Attribute %s not present.\n",
295 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER));
296 ZERO_STRUCT(td->security_identifier);
298 res = string_to_sid(&td->security_identifier, dummy);
305 get_data_blob_from_ldap_msg(td, ldap_state, entry,
306 LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
307 &td->trust_auth_incoming);
309 get_data_blob_from_ldap_msg(td, ldap_state, entry,
310 LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
311 &td->trust_auth_outgoing);
313 td->netbios_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
315 LDAP_ATTRIBUTE_FLAT_NAME,
317 if (td->netbios_name == NULL) {
318 DEBUG(9, ("Attribute %s not present.\n",
319 LDAP_ATTRIBUTE_FLAT_NAME));
322 td->domain_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
324 LDAP_ATTRIBUTE_TRUST_PARTNER,
326 if (td->domain_name == NULL) {
327 DEBUG(9, ("Attribute %s not present.\n",
328 LDAP_ATTRIBUTE_TRUST_PARTNER));
331 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
332 LDAP_ATTRIBUTE_TRUST_DIRECTION,
333 &td->trust_direction);
338 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
339 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
340 &td->trust_attributes);
345 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
346 LDAP_ATTRIBUTE_TRUST_TYPE,
352 get_data_blob_from_ldap_msg(td, ldap_state, entry,
353 LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO,
354 &td->trust_forest_trust_info);
361 static NTSTATUS ipasam_get_trusted_domain(struct pdb_methods *methods,
364 struct pdb_trusted_domain **td)
366 struct ldapsam_privates *ldap_state =
367 (struct ldapsam_privates *)methods->private_data;
368 LDAPMessage *entry = NULL;
370 DEBUG(10, ("ipasam_get_trusted_domain called for domain %s\n", domain));
372 if (!get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
374 return NT_STATUS_UNSUCCESSFUL;
377 DEBUG(5, ("ipasam_get_trusted_domain: no such trusted domain: "
379 return NT_STATUS_NO_SUCH_DOMAIN;
382 if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
383 return NT_STATUS_UNSUCCESSFUL;
389 static NTSTATUS ipasam_get_trusted_domain_by_sid(struct pdb_methods *methods,
392 struct pdb_trusted_domain **td)
394 struct ldapsam_privates *ldap_state =
395 (struct ldapsam_privates *)methods->private_data;
396 LDAPMessage *entry = NULL;
399 sid_str = sid_string_tos(sid);
401 DEBUG(10, ("ipasam_get_trusted_domain_by_sid called for sid %s\n",
404 if (!get_trusted_domain_by_sid_int(ldap_state, talloc_tos(), sid_str,
406 return NT_STATUS_UNSUCCESSFUL;
409 DEBUG(5, ("ipasam_get_trusted_domain_by_sid: no trusted domain "
410 "with sid: %s\n", sid_str));
411 return NT_STATUS_NO_SUCH_DOMAIN;
414 if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
415 return NT_STATUS_UNSUCCESSFUL;
421 static bool smbldap_make_mod_uint32_t(LDAP *ldap_struct, LDAPMessage *entry,
422 LDAPMod ***mods, const char *attribute,
427 dummy = talloc_asprintf(talloc_tos(), "%lu", (unsigned long) val);
431 smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
437 static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
439 const struct pdb_trusted_domain *td)
441 struct ldapsam_privates *ldap_state =
442 (struct ldapsam_privates *)methods->private_data;
443 LDAPMessage *entry = NULL;
446 char *trusted_dn = NULL;
449 DEBUG(10, ("ipasam_set_trusted_domain called for domain %s\n", domain));
451 res = get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
454 return NT_STATUS_UNSUCCESSFUL;
458 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
459 LDAP_OBJ_TRUSTED_DOMAIN);
461 if (td->netbios_name != NULL) {
462 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
463 LDAP_ATTRIBUTE_FLAT_NAME,
467 if (td->domain_name != NULL) {
468 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
469 LDAP_ATTRIBUTE_TRUST_PARTNER,
473 if (!is_null_sid(&td->security_identifier)) {
474 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
475 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
476 sid_string_tos(&td->security_identifier));
479 if (td->trust_type != 0) {
480 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
481 &mods, LDAP_ATTRIBUTE_TRUST_TYPE,
484 return NT_STATUS_UNSUCCESSFUL;
488 if (td->trust_attributes != 0) {
489 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
491 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
492 td->trust_attributes);
494 return NT_STATUS_UNSUCCESSFUL;
498 if (td->trust_direction != 0) {
499 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
501 LDAP_ATTRIBUTE_TRUST_DIRECTION,
502 td->trust_direction);
504 return NT_STATUS_UNSUCCESSFUL;
508 if (td->trust_auth_outgoing.data != NULL) {
509 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
510 LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
511 &td->trust_auth_outgoing);
514 if (td->trust_auth_incoming.data != NULL) {
515 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
516 LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
517 &td->trust_auth_incoming);
520 if (td->trust_forest_trust_info.data != NULL) {
521 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
522 LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO,
523 &td->trust_forest_trust_info);
526 talloc_autofree_ldapmod(talloc_tos(), mods);
528 trusted_dn = trusted_domain_dn(ldap_state, domain);
529 if (trusted_dn == NULL) {
530 return NT_STATUS_NO_MEMORY;
533 ret = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
535 ret = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
538 if (ret != LDAP_SUCCESS) {
539 DEBUG(1, ("error writing trusted domain data!\n"));
540 return NT_STATUS_UNSUCCESSFUL;
545 static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
549 struct ldapsam_privates *ldap_state =
550 (struct ldapsam_privates *)methods->private_data;
551 LDAPMessage *entry = NULL;
554 if (!get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
556 return NT_STATUS_UNSUCCESSFUL;
560 DEBUG(5, ("ipasam_del_trusted_domain: no such trusted domain: "
562 return NT_STATUS_NO_SUCH_DOMAIN;
565 dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
567 DEBUG(0,("ipasam_del_trusted_domain: Out of memory!\n"));
568 return NT_STATUS_NO_MEMORY;
571 ret = smbldap_delete(ldap_state->smbldap_state, dn);
572 if (ret != LDAP_SUCCESS) {
573 return NT_STATUS_UNSUCCESSFUL;
579 static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods,
581 uint32_t *num_domains,
582 struct pdb_trusted_domain ***domains)
585 struct ldapsam_privates *ldap_state =
586 (struct ldapsam_privates *)methods->private_data;
587 char *base_dn = NULL;
589 int scope = LDAP_SCOPE_SUBTREE;
590 LDAPMessage *result = NULL;
591 LDAPMessage *entry = NULL;
593 filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
594 LDAP_OBJ_TRUSTED_DOMAIN);
595 if (filter == NULL) {
596 return NT_STATUS_NO_MEMORY;
599 base_dn = trusted_domain_base_dn(ldap_state);
600 if (base_dn == NULL) {
602 return NT_STATUS_NO_MEMORY;
605 rc = smbldap_search(ldap_state->smbldap_state, base_dn, scope, filter,
608 TALLOC_FREE(base_dn);
610 if (result != NULL) {
611 talloc_autofree_ldapmsg(mem_ctx, result);
614 if (rc == LDAP_NO_SUCH_OBJECT) {
620 if (rc != LDAP_SUCCESS) {
621 return NT_STATUS_UNSUCCESSFUL;
625 if (!(*domains = TALLOC_ARRAY(mem_ctx, struct pdb_trusted_domain *, 1))) {
626 DEBUG(1, ("talloc failed\n"));
627 return NT_STATUS_NO_MEMORY;
630 for (entry = ldap_first_entry(priv2ld(ldap_state), result);
632 entry = ldap_next_entry(priv2ld(ldap_state), entry))
634 struct pdb_trusted_domain *dom_info;
636 if (!fill_pdb_trusted_domain(*domains, ldap_state, entry,
638 return NT_STATUS_UNSUCCESSFUL;
641 ADD_TO_ARRAY(*domains, struct pdb_trusted_domain *, dom_info,
642 domains, num_domains);
644 if (*domains == NULL) {
645 DEBUG(1, ("talloc failed\n"));
646 return NT_STATUS_NO_MEMORY;
650 DEBUG(5, ("ipasam_enum_trusted_domains: got %d domains\n", *num_domains));
654 static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
656 uint32_t *num_domains,
657 struct trustdom_info ***domains)
660 struct pdb_trusted_domain **td;
663 status = ipasam_enum_trusted_domains(methods, talloc_tos(),
665 if (!NT_STATUS_IS_OK(status)) {
669 if (*num_domains == 0) {
673 if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *,
675 DEBUG(1, ("talloc failed\n"));
676 return NT_STATUS_NO_MEMORY;
679 for (i = 0; i < *num_domains; i++) {
680 struct trustdom_info *dom_info;
682 dom_info = TALLOC_P(*domains, struct trustdom_info);
683 if (dom_info == NULL) {
684 DEBUG(1, ("talloc failed\n"));
685 return NT_STATUS_NO_MEMORY;
688 dom_info->name = talloc_steal(mem_ctx, td[i]->netbios_name);
689 sid_copy(&dom_info->sid, &td[i]->security_identifier);
691 (*domains)[i] = dom_info;
697 static uint32_t pdb_ipasam_capabilities(struct pdb_methods *methods)
699 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
702 static struct pdb_domain_info *pdb_ipasam_get_domain_info(struct pdb_methods *pdb_methods,
705 struct pdb_domain_info *info;
707 struct ldapsam_privates *ldap_state = pdb_methods->private_data;
709 info = talloc(mem_ctx, struct pdb_domain_info);
714 info->name = talloc_strdup(info, ldap_state->domain_name);
715 if (info->name == NULL) {
719 /* TODO: read dns_domain, dns_forest and guid from LDAP */
720 info->dns_domain = talloc_strdup(info, lp_realm());
721 if (info->dns_domain == NULL) {
724 strlower_m(info->dns_domain);
725 info->dns_forest = talloc_strdup(info, info->dns_domain);
726 sid_copy(&info->sid, &ldap_state->domain_sid);
728 status = GUID_from_string("testguid", &info->guid);
737 static NTSTATUS modify_ipa_password_exop(struct ldapsam_privates *ldap_state,
738 struct samu *sampass)
741 BerElement *ber = NULL;
742 struct berval *bv = NULL;
744 struct berval *retdata = NULL;
745 const char *password;
748 password = pdb_get_plaintext_passwd(sampass);
749 if (password == NULL || *password == '\0') {
750 return NT_STATUS_INVALID_PARAMETER;
753 dn = get_account_dn(pdb_get_username(sampass));
755 return NT_STATUS_INVALID_PARAMETER;
758 ber = ber_alloc_t( LBER_USE_DER );
760 DEBUG(7, ("ber_alloc_t failed.\n"));
761 return NT_STATUS_NO_MEMORY;
764 ret = ber_printf(ber, "{tsts}", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, dn,
765 LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, password);
767 DEBUG(7, ("ber_printf failed.\n"));
769 return NT_STATUS_UNSUCCESSFUL;
772 ret = ber_flatten(ber, &bv);
775 DEBUG(1, ("ber_flatten failed.\n"));
776 return NT_STATUS_UNSUCCESSFUL;
779 ret = smbldap_extended_operation(ldap_state->smbldap_state,
780 LDAP_EXOP_MODIFY_PASSWD, bv, NULL,
781 NULL, &retoid, &retdata);
787 ldap_memfree(retoid);
789 if (ret != LDAP_SUCCESS) {
790 DEBUG(1, ("smbldap_extended_operation LDAP_EXOP_MODIFY_PASSWD failed.\n"));
791 return NT_STATUS_UNSUCCESSFUL;
797 static NTSTATUS ipasam_get_objectclasses(struct ldapsam_privates *ldap_state,
798 const char *dn, LDAPMessage *entry,
799 uint32_t *has_objectclass)
801 char **objectclasses;
804 objectclasses = ldap_get_values(priv2ld(ldap_state), entry,
805 LDAP_ATTRIBUTE_OBJECTCLASS);
806 if (objectclasses == NULL) {
807 DEBUG(0, ("Entry [%s] does not have any objectclasses.\n", dn));
808 return NT_STATUS_INTERNAL_DB_CORRUPTION;
811 *has_objectclass = 0;
812 for (c = 0; objectclasses[c] != NULL; c++) {
813 if (strequal(objectclasses[c], LDAP_OBJ_KRB_PRINCIPAL)) {
814 *has_objectclass |= HAS_KRB_PRINCIPAL;
815 } else if (strequal(objectclasses[c],
816 LDAP_OBJ_KRB_PRINCIPAL_AUX)) {
817 *has_objectclass |= HAS_KRB_PRINCIPAL_AUX;
818 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAOBJECT)) {
819 *has_objectclass |= HAS_IPAOBJECT;
820 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAHOST)) {
821 *has_objectclass |= HAS_IPAHOST;
822 } else if (strequal(objectclasses[c], LDAP_OBJ_POSIXACCOUNT)) {
823 *has_objectclass |= HAS_POSIXACCOUNT;
826 ldap_value_free(objectclasses);
831 static NTSTATUS find_user(struct ldapsam_privates *ldap_state, const char *name,
832 char **_dn, uint32_t *_has_objectclass)
837 LDAPMessage *result = NULL;
838 LDAPMessage *entry = NULL;
841 uint32_t has_objectclass;
844 username = escape_ldap_string(talloc_tos(), name);
845 if (username == NULL) {
846 return NT_STATUS_NO_MEMORY;
848 filter = talloc_asprintf(talloc_tos(), "(&(uid=%s)(objectClass=%s))",
849 username, LDAP_OBJ_POSIXACCOUNT);
850 if (filter == NULL) {
851 return NT_STATUS_NO_MEMORY;
853 TALLOC_FREE(username);
855 ret = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL,
857 if (ret != LDAP_SUCCESS) {
858 DEBUG(0, ("smbldap_search_suffix failed.\n"));
859 return NT_STATUS_ACCESS_DENIED;
862 num_result = ldap_count_entries(priv2ld(ldap_state), result);
864 if (num_result != 1) {
865 if (num_result == 0) {
866 status = NT_STATUS_NO_SUCH_USER;
868 DEBUG (0, ("find_user: More than one user with name [%s] ?!\n",
870 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
875 entry = ldap_first_entry(priv2ld(ldap_state), result);
877 DEBUG(0,("find_user: Out of memory!\n"));
878 status = NT_STATUS_UNSUCCESSFUL;
882 dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
884 DEBUG(0,("find_user: Out of memory!\n"));
885 status = NT_STATUS_NO_MEMORY;
889 status = ipasam_get_objectclasses(ldap_state, dn, entry, &has_objectclass);
890 if (!NT_STATUS_IS_OK(status)) {
895 *_has_objectclass = has_objectclass;
897 status = NT_STATUS_OK;
900 ldap_msgfree(result);
905 static NTSTATUS ipasam_add_posix_account_objectclass(struct ldapsam_privates *ldap_state,
908 const char *username)
911 LDAPMod **mods = NULL;
914 smbldap_set_mod(&mods, LDAP_MOD_ADD,
915 "objectclass", "posixAccount");
916 smbldap_set_mod(&mods, LDAP_MOD_ADD,
918 smbldap_set_mod(&mods, LDAP_MOD_ADD,
919 "gidNumber", "12345");
920 smbldap_set_mod(&mods, LDAP_MOD_ADD,
921 "homeDirectory", "/dev/null");
923 if (ldap_op == LDAP_MOD_ADD) {
924 ret = smbldap_add(ldap_state->smbldap_state, dn, mods);
926 ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
928 ldap_mods_free(mods, 1);
929 if (ret != LDAP_SUCCESS) {
930 DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
938 static NTSTATUS ipasam_add_ipa_objectclasses(struct ldapsam_privates *ldap_state,
939 const char *dn, const char *name,
942 uint32_t has_objectclass)
944 LDAPMod **mods = NULL;
949 if (!(has_objectclass & HAS_KRB_PRINCIPAL)); {
950 smbldap_set_mod(&mods, LDAP_MOD_ADD,
951 LDAP_ATTRIBUTE_OBJECTCLASS,
952 LDAP_OBJ_KRB_PRINCIPAL);
955 princ = talloc_asprintf(talloc_tos(), "%s@%s", name, lp_realm());
957 return NT_STATUS_NO_MEMORY;
960 smbldap_set_mod(&mods, LDAP_MOD_ADD, LDAP_ATTRIBUTE_KRB_PRINCIPAL, princ);
962 if (!(has_objectclass & HAS_KRB_PRINCIPAL_AUX)); {
963 smbldap_set_mod(&mods, LDAP_MOD_ADD,
964 LDAP_ATTRIBUTE_OBJECTCLASS,
965 LDAP_OBJ_KRB_PRINCIPAL_AUX);
968 if (!(has_objectclass & HAS_IPAOBJECT)) {
969 smbldap_set_mod(&mods, LDAP_MOD_ADD,
970 LDAP_ATTRIBUTE_OBJECTCLASS, LDAP_OBJ_IPAOBJECT);
973 if ((acct_flags != 0) &&
974 (((acct_flags & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
975 ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))) {
977 if (!(has_objectclass & HAS_IPAHOST)) {
978 smbldap_set_mod(&mods, LDAP_MOD_ADD,
979 LDAP_ATTRIBUTE_OBJECTCLASS,
983 if (domain == NULL) {
984 return NT_STATUS_INVALID_PARAMETER;
987 smbldap_set_mod(&mods, LDAP_MOD_ADD,
991 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
992 smbldap_set_mod(&mods, LDAP_MOD_ADD,
993 "objectclass", "posixAccount");
995 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
996 smbldap_set_mod(&mods, LDAP_MOD_ADD,
997 "gidNumber", "12345");
998 smbldap_set_mod(&mods, LDAP_MOD_ADD,
999 "homeDirectory", "/dev/null");
1001 ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1002 ldap_mods_free(mods, 1);
1003 if (ret != LDAP_SUCCESS) {
1004 DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
1009 return NT_STATUS_OK;
1012 static NTSTATUS pdb_ipasam_add_sam_account(struct pdb_methods *pdb_methods,
1013 struct samu *sampass)
1016 struct ldapsam_privates *ldap_state;
1019 uint32_t has_objectclass;
1021 ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1023 status = ldap_state->ipasam_privates->ldapsam_add_sam_account(pdb_methods,
1025 if (!NT_STATUS_IS_OK(status)) {
1029 if (ldap_state->ipasam_privates->server_is_ipa) {
1030 name = pdb_get_username(sampass);
1031 if (name == NULL || *name == '\0') {
1032 return NT_STATUS_INVALID_PARAMETER;
1035 status = find_user(ldap_state, name, &dn, &has_objectclass);
1036 if (!NT_STATUS_IS_OK(status)) {
1040 status = ipasam_add_ipa_objectclasses(ldap_state, dn, name,
1041 pdb_get_domain(sampass),
1042 pdb_get_acct_ctrl(sampass),
1044 if (!NT_STATUS_IS_OK(status)) {
1048 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1049 status = ipasam_add_posix_account_objectclass(ldap_state,
1052 if (!NT_STATUS_IS_OK(status)) {
1057 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1058 status = modify_ipa_password_exop(ldap_state, sampass);
1059 if (!NT_STATUS_IS_OK(status)) {
1065 return NT_STATUS_OK;
1068 static NTSTATUS pdb_ipasam_update_sam_account(struct pdb_methods *pdb_methods,
1069 struct samu *sampass)
1072 struct ldapsam_privates *ldap_state;
1073 ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1075 status = ldap_state->ipasam_privates->ldapsam_update_sam_account(pdb_methods,
1077 if (!NT_STATUS_IS_OK(status)) {
1081 if (ldap_state->ipasam_privates->server_is_ipa) {
1082 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1083 status = modify_ipa_password_exop(ldap_state, sampass);
1084 if (!NT_STATUS_IS_OK(status)) {
1090 return NT_STATUS_OK;
1093 static NTSTATUS ipasam_create_user(struct pdb_methods *pdb_methods,
1094 TALLOC_CTX *tmp_ctx, const char *name,
1095 uint32_t acb_info, uint32_t *rid)
1098 struct ldapsam_privates *ldap_state;
1099 int ldap_op = LDAP_MOD_REPLACE;
1101 uint32_t has_objectclass = 0;
1103 ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1105 if (name == NULL || *name == '\0') {
1106 return NT_STATUS_INVALID_PARAMETER;
1109 status = find_user(ldap_state, name, &dn, &has_objectclass);
1110 if (NT_STATUS_IS_OK(status)) {
1111 ldap_op = LDAP_MOD_REPLACE;
1112 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1113 ldap_op = LDAP_MOD_ADD;
1118 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1119 status = ipasam_add_posix_account_objectclass(ldap_state, ldap_op,
1121 if (!NT_STATUS_IS_OK(status)) {
1126 status = ldap_state->ipasam_privates->ldapsam_create_user(pdb_methods,
1129 if (!NT_STATUS_IS_OK(status)) {
1133 status = ipasam_add_ipa_objectclasses(ldap_state, dn, name, lp_realm(),
1134 acb_info, has_objectclass);
1135 if (!NT_STATUS_IS_OK(status)) {
1139 return NT_STATUS_OK;
1142 static NTSTATUS pdb_init_IPA_ldapsam(struct pdb_methods **pdb_method, const char *location)
1144 struct ldapsam_privates *ldap_state;
1147 status = pdb_init_ldapsam(pdb_method, location);
1148 if (!NT_STATUS_IS_OK(status)) {
1152 (*pdb_method)->name = "IPA_ldapsam";
1154 ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
1155 ldap_state->ipasam_privates = talloc_zero(ldap_state,
1156 struct ipasam_privates);
1157 if (ldap_state->ipasam_privates == NULL) {
1158 return NT_STATUS_NO_MEMORY;
1160 ldap_state->is_ipa_ldap = True;
1162 ldap_state->ipasam_privates->server_is_ipa = smbldap_has_extension(
1163 priv2ld(ldap_state), IPA_KEYTAB_SET_OID);
1164 ldap_state->ipasam_privates->ldapsam_add_sam_account = (*pdb_method)->add_sam_account;
1165 ldap_state->ipasam_privates->ldapsam_update_sam_account = (*pdb_method)->update_sam_account;
1166 ldap_state->ipasam_privates->ldapsam_create_user = (*pdb_method)->create_user;
1168 (*pdb_method)->add_sam_account = pdb_ipasam_add_sam_account;
1169 (*pdb_method)->update_sam_account = pdb_ipasam_update_sam_account;
1171 if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
1172 if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
1173 (*pdb_method)->create_user = ipasam_create_user;
1177 (*pdb_method)->capabilities = pdb_ipasam_capabilities;
1178 (*pdb_method)->get_domain_info = pdb_ipasam_get_domain_info;
1180 (*pdb_method)->get_trusteddom_pw = ipasam_get_trusteddom_pw;
1181 (*pdb_method)->set_trusteddom_pw = ipasam_set_trusteddom_pw;
1182 (*pdb_method)->del_trusteddom_pw = ipasam_del_trusteddom_pw;
1183 (*pdb_method)->enum_trusteddoms = ipasam_enum_trusteddoms;
1185 (*pdb_method)->get_trusted_domain = ipasam_get_trusted_domain;
1186 (*pdb_method)->get_trusted_domain_by_sid = ipasam_get_trusted_domain_by_sid;
1187 (*pdb_method)->set_trusted_domain = ipasam_set_trusted_domain;
1188 (*pdb_method)->del_trusted_domain = ipasam_del_trusted_domain;
1189 (*pdb_method)->enum_trusted_domains = ipasam_enum_trusted_domains;
1191 return NT_STATUS_OK;
1194 NTSTATUS pdb_ipa_init(void)
1198 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "IPA_ldapsam", pdb_init_IPA_ldapsam)))
1201 return NT_STATUS_OK;