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