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/>.
25 #define LDAP_TRUST_CONTAINER "ou=system"
26 #define LDAP_ATTRIBUTE_CN "cn"
27 #define LDAP_ATTRIBUTE_TRUST_TYPE "sambaTrustType"
28 #define LDAP_ATTRIBUTE_TRUST_ATTRIBUTES "sambaTrustAttributes"
29 #define LDAP_ATTRIBUTE_TRUST_DIRECTION "sambaTrustDirection"
30 #define LDAP_ATTRIBUTE_TRUST_PARTNER "sambaTrustPartner"
31 #define LDAP_ATTRIBUTE_FLAT_NAME "sambaFlatName"
32 #define LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING "sambaTrustAuthOutgoing"
33 #define LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING "sambaTrustAuthIncoming"
34 #define LDAP_ATTRIBUTE_SECURITY_IDENTIFIER "sambaSecurityIdentifier"
36 static bool ipasam_get_trusteddom_pw(struct pdb_methods *methods,
40 time_t *pass_last_set_time)
45 static bool ipasam_set_trusteddom_pw(struct pdb_methods *methods,
48 const struct dom_sid *sid)
53 static bool ipasam_del_trusteddom_pw(struct pdb_methods *methods,
59 static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
61 uint32_t *num_domains,
62 struct trustdom_info ***domains)
64 return NT_STATUS_NOT_IMPLEMENTED;
67 static char *trusted_domain_dn(struct ldapsam_privates *ldap_state,
70 return talloc_asprintf(talloc_tos(), "%s=%s,%s,%s",
71 LDAP_ATTRIBUTE_CN, domain,
72 LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
75 static char *trusted_domain_base_dn(struct ldapsam_privates *ldap_state)
77 return talloc_asprintf(talloc_tos(), "%s,%s",
78 LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
81 static bool get_trusted_domain_int(struct ldapsam_privates *ldap_state,
83 const char *domain, LDAPMessage **entry)
88 LDAPMessage *result = NULL;
91 filter = talloc_asprintf(talloc_tos(),
92 "(&(objectClass=%s)(|(sambaFlatName=%s)(cn=%s)(sambaTrustPartner=%s)))",
93 LDAP_OBJ_TRUSTED_DOMAIN, domain, domain, domain);
98 base_dn = trusted_domain_base_dn(ldap_state);
99 if (base_dn == NULL) {
104 rc = smbldap_search(ldap_state->smbldap_state, base_dn,
105 LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
107 TALLOC_FREE(base_dn);
109 if (result != NULL) {
110 talloc_autofree_ldapmsg(mem_ctx, result);
113 if (rc == LDAP_NO_SUCH_OBJECT) {
118 if (rc != LDAP_SUCCESS) {
122 num_result = ldap_count_entries(priv2ld(ldap_state), result);
124 if (num_result > 1) {
125 DEBUG(1, ("get_trusted_domain_int: more than one "
126 "%s object for domain '%s'?!\n",
127 LDAP_OBJ_TRUSTED_DOMAIN, domain));
131 if (num_result == 0) {
132 DEBUG(1, ("get_trusted_domain_int: no "
133 "%s object for domain %s.\n",
134 LDAP_OBJ_TRUSTED_DOMAIN, domain));
137 *entry = ldap_first_entry(priv2ld(ldap_state), result);
143 static bool get_uint32_t_from_ldap_msg(struct ldapsam_privates *ldap_state,
152 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
155 DEBUG(9, ("Attribute %s not present.\n", attr));
160 l = strtoul(dummy, &endptr, 10);
163 if (l < 0 || l > UINT32_MAX || *endptr != '\0') {
172 static void get_data_blob_from_ldap_msg(TALLOC_CTX *mem_ctx,
173 struct ldapsam_privates *ldap_state,
174 LDAPMessage *entry, const char *attr,
180 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, attr,
183 DEBUG(9, ("Attribute %s not present.\n", attr));
186 blob = base64_decode_data_blob(dummy);
187 if (blob.length == 0) {
190 _blob->length = blob.length;
191 _blob->data = talloc_steal(mem_ctx, blob.data);
197 static bool fill_pdb_trusted_domain(TALLOC_CTX *mem_ctx,
198 struct ldapsam_privates *ldap_state,
200 struct pdb_trusted_domain **_td)
204 struct pdb_trusted_domain *td;
210 td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
215 /* All attributes are MAY */
217 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
218 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
221 DEBUG(9, ("Attribute %s not present.\n",
222 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER));
223 ZERO_STRUCT(td->security_identifier);
225 res = string_to_sid(&td->security_identifier, dummy);
232 get_data_blob_from_ldap_msg(td, ldap_state, entry,
233 LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
234 &td->trust_auth_incoming);
236 get_data_blob_from_ldap_msg(td, ldap_state, entry,
237 LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
238 &td->trust_auth_outgoing);
240 td->netbios_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
242 LDAP_ATTRIBUTE_FLAT_NAME,
244 if (td->netbios_name == NULL) {
245 DEBUG(9, ("Attribute %s not present.\n",
246 LDAP_ATTRIBUTE_FLAT_NAME));
249 td->domain_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
251 LDAP_ATTRIBUTE_TRUST_PARTNER,
253 if (td->domain_name == NULL) {
254 DEBUG(9, ("Attribute %s not present.\n",
255 LDAP_ATTRIBUTE_TRUST_PARTNER));
258 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
259 LDAP_ATTRIBUTE_TRUST_DIRECTION,
260 &td->trust_direction);
265 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
266 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
267 &td->trust_attributes);
272 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
273 LDAP_ATTRIBUTE_TRUST_TYPE,
284 static NTSTATUS ipasam_get_trusted_domain(struct pdb_methods *methods,
287 struct pdb_trusted_domain **td)
289 struct ldapsam_privates *ldap_state =
290 (struct ldapsam_privates *)methods->private_data;
291 LDAPMessage *entry = NULL;
293 DEBUG(10, ("ipasam_get_trusted_domain called for domain %s\n", domain));
295 if (!get_trusted_domain_int(ldap_state, talloc_tos(), domain, &entry)) {
296 return NT_STATUS_UNSUCCESSFUL;
299 DEBUG(5, ("ipasam_get_trusted_domain: no such trusted domain: "
301 return NT_STATUS_NO_SUCH_DOMAIN;
304 if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
305 return NT_STATUS_UNSUCCESSFUL;
311 static bool smbldap_make_mod_uint32_t(LDAP *ldap_struct, LDAPMessage *entry,
312 LDAPMod ***mods, const char *attribute,
317 dummy = talloc_asprintf(talloc_tos(), "%lu", (unsigned long) val);
321 smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
327 static bool smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *entry,
328 LDAPMod ***mods, const char *attribute,
333 dummy = base64_encode_data_blob(talloc_tos(), blob);
338 smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
344 static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
346 const struct pdb_trusted_domain *td)
348 struct ldapsam_privates *ldap_state =
349 (struct ldapsam_privates *)methods->private_data;
350 LDAPMessage *entry = NULL;
353 char *trusted_dn = NULL;
356 DEBUG(10, ("ipasam_set_trusted_domain called for domain %s\n", domain));
358 res = get_trusted_domain_int(ldap_state, talloc_tos(), domain, &entry);
360 return NT_STATUS_UNSUCCESSFUL;
364 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
365 LDAP_OBJ_TRUSTED_DOMAIN);
367 if (td->netbios_name != NULL) {
368 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
369 LDAP_ATTRIBUTE_FLAT_NAME,
373 if (td->domain_name != NULL) {
374 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
375 LDAP_ATTRIBUTE_TRUST_PARTNER,
379 if (!is_null_sid(&td->security_identifier)) {
380 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
381 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
382 sid_string_tos(&td->security_identifier));
385 if (td->trust_type != 0) {
386 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
387 &mods, LDAP_ATTRIBUTE_TRUST_TYPE,
390 return NT_STATUS_UNSUCCESSFUL;
394 if (td->trust_attributes != 0) {
395 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
397 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
398 td->trust_attributes);
400 return NT_STATUS_UNSUCCESSFUL;
404 if (td->trust_direction != 0) {
405 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
407 LDAP_ATTRIBUTE_TRUST_DIRECTION,
408 td->trust_direction);
410 return NT_STATUS_UNSUCCESSFUL;
414 if (td->trust_auth_outgoing.data != NULL) {
415 res = smbldap_make_mod_blob(priv2ld(ldap_state), entry,
417 LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
418 td->trust_auth_outgoing);
420 return NT_STATUS_UNSUCCESSFUL;
424 if (td->trust_auth_incoming.data != NULL) {
425 res = smbldap_make_mod_blob(priv2ld(ldap_state), entry,
427 LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
428 td->trust_auth_incoming);
430 return NT_STATUS_UNSUCCESSFUL;
434 talloc_autofree_ldapmod(talloc_tos(), mods);
436 trusted_dn = trusted_domain_dn(ldap_state, domain);
437 if (trusted_dn == NULL) {
438 return NT_STATUS_NO_MEMORY;
441 ret = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
443 ret = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
446 if (ret != LDAP_SUCCESS) {
447 DEBUG(1, ("error writing trusted domain data!\n"));
448 return NT_STATUS_UNSUCCESSFUL;
453 static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
457 struct ldapsam_privates *ldap_state =
458 (struct ldapsam_privates *)methods->private_data;
459 LDAPMessage *entry = NULL;
462 if (!get_trusted_domain_int(ldap_state, talloc_tos(), domain, &entry)) {
463 return NT_STATUS_UNSUCCESSFUL;
467 DEBUG(5, ("ipasam_del_trusted_domain: no such trusted domain: "
469 return NT_STATUS_NO_SUCH_DOMAIN;
472 dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
474 DEBUG(0,("ipasam_del_trusted_domain: Out of memory!\n"));
475 return NT_STATUS_NO_MEMORY;
478 ret = smbldap_delete(ldap_state->smbldap_state, dn);
479 if (ret != LDAP_SUCCESS) {
480 return NT_STATUS_UNSUCCESSFUL;
486 static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods,
488 uint32_t *num_domains,
489 struct pdb_trusted_domain ***domains)
492 struct ldapsam_privates *ldap_state =
493 (struct ldapsam_privates *)methods->private_data;
494 char *base_dn = NULL;
496 int scope = LDAP_SCOPE_SUBTREE;
497 LDAPMessage *result = NULL;
498 LDAPMessage *entry = NULL;
500 filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
501 LDAP_OBJ_TRUSTED_DOMAIN);
502 if (filter == NULL) {
503 return NT_STATUS_NO_MEMORY;
506 base_dn = trusted_domain_base_dn(ldap_state);
507 if (base_dn == NULL) {
509 return NT_STATUS_NO_MEMORY;
512 rc = smbldap_search(ldap_state->smbldap_state, base_dn, scope, filter,
515 TALLOC_FREE(base_dn);
517 if (result != NULL) {
518 talloc_autofree_ldapmsg(mem_ctx, result);
521 if (rc == LDAP_NO_SUCH_OBJECT) {
527 if (rc != LDAP_SUCCESS) {
528 return NT_STATUS_UNSUCCESSFUL;
532 if (!(*domains = TALLOC_ARRAY(mem_ctx, struct pdb_trusted_domain *, 1))) {
533 DEBUG(1, ("talloc failed\n"));
534 return NT_STATUS_NO_MEMORY;
537 for (entry = ldap_first_entry(priv2ld(ldap_state), result);
539 entry = ldap_next_entry(priv2ld(ldap_state), entry))
541 struct pdb_trusted_domain *dom_info;
543 if (!fill_pdb_trusted_domain(*domains, ldap_state, entry,
545 return NT_STATUS_UNSUCCESSFUL;
548 ADD_TO_ARRAY(*domains, struct pdb_trusted_domain *, dom_info,
549 domains, num_domains);
551 if (*domains == NULL) {
552 DEBUG(1, ("talloc failed\n"));
553 return NT_STATUS_NO_MEMORY;
557 DEBUG(5, ("ipasam_enum_trusted_domains: got %d domains\n", *num_domains));
561 static NTSTATUS pdb_init_IPA_ldapsam(struct pdb_methods **pdb_method, const char *location)
563 struct ldapsam_privates *ldap_state;
565 NTSTATUS nt_status = pdb_init_ldapsam(pdb_method, location);
567 (*pdb_method)->name = "IPA_ldapsam";
569 ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
570 ldap_state->is_ipa_ldap = true;
572 (*pdb_method)->get_trusteddom_pw = ipasam_get_trusteddom_pw;
573 (*pdb_method)->set_trusteddom_pw = ipasam_set_trusteddom_pw;
574 (*pdb_method)->del_trusteddom_pw = ipasam_del_trusteddom_pw;
575 (*pdb_method)->enum_trusteddoms = ipasam_enum_trusteddoms;
577 (*pdb_method)->get_trusted_domain = ipasam_get_trusted_domain;
578 (*pdb_method)->set_trusted_domain = ipasam_set_trusted_domain;
579 (*pdb_method)->del_trusted_domain = ipasam_del_trusted_domain;
580 (*pdb_method)->enum_trusted_domains = ipasam_enum_trusted_domains;
585 NTSTATUS pdb_ipa_init(void)
589 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "IPA_ldapsam", pdb_init_IPA_ldapsam)))