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