s3-passdb: Added python method to get_global_sam_sid
[idra/samba.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(*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
977         smbldap_set_mod(&mods, LDAP_MOD_ADD,
978                         "objectclass", "posixAccount");
979         smbldap_set_mod(&mods, LDAP_MOD_ADD,
980                         "cn", username);
981         smbldap_set_mod(&mods, LDAP_MOD_ADD,
982                         "uidNumber", IPA_MAGIC_ID_STR);
983         smbldap_set_mod(&mods, LDAP_MOD_ADD,
984                         "gidNumber", "12345");
985         smbldap_set_mod(&mods, LDAP_MOD_ADD,
986                         "homeDirectory", "/dev/null");
987
988         if (ldap_op == LDAP_MOD_ADD) {
989             ret = smbldap_add(ldap_state->smbldap_state, dn, mods);
990         } else {
991             ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
992         }
993         ldap_mods_free(mods, 1);
994         if (ret != LDAP_SUCCESS) {
995                 DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
996                           username, dn));
997                 return NT_STATUS_LDAP(ret);
998         }
999
1000         return NT_STATUS_OK;
1001 }
1002
1003 static NTSTATUS ipasam_add_ipa_group_objectclasses(struct ldapsam_privates *ldap_state,
1004                                                    const char *dn,
1005                                                    const char *name,
1006                                                    uint32_t has_objectclass)
1007 {
1008         LDAPMod **mods = NULL;
1009         int ret;
1010
1011         if (!(has_objectclass & HAS_GROUPOFNAMES)) {
1012                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1013                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1014                                 LDAP_OBJ_GROUPOFNAMES);
1015         }
1016
1017         if (!(has_objectclass & HAS_NESTEDGROUP)) {
1018                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1019                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1020                                 LDAP_OBJ_NESTEDGROUP);
1021         }
1022
1023         if (!(has_objectclass & HAS_IPAUSERGROUP)) {
1024                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1025                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1026                                 LDAP_OBJ_IPAUSERGROUP);
1027         }
1028
1029         if (!(has_objectclass & HAS_IPAOBJECT)) {
1030                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1031                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1032                                 LDAP_OBJ_IPAOBJECT);
1033         }
1034
1035         if (!(has_objectclass & HAS_POSIXGROUP)) {
1036                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1037                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1038                                 LDAP_OBJ_POSIXGROUP);
1039                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1040                                 LDAP_ATTRIBUTE_CN,
1041                                 name);
1042                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1043                                 LDAP_ATTRIBUTE_GIDNUMBER,
1044                                 IPA_MAGIC_ID_STR);
1045         }
1046
1047         ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1048         ldap_mods_free(mods, 1);
1049         if (ret != LDAP_SUCCESS) {
1050                 DEBUG(1, ("failed to modify/add group %s (dn = %s)\n",
1051                           name, dn));
1052                 return NT_STATUS_LDAP(ret);
1053         }
1054
1055         return NT_STATUS_OK;
1056 }
1057
1058 static NTSTATUS ipasam_add_ipa_objectclasses(struct ldapsam_privates *ldap_state,
1059                                              const char *dn, const char *name,
1060                                              const char *domain,
1061                                              uint32_t acct_flags,
1062                                              uint32_t has_objectclass)
1063 {
1064         LDAPMod **mods = NULL;
1065         int ret;
1066         char *princ;
1067
1068         if (!(has_objectclass & HAS_KRB_PRINCIPAL)) {
1069                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1070                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1071                                 LDAP_OBJ_KRB_PRINCIPAL);
1072
1073                 princ = talloc_asprintf(talloc_tos(), "%s@%s", name, lp_realm());
1074                 if (princ == NULL) {
1075                         return NT_STATUS_NO_MEMORY;
1076                 }
1077
1078                 smbldap_set_mod(&mods, LDAP_MOD_ADD, LDAP_ATTRIBUTE_KRB_PRINCIPAL, princ);
1079         }
1080
1081         if (!(has_objectclass & HAS_KRB_PRINCIPAL_AUX)) {
1082                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1083                                 LDAP_ATTRIBUTE_OBJECTCLASS,
1084                                 LDAP_OBJ_KRB_PRINCIPAL_AUX);
1085         }
1086
1087         if (!(has_objectclass & HAS_IPAOBJECT)) {
1088                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1089                                 LDAP_ATTRIBUTE_OBJECTCLASS, LDAP_OBJ_IPAOBJECT);
1090         }
1091
1092         if ((acct_flags != 0) &&
1093             (((acct_flags & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
1094             ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))) {
1095
1096                 if (!(has_objectclass & HAS_IPAHOST)) {
1097                         smbldap_set_mod(&mods, LDAP_MOD_ADD,
1098                                         LDAP_ATTRIBUTE_OBJECTCLASS,
1099                                         LDAP_OBJ_IPAHOST);
1100
1101                         if (domain == NULL) {
1102                                 return NT_STATUS_INVALID_PARAMETER;
1103                         }
1104
1105                         smbldap_set_mod(&mods, LDAP_MOD_ADD,
1106                                         "fqdn", domain);
1107                 }
1108         }
1109
1110         if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1111                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1112                                 "objectclass", "posixAccount");
1113                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
1114                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1115                                 "uidNumber", IPA_MAGIC_ID_STR);
1116                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1117                                 "gidNumber", "12345");
1118                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1119                                 "homeDirectory", "/dev/null");
1120         }
1121
1122         if (mods != NULL) {
1123                 ret = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1124                 ldap_mods_free(mods, 1);
1125                 if (ret != LDAP_SUCCESS) {
1126                         DEBUG(1, ("failed to modify/add user with uid = %s (dn = %s)\n",
1127                                   name, dn));
1128                         return NT_STATUS_LDAP(ret);
1129                 }
1130         }
1131
1132         return NT_STATUS_OK;
1133 }
1134
1135 static NTSTATUS pdb_ipasam_add_sam_account(struct pdb_methods *pdb_methods,
1136                                            struct samu *sampass)
1137 {
1138         NTSTATUS status;
1139         struct ldapsam_privates *ldap_state;
1140         const char *name;
1141         char *dn;
1142         uint32_t has_objectclass;
1143         uint32_t rid;
1144         struct dom_sid user_sid;
1145
1146         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1147
1148         if (IS_SAM_SET(sampass, PDB_USERSID) ||
1149             IS_SAM_CHANGED(sampass, PDB_USERSID)) {
1150                 if (!pdb_new_rid(&rid)) {
1151                         return NT_STATUS_DS_NO_MORE_RIDS;
1152                 }
1153                 sid_compose(&user_sid, get_global_sam_sid(), rid);
1154                 if (!pdb_set_user_sid(sampass, &user_sid, PDB_SET)) {
1155                         return NT_STATUS_UNSUCCESSFUL;
1156                 }
1157         }
1158
1159         status = ldap_state->ipasam_privates->ldapsam_add_sam_account(pdb_methods,
1160                                                                       sampass);
1161         if (!NT_STATUS_IS_OK(status)) {
1162                 return status;
1163         }
1164
1165         if (ldap_state->ipasam_privates->server_is_ipa) {
1166                 name = pdb_get_username(sampass);
1167                 if (name == NULL || *name == '\0') {
1168                         return NT_STATUS_INVALID_PARAMETER;
1169                 }
1170
1171                 status = find_user(ldap_state, name, &dn, &has_objectclass);
1172                 if (!NT_STATUS_IS_OK(status)) {
1173                         return status;
1174                 }
1175
1176                 status = ipasam_add_ipa_objectclasses(ldap_state, dn, name,
1177                                                       pdb_get_domain(sampass),
1178                                                       pdb_get_acct_ctrl(sampass),
1179                                                       has_objectclass);
1180                 if (!NT_STATUS_IS_OK(status)) {
1181                         return status;
1182                 }
1183
1184                 if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1185                         status = ipasam_add_posix_account_objectclass(ldap_state,
1186                                                                       LDAP_MOD_REPLACE,
1187                                                                       dn, name);
1188                         if (!NT_STATUS_IS_OK(status)) {
1189                                 return status;
1190                         }
1191                 }
1192
1193                 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1194                         status = modify_ipa_password_exop(ldap_state, sampass);
1195                         if (!NT_STATUS_IS_OK(status)) {
1196                                 return status;
1197                         }
1198                 }
1199         }
1200
1201         return NT_STATUS_OK;
1202 }
1203
1204 static NTSTATUS pdb_ipasam_update_sam_account(struct pdb_methods *pdb_methods,
1205                                               struct samu *sampass)
1206 {
1207         NTSTATUS status;
1208         struct ldapsam_privates *ldap_state;
1209         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1210
1211         status = ldap_state->ipasam_privates->ldapsam_update_sam_account(pdb_methods,
1212                                                                          sampass);
1213         if (!NT_STATUS_IS_OK(status)) {
1214                 return status;
1215         }
1216
1217         if (ldap_state->ipasam_privates->server_is_ipa) {
1218                 if (pdb_get_init_flags(sampass, PDB_PLAINTEXT_PW) == PDB_CHANGED) {
1219                         status = modify_ipa_password_exop(ldap_state, sampass);
1220                         if (!NT_STATUS_IS_OK(status)) {
1221                                 return status;
1222                         }
1223                 }
1224         }
1225
1226         return NT_STATUS_OK;
1227 }
1228
1229 static NTSTATUS ipasam_create_dom_group(struct pdb_methods *pdb_methods,
1230                                         TALLOC_CTX *tmp_ctx, const char *name,
1231                                         uint32_t *rid)
1232 {
1233         NTSTATUS status;
1234         struct ldapsam_privates *ldap_state;
1235         int ldap_op = LDAP_MOD_REPLACE;
1236         char *dn;
1237         uint32_t has_objectclass = 0;
1238
1239         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1240
1241         if (name == NULL || *name == '\0') {
1242                 return NT_STATUS_INVALID_PARAMETER;
1243         }
1244
1245         status = find_group(ldap_state, name, &dn, &has_objectclass);
1246         if (NT_STATUS_IS_OK(status)) {
1247                 ldap_op = LDAP_MOD_REPLACE;
1248         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1249                 ldap_op = LDAP_MOD_ADD;
1250         } else {
1251                 return status;
1252         }
1253
1254         if (!(has_objectclass & HAS_POSIXGROUP)) {
1255                 status = ipasam_add_ipa_group_objectclasses(ldap_state, dn,
1256                                                             name,
1257                                                             has_objectclass);
1258                 if (!NT_STATUS_IS_OK(status)) {
1259                         return status;
1260                 }
1261         }
1262
1263         status = ldap_state->ipasam_privates->ldapsam_create_dom_group(pdb_methods,
1264                                                                        tmp_ctx,
1265                                                                        name,
1266                                                                        rid);
1267         if (!NT_STATUS_IS_OK(status)) {
1268                 return status;
1269         }
1270
1271         return NT_STATUS_OK;
1272 }
1273 static NTSTATUS ipasam_create_user(struct pdb_methods *pdb_methods,
1274                                    TALLOC_CTX *tmp_ctx, const char *name,
1275                                    uint32_t acb_info, uint32_t *rid)
1276 {
1277         NTSTATUS status;
1278         struct ldapsam_privates *ldap_state;
1279         int ldap_op = LDAP_MOD_REPLACE;
1280         char *dn;
1281         uint32_t has_objectclass = 0;
1282
1283         ldap_state = (struct ldapsam_privates *)(pdb_methods->private_data);
1284
1285         if (name == NULL || *name == '\0') {
1286                 return NT_STATUS_INVALID_PARAMETER;
1287         }
1288
1289         status = find_user(ldap_state, name, &dn, &has_objectclass);
1290         if (NT_STATUS_IS_OK(status)) {
1291                 ldap_op = LDAP_MOD_REPLACE;
1292         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1293                 char *escape_username;
1294                 ldap_op = LDAP_MOD_ADD;
1295                 escape_username = escape_rdn_val_string_alloc(name);
1296                 if (!escape_username) {
1297                         return NT_STATUS_NO_MEMORY;
1298                 }
1299                 if (name[strlen(name)-1] == '$') {
1300                         dn = talloc_asprintf(tmp_ctx, "uid=%s,%s",
1301                                              escape_username,
1302                                              lp_ldap_machine_suffix());
1303                 } else {
1304                         dn = talloc_asprintf(tmp_ctx, "uid=%s,%s",
1305                                              escape_username,
1306                                              lp_ldap_user_suffix());
1307                 }
1308                 SAFE_FREE(escape_username);
1309                 if (!dn) {
1310                         return NT_STATUS_NO_MEMORY;
1311                 }
1312         } else {
1313                 return status;
1314         }
1315
1316         if (!(has_objectclass & HAS_POSIXACCOUNT)) {
1317                 status = ipasam_add_posix_account_objectclass(ldap_state, ldap_op,
1318                                                               dn, name);
1319                 if (!NT_STATUS_IS_OK(status)) {
1320                         return status;
1321                 }
1322                 has_objectclass |= HAS_POSIXACCOUNT;
1323         }
1324
1325         status = ldap_state->ipasam_privates->ldapsam_create_user(pdb_methods,
1326                                                                   tmp_ctx, name,
1327                                                                   acb_info, rid);
1328         if (!NT_STATUS_IS_OK(status)) {
1329                 return status;
1330         }
1331
1332         status = ipasam_add_ipa_objectclasses(ldap_state, dn, name, lp_realm(),
1333                                               acb_info, has_objectclass);
1334         if (!NT_STATUS_IS_OK(status)) {
1335                 return status;
1336         }
1337
1338         return NT_STATUS_OK;
1339 }
1340
1341 static NTSTATUS pdb_init_IPA_ldapsam(struct pdb_methods **pdb_method, const char *location)
1342 {
1343         struct ldapsam_privates *ldap_state;
1344         NTSTATUS status;
1345
1346         status = pdb_init_ldapsam(pdb_method, location);
1347         if (!NT_STATUS_IS_OK(status)) {
1348                 return status;
1349         }
1350
1351         (*pdb_method)->name = "IPA_ldapsam";
1352
1353         ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
1354         ldap_state->ipasam_privates = talloc_zero(ldap_state,
1355                                                   struct ipasam_privates);
1356         if (ldap_state->ipasam_privates == NULL) {
1357                 return NT_STATUS_NO_MEMORY;
1358         }
1359         ldap_state->is_ipa_ldap = True;
1360
1361         ldap_state->ipasam_privates->server_is_ipa = smbldap_has_extension(
1362                                         priv2ld(ldap_state), IPA_KEYTAB_SET_OID);
1363         ldap_state->ipasam_privates->ldapsam_add_sam_account = (*pdb_method)->add_sam_account;
1364         ldap_state->ipasam_privates->ldapsam_update_sam_account = (*pdb_method)->update_sam_account;
1365         ldap_state->ipasam_privates->ldapsam_create_user = (*pdb_method)->create_user;
1366         ldap_state->ipasam_privates->ldapsam_create_dom_group = (*pdb_method)->create_dom_group;
1367
1368         (*pdb_method)->add_sam_account = pdb_ipasam_add_sam_account;
1369         (*pdb_method)->update_sam_account = pdb_ipasam_update_sam_account;
1370
1371         if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
1372                 if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
1373                         (*pdb_method)->create_user = ipasam_create_user;
1374                         (*pdb_method)->create_dom_group = ipasam_create_dom_group;
1375                 }
1376         }
1377
1378         (*pdb_method)->capabilities = pdb_ipasam_capabilities;
1379         (*pdb_method)->get_domain_info = pdb_ipasam_get_domain_info;
1380
1381         (*pdb_method)->get_trusteddom_pw = ipasam_get_trusteddom_pw;
1382         (*pdb_method)->set_trusteddom_pw = ipasam_set_trusteddom_pw;
1383         (*pdb_method)->del_trusteddom_pw = ipasam_del_trusteddom_pw;
1384         (*pdb_method)->enum_trusteddoms = ipasam_enum_trusteddoms;
1385
1386         (*pdb_method)->get_trusted_domain = ipasam_get_trusted_domain;
1387         (*pdb_method)->get_trusted_domain_by_sid = ipasam_get_trusted_domain_by_sid;
1388         (*pdb_method)->set_trusted_domain = ipasam_set_trusted_domain;
1389         (*pdb_method)->del_trusted_domain = ipasam_del_trusted_domain;
1390         (*pdb_method)->enum_trusted_domains = ipasam_enum_trusted_domains;
1391
1392         return NT_STATUS_OK;
1393 }
1394
1395 NTSTATUS pdb_ipa_init(void)
1396 {
1397         NTSTATUS nt_status;
1398
1399         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "IPA_ldapsam", pdb_init_IPA_ldapsam)))
1400                 return nt_status;
1401
1402         return NT_STATUS_OK;
1403 }