s3:passdb:pdb_ipa: fix a C++ implicit void * cast warnings
[obnox/samba-ctdb.git] / source3 / passdb / pdb_ipa.c
1 /*
2    Unix SMB/CIFS implementation.
3    IPA helper functions for SAMBA
4    Copyright (C) Sumit Bose <sbose@redhat.com> 2010
5
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.
10
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.
15
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/>.
18
19 */
20
21 #include "includes.h"
22 #include "passdb.h"
23 #include "libcli/security/dom_sid.h"
24 #include "../librpc/ndr/libndr.h"
25 #include "librpc/gen_ndr/samr.h"
26
27 #include "smbldap.h"
28
29 #define IPA_KEYTAB_SET_OID "2.16.840.1.113730.3.8.3.1"
30 #define IPA_MAGIC_ID_STR "999"
31
32 #define LDAP_TRUST_CONTAINER "ou=system"
33 #define LDAP_ATTRIBUTE_CN "cn"
34 #define LDAP_ATTRIBUTE_TRUST_TYPE "sambaTrustType"
35 #define LDAP_ATTRIBUTE_TRUST_ATTRIBUTES "sambaTrustAttributes"
36 #define LDAP_ATTRIBUTE_TRUST_DIRECTION "sambaTrustDirection"
37 #define LDAP_ATTRIBUTE_TRUST_PARTNER "sambaTrustPartner"
38 #define LDAP_ATTRIBUTE_FLAT_NAME "sambaFlatName"
39 #define LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING "sambaTrustAuthOutgoing"
40 #define LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING "sambaTrustAuthIncoming"
41 #define LDAP_ATTRIBUTE_SECURITY_IDENTIFIER "sambaSecurityIdentifier"
42 #define LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO "sambaTrustForestTrustInfo"
43 #define LDAP_ATTRIBUTE_OBJECTCLASS "objectClass"
44
45 #define LDAP_OBJ_KRB_PRINCIPAL "krbPrincipal"
46 #define LDAP_OBJ_KRB_PRINCIPAL_AUX "krbPrincipalAux"
47 #define LDAP_ATTRIBUTE_KRB_PRINCIPAL "krbPrincipalName"
48
49 #define LDAP_OBJ_IPAOBJECT "ipaObject"
50 #define LDAP_OBJ_IPAHOST "ipaHost"
51 #define LDAP_OBJ_POSIXACCOUNT "posixAccount"
52
53 #define LDAP_OBJ_GROUPOFNAMES "groupOfNames"
54 #define LDAP_OBJ_NESTEDGROUP "nestedGroup"
55 #define LDAP_OBJ_IPAUSERGROUP "ipaUserGroup"
56 #define LDAP_OBJ_POSIXGROUP "posixGroup"
57
58 #define HAS_KRB_PRINCIPAL (1<<0)
59 #define HAS_KRB_PRINCIPAL_AUX (1<<1)
60 #define HAS_IPAOBJECT (1<<2)
61 #define HAS_IPAHOST (1<<3)
62 #define HAS_POSIXACCOUNT (1<<4)
63 #define HAS_GROUPOFNAMES (1<<5)
64 #define HAS_NESTEDGROUP (1<<6)
65 #define HAS_IPAUSERGROUP (1<<7)
66 #define HAS_POSIXGROUP (1<<8)
67
68 struct ipasam_privates {
69         bool server_is_ipa;
70         NTSTATUS (*ldapsam_add_sam_account)(struct pdb_methods *,
71                                             struct samu *sampass);
72         NTSTATUS (*ldapsam_update_sam_account)(struct pdb_methods *,
73                                                struct samu *sampass);
74         NTSTATUS (*ldapsam_create_user)(struct pdb_methods *my_methods,
75                                         TALLOC_CTX *tmp_ctx, const char *name,
76                                         uint32_t acb_info, uint32_t *rid);
77         NTSTATUS (*ldapsam_create_dom_group)(struct pdb_methods *my_methods,
78                                              TALLOC_CTX *tmp_ctx,
79                                              const char *name,
80                                              uint32_t *rid);
81 };
82
83 static bool ipasam_get_trusteddom_pw(struct pdb_methods *methods,
84                                       const char *domain,
85                                       char** pwd,
86                                       struct dom_sid *sid,
87                                       time_t *pass_last_set_time)
88 {
89         return false;
90 }
91
92 static bool ipasam_set_trusteddom_pw(struct pdb_methods *methods,
93                                       const char* domain,
94                                       const char* pwd,
95                                       const struct dom_sid *sid)
96 {
97         return false;
98 }
99
100 static bool ipasam_del_trusteddom_pw(struct pdb_methods *methods,
101                                       const char *domain)
102 {
103         return false;
104 }
105
106 static char *get_account_dn(const char *name)
107 {
108         char *escape_name;
109         char *dn;
110
111         escape_name = escape_rdn_val_string_alloc(name);
112         if (!escape_name) {
113                 return NULL;
114         }
115
116         if (name[strlen(name)-1] == '$') {
117                 dn = talloc_asprintf(talloc_tos(), "uid=%s,%s", escape_name,
118                                      lp_ldap_machine_suffix());
119         } else {
120                 dn = talloc_asprintf(talloc_tos(), "uid=%s,%s", escape_name,
121                                      lp_ldap_user_suffix());
122         }
123
124         SAFE_FREE(escape_name);
125
126         return dn;
127 }
128
129 static char *trusted_domain_dn(struct ldapsam_privates *ldap_state,
130                                const char *domain)
131 {
132         return talloc_asprintf(talloc_tos(), "%s=%s,%s,%s",
133                                LDAP_ATTRIBUTE_CN, domain,
134                                LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
135 }
136
137 static char *trusted_domain_base_dn(struct ldapsam_privates *ldap_state)
138 {
139         return talloc_asprintf(talloc_tos(), "%s,%s",
140                                LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
141 }
142
143 static bool get_trusted_domain_int(struct ldapsam_privates *ldap_state,
144                                    TALLOC_CTX *mem_ctx,
145                                    const char *filter, LDAPMessage **entry)
146 {
147         int rc;
148         char *base_dn = NULL;
149         LDAPMessage *result = NULL;
150         uint32_t num_result;
151
152         base_dn = trusted_domain_base_dn(ldap_state);
153         if (base_dn == NULL) {
154                 return false;
155         }
156
157         rc = smbldap_search(ldap_state->smbldap_state, base_dn,
158                             LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
159         TALLOC_FREE(base_dn);
160
161         if (result != NULL) {
162                 talloc_autofree_ldapmsg(mem_ctx, result);
163         }
164
165         if (rc == LDAP_NO_SUCH_OBJECT) {
166                 *entry = NULL;
167                 return true;
168         }
169
170         if (rc != LDAP_SUCCESS) {
171                 return false;
172         }
173
174         num_result = ldap_count_entries(priv2ld(ldap_state), result);
175
176         if (num_result > 1) {
177                 DEBUG(1, ("get_trusted_domain_int: more than one "
178                           "%s object with filter '%s'?!\n",
179                           LDAP_OBJ_TRUSTED_DOMAIN, filter));
180                 return false;
181         }
182
183         if (num_result == 0) {
184                 DEBUG(1, ("get_trusted_domain_int: no "
185                           "%s object with filter '%s'.\n",
186                           LDAP_OBJ_TRUSTED_DOMAIN, filter));
187                 *entry = NULL;
188         } else {
189                 *entry = ldap_first_entry(priv2ld(ldap_state), result);
190         }
191
192         return true;
193 }
194
195 static bool get_trusted_domain_by_name_int(struct ldapsam_privates *ldap_state,
196                                           TALLOC_CTX *mem_ctx,
197                                           const char *domain,
198                                           LDAPMessage **entry)
199 {
200         char *filter = NULL;
201
202         filter = talloc_asprintf(talloc_tos(),
203                                  "(&(objectClass=%s)(|(%s=%s)(%s=%s)(cn=%s)))",
204                                  LDAP_OBJ_TRUSTED_DOMAIN,
205                                  LDAP_ATTRIBUTE_FLAT_NAME, domain,
206                                  LDAP_ATTRIBUTE_TRUST_PARTNER, domain, domain);
207         if (filter == NULL) {
208                 return false;
209         }
210
211         return get_trusted_domain_int(ldap_state, mem_ctx, filter, entry);
212 }
213
214 static bool get_trusted_domain_by_sid_int(struct ldapsam_privates *ldap_state,
215                                            TALLOC_CTX *mem_ctx,
216                                            const char *sid, LDAPMessage **entry)
217 {
218         char *filter = NULL;
219
220         filter = talloc_asprintf(talloc_tos(), "(&(objectClass=%s)(%s=%s))",
221                                  LDAP_OBJ_TRUSTED_DOMAIN,
222                                  LDAP_ATTRIBUTE_SECURITY_IDENTIFIER, sid);
223         if (filter == NULL) {
224                 return false;
225         }
226
227         return get_trusted_domain_int(ldap_state, mem_ctx, filter, entry);
228 }
229
230 static bool get_uint32_t_from_ldap_msg(struct ldapsam_privates *ldap_state,
231                                        LDAPMessage *entry,
232                                        const char *attr,
233                                        uint32_t *val)
234 {
235         char *dummy;
236         long int l;
237         char *endptr;
238
239         dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
240                                                 attr, talloc_tos());
241         if (dummy == NULL) {
242                 DEBUG(9, ("Attribute %s not present.\n", attr));
243                 *val = 0;
244                 return true;
245         }
246
247         l = strtoul(dummy, &endptr, 10);
248         TALLOC_FREE(dummy);
249
250         if (l < 0 || l > UINT32_MAX || *endptr != '\0') {
251                 return false;
252         }
253
254         *val = l;
255
256         return true;
257 }
258
259 static void get_data_blob_from_ldap_msg(TALLOC_CTX *mem_ctx,
260                                         struct ldapsam_privates *ldap_state,
261                                         LDAPMessage *entry, const char *attr,
262                                         DATA_BLOB *_blob)
263 {
264         char *dummy;
265         DATA_BLOB blob;
266
267         dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, attr,
268                                                 talloc_tos());
269         if (dummy == NULL) {
270                 DEBUG(9, ("Attribute %s not present.\n", attr));
271                 ZERO_STRUCTP(_blob);
272         } else {
273                 blob = base64_decode_data_blob(dummy);
274                 if (blob.length == 0) {
275                         ZERO_STRUCTP(_blob);
276                 } else {
277                         _blob->length = blob.length;
278                         _blob->data = talloc_steal(mem_ctx, blob.data);
279                 }
280         }
281         TALLOC_FREE(dummy);
282 }
283
284 static bool fill_pdb_trusted_domain(TALLOC_CTX *mem_ctx,
285                                     struct ldapsam_privates *ldap_state,
286                                     LDAPMessage *entry,
287                                     struct pdb_trusted_domain **_td)
288 {
289         char *dummy;
290         bool res;
291         struct pdb_trusted_domain *td;
292
293         if (entry == NULL) {
294                 return false;
295         }
296
297         td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
298         if (td == NULL) {
299                 return false;
300         }
301
302         /* All attributes are MAY */
303
304         dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
305                                                 LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
306                                                 talloc_tos());
307         if (dummy == NULL) {
308                 DEBUG(9, ("Attribute %s not present.\n",
309                           LDAP_ATTRIBUTE_SECURITY_IDENTIFIER));
310                 ZERO_STRUCT(td->security_identifier);
311         } else {
312                 res = string_to_sid(&td->security_identifier, dummy);
313                 TALLOC_FREE(dummy);
314                 if (!res) {
315                         return false;
316                 }
317         }
318
319         get_data_blob_from_ldap_msg(td, ldap_state, entry,
320                                     LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
321                                     &td->trust_auth_incoming);
322
323         get_data_blob_from_ldap_msg(td, ldap_state, entry,
324                                     LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
325                                     &td->trust_auth_outgoing);
326
327         td->netbios_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
328                                                            entry,
329                                                            LDAP_ATTRIBUTE_FLAT_NAME,
330                                                            td);
331         if (td->netbios_name == NULL) {
332                 DEBUG(9, ("Attribute %s not present.\n",
333                           LDAP_ATTRIBUTE_FLAT_NAME));
334         }
335
336         td->domain_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
337                                                           entry,
338                                                           LDAP_ATTRIBUTE_TRUST_PARTNER,
339                                                           td);
340         if (td->domain_name == NULL) {
341                 DEBUG(9, ("Attribute %s not present.\n",
342                           LDAP_ATTRIBUTE_TRUST_PARTNER));
343         }
344
345         res = get_uint32_t_from_ldap_msg(ldap_state, entry,
346                                          LDAP_ATTRIBUTE_TRUST_DIRECTION,
347                                          &td->trust_direction);
348         if (!res) {
349                 return false;
350         }
351
352         res = get_uint32_t_from_ldap_msg(ldap_state, entry,
353                                          LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
354                                          &td->trust_attributes);
355         if (!res) {
356                 return false;
357         }
358
359         res = get_uint32_t_from_ldap_msg(ldap_state, entry,
360                                          LDAP_ATTRIBUTE_TRUST_TYPE,
361                                          &td->trust_type);
362         if (!res) {
363                 return false;
364         }
365
366         get_data_blob_from_ldap_msg(td, ldap_state, entry,
367                                     LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO,
368                                     &td->trust_forest_trust_info);
369
370         *_td = td;
371
372         return true;
373 }
374
375 static NTSTATUS ipasam_get_trusted_domain(struct pdb_methods *methods,
376                                           TALLOC_CTX *mem_ctx,
377                                           const char *domain,
378                                           struct pdb_trusted_domain **td)
379 {
380         struct ldapsam_privates *ldap_state =
381                 (struct ldapsam_privates *)methods->private_data;
382         LDAPMessage *entry = NULL;
383
384         DEBUG(10, ("ipasam_get_trusted_domain called for domain %s\n", domain));
385
386         if (!get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
387                                             &entry)) {
388                 return NT_STATUS_UNSUCCESSFUL;
389         }
390         if (entry == NULL) {
391                 DEBUG(5, ("ipasam_get_trusted_domain: no such trusted domain: "
392                           "%s\n", domain));
393                 return NT_STATUS_NO_SUCH_DOMAIN;
394         }
395
396         if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
397                 return NT_STATUS_UNSUCCESSFUL;
398         }
399
400         return NT_STATUS_OK;
401 }
402
403 static NTSTATUS ipasam_get_trusted_domain_by_sid(struct pdb_methods *methods,
404                                                  TALLOC_CTX *mem_ctx,
405                                                  struct dom_sid *sid,
406                                                  struct pdb_trusted_domain **td)
407 {
408         struct ldapsam_privates *ldap_state =
409                 (struct ldapsam_privates *)methods->private_data;
410         LDAPMessage *entry = NULL;
411         char *sid_str;
412
413         sid_str = sid_string_tos(sid);
414
415         DEBUG(10, ("ipasam_get_trusted_domain_by_sid called for sid %s\n",
416                    sid_str));
417
418         if (!get_trusted_domain_by_sid_int(ldap_state, talloc_tos(), sid_str,
419                                            &entry)) {
420                 return NT_STATUS_UNSUCCESSFUL;
421         }
422         if (entry == NULL) {
423                 DEBUG(5, ("ipasam_get_trusted_domain_by_sid: no trusted domain "
424                           "with sid: %s\n", sid_str));
425                 return NT_STATUS_NO_SUCH_DOMAIN;
426         }
427
428         if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
429                 return NT_STATUS_UNSUCCESSFUL;
430         }
431
432         return NT_STATUS_OK;
433 }
434
435 static bool smbldap_make_mod_uint32_t(LDAP *ldap_struct, LDAPMessage *entry,
436                                       LDAPMod ***mods, const char *attribute,
437                                       const uint32_t val)
438 {
439         char *dummy;
440
441         dummy = talloc_asprintf(talloc_tos(), "%lu", (unsigned long) val);
442         if (dummy == NULL) {
443                 return false;
444         }
445         smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
446         TALLOC_FREE(dummy);
447
448         return true;
449 }
450
451 static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
452                                           const char* domain,
453                                           const struct pdb_trusted_domain *td)
454 {
455         struct ldapsam_privates *ldap_state =
456                 (struct ldapsam_privates *)methods->private_data;
457         LDAPMessage *entry = NULL;
458         LDAPMod **mods;
459         bool res;
460         char *trusted_dn = NULL;
461         int ret;
462
463         DEBUG(10, ("ipasam_set_trusted_domain called for domain %s\n", domain));
464
465         res = get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
466                                              &entry);
467         if (!res) {
468                 return NT_STATUS_UNSUCCESSFUL;
469         }
470
471         mods = NULL;
472         smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
473                          LDAP_OBJ_TRUSTED_DOMAIN);
474
475         if (td->netbios_name != NULL) {
476                 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
477                                  LDAP_ATTRIBUTE_FLAT_NAME,
478                                  td->netbios_name);
479         }
480
481         if (td->domain_name != NULL) {
482                 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
483                                  LDAP_ATTRIBUTE_TRUST_PARTNER,
484                                  td->domain_name);
485         }
486
487         if (!is_null_sid(&td->security_identifier)) {
488                 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
489                                  LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
490                                  sid_string_tos(&td->security_identifier));
491         }
492
493         if (td->trust_type != 0) {
494                 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
495                                                 &mods, LDAP_ATTRIBUTE_TRUST_TYPE,
496                                                 td->trust_type);
497                 if (!res) {
498                         return NT_STATUS_UNSUCCESSFUL;
499                 }
500         }
501
502         if (td->trust_attributes != 0) {
503                 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
504                                                 &mods,
505                                                 LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
506                                                 td->trust_attributes);
507                 if (!res) {
508                         return NT_STATUS_UNSUCCESSFUL;
509                 }
510         }
511
512         if (td->trust_direction != 0) {
513                 res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
514                                                 &mods,
515                                                 LDAP_ATTRIBUTE_TRUST_DIRECTION,
516                                                 td->trust_direction);
517                 if (!res) {
518                         return NT_STATUS_UNSUCCESSFUL;
519                 }
520         }
521
522         if (td->trust_auth_outgoing.data != NULL) {
523                 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
524                                       LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
525                                       &td->trust_auth_outgoing);
526         }
527
528         if (td->trust_auth_incoming.data != NULL) {
529                 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
530                                       LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
531                                       &td->trust_auth_incoming);
532         }
533
534         if (td->trust_forest_trust_info.data != NULL) {
535                 smbldap_make_mod_blob(priv2ld(ldap_state), entry, &mods,
536                                       LDAP_ATTRIBUTE_TRUST_FOREST_TRUST_INFO,
537                                       &td->trust_forest_trust_info);
538         }
539
540         talloc_autofree_ldapmod(talloc_tos(), mods);
541
542         trusted_dn = trusted_domain_dn(ldap_state, domain);
543         if (trusted_dn == NULL) {
544                 return NT_STATUS_NO_MEMORY;
545         }
546         if (entry == NULL) {
547                 ret = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
548         } else {
549                 ret = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
550         }
551
552         if (ret != LDAP_SUCCESS) {
553                 DEBUG(1, ("error writing trusted domain data!\n"));
554                 return NT_STATUS_UNSUCCESSFUL;
555         }
556         return NT_STATUS_OK;
557 }
558
559 static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
560                                            const char *domain)
561 {
562         int ret;
563         struct ldapsam_privates *ldap_state =
564                 (struct ldapsam_privates *)methods->private_data;
565         LDAPMessage *entry = NULL;
566         const char *dn;
567
568         if (!get_trusted_domain_by_name_int(ldap_state, talloc_tos(), domain,
569                                             &entry)) {
570                 return NT_STATUS_UNSUCCESSFUL;
571         }
572
573         if (entry == NULL) {
574                 DEBUG(5, ("ipasam_del_trusted_domain: no such trusted domain: "
575                           "%s\n", domain));
576                 return NT_STATUS_NO_SUCH_DOMAIN;
577         }
578
579         dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
580         if (dn == NULL) {
581                 DEBUG(0,("ipasam_del_trusted_domain: Out of memory!\n"));
582                 return NT_STATUS_NO_MEMORY;
583         }
584
585         ret = smbldap_delete(ldap_state->smbldap_state, dn);
586         if (ret != LDAP_SUCCESS) {
587                 return NT_STATUS_UNSUCCESSFUL;
588         }
589
590         return NT_STATUS_OK;
591 }
592
593 static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods,
594                                             TALLOC_CTX *mem_ctx,
595                                             uint32_t *num_domains,
596                                             struct pdb_trusted_domain ***domains)
597 {
598         int rc;
599         struct ldapsam_privates *ldap_state =
600                 (struct ldapsam_privates *)methods->private_data;
601         char *base_dn = NULL;
602         char *filter = NULL;
603         int scope = LDAP_SCOPE_SUBTREE;
604         LDAPMessage *result = NULL;
605         LDAPMessage *entry = NULL;
606
607         filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
608                                  LDAP_OBJ_TRUSTED_DOMAIN);
609         if (filter == NULL) {
610                 return NT_STATUS_NO_MEMORY;
611         }
612
613         base_dn = trusted_domain_base_dn(ldap_state);
614         if (base_dn == NULL) {
615                 TALLOC_FREE(filter);
616                 return NT_STATUS_NO_MEMORY;
617         }
618
619         rc = smbldap_search(ldap_state->smbldap_state, base_dn, scope, filter,
620                             NULL, 0, &result);
621         TALLOC_FREE(filter);
622         TALLOC_FREE(base_dn);
623
624         if (result != NULL) {
625                 talloc_autofree_ldapmsg(mem_ctx, result);
626         }
627
628         if (rc == LDAP_NO_SUCH_OBJECT) {
629                 *num_domains = 0;
630                 *domains = NULL;
631                 return NT_STATUS_OK;
632         }
633
634         if (rc != LDAP_SUCCESS) {
635                 return NT_STATUS_UNSUCCESSFUL;
636         }
637
638         *num_domains = 0;
639         if (!(*domains = TALLOC_ARRAY(mem_ctx, struct pdb_trusted_domain *, 1))) {
640                 DEBUG(1, ("talloc failed\n"));
641                 return NT_STATUS_NO_MEMORY;
642         }
643
644         for (entry = ldap_first_entry(priv2ld(ldap_state), result);
645              entry != NULL;
646              entry = ldap_next_entry(priv2ld(ldap_state), entry))
647         {
648                 struct pdb_trusted_domain *dom_info;
649
650                 if (!fill_pdb_trusted_domain(*domains, ldap_state, entry,
651                                              &dom_info)) {
652                         return NT_STATUS_UNSUCCESSFUL;
653                 }
654
655                 ADD_TO_ARRAY(*domains, struct pdb_trusted_domain *, dom_info,
656                              domains, num_domains);
657
658                 if (*domains == NULL) {
659                         DEBUG(1, ("talloc failed\n"));
660                         return NT_STATUS_NO_MEMORY;
661                 }
662         }
663
664         DEBUG(5, ("ipasam_enum_trusted_domains: got %d domains\n", *num_domains));
665         return NT_STATUS_OK;
666 }
667
668 static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
669                                          TALLOC_CTX *mem_ctx,
670                                          uint32_t *num_domains,
671                                          struct trustdom_info ***domains)
672 {
673         NTSTATUS status;
674         struct pdb_trusted_domain **td;
675         int i;
676
677         status = ipasam_enum_trusted_domains(methods, talloc_tos(),
678                                              num_domains, &td);
679         if (!NT_STATUS_IS_OK(status)) {
680                 return status;
681         }
682
683         if (*num_domains == 0) {
684                 return NT_STATUS_OK;
685         }
686
687         if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *,
688                                       *num_domains))) {
689                 DEBUG(1, ("talloc failed\n"));
690                 return NT_STATUS_NO_MEMORY;
691         }
692
693         for (i = 0; i < *num_domains; i++) {
694                 struct trustdom_info *dom_info;
695
696                 dom_info = TALLOC_P(*domains, struct trustdom_info);
697                 if (dom_info == NULL) {
698                         DEBUG(1, ("talloc failed\n"));
699                         return NT_STATUS_NO_MEMORY;
700                 }
701
702                 dom_info->name = talloc_steal(mem_ctx, td[i]->netbios_name);
703                 sid_copy(&dom_info->sid, &td[i]->security_identifier);
704
705                 (*domains)[i] = dom_info;
706         }
707
708         return NT_STATUS_OK;
709 }
710
711 static uint32_t pdb_ipasam_capabilities(struct pdb_methods *methods)
712 {
713         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
714 }
715
716 static struct pdb_domain_info *pdb_ipasam_get_domain_info(struct pdb_methods *pdb_methods,
717                                                           TALLOC_CTX *mem_ctx)
718 {
719         struct pdb_domain_info *info;
720         NTSTATUS status;
721         struct ldapsam_privates *ldap_state =
722                         (struct ldapsam_privates *)pdb_methods->private_data;
723
724         info = talloc(mem_ctx, struct pdb_domain_info);
725         if (info == NULL) {
726                 return NULL;
727         }
728
729         info->name = talloc_strdup(info, ldap_state->domain_name);
730         if (info->name == NULL) {
731                 goto fail;
732         }
733
734         /* TODO: read dns_domain, dns_forest and guid from LDAP */
735         info->dns_domain = talloc_strdup(info, lp_realm());
736         if (info->dns_domain == NULL) {
737                 goto fail;
738         }
739         strlower_m(info->dns_domain);
740         info->dns_forest = talloc_strdup(info, info->dns_domain);
741         sid_copy(&info->sid, &ldap_state->domain_sid);
742
743         status = GUID_from_string("testguid", &info->guid);
744
745         return info;
746
747 fail:
748         TALLOC_FREE(info);
749         return NULL;
750 }
751
752 static NTSTATUS modify_ipa_password_exop(struct ldapsam_privates *ldap_state,
753                                          struct samu *sampass)
754 {
755         int ret;
756         BerElement *ber = NULL;
757         struct berval *bv = NULL;
758         char *retoid = NULL;
759         struct berval *retdata = NULL;
760         const char *password;
761         char *dn;
762
763         password = pdb_get_plaintext_passwd(sampass);
764         if (password == NULL || *password == '\0') {
765                 return NT_STATUS_INVALID_PARAMETER;
766         }
767
768         dn = get_account_dn(pdb_get_username(sampass));
769         if (dn == NULL) {
770                 return NT_STATUS_INVALID_PARAMETER;
771         }
772
773         ber = ber_alloc_t( LBER_USE_DER );
774         if (ber == NULL) {
775                 DEBUG(7, ("ber_alloc_t failed.\n"));
776                 return NT_STATUS_NO_MEMORY;
777         }
778
779         ret = ber_printf(ber, "{tsts}", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, dn,
780                          LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, password);
781         if (ret == -1) {
782                 DEBUG(7, ("ber_printf failed.\n"));
783                 ber_free(ber, 1);
784                 return NT_STATUS_UNSUCCESSFUL;
785         }
786
787         ret = ber_flatten(ber, &bv);
788         ber_free(ber, 1);
789         if (ret == -1) {
790                 DEBUG(1, ("ber_flatten failed.\n"));
791                 return NT_STATUS_UNSUCCESSFUL;
792         }
793
794         ret = smbldap_extended_operation(ldap_state->smbldap_state,
795                                          LDAP_EXOP_MODIFY_PASSWD, bv, NULL,
796                                          NULL, &retoid, &retdata);
797         ber_bvfree(bv);
798         if (retdata) {
799                 ber_bvfree(retdata);
800         }
801         if (retoid) {
802                 ldap_memfree(retoid);
803         }
804         if (ret != LDAP_SUCCESS) {
805                 DEBUG(1, ("smbldap_extended_operation LDAP_EXOP_MODIFY_PASSWD failed.\n"));
806                 return NT_STATUS_UNSUCCESSFUL;
807         }
808
809         return NT_STATUS_OK;
810 }
811
812 static NTSTATUS ipasam_get_objectclasses(struct ldapsam_privates *ldap_state,
813                                          const char *dn, LDAPMessage *entry,
814                                          uint32_t *has_objectclass)
815 {
816         char **objectclasses;
817         size_t c;
818
819         objectclasses = ldap_get_values(priv2ld(ldap_state), entry,
820                                         LDAP_ATTRIBUTE_OBJECTCLASS);
821         if (objectclasses == NULL) {
822                 DEBUG(0, ("Entry [%s] does not have any objectclasses.\n", dn));
823                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
824         }
825
826         *has_objectclass = 0;
827         for (c = 0; objectclasses[c] != NULL; c++) {
828                 if (strequal(objectclasses[c], LDAP_OBJ_KRB_PRINCIPAL)) {
829                         *has_objectclass |= HAS_KRB_PRINCIPAL;
830                 } else if (strequal(objectclasses[c],
831                            LDAP_OBJ_KRB_PRINCIPAL_AUX)) {
832                         *has_objectclass |= HAS_KRB_PRINCIPAL_AUX;
833                 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAOBJECT)) {
834                         *has_objectclass |= HAS_IPAOBJECT;
835                 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAHOST)) {
836                         *has_objectclass |= HAS_IPAHOST;
837                 } else if (strequal(objectclasses[c], LDAP_OBJ_POSIXACCOUNT)) {
838                         *has_objectclass |= HAS_POSIXACCOUNT;
839                 } else if (strequal(objectclasses[c], LDAP_OBJ_GROUPOFNAMES)) {
840                         *has_objectclass |= HAS_GROUPOFNAMES;
841                 } else if (strequal(objectclasses[c], LDAP_OBJ_NESTEDGROUP)) {
842                         *has_objectclass |= HAS_NESTEDGROUP;
843                 } else if (strequal(objectclasses[c], LDAP_OBJ_IPAUSERGROUP)) {
844                         *has_objectclass |= HAS_IPAUSERGROUP;
845                 } else if (strequal(objectclasses[c], LDAP_OBJ_POSIXGROUP)) {
846                         *has_objectclass |= HAS_POSIXGROUP;
847                 }
848         }
849         ldap_value_free(objectclasses);
850
851         return NT_STATUS_OK;
852 }
853
854 enum obj_type {
855         IPA_NO_OBJ = 0,
856         IPA_USER_OBJ,
857         IPA_GROUP_OBJ
858 };
859
860 static NTSTATUS find_obj(struct ldapsam_privates *ldap_state, const char *name,
861                          enum obj_type type, char **_dn,
862                          uint32_t *_has_objectclass)
863 {
864         int ret;
865         char *username;
866         char *filter;
867         LDAPMessage *result = NULL;
868         LDAPMessage *entry = NULL;
869         int num_result;
870         char *dn;
871         uint32_t has_objectclass;
872         NTSTATUS status;
873         const char *obj_class = NULL;
874
875         switch (type) {
876                 case IPA_USER_OBJ:
877                         obj_class = LDAP_OBJ_POSIXACCOUNT;
878                         break;
879                 case IPA_GROUP_OBJ:
880                         obj_class = LDAP_OBJ_POSIXGROUP;
881                         break;
882                 default:
883                         DEBUG(0, ("Unsupported IPA object.\n"));
884                         return NT_STATUS_INVALID_PARAMETER;
885         }
886
887         username = escape_ldap_string(talloc_tos(), name);
888         if (username == NULL) {
889                 return NT_STATUS_NO_MEMORY;
890         }
891         filter = talloc_asprintf(talloc_tos(), "(&(uid=%s)(objectClass=%s))",
892                                  username, obj_class);
893         if (filter == NULL) {
894                 return NT_STATUS_NO_MEMORY;
895         }
896         TALLOC_FREE(username);
897
898         ret = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL,
899                                     &result);
900         if (ret != LDAP_SUCCESS) {
901                 DEBUG(0, ("smbldap_search_suffix failed.\n"));
902                 return NT_STATUS_ACCESS_DENIED;
903         }
904
905         num_result = ldap_count_entries(priv2ld(ldap_state), result);
906
907         if (num_result != 1) {
908                 if (num_result == 0) {
909                         switch (type) {
910                                 case IPA_USER_OBJ:
911                                         status = NT_STATUS_NO_SUCH_USER;
912                                         break;
913                                 case IPA_GROUP_OBJ:
914                                         status = NT_STATUS_NO_SUCH_GROUP;
915                                         break;
916                                 default:
917                                         status = NT_STATUS_INVALID_PARAMETER;
918                         }
919                 } else {
920                         DEBUG (0, ("find_user: More than one object with name [%s] ?!\n",
921                                    name));
922                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
923                 }
924                 goto done;
925         }
926
927         entry = ldap_first_entry(priv2ld(ldap_state), result);
928         if (!entry) {
929                 DEBUG(0,("find_user: Out of memory!\n"));
930                 status = NT_STATUS_UNSUCCESSFUL;
931                 goto done;
932         }
933
934         dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
935         if (!dn) {
936                 DEBUG(0,("find_user: Out of memory!\n"));
937                 status = NT_STATUS_NO_MEMORY;
938                 goto done;
939         }
940
941         status = ipasam_get_objectclasses(ldap_state, dn, entry, &has_objectclass);
942         if (!NT_STATUS_IS_OK(status)) {
943                 goto done;
944         }
945
946         *_dn = dn;
947         *_has_objectclass = has_objectclass;
948
949         status = NT_STATUS_OK;
950
951 done:
952         ldap_msgfree(result);
953
954         return status;
955 }
956
957 static NTSTATUS find_user(struct ldapsam_privates *ldap_state, const char *name,
958                           char **_dn, uint32_t *_has_objectclass)
959 {
960         return find_obj(ldap_state, name, IPA_USER_OBJ, _dn, _has_objectclass);
961 }
962
963 static NTSTATUS find_group(struct ldapsam_privates *ldap_state, const char *name,
964                            char **_dn, uint32_t *_has_objectclass)
965 {
966         return find_obj(ldap_state, name, IPA_GROUP_OBJ, _dn, _has_objectclass);
967 }
968
969 static NTSTATUS ipasam_add_posix_account_objectclass(struct ldapsam_privates *ldap_state,
970                                                      int ldap_op,
971                                                      const char *dn,
972                                                      const char *username)
973 {
974         int ret;
975         LDAPMod **mods = NULL;
976         NTSTATUS status;
977
978         smbldap_set_mod(&mods, LDAP_MOD_ADD,
979                         "objectclass", "posixAccount");
980         smbldap_set_mod(&mods, LDAP_MOD_ADD,
981                         "cn", username);
982         smbldap_set_mod(&mods, LDAP_MOD_ADD,
983                         "uidNumber", IPA_MAGIC_ID_STR);
984         smbldap_set_mod(&mods, LDAP_MOD_ADD,
985                         "gidNumber", "12345");
986         smbldap_set_mod(&mods, LDAP_MOD_ADD,
987                         "homeDirectory", "/dev/null");
988
989         if (ldap_op == LDAP_MOD_ADD) {
990             ret = smbldap_add(ldap_state->smbldap_state, dn, mods);
991         } else {
992             ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
993         }
994         ldap_mods_free(mods, 1);
995         if (ret != LDAP_SUCCESS) {
996                 DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
997                           username, dn));
998                 return status;
999         }
1000
1001         return NT_STATUS_OK;
1002 }
1003
1004 static NTSTATUS ipasam_add_ipa_group_objectclasses(struct ldapsam_privates *ldap_state,
1005                                                    const char *dn,
1006                                                    const char *name,
1007                                                    uint32_t has_objectclass)
1008 {
1009         LDAPMod **mods = NULL;
1010         NTSTATUS status;
1011         int ret;
1012
1013         if (!(has_objectclass & HAS_GROUPOFNAMES)) {
1014                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1015                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1016                                 LDAP_OBJ_GROUPOFNAMES);
1017         }
1018
1019         if (!(has_objectclass & HAS_NESTEDGROUP)) {
1020                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1021                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1022                                 LDAP_OBJ_NESTEDGROUP);
1023         }
1024
1025         if (!(has_objectclass & HAS_IPAUSERGROUP)) {
1026                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1027                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1028                                 LDAP_OBJ_IPAUSERGROUP);
1029         }
1030
1031         if (!(has_objectclass & HAS_IPAOBJECT)) {
1032                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1033                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1034                                 LDAP_OBJ_IPAOBJECT);
1035         }
1036
1037         if (!(has_objectclass & HAS_POSIXGROUP)) {
1038                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1039                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1040                                 LDAP_OBJ_POSIXGROUP);
1041                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1042                                 LDAP_ATTRIBUTE_CN,
1043                                 name);
1044                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1045                                 LDAP_ATTRIBUTE_GIDNUMBER,
1046                                 IPA_MAGIC_ID_STR);
1047         }
1048
1049         ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1050         ldap_mods_free(mods, 1);
1051         if (ret != LDAP_SUCCESS) {
1052                 DEBUG(1, ("failed to modify/add group %s (dn = %s)\n",
1053                           name, dn));
1054                 return status;
1055         }
1056
1057         return NT_STATUS_OK;
1058 }
1059
1060 static NTSTATUS ipasam_add_ipa_objectclasses(struct ldapsam_privates *ldap_state,
1061                                              const char *dn, const char *name,
1062                                              const char *domain,
1063                                              uint32_t acct_flags,
1064                                              uint32_t has_objectclass)
1065 {
1066         LDAPMod **mods = NULL;
1067         NTSTATUS status;
1068         int ret;
1069         char *princ;
1070
1071         if (!(has_objectclass & HAS_KRB_PRINCIPAL)) {
1072                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1073                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1074                                 LDAP_OBJ_KRB_PRINCIPAL);
1075
1076                 princ = talloc_asprintf(talloc_tos(), "%s@%s", name, lp_realm());
1077                 if (princ == NULL) {
1078                         return NT_STATUS_NO_MEMORY;
1079                 }
1080
1081                 smbldap_set_mod(&mods, LDAP_MOD_ADD, LDAP_ATTRIBUTE_KRB_PRINCIPAL, princ);
1082         }
1083
1084         if (!(has_objectclass & HAS_KRB_PRINCIPAL_AUX)); {
1085                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1086                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1087                                 LDAP_OBJ_KRB_PRINCIPAL_AUX);
1088         }
1089
1090         if (!(has_objectclass & HAS_IPAOBJECT)) {
1091                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1092                                 LDAP_ATTRIBUTE_OBJECTCLASS, LDAP_OBJ_IPAOBJECT);
1093         }
1094
1095         if ((acct_flags != 0) &&
1096             (((acct_flags & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
1097             ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))) {
1098
1099                 if (!(has_objectclass & HAS_IPAHOST)) {
1100                         smbldap_set_mod(&mods, LDAP_MOD_ADD,
1101                                         LDAP_ATTRIBUTE_OBJECTCLASS,
1102                                         LDAP_OBJ_IPAHOST);
1103
1104                         if (domain == NULL) {
1105                                 return NT_STATUS_INVALID_PARAMETER;
1106                         }
1107
1108                         smbldap_set_mod(&mods, LDAP_MOD_ADD,
1109                                         "fqdn", domain);
1110                 }
1111         }
1112
1113         if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1114                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1115                                 "objectclass", "posixAccount");
1116                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
1117                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1118                                 "uidNumber", IPA_MAGIC_ID_STR);
1119                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1120                                 "gidNumber", "12345");
1121                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1122                                 "homeDirectory", "/dev/null");
1123         }
1124
1125         if (mods != NULL) {
1126                 ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1127                 ldap_mods_free(mods, 1);
1128                 if (ret != LDAP_SUCCESS) {
1129                         DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
1130                                   name, dn));
1131                         return status;
1132                 }
1133         }
1134
1135         return NT_STATUS_OK;
1136 }
1137
1138 static NTSTATUS pdb_ipasam_add_sam_account(struct pdb_methods *pdb_methods,
1139                                            struct samu *sampass)
1140 {
1141         NTSTATUS status;
1142         struct ldapsam_privates *ldap_state;
1143         const char *name;
1144         char *dn;
1145         uint32_t has_objectclass;
1146         uint32_t rid;
1147         struct dom_sid user_sid;
1148
1149         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1150
1151         if (IS_SAM_SET(sampass, PDB_USERSID) ||
1152             IS_SAM_CHANGED(sampass, PDB_USERSID)) {
1153                 if (!pdb_new_rid(&rid)) {
1154                         return NT_STATUS_DS_NO_MORE_RIDS;
1155                 }
1156                 sid_compose(&user_sid, get_global_sam_sid(), rid);
1157                 if (!pdb_set_user_sid(sampass, &user_sid, PDB_SET)) {
1158                         return NT_STATUS_UNSUCCESSFUL;
1159                 }
1160         }
1161
1162         status = ldap_state->ipasam_privates->ldapsam_add_sam_account(pdb_methods,
1163                                                                       sampass);
1164         if (!NT_STATUS_IS_OK(status)) {
1165                 return status;
1166         }
1167
1168         if (ldap_state->ipasam_privates->server_is_ipa) {
1169                 name = pdb_get_username(sampass);
1170                 if (name == NULL || *name == '\0') {
1171                         return NT_STATUS_INVALID_PARAMETER;
1172                 }
1173
1174                 status = find_user(ldap_state, name, &dn, &has_objectclass);
1175                 if (!NT_STATUS_IS_OK(status)) {
1176                         return status;
1177                 }
1178
1179                 status = ipasam_add_ipa_objectclasses(ldap_state, dn, name,
1180                                                       pdb_get_domain(sampass),
1181                                                       pdb_get_acct_ctrl(sampass),
1182                                                       has_objectclass);
1183                 if (!NT_STATUS_IS_OK(status)) {
1184                         return status;
1185                 }
1186
1187                 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1188                         status = ipasam_add_posix_account_objectclass(ldap_state,
1189                                                                       LDAP_MOD_REPLACE,
1190                                                                       dn, name);
1191                         if (!NT_STATUS_IS_OK(status)) {
1192                                 return status;
1193                         }
1194                 }
1195
1196                 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1197                         status = modify_ipa_password_exop(ldap_state, sampass);
1198                         if (!NT_STATUS_IS_OK(status)) {
1199                                 return status;
1200                         }
1201                 }
1202         }
1203
1204         return NT_STATUS_OK;
1205 }
1206
1207 static NTSTATUS pdb_ipasam_update_sam_account(struct pdb_methods *pdb_methods,
1208                                               struct samu *sampass)
1209 {
1210         NTSTATUS status;
1211         struct ldapsam_privates *ldap_state;
1212         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1213
1214         status = ldap_state->ipasam_privates->ldapsam_update_sam_account(pdb_methods,
1215                                                                          sampass);
1216         if (!NT_STATUS_IS_OK(status)) {
1217                 return status;
1218         }
1219
1220         if (ldap_state->ipasam_privates->server_is_ipa) {
1221                 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1222                         status = modify_ipa_password_exop(ldap_state, sampass);
1223                         if (!NT_STATUS_IS_OK(status)) {
1224                                 return status;
1225                         }
1226                 }
1227         }
1228
1229         return NT_STATUS_OK;
1230 }
1231
1232 static NTSTATUS ipasam_create_dom_group(struct pdb_methods *pdb_methods,
1233                                         TALLOC_CTX *tmp_ctx, const char *name,
1234                                         uint32_t *rid)
1235 {
1236         NTSTATUS status;
1237         struct ldapsam_privates *ldap_state;
1238         int ldap_op = LDAP_MOD_REPLACE;
1239         char *dn;
1240         uint32_t has_objectclass = 0;
1241
1242         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1243
1244         if (name == NULL || *name == '\0') {
1245                 return NT_STATUS_INVALID_PARAMETER;
1246         }
1247
1248         status = find_group(ldap_state, name, &dn, &has_objectclass);
1249         if (NT_STATUS_IS_OK(status)) {
1250                 ldap_op = LDAP_MOD_REPLACE;
1251         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1252                 ldap_op = LDAP_MOD_ADD;
1253         } else {
1254                 return status;
1255         }
1256
1257         if (!(has_objectclass & HAS_POSIXGROUP)) {
1258                 status = ipasam_add_ipa_group_objectclasses(ldap_state, dn,
1259                                                             name,
1260                                                             has_objectclass);
1261                 if (!NT_STATUS_IS_OK(status)) {
1262                         return status;
1263                 }
1264         }
1265
1266         status = ldap_state->ipasam_privates->ldapsam_create_dom_group(pdb_methods,
1267                                                                        tmp_ctx,
1268                                                                        name,
1269                                                                        rid);
1270         if (!NT_STATUS_IS_OK(status)) {
1271                 return status;
1272         }
1273
1274         return NT_STATUS_OK;
1275 }
1276 static NTSTATUS ipasam_create_user(struct pdb_methods *pdb_methods,
1277                                    TALLOC_CTX *tmp_ctx, const char *name,
1278                                    uint32_t acb_info, uint32_t *rid)
1279 {
1280         NTSTATUS status;
1281         struct ldapsam_privates *ldap_state;
1282         int ldap_op = LDAP_MOD_REPLACE;
1283         char *dn;
1284         uint32_t has_objectclass = 0;
1285
1286         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1287
1288         if (name == NULL || *name == '\0') {
1289                 return NT_STATUS_INVALID_PARAMETER;
1290         }
1291
1292         status = find_user(ldap_state, name, &dn, &has_objectclass);
1293         if (NT_STATUS_IS_OK(status)) {
1294                 ldap_op = LDAP_MOD_REPLACE;
1295         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1296                 char *escape_username;
1297                 ldap_op = LDAP_MOD_ADD;
1298                 escape_username = escape_rdn_val_string_alloc(name);
1299                 if (!escape_username) {
1300                         return NT_STATUS_NO_MEMORY;
1301                 }
1302                 if (name[strlen(name)-1] == '$') {
1303                         dn = talloc_asprintf(tmp_ctx, "uid=%s,%s",
1304                                              escape_username,
1305                                              lp_ldap_machine_suffix());
1306                 } else {
1307                         dn = talloc_asprintf(tmp_ctx, "uid=%s,%s",
1308                                              escape_username,
1309                                              lp_ldap_user_suffix());
1310                 }
1311                 SAFE_FREE(escape_username);
1312                 if (!dn) {
1313                         return NT_STATUS_NO_MEMORY;
1314                 }
1315         } else {
1316                 return status;
1317         }
1318
1319         if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1320                 status = ipasam_add_posix_account_objectclass(ldap_state, ldap_op,
1321                                                               dn, name);
1322                 if (!NT_STATUS_IS_OK(status)) {
1323                         return status;
1324                 }
1325                 has_objectclass |= HAS_POSIXACCOUNT;
1326         }
1327
1328         status = ldap_state->ipasam_privates->ldapsam_create_user(pdb_methods,
1329                                                                   tmp_ctx, name,
1330                                                                   acb_info, rid);
1331         if (!NT_STATUS_IS_OK(status)) {
1332                 return status;
1333         }
1334
1335         status = ipasam_add_ipa_objectclasses(ldap_state, dn, name, lp_realm(),
1336                                               acb_info, has_objectclass);
1337         if (!NT_STATUS_IS_OK(status)) {
1338                 return status;
1339         }
1340
1341         return NT_STATUS_OK;
1342 }
1343
1344 static NTSTATUS pdb_init_IPA_ldapsam(struct pdb_methods **pdb_method, const char *location)
1345 {
1346         struct ldapsam_privates *ldap_state;
1347         NTSTATUS status;
1348
1349         status = pdb_init_ldapsam(pdb_method, location);
1350         if (!NT_STATUS_IS_OK(status)) {
1351                 return status;
1352         }
1353
1354         (*pdb_method)->name = "IPA_ldapsam";
1355
1356         ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
1357         ldap_state->ipasam_privates = talloc_zero(ldap_state,
1358                                                   struct ipasam_privates);
1359         if (ldap_state->ipasam_privates == NULL) {
1360                 return NT_STATUS_NO_MEMORY;
1361         }
1362         ldap_state->is_ipa_ldap = True;
1363
1364         ldap_state->ipasam_privates->server_is_ipa = smbldap_has_extension(
1365                                         priv2ld(ldap_state), IPA_KEYTAB_SET_OID);
1366         ldap_state->ipasam_privates->ldapsam_add_sam_account = (*pdb_method)->add_sam_account;
1367         ldap_state->ipasam_privates->ldapsam_update_sam_account = (*pdb_method)->update_sam_account;
1368         ldap_state->ipasam_privates->ldapsam_create_user = (*pdb_method)->create_user;
1369         ldap_state->ipasam_privates->ldapsam_create_dom_group = (*pdb_method)->create_dom_group;
1370
1371         (*pdb_method)->add_sam_account = pdb_ipasam_add_sam_account;
1372         (*pdb_method)->update_sam_account = pdb_ipasam_update_sam_account;
1373
1374         if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
1375                 if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
1376                         (*pdb_method)->create_user = ipasam_create_user;
1377                         (*pdb_method)->create_dom_group = ipasam_create_dom_group;
1378                 }
1379         }
1380
1381         (*pdb_method)->capabilities = pdb_ipasam_capabilities;
1382         (*pdb_method)->get_domain_info = pdb_ipasam_get_domain_info;
1383
1384         (*pdb_method)->get_trusteddom_pw = ipasam_get_trusteddom_pw;
1385         (*pdb_method)->set_trusteddom_pw = ipasam_set_trusteddom_pw;
1386         (*pdb_method)->del_trusteddom_pw = ipasam_del_trusteddom_pw;
1387         (*pdb_method)->enum_trusteddoms = ipasam_enum_trusteddoms;
1388
1389         (*pdb_method)->get_trusted_domain = ipasam_get_trusted_domain;
1390         (*pdb_method)->get_trusted_domain_by_sid = ipasam_get_trusted_domain_by_sid;
1391         (*pdb_method)->set_trusted_domain = ipasam_set_trusted_domain;
1392         (*pdb_method)->del_trusted_domain = ipasam_del_trusted_domain;
1393         (*pdb_method)->enum_trusted_domains = ipasam_enum_trusted_domains;
1394
1395         return NT_STATUS_OK;
1396 }
1397
1398 NTSTATUS pdb_ipa_init(void)
1399 {
1400         NTSTATUS nt_status;
1401
1402         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "IPA_ldapsam", pdb_init_IPA_ldapsam)))
1403                 return nt_status;
1404
1405         return NT_STATUS_OK;
1406 }