s3-ipasam: implement enum_trusted_domains
[Samba.git] / source3 / passdb / pdb_ipa.c
blobeb819b9d349961edeb1f3337e9e22c49f84ea440
1 /*
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/>.
21 #include "includes.h"
23 #include "smbldap.h"
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,
37 const char *domain,
38 char** pwd,
39 struct dom_sid *sid,
40 time_t *pass_last_set_time)
42 return false;
45 static bool ipasam_set_trusteddom_pw(struct pdb_methods *methods,
46 const char* domain,
47 const char* pwd,
48 const struct dom_sid *sid)
50 return false;
53 static bool ipasam_del_trusteddom_pw(struct pdb_methods *methods,
54 const char *domain)
56 return false;
59 static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
60 TALLOC_CTX *mem_ctx,
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,
68 const char *domain)
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,
82 TALLOC_CTX *mem_ctx,
83 const char *domain, LDAPMessage **entry)
85 int rc;
86 char *filter = NULL;
87 char *base_dn = NULL;
88 LDAPMessage *result = NULL;
89 uint32_t num_result;
91 filter = talloc_asprintf(talloc_tos(),
92 "(&(objectClass=%s)(|(sambaFlatName=%s)(cn=%s)(sambaTrustPartner=%s)))",
93 LDAP_OBJ_TRUSTED_DOMAIN, domain, domain, domain);
94 if (filter == NULL) {
95 return false;
98 base_dn = trusted_domain_base_dn(ldap_state);
99 if (base_dn == NULL) {
100 TALLOC_FREE(filter);
101 return false;
104 rc = smbldap_search(ldap_state->smbldap_state, base_dn,
105 LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
106 TALLOC_FREE(filter);
107 TALLOC_FREE(base_dn);
109 if (result != NULL) {
110 talloc_autofree_ldapmsg(mem_ctx, result);
113 if (rc == LDAP_NO_SUCH_OBJECT) {
114 *entry = NULL;
115 return true;
118 if (rc != LDAP_SUCCESS) {
119 return false;
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));
128 return false;
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));
135 *entry = NULL;
136 } else {
137 *entry = ldap_first_entry(priv2ld(ldap_state), result);
140 return true;
143 static bool get_uint32_t_from_ldap_msg(struct ldapsam_privates *ldap_state,
144 LDAPMessage *entry,
145 const char *attr,
146 uint32_t *val)
148 char *dummy;
149 long int l;
150 char *endptr;
152 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
153 attr, talloc_tos());
154 if (dummy == NULL) {
155 DEBUG(9, ("Attribute %s not present.\n", attr));
156 *val = 0;
157 return true;
160 l = strtoul(dummy, &endptr, 10);
161 TALLOC_FREE(dummy);
163 if (l < 0 || l > UINT32_MAX || *endptr != '\0') {
164 return false;
167 *val = l;
169 return true;
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,
175 DATA_BLOB *_blob)
177 char *dummy;
178 DATA_BLOB blob;
180 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, attr,
181 talloc_tos());
182 if (dummy == NULL) {
183 DEBUG(9, ("Attribute %s not present.\n", attr));
184 ZERO_STRUCTP(_blob);
185 } else {
186 blob = base64_decode_data_blob(dummy);
187 if (blob.length == 0) {
188 ZERO_STRUCTP(_blob);
189 } else {
190 _blob->length = blob.length;
191 _blob->data = talloc_steal(mem_ctx, blob.data);
194 TALLOC_FREE(dummy);
197 static bool fill_pdb_trusted_domain(TALLOC_CTX *mem_ctx,
198 struct ldapsam_privates *ldap_state,
199 LDAPMessage *entry,
200 struct pdb_trusted_domain **_td)
202 char *dummy;
203 bool res;
204 struct pdb_trusted_domain *td;
206 if (entry == NULL) {
207 return false;
210 td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
211 if (td == NULL) {
212 return false;
215 /* All attributes are MAY */
217 dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
218 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
219 talloc_tos());
220 if (dummy == NULL) {
221 DEBUG(9, ("Attribute %s not present.\n",
222 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER));
223 ZERO_STRUCT(td->security_identifier);
224 } else {
225 res = string_to_sid(&td->security_identifier, dummy);
226 TALLOC_FREE(dummy);
227 if (!res) {
228 return false;
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),
241 entry,
242 LDAP_ATTRIBUTE_FLAT_NAME,
243 td);
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),
250 entry,
251 LDAP_ATTRIBUTE_TRUST_PARTNER,
252 td);
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);
261 if (!res) {
262 return false;
265 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
266 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
267 &td->trust_attributes);
268 if (!res) {
269 return false;
272 res = get_uint32_t_from_ldap_msg(ldap_state, entry,
273 LDAP_ATTRIBUTE_TRUST_TYPE,
274 &td->trust_type);
275 if (!res) {
276 return false;
279 *_td = td;
281 return true;
284 static NTSTATUS ipasam_get_trusted_domain(struct pdb_methods *methods,
285 TALLOC_CTX *mem_ctx,
286 const char *domain,
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;
298 if (entry == NULL) {
299 DEBUG(5, ("ipasam_get_trusted_domain: no such trusted domain: "
300 "%s\n", 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;
308 return NT_STATUS_OK;
311 static bool smbldap_make_mod_uint32_t(LDAP *ldap_struct, LDAPMessage *entry,
312 LDAPMod ***mods, const char *attribute,
313 const uint32_t val)
315 char *dummy;
317 dummy = talloc_asprintf(talloc_tos(), "%lu", (unsigned long) val);
318 if (dummy == NULL) {
319 return false;
321 smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
322 TALLOC_FREE(dummy);
324 return true;
327 static bool smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *entry,
328 LDAPMod ***mods, const char *attribute,
329 DATA_BLOB blob)
331 char *dummy;
333 dummy = base64_encode_data_blob(talloc_tos(), blob);
334 if (dummy == NULL) {
335 return false;
338 smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
339 TALLOC_FREE(dummy);
341 return true;
344 static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
345 const char* domain,
346 const struct pdb_trusted_domain *td)
348 struct ldapsam_privates *ldap_state =
349 (struct ldapsam_privates *)methods->private_data;
350 LDAPMessage *entry = NULL;
351 LDAPMod **mods;
352 bool res;
353 char *trusted_dn = NULL;
354 int ret;
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);
359 if (!res) {
360 return NT_STATUS_UNSUCCESSFUL;
363 mods = NULL;
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,
370 td->netbios_name);
373 if (td->domain_name != NULL) {
374 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
375 LDAP_ATTRIBUTE_TRUST_PARTNER,
376 td->domain_name);
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,
388 td->trust_type);
389 if (!res) {
390 return NT_STATUS_UNSUCCESSFUL;
394 if (td->trust_attributes != 0) {
395 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
396 &mods,
397 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
398 td->trust_attributes);
399 if (!res) {
400 return NT_STATUS_UNSUCCESSFUL;
404 if (td->trust_direction != 0) {
405 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
406 &mods,
407 LDAP_ATTRIBUTE_TRUST_DIRECTION,
408 td->trust_direction);
409 if (!res) {
410 return NT_STATUS_UNSUCCESSFUL;
414 if (td->trust_auth_outgoing.data != NULL) {
415 res = smbldap_make_mod_blob(priv2ld(ldap_state), entry,
416 &mods,
417 LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
418 td->trust_auth_outgoing);
419 if (!res) {
420 return NT_STATUS_UNSUCCESSFUL;
424 if (td->trust_auth_incoming.data != NULL) {
425 res = smbldap_make_mod_blob(priv2ld(ldap_state), entry,
426 &mods,
427 LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
428 td->trust_auth_incoming);
429 if (!res) {
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;
440 if (entry == NULL) {
441 ret = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
442 } else {
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;
450 return NT_STATUS_OK;
453 static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
454 const char *domain)
456 int ret;
457 struct ldapsam_privates *ldap_state =
458 (struct ldapsam_privates *)methods->private_data;
459 LDAPMessage *entry = NULL;
460 const char *dn;
462 if (!get_trusted_domain_int(ldap_state, talloc_tos(), domain, &entry)) {
463 return NT_STATUS_UNSUCCESSFUL;
466 if (entry == NULL) {
467 DEBUG(5, ("ipasam_del_trusted_domain: no such trusted domain: "
468 "%s\n", domain));
469 return NT_STATUS_NO_SUCH_DOMAIN;
472 dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
473 if (dn == NULL) {
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;
483 return NT_STATUS_OK;
486 static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods,
487 TALLOC_CTX *mem_ctx,
488 uint32_t *num_domains,
489 struct pdb_trusted_domain ***domains)
491 int rc;
492 struct ldapsam_privates *ldap_state =
493 (struct ldapsam_privates *)methods->private_data;
494 char *base_dn = NULL;
495 char *filter = 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) {
508 TALLOC_FREE(filter);
509 return NT_STATUS_NO_MEMORY;
512 rc = smbldap_search(ldap_state->smbldap_state, base_dn, scope, filter,
513 NULL, 0, &result);
514 TALLOC_FREE(filter);
515 TALLOC_FREE(base_dn);
517 if (result != NULL) {
518 talloc_autofree_ldapmsg(mem_ctx, result);
521 if (rc == LDAP_NO_SUCH_OBJECT) {
522 *num_domains = 0;
523 *domains = NULL;
524 return NT_STATUS_OK;
527 if (rc != LDAP_SUCCESS) {
528 return NT_STATUS_UNSUCCESSFUL;
531 *num_domains = 0;
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);
538 entry != NULL;
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,
544 &dom_info)) {
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));
558 return NT_STATUS_OK;
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;
582 return nt_status;
585 NTSTATUS pdb_ipa_init(void)
587 NTSTATUS nt_status;
589 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "IPA_ldapsam", pdb_init_IPA_ldapsam)))
590 return nt_status;
592 return NT_STATUS_OK;