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