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