Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-abartlet
[kai/samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the lsarpc pipe
5
6    Copyright (C) Andrew Tridgell 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "rpc_server/lsa/lsa.h"
24 #include "util/util_ldb.h"
25 #include "libcli/ldap/ldap_ndr.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28
29 /*
30   this type allows us to distinguish handle types
31 */
32
33 /*
34   state associated with a lsa_OpenAccount() operation
35 */
36 struct lsa_account_state {
37         struct lsa_policy_state *policy;
38         uint32_t access_mask;
39         struct dom_sid *account_sid;
40 };
41
42
43 /*
44   state associated with a lsa_OpenSecret() operation
45 */
46 struct lsa_secret_state {
47         struct lsa_policy_state *policy;
48         uint32_t access_mask;
49         struct ldb_dn *secret_dn;
50         struct ldb_context *sam_ldb;
51         bool global;
52 };
53
54 /*
55   state associated with a lsa_OpenTrustedDomain() operation
56 */
57 struct lsa_trusted_domain_state {
58         struct lsa_policy_state *policy;
59         uint32_t access_mask;
60         struct ldb_dn *trusted_domain_dn;
61 };
62
63 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
64                                       TALLOC_CTX *mem_ctx,
65                                       struct lsa_EnumAccountRights *r);
66
67 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
68                                            TALLOC_CTX *mem_ctx,
69                                            struct lsa_policy_state *state,
70                                            int ldb_flag,
71                                            struct dom_sid *sid,
72                                            const struct lsa_RightSet *rights);
73
74 /* 
75   lsa_Close 
76 */
77 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
78                           struct lsa_Close *r)
79 {
80         struct dcesrv_handle *h;
81
82         *r->out.handle = *r->in.handle;
83
84         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
85
86         talloc_free(h);
87
88         ZERO_STRUCTP(r->out.handle);
89
90         return NT_STATUS_OK;
91 }
92
93
94 /* 
95   lsa_Delete 
96 */
97 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
98                            struct lsa_Delete *r)
99 {
100         return NT_STATUS_NOT_SUPPORTED;
101 }
102
103
104 /* 
105   lsa_DeleteObject
106 */
107 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
108                        struct lsa_DeleteObject *r)
109 {
110         struct dcesrv_handle *h;
111         int ret;
112
113         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
114
115         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
116                 struct lsa_secret_state *secret_state = h->data;
117
118                 /* Ensure user is permitted to delete this... */
119                 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
120                 {
121                 case SECURITY_SYSTEM:
122                 case SECURITY_ADMINISTRATOR:
123                         break;
124                 default:
125                         /* Users and annonymous are not allowed delete things */
126                         return NT_STATUS_ACCESS_DENIED;
127                 }
128
129                 ret = ldb_delete(secret_state->sam_ldb, 
130                                  secret_state->secret_dn);
131                 talloc_free(h);
132                 if (ret != 0) {
133                         return NT_STATUS_INVALID_HANDLE;
134                 }
135
136                 ZERO_STRUCTP(r->out.handle);
137
138                 return NT_STATUS_OK;
139         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
140                 struct lsa_trusted_domain_state *trusted_domain_state = h->data;
141                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
142                                  trusted_domain_state->trusted_domain_dn);
143                 talloc_free(h);
144                 if (ret != 0) {
145                         return NT_STATUS_INVALID_HANDLE;
146                 }
147
148                 ZERO_STRUCTP(r->out.handle);
149
150                 return NT_STATUS_OK;
151         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
152                 struct lsa_RightSet *rights;
153                 struct lsa_account_state *astate;
154                 struct lsa_EnumAccountRights r2;
155                 NTSTATUS status;
156
157                 rights = talloc(mem_ctx, struct lsa_RightSet);
158
159                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
160                 
161                 astate = h->data;
162
163                 r2.in.handle = &astate->policy->handle->wire_handle;
164                 r2.in.sid = astate->account_sid;
165                 r2.out.rights = rights;
166
167                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
168                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
169                         return NT_STATUS_OK;
170                 }
171
172                 if (!NT_STATUS_IS_OK(status)) {
173                         return status;
174                 }
175
176                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
177                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
178                                                     r2.out.rights);
179                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
180                         return NT_STATUS_OK;
181                 }
182
183                 if (!NT_STATUS_IS_OK(status)) {
184                         return status;
185                 }
186
187                 ZERO_STRUCTP(r->out.handle);
188         } 
189         
190         return NT_STATUS_INVALID_HANDLE;
191 }
192
193
194 /* 
195   lsa_EnumPrivs 
196 */
197 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
198                               struct lsa_EnumPrivs *r)
199 {
200         struct dcesrv_handle *h;
201         struct lsa_policy_state *state;
202         int i;
203         const char *privname;
204
205         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
206
207         state = h->data;
208
209         i = *r->in.resume_handle;
210         if (i == 0) i = 1;
211
212         while ((privname = sec_privilege_name(i)) &&
213                r->out.privs->count < r->in.max_count) {
214                 struct lsa_PrivEntry *e;
215
216                 r->out.privs->privs = talloc_realloc(r->out.privs,
217                                                        r->out.privs->privs, 
218                                                        struct lsa_PrivEntry, 
219                                                        r->out.privs->count+1);
220                 if (r->out.privs->privs == NULL) {
221                         return NT_STATUS_NO_MEMORY;
222                 }
223                 e = &r->out.privs->privs[r->out.privs->count];
224                 e->luid.low = i;
225                 e->luid.high = 0;
226                 e->name.string = privname;
227                 r->out.privs->count++;
228                 i++;
229         }
230
231         *r->out.resume_handle = i;
232
233         return NT_STATUS_OK;
234 }
235
236
237 /* 
238   lsa_QuerySecObj 
239 */
240 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
241                                   struct lsa_QuerySecurity *r)
242 {
243         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
244 }
245
246
247 /* 
248   lsa_SetSecObj 
249 */
250 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
251                               struct lsa_SetSecObj *r)
252 {
253         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
254 }
255
256
257 /* 
258   lsa_ChangePassword 
259 */
260 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
261                                    struct lsa_ChangePassword *r)
262 {
263         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
264 }
265
266 /* 
267   dssetup_DsRoleGetPrimaryDomainInformation 
268
269   This is not an LSA call, but is the only call left on the DSSETUP
270   pipe (after the pipe was truncated), and needs lsa_get_policy_state
271 */
272 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
273                                                  TALLOC_CTX *mem_ctx,
274                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
275 {
276         union dssetup_DsRoleInfo *info;
277
278         info = talloc(mem_ctx, union dssetup_DsRoleInfo);
279         W_ERROR_HAVE_NO_MEMORY(info);
280
281         switch (r->in.level) {
282         case DS_ROLE_BASIC_INFORMATION:
283         {
284                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
285                 uint32_t flags = 0;
286                 const char *domain = NULL;
287                 const char *dns_domain = NULL;
288                 const char *forest = NULL;
289                 struct GUID domain_guid;
290                 struct lsa_policy_state *state;
291
292                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
293                 if (!NT_STATUS_IS_OK(status)) {
294                         return ntstatus_to_werror(status);
295                 }
296
297                 ZERO_STRUCT(domain_guid);
298
299                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
300                 case ROLE_STANDALONE:
301                         role            = DS_ROLE_STANDALONE_SERVER;
302                         break;
303                 case ROLE_DOMAIN_MEMBER:
304                         role            = DS_ROLE_MEMBER_SERVER;
305                         break;
306                 case ROLE_DOMAIN_CONTROLLER:
307                         if (samdb_is_pdc(state->sam_ldb)) {
308                                 role    = DS_ROLE_PRIMARY_DC;
309                         } else {
310                                 role    = DS_ROLE_BACKUP_DC;
311                         }
312                         break;
313                 }
314
315                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
316                 case ROLE_STANDALONE:
317                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
318                         W_ERROR_HAVE_NO_MEMORY(domain);
319                         break;
320                 case ROLE_DOMAIN_MEMBER:
321                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
322                         W_ERROR_HAVE_NO_MEMORY(domain);
323                         /* TODO: what is with dns_domain and forest and guid? */
324                         break;
325                 case ROLE_DOMAIN_CONTROLLER:
326                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
327
328                         if (state->mixed_domain == 1) {
329                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
330                         }
331                         
332                         domain          = state->domain_name;
333                         dns_domain      = state->domain_dns;
334                         forest          = state->forest_dns;
335
336                         domain_guid     = state->domain_guid;
337                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
338                         break;
339                 }
340
341                 info->basic.role        = role; 
342                 info->basic.flags       = flags;
343                 info->basic.domain      = domain;
344                 info->basic.dns_domain  = dns_domain;
345                 info->basic.forest      = forest;
346                 info->basic.domain_guid = domain_guid;
347
348                 r->out.info = info;
349                 return WERR_OK;
350         }
351         case DS_ROLE_UPGRADE_STATUS:
352         {
353                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
354                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
355
356                 r->out.info = info;
357                 return WERR_OK;
358         }
359         case DS_ROLE_OP_STATUS:
360         {
361                 info->opstatus.status = DS_ROLE_OP_IDLE;
362
363                 r->out.info = info;
364                 return WERR_OK;
365         }
366         default:
367                 return WERR_INVALID_PARAM;
368         }
369
370         return WERR_INVALID_PARAM;
371 }
372
373
374 /*
375   fill in the AccountDomain info
376 */
377 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
378                                        struct lsa_DomainInfo *info)
379 {
380         info->name.string = state->domain_name;
381         info->sid         = state->domain_sid;
382
383         return NT_STATUS_OK;
384 }
385
386 /*
387   fill in the DNS domain info
388 */
389 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
390                              struct lsa_DnsDomainInfo *info)
391 {
392         info->name.string = state->domain_name;
393         info->sid         = state->domain_sid;
394         info->dns_domain.string = state->domain_dns;
395         info->dns_forest.string = state->forest_dns;
396         info->domain_guid       = state->domain_guid;
397
398         return NT_STATUS_OK;
399 }
400
401 /* 
402   lsa_QueryInfoPolicy2
403 */
404 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
405                                      struct lsa_QueryInfoPolicy2 *r)
406 {
407         struct lsa_policy_state *state;
408         struct dcesrv_handle *h;
409
410         r->out.info = NULL;
411
412         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
413
414         state = h->data;
415
416         r->out.info = talloc(mem_ctx, union lsa_PolicyInformation);
417         if (!r->out.info) {
418                 return NT_STATUS_NO_MEMORY;
419         }
420
421         ZERO_STRUCTP(r->out.info);
422
423         switch (r->in.level) {
424         case LSA_POLICY_INFO_DOMAIN:
425         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
426                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
427
428         case LSA_POLICY_INFO_DNS:
429                 return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
430         case LSA_POLICY_INFO_DB:
431         case LSA_POLICY_INFO_AUDIT_FULL_SET:
432         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
433                 return NT_STATUS_INVALID_PARAMETER;
434         }
435
436         return NT_STATUS_INVALID_INFO_CLASS;
437 }
438
439 /* 
440   lsa_QueryInfoPolicy 
441 */
442 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
443                                     struct lsa_QueryInfoPolicy *r)
444 {
445         struct lsa_QueryInfoPolicy2 r2;
446         NTSTATUS status;
447
448         r2.in.handle = r->in.handle;
449         r2.in.level = r->in.level;
450         
451         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
452
453         r->out.info = r2.out.info;
454
455         return status;
456 }
457
458 /* 
459   lsa_SetInfoPolicy 
460 */
461 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
462                                   struct lsa_SetInfoPolicy *r)
463 {
464         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
465 }
466
467
468 /* 
469   lsa_ClearAuditLog 
470 */
471 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
472                                   struct lsa_ClearAuditLog *r)
473 {
474         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
475 }
476
477
478 /* 
479   lsa_CreateAccount 
480
481   This call does not seem to have any long-term effects, hence no database operations
482 */
483 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
484                                   struct lsa_CreateAccount *r)
485 {
486         struct lsa_account_state *astate;
487
488         struct lsa_policy_state *state;
489         struct dcesrv_handle *h, *ah;
490
491         ZERO_STRUCTP(r->out.acct_handle);
492
493         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
494
495         state = h->data;
496
497         astate = talloc(dce_call->conn, struct lsa_account_state);
498         if (astate == NULL) {
499                 return NT_STATUS_NO_MEMORY;
500         }
501
502         astate->account_sid = dom_sid_dup(astate, r->in.sid);
503         if (astate->account_sid == NULL) {
504                 talloc_free(astate);
505                 return NT_STATUS_NO_MEMORY;
506         }
507         
508         astate->policy = talloc_reference(astate, state);
509         astate->access_mask = r->in.access_mask;
510
511         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
512         if (!ah) {
513                 talloc_free(astate);
514                 return NT_STATUS_NO_MEMORY;
515         }
516
517         ah->data = talloc_steal(ah, astate);
518
519         *r->out.acct_handle = ah->wire_handle;
520
521         return NT_STATUS_OK;
522 }
523
524
525 /* 
526   lsa_EnumAccounts 
527 */
528 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
529                                  struct lsa_EnumAccounts *r)
530 {
531         struct dcesrv_handle *h;
532         struct lsa_policy_state *state;
533         int ret, i;
534         struct ldb_message **res;
535         const char * const attrs[] = { "objectSid", NULL};
536         uint32_t count;
537
538         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
539
540         state = h->data;
541
542         /* NOTE: This call must only return accounts that have at least
543            one privilege set 
544         */
545         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
546                            "(&(objectSid=*)(privilege=*))");
547         if (ret < 0) {
548                 return NT_STATUS_NO_SUCH_USER;
549         }
550
551         if (*r->in.resume_handle >= ret) {
552                 return NT_STATUS_NO_MORE_ENTRIES;
553         }
554
555         count = ret - *r->in.resume_handle;
556         if (count > r->in.num_entries) {
557                 count = r->in.num_entries;
558         }
559
560         if (count == 0) {
561                 return NT_STATUS_NO_MORE_ENTRIES;
562         }
563
564         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
565         if (r->out.sids->sids == NULL) {
566                 return NT_STATUS_NO_MEMORY;
567         }
568
569         for (i=0;i<count;i++) {
570                 r->out.sids->sids[i].sid = 
571                         samdb_result_dom_sid(r->out.sids->sids, 
572                                              res[i + *r->in.resume_handle],
573                                              "objectSid");
574                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
575         }
576
577         r->out.sids->num_sids = count;
578         *r->out.resume_handle = count + *r->in.resume_handle;
579
580         return NT_STATUS_OK;
581         
582 }
583
584
585 /*
586   lsa_CreateTrustedDomainEx2
587 */
588 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
589                                            TALLOC_CTX *mem_ctx,
590                                            struct lsa_CreateTrustedDomainEx2 *r)
591 {
592         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
593 }
594
595 /*
596   lsa_CreateTrustedDomainEx
597 */
598 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
599                                           TALLOC_CTX *mem_ctx,
600                                           struct lsa_CreateTrustedDomainEx *r)
601 {
602         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
603 }
604
605 /* 
606   lsa_CreateTrustedDomain 
607 */
608 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
609                                         struct lsa_CreateTrustedDomain *r)
610 {
611         struct dcesrv_handle *policy_handle;
612         struct lsa_policy_state *policy_state;
613         struct lsa_trusted_domain_state *trusted_domain_state;
614         struct dcesrv_handle *handle;
615         struct ldb_message **msgs, *msg;
616         const char *attrs[] = {
617                 NULL
618         };
619         const char *name;
620         int ret;
621
622         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
623         ZERO_STRUCTP(r->out.trustdom_handle);
624         
625         policy_state = policy_handle->data;
626
627         if (!r->in.info->name.string) {
628                 return NT_STATUS_INVALID_PARAMETER;
629         }
630         name = r->in.info->name.string;
631         
632         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
633         if (!trusted_domain_state) {
634                 return NT_STATUS_NO_MEMORY;
635         }
636         trusted_domain_state->policy = policy_state;
637
638         msg = ldb_msg_new(mem_ctx);
639         if (msg == NULL) {
640                 return NT_STATUS_NO_MEMORY;
641         }
642
643         /* search for the trusted_domain record */
644         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
645                            mem_ctx, policy_state->system_dn, &msgs, attrs,
646                            "(&(cn=%s)(objectclass=trustedDomain))", 
647                            ldb_binary_encode_string(mem_ctx, r->in.info->name.string));
648         if (ret > 0) {
649                 return NT_STATUS_OBJECT_NAME_COLLISION;
650         }
651         
652         if (ret < 0 || ret > 1) {
653                 DEBUG(0,("Found %d records matching DN %s\n", ret,
654                          ldb_dn_get_linearized(policy_state->system_dn)));
655                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
656         }
657         
658         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
659         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
660                 return NT_STATUS_NO_MEMORY;
661         }
662         
663         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", name);
664
665         if (r->in.info->sid) {
666                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
667                 if (!sid_string) {
668                         return NT_STATUS_NO_MEMORY;
669                 }
670                         
671                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
672         }
673
674         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
675
676         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustType", LSA_TRUST_TYPE_DOWNLEVEL);
677
678         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustAttributes", 0);
679
680         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustDirection", LSA_TRUST_DIRECTION_OUTBOUND);
681         
682         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
683
684         /* create the trusted_domain */
685         ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
686         switch (ret) {
687         case  LDB_SUCCESS:
688                 break;
689         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
690                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
691                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
692                          ldb_dn_get_linearized(msg->dn),
693                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
694                 return NT_STATUS_DOMAIN_EXISTS;
695         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
696                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
697                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
698                          ldb_dn_get_linearized(msg->dn),
699                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
700                 return NT_STATUS_ACCESS_DENIED;
701         default:
702                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
703                 DEBUG(0,("Failed to create user record %s: %s\n",
704                          ldb_dn_get_linearized(msg->dn),
705                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
706                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
707         }
708
709         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
710         if (!handle) {
711                 return NT_STATUS_NO_MEMORY;
712         }
713         
714         handle->data = talloc_steal(handle, trusted_domain_state);
715         
716         trusted_domain_state->access_mask = r->in.access_mask;
717         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
718         
719         *r->out.trustdom_handle = handle->wire_handle;
720         
721         return NT_STATUS_OK;
722 }
723
724 /* 
725   lsa_OpenTrustedDomain
726 */
727 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
728                                       struct lsa_OpenTrustedDomain *r)
729 {
730         struct dcesrv_handle *policy_handle;
731         
732         struct lsa_policy_state *policy_state;
733         struct lsa_trusted_domain_state *trusted_domain_state;
734         struct dcesrv_handle *handle;
735         struct ldb_message **msgs;
736         const char *attrs[] = {
737                 NULL
738         };
739
740         const char *sid_string;
741         int ret;
742
743         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
744         ZERO_STRUCTP(r->out.trustdom_handle);
745         policy_state = policy_handle->data;
746
747         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
748         if (!trusted_domain_state) {
749                 return NT_STATUS_NO_MEMORY;
750         }
751         trusted_domain_state->policy = policy_state;
752
753         sid_string = dom_sid_string(mem_ctx, r->in.sid);
754         if (!sid_string) {
755                 return NT_STATUS_NO_MEMORY;
756         }
757
758         /* search for the trusted_domain record */
759         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
760                            mem_ctx, policy_state->system_dn, &msgs, attrs,
761                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
762                            sid_string);
763         if (ret == 0) {
764                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
765         }
766         
767         if (ret != 1) {
768                 DEBUG(0,("Found %d records matching DN %s\n", ret,
769                          ldb_dn_get_linearized(policy_state->system_dn)));
770                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
771         }
772
773         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
774         
775         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
776         if (!handle) {
777                 return NT_STATUS_NO_MEMORY;
778         }
779         
780         handle->data = talloc_steal(handle, trusted_domain_state);
781         
782         trusted_domain_state->access_mask = r->in.access_mask;
783         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
784         
785         *r->out.trustdom_handle = handle->wire_handle;
786         
787         return NT_STATUS_OK;
788 }
789
790
791 /*
792   lsa_OpenTrustedDomainByName
793 */
794 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
795                                             TALLOC_CTX *mem_ctx,
796                                             struct lsa_OpenTrustedDomainByName *r)
797 {
798         struct dcesrv_handle *policy_handle;
799         
800         struct lsa_policy_state *policy_state;
801         struct lsa_trusted_domain_state *trusted_domain_state;
802         struct dcesrv_handle *handle;
803         struct ldb_message **msgs;
804         const char *attrs[] = {
805                 NULL
806         };
807
808         int ret;
809
810         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
811         ZERO_STRUCTP(r->out.trustdom_handle);
812         policy_state = policy_handle->data;
813
814         if (!r->in.name.string) {
815                 return NT_STATUS_INVALID_PARAMETER;
816         }
817         
818         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
819         if (!trusted_domain_state) {
820                 return NT_STATUS_NO_MEMORY;
821         }
822         trusted_domain_state->policy = policy_state;
823
824         /* search for the trusted_domain record */
825         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
826                            mem_ctx, policy_state->system_dn, &msgs, attrs,
827                            "(&(flatname=%s)(objectclass=trustedDomain))", 
828                            ldb_binary_encode_string(mem_ctx, r->in.name.string));
829         if (ret == 0) {
830                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
831         }
832         
833         if (ret != 1) {
834                 DEBUG(0,("Found %d records matching DN %s\n", ret,
835                          ldb_dn_get_linearized(policy_state->system_dn)));
836                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
837         }
838
839         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
840         
841         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
842         if (!handle) {
843                 return NT_STATUS_NO_MEMORY;
844         }
845         
846         handle->data = talloc_steal(handle, trusted_domain_state);
847         
848         trusted_domain_state->access_mask = r->in.access_mask;
849         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
850         
851         *r->out.trustdom_handle = handle->wire_handle;
852         
853         return NT_STATUS_OK;
854 }
855
856
857
858 /* 
859   lsa_SetTrustedDomainInfo
860 */
861 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
862                                          struct lsa_SetTrustedDomainInfo *r)
863 {
864         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
865 }
866
867
868
869 /* 
870   lsa_SetInfomrationTrustedDomain
871 */
872 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, 
873                                                 TALLOC_CTX *mem_ctx,
874                                                 struct lsa_SetInformationTrustedDomain *r)
875 {
876         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
877 }
878
879
880 /* 
881   lsa_DeleteTrustedDomain
882 */
883 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
884                                       struct lsa_DeleteTrustedDomain *r)
885 {
886         NTSTATUS status;
887         struct lsa_OpenTrustedDomain open;
888         struct lsa_DeleteObject delete;
889         struct dcesrv_handle *h;
890
891         open.in.handle = r->in.handle;
892         open.in.sid = r->in.dom_sid;
893         open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
894         open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
895         if (!open.out.trustdom_handle) {
896                 return NT_STATUS_NO_MEMORY;
897         }
898         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
899         if (!NT_STATUS_IS_OK(status)) {
900                 return status;
901         }
902
903         DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
904         talloc_steal(mem_ctx, h);
905
906         delete.in.handle = open.out.trustdom_handle;
907         delete.out.handle = open.out.trustdom_handle;
908         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &delete);
909         if (!NT_STATUS_IS_OK(status)) {
910                 return status;
911         }
912         return NT_STATUS_OK;
913 }
914
915 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
916                                      struct ldb_message *msg, 
917                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
918 {
919         info_ex->domain_name.string
920                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
921         info_ex->netbios_name.string
922                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
923         info_ex->sid 
924                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
925         info_ex->trust_direction
926                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
927         info_ex->trust_type
928                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
929         info_ex->trust_attributes
930                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
931         return NT_STATUS_OK;
932 }
933
934 /* 
935   lsa_QueryTrustedDomainInfo
936 */
937 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
938                                            struct lsa_QueryTrustedDomainInfo *r)
939 {
940         struct dcesrv_handle *h;
941         struct lsa_trusted_domain_state *trusted_domain_state;
942         struct ldb_message *msg;
943         int ret;
944         struct ldb_message **res;
945         const char *attrs[] = {
946                 "flatname", 
947                 "trustPartner",
948                 "securityIdentifier",
949                 "trustDirection",
950                 "trustType",
951                 "trustAttributes", 
952                 "msDs-supportedEncryptionTypes",
953                 NULL
954         };
955
956         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
957
958         trusted_domain_state = h->data;
959
960         /* pull all the user attributes */
961         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
962                               trusted_domain_state->trusted_domain_dn, &res, attrs);
963         if (ret != 1) {
964                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
965         }
966         msg = res[0];
967         
968         r->out.info = talloc(mem_ctx, union lsa_TrustedDomainInfo);
969         if (!r->out.info) {
970                 return NT_STATUS_NO_MEMORY;
971         }
972         switch (r->in.level) {
973         case LSA_TRUSTED_DOMAIN_INFO_NAME:
974                 r->out.info->name.netbios_name.string
975                         = samdb_result_string(msg, "flatname", NULL);                                      
976                 break;
977         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
978                 r->out.info->posix_offset.posix_offset
979                         = samdb_result_uint(msg, "posixOffset", 0);                                        
980                 break;
981 #if 0  /* Win2k3 doesn't implement this */
982         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
983                 r->out.info->info_basic.netbios_name.string 
984                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
985                 r->out.info->info_basic.sid
986                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
987                 break;
988 #endif
989         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
990                 return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_ex);
991
992         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
993                 ZERO_STRUCT(r->out.info->full_info);
994                 return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex);
995
996         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
997                 ZERO_STRUCT(r->out.info->info2_internal);
998                 r->out.info->info2_internal.posix_offset.posix_offset
999                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1000                 return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info2_internal.info_ex);
1001                 
1002         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES:
1003                 r->out.info->enc_types.enc_types
1004                         = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
1005                 break;
1006
1007         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
1008         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
1009                 /* oops, we don't want to return the info after all */
1010                 talloc_free(r->out.info);
1011                 r->out.info = NULL;
1012                 return NT_STATUS_INVALID_PARAMETER;
1013         default:
1014                 /* oops, we don't want to return the info after all */
1015                 talloc_free(r->out.info);
1016                 r->out.info = NULL;
1017                 return NT_STATUS_INVALID_INFO_CLASS;
1018         }
1019
1020         return NT_STATUS_OK;
1021 }
1022
1023
1024 /* 
1025   lsa_QueryTrustedDomainInfoBySid
1026 */
1027 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1028                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
1029 {
1030         NTSTATUS status;
1031         struct lsa_OpenTrustedDomain open;
1032         struct lsa_QueryTrustedDomainInfo query;
1033         struct dcesrv_handle *h;
1034         open.in.handle = r->in.handle;
1035         open.in.sid = r->in.dom_sid;
1036         open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1037         open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1038         if (!open.out.trustdom_handle) {
1039                 return NT_STATUS_NO_MEMORY;
1040         }
1041         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
1042         if (!NT_STATUS_IS_OK(status)) {
1043                 return status;
1044         }
1045
1046         /* Ensure this handle goes away at the end of this call */
1047         DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
1048         talloc_steal(mem_ctx, h);
1049         
1050         query.in.trustdom_handle = open.out.trustdom_handle;
1051         query.in.level = r->in.level;
1052         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1053         if (!NT_STATUS_IS_OK(status)) {
1054                 return status;
1055         }
1056         
1057         r->out.info = query.out.info;
1058         return NT_STATUS_OK;
1059 }
1060
1061 /*
1062   lsa_SetTrustedDomainInfoByName
1063 */
1064 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1065                                                TALLOC_CTX *mem_ctx,
1066                                                struct lsa_SetTrustedDomainInfoByName *r)
1067 {
1068         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1069 }
1070
1071 /* 
1072    lsa_QueryTrustedDomainInfoByName
1073 */
1074 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1075                                                  TALLOC_CTX *mem_ctx,
1076                                                  struct lsa_QueryTrustedDomainInfoByName *r)
1077 {
1078         NTSTATUS status;
1079         struct lsa_OpenTrustedDomainByName open;
1080         struct lsa_QueryTrustedDomainInfo query;
1081         struct dcesrv_handle *h;
1082         open.in.handle = r->in.handle;
1083         open.in.name = r->in.trusted_domain;
1084         open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1085         open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1086         if (!open.out.trustdom_handle) {
1087                 return NT_STATUS_NO_MEMORY;
1088         }
1089         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &open);
1090         if (!NT_STATUS_IS_OK(status)) {
1091                 return status;
1092         }
1093         
1094         /* Ensure this handle goes away at the end of this call */
1095         DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
1096         talloc_steal(mem_ctx, h);
1097
1098         query.in.trustdom_handle = open.out.trustdom_handle;
1099         query.in.level = r->in.level;
1100         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1101         if (!NT_STATUS_IS_OK(status)) {
1102                 return status;
1103         }
1104         
1105         r->out.info = query.out.info;
1106         return NT_STATUS_OK;
1107 }
1108
1109 /*
1110   lsa_CloseTrustedDomainEx 
1111 */
1112 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
1113                                          TALLOC_CTX *mem_ctx,
1114                                          struct lsa_CloseTrustedDomainEx *r)
1115 {
1116         /* The result of a bad hair day from an IDL programmer?  Not
1117          * implmented in Win2k3.  You should always just lsa_Close
1118          * anyway. */
1119         return NT_STATUS_NOT_IMPLEMENTED;
1120 }
1121
1122
1123 /*
1124   comparison function for sorting lsa_DomainInformation array
1125 */
1126 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
1127 {
1128         return strcasecmp_m(e1->name.string, e2->name.string);
1129 }
1130
1131 /* 
1132   lsa_EnumTrustDom 
1133 */
1134 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1135                                  struct lsa_EnumTrustDom *r)
1136 {
1137         struct dcesrv_handle *policy_handle;
1138         struct lsa_DomainInfo *entries;
1139         struct lsa_policy_state *policy_state;
1140         struct ldb_message **domains;
1141         const char *attrs[] = {
1142                 "flatname", 
1143                 "securityIdentifier",
1144                 NULL
1145         };
1146
1147
1148         int count, i;
1149
1150         *r->out.resume_handle = 0;
1151
1152         r->out.domains->domains = NULL;
1153         r->out.domains->count = 0;
1154
1155         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1156
1157         policy_state = policy_handle->data;
1158
1159         /* search for all users in this domain. This could possibly be cached and 
1160            resumed based on resume_key */
1161         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1162                              "objectclass=trustedDomain");
1163         if (count == -1) {
1164                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1165         }
1166
1167         /* convert to lsa_TrustInformation format */
1168         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
1169         if (!entries) {
1170                 return NT_STATUS_NO_MEMORY;
1171         }
1172         for (i=0;i<count;i++) {
1173                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
1174                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
1175         }
1176
1177         /* sort the results by name */
1178         qsort(entries, count, sizeof(*entries), 
1179               (comparison_fn_t)compare_DomainInfo);
1180
1181         if (*r->in.resume_handle >= count) {
1182                 *r->out.resume_handle = -1;
1183
1184                 return NT_STATUS_NO_MORE_ENTRIES;
1185         }
1186
1187         /* return the rest, limit by max_size. Note that we 
1188            use the w2k3 element size value of 60 */
1189         r->out.domains->count = count - *r->in.resume_handle;
1190         r->out.domains->count = MIN(r->out.domains->count, 
1191                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
1192
1193         r->out.domains->domains = entries + *r->in.resume_handle;
1194         r->out.domains->count = r->out.domains->count;
1195
1196         if (r->out.domains->count < count - *r->in.resume_handle) {
1197                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1198                 return STATUS_MORE_ENTRIES;
1199         }
1200
1201         return NT_STATUS_OK;
1202 }
1203
1204 /*
1205   comparison function for sorting lsa_DomainInformation array
1206 */
1207 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
1208 {
1209         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
1210 }
1211
1212 /* 
1213   lsa_EnumTrustedDomainsEx 
1214 */
1215 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1216                                         struct lsa_EnumTrustedDomainsEx *r)
1217 {
1218         struct dcesrv_handle *policy_handle;
1219         struct lsa_TrustDomainInfoInfoEx *entries;
1220         struct lsa_policy_state *policy_state;
1221         struct ldb_message **domains;
1222         const char *attrs[] = {
1223                 "flatname", 
1224                 "trustPartner",
1225                 "securityIdentifier",
1226                 "trustDirection",
1227                 "trustType",
1228                 "trustAttributes", 
1229                 NULL
1230         };
1231         NTSTATUS nt_status;
1232
1233         int count, i;
1234
1235         *r->out.resume_handle = 0;
1236
1237         r->out.domains->domains = NULL;
1238         r->out.domains->count = 0;
1239
1240         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1241
1242         policy_state = policy_handle->data;
1243
1244         /* search for all users in this domain. This could possibly be cached and 
1245            resumed based on resume_key */
1246         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1247                              "objectclass=trustedDomain");
1248         if (count == -1) {
1249                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1250         }
1251
1252         /* convert to lsa_DomainInformation format */
1253         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
1254         if (!entries) {
1255                 return NT_STATUS_NO_MEMORY;
1256         }
1257         for (i=0;i<count;i++) {
1258                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
1259                 if (!NT_STATUS_IS_OK(nt_status)) {
1260                         return nt_status;
1261                 }
1262         }
1263
1264         /* sort the results by name */
1265         qsort(entries, count, sizeof(*entries), 
1266               (comparison_fn_t)compare_TrustDomainInfoInfoEx);
1267
1268         if (*r->in.resume_handle >= count) {
1269                 *r->out.resume_handle = -1;
1270
1271                 return NT_STATUS_NO_MORE_ENTRIES;
1272         }
1273
1274         /* return the rest, limit by max_size. Note that we 
1275            use the w2k3 element size value of 60 */
1276         r->out.domains->count = count - *r->in.resume_handle;
1277         r->out.domains->count = MIN(r->out.domains->count, 
1278                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
1279
1280         r->out.domains->domains = entries + *r->in.resume_handle;
1281         r->out.domains->count = r->out.domains->count;
1282
1283         if (r->out.domains->count < count - *r->in.resume_handle) {
1284                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1285                 return STATUS_MORE_ENTRIES;
1286         }
1287
1288         return NT_STATUS_OK;
1289 }
1290
1291
1292 /* 
1293   lsa_OpenAccount 
1294 */
1295 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1296                                 struct lsa_OpenAccount *r)
1297 {
1298         struct dcesrv_handle *h, *ah;
1299         struct lsa_policy_state *state;
1300         struct lsa_account_state *astate;
1301
1302         ZERO_STRUCTP(r->out.acct_handle);
1303
1304         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1305
1306         state = h->data;
1307
1308         astate = talloc(dce_call->conn, struct lsa_account_state);
1309         if (astate == NULL) {
1310                 return NT_STATUS_NO_MEMORY;
1311         }
1312
1313         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1314         if (astate->account_sid == NULL) {
1315                 talloc_free(astate);
1316                 return NT_STATUS_NO_MEMORY;
1317         }
1318         
1319         astate->policy = talloc_reference(astate, state);
1320         astate->access_mask = r->in.access_mask;
1321
1322         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1323         if (!ah) {
1324                 talloc_free(astate);
1325                 return NT_STATUS_NO_MEMORY;
1326         }
1327
1328         ah->data = talloc_steal(ah, astate);
1329
1330         *r->out.acct_handle = ah->wire_handle;
1331
1332         return NT_STATUS_OK;
1333 }
1334
1335
1336 /* 
1337   lsa_EnumPrivsAccount 
1338 */
1339 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1340                                      TALLOC_CTX *mem_ctx,
1341                                      struct lsa_EnumPrivsAccount *r)
1342 {
1343         struct dcesrv_handle *h;
1344         struct lsa_account_state *astate;
1345         int ret, i;
1346         struct ldb_message **res;
1347         const char * const attrs[] = { "privilege", NULL};
1348         struct ldb_message_element *el;
1349         const char *sidstr;
1350
1351         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1352
1353         astate = h->data;
1354
1355         r->out.privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1356         r->out.privs->count = 0;
1357         r->out.privs->unknown = 0;
1358         r->out.privs->set = NULL;
1359
1360         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
1361         if (sidstr == NULL) {
1362                 return NT_STATUS_NO_MEMORY;
1363         }
1364
1365         ret = gendb_search(astate->policy->sam_ldb, mem_ctx, NULL, &res, attrs, 
1366                            "objectSid=%s", sidstr);
1367         if (ret != 1) {
1368                 return NT_STATUS_OK;
1369         }
1370
1371         el = ldb_msg_find_element(res[0], "privilege");
1372         if (el == NULL || el->num_values == 0) {
1373                 return NT_STATUS_OK;
1374         }
1375
1376         r->out.privs->set = talloc_array(r->out.privs, 
1377                                          struct lsa_LUIDAttribute, el->num_values);
1378         if (r->out.privs->set == NULL) {
1379                 return NT_STATUS_NO_MEMORY;
1380         }
1381
1382         for (i=0;i<el->num_values;i++) {
1383                 int id = sec_privilege_id((const char *)el->values[i].data);
1384                 if (id == -1) {
1385                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1386                 }
1387                 r->out.privs->set[i].attribute = 0;
1388                 r->out.privs->set[i].luid.low = id;
1389                 r->out.privs->set[i].luid.high = 0;
1390         }
1391
1392         r->out.privs->count = el->num_values;
1393
1394         return NT_STATUS_OK;
1395 }
1396
1397 /* 
1398   lsa_EnumAccountRights 
1399 */
1400 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1401                                       TALLOC_CTX *mem_ctx,
1402                                       struct lsa_EnumAccountRights *r)
1403 {
1404         struct dcesrv_handle *h;
1405         struct lsa_policy_state *state;
1406         int ret, i;
1407         struct ldb_message **res;
1408         const char * const attrs[] = { "privilege", NULL};
1409         const char *sidstr;
1410         struct ldb_message_element *el;
1411
1412         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1413
1414         state = h->data;
1415
1416         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
1417         if (sidstr == NULL) {
1418                 return NT_STATUS_NO_MEMORY;
1419         }
1420
1421         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
1422                            "(&(objectSid=%s)(privilege=*))", sidstr);
1423         if (ret == 0) {
1424                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1425         }
1426         if (ret > 1) {
1427                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1428         }
1429         if (ret == -1) {
1430                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
1431                           dom_sid_string(mem_ctx, r->in.sid),
1432                           ldb_errstring(state->sam_ldb)));
1433                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1434         }
1435
1436         el = ldb_msg_find_element(res[0], "privilege");
1437         if (el == NULL || el->num_values == 0) {
1438                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1439         }
1440
1441         r->out.rights->count = el->num_values;
1442         r->out.rights->names = talloc_array(r->out.rights, 
1443                                             struct lsa_StringLarge, r->out.rights->count);
1444         if (r->out.rights->names == NULL) {
1445                 return NT_STATUS_NO_MEMORY;
1446         }
1447
1448         for (i=0;i<el->num_values;i++) {
1449                 r->out.rights->names[i].string = (const char *)el->values[i].data;
1450         }
1451
1452         return NT_STATUS_OK;
1453 }
1454
1455
1456
1457 /* 
1458   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1459 */
1460 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1461                                            TALLOC_CTX *mem_ctx,
1462                                            struct lsa_policy_state *state,
1463                                            int ldb_flag,
1464                                            struct dom_sid *sid,
1465                                            const struct lsa_RightSet *rights)
1466 {
1467         const char *sidstr;
1468         struct ldb_message *msg;
1469         struct ldb_message_element *el;
1470         int i, ret;
1471         struct lsa_EnumAccountRights r2;
1472
1473         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
1474         if (sidstr == NULL) {
1475                 return NT_STATUS_NO_MEMORY;
1476         }
1477
1478         msg = ldb_msg_new(mem_ctx);
1479         if (msg == NULL) {
1480                 return NT_STATUS_NO_MEMORY;
1481         }
1482
1483         msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx, 
1484                                   NULL, "objectSid=%s", sidstr);
1485         if (msg->dn == NULL) {
1486                 NTSTATUS status;
1487                 if (ldb_flag == LDB_FLAG_MOD_DELETE) {
1488                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1489                 }
1490                 status = samdb_create_foreign_security_principal(state->sam_ldb, mem_ctx, 
1491                                                                  sid, &msg->dn);
1492                 if (!NT_STATUS_IS_OK(status)) {
1493                         return status;
1494                 }
1495                 return NT_STATUS_NO_SUCH_USER;
1496         }
1497
1498         if (ldb_msg_add_empty(msg, "privilege", ldb_flag, NULL)) {
1499                 return NT_STATUS_NO_MEMORY;
1500         }
1501
1502         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1503                 NTSTATUS status;
1504
1505                 r2.in.handle = &state->handle->wire_handle;
1506                 r2.in.sid = sid;
1507                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1508
1509                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1510                 if (!NT_STATUS_IS_OK(status)) {
1511                         ZERO_STRUCTP(r2.out.rights);
1512                 }
1513         }
1514
1515         for (i=0;i<rights->count;i++) {
1516                 if (sec_privilege_id(rights->names[i].string) == -1) {
1517                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1518                 }
1519
1520                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
1521                         int j;
1522                         for (j=0;j<r2.out.rights->count;j++) {
1523                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
1524                                                rights->names[i].string) == 0) {
1525                                         break;
1526                                 }
1527                         }
1528                         if (j != r2.out.rights->count) continue;
1529                 }
1530
1531                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
1532                 if (ret != LDB_SUCCESS) {
1533                         return NT_STATUS_NO_MEMORY;
1534                 }
1535         }
1536
1537         el = ldb_msg_find_element(msg, "privilege");
1538         if (!el) {
1539                 return NT_STATUS_OK;
1540         }
1541
1542         ret = ldb_modify(state->sam_ldb, msg);
1543         if (ret != 0) {
1544                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1545                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1546                 }
1547                 DEBUG(3, ("Could not %s attributes from %s: %s", 
1548                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
1549                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)));
1550                 return NT_STATUS_UNEXPECTED_IO_ERROR;
1551         }
1552
1553         return NT_STATUS_OK;
1554 }
1555
1556 /* 
1557   lsa_AddPrivilegesToAccount
1558 */
1559 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1560                                            struct lsa_AddPrivilegesToAccount *r)
1561 {
1562         struct lsa_RightSet rights;
1563         struct dcesrv_handle *h;
1564         struct lsa_account_state *astate;
1565         int i;
1566
1567         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1568
1569         astate = h->data;
1570
1571         rights.count = r->in.privs->count;
1572         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
1573         if (rights.names == NULL) {
1574                 return NT_STATUS_NO_MEMORY;
1575         }
1576         for (i=0;i<rights.count;i++) {
1577                 int id = r->in.privs->set[i].luid.low;
1578                 if (r->in.privs->set[i].luid.high) {
1579                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1580                 }
1581                 rights.names[i].string = sec_privilege_name(id);
1582                 if (rights.names[i].string == NULL) {
1583                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1584                 }
1585         }
1586
1587         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1588                                           LDB_FLAG_MOD_ADD, astate->account_sid,
1589                                           &rights);
1590 }
1591
1592
1593 /* 
1594   lsa_RemovePrivilegesFromAccount
1595 */
1596 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1597                                                 struct lsa_RemovePrivilegesFromAccount *r)
1598 {
1599         struct lsa_RightSet *rights;
1600         struct dcesrv_handle *h;
1601         struct lsa_account_state *astate;
1602         int i;
1603
1604         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1605
1606         astate = h->data;
1607
1608         rights = talloc(mem_ctx, struct lsa_RightSet);
1609
1610         if (r->in.remove_all == 1 && 
1611             r->in.privs == NULL) {
1612                 struct lsa_EnumAccountRights r2;
1613                 NTSTATUS status;
1614
1615                 r2.in.handle = &astate->policy->handle->wire_handle;
1616                 r2.in.sid = astate->account_sid;
1617                 r2.out.rights = rights;
1618
1619                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1620                 if (!NT_STATUS_IS_OK(status)) {
1621                         return status;
1622                 }
1623
1624                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1625                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
1626                                                   r2.out.rights);
1627         }
1628
1629         if (r->in.remove_all != 0) {
1630                 return NT_STATUS_INVALID_PARAMETER;
1631         }
1632
1633         rights->count = r->in.privs->count;
1634         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
1635         if (rights->names == NULL) {
1636                 return NT_STATUS_NO_MEMORY;
1637         }
1638         for (i=0;i<rights->count;i++) {
1639                 int id = r->in.privs->set[i].luid.low;
1640                 if (r->in.privs->set[i].luid.high) {
1641                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1642                 }
1643                 rights->names[i].string = sec_privilege_name(id);
1644                 if (rights->names[i].string == NULL) {
1645                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1646                 }
1647         }
1648
1649         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1650                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
1651                                           rights);
1652 }
1653
1654
1655 /* 
1656   lsa_GetQuotasForAccount
1657 */
1658 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1659                        struct lsa_GetQuotasForAccount *r)
1660 {
1661         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1662 }
1663
1664
1665 /* 
1666   lsa_SetQuotasForAccount
1667 */
1668 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1669                        struct lsa_SetQuotasForAccount *r)
1670 {
1671         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1672 }
1673
1674
1675 /* 
1676   lsa_GetSystemAccessAccount
1677 */
1678 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1679                        struct lsa_GetSystemAccessAccount *r)
1680 {
1681         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1682 }
1683
1684
1685 /* 
1686   lsa_SetSystemAccessAccount
1687 */
1688 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1689                        struct lsa_SetSystemAccessAccount *r)
1690 {
1691         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1692 }
1693
1694
1695 /* 
1696   lsa_CreateSecret 
1697 */
1698 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1699                                  struct lsa_CreateSecret *r)
1700 {
1701         struct dcesrv_handle *policy_handle;
1702         struct lsa_policy_state *policy_state;
1703         struct lsa_secret_state *secret_state;
1704         struct dcesrv_handle *handle;
1705         struct ldb_message **msgs, *msg;
1706         const char *errstr;
1707         const char *attrs[] = {
1708                 NULL
1709         };
1710
1711         const char *name;
1712
1713         int ret;
1714
1715         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1716         ZERO_STRUCTP(r->out.sec_handle);
1717         
1718         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
1719         {
1720         case SECURITY_SYSTEM:
1721         case SECURITY_ADMINISTRATOR:
1722                 break;
1723         default:
1724                 /* Users and annonymous are not allowed create secrets */
1725                 return NT_STATUS_ACCESS_DENIED;
1726         }
1727
1728         policy_state = policy_handle->data;
1729
1730         if (!r->in.name.string) {
1731                 return NT_STATUS_INVALID_PARAMETER;
1732         }
1733         
1734         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1735         if (!secret_state) {
1736                 return NT_STATUS_NO_MEMORY;
1737         }
1738         secret_state->policy = policy_state;
1739
1740         msg = ldb_msg_new(mem_ctx);
1741         if (msg == NULL) {
1742                 return NT_STATUS_NO_MEMORY;
1743         }
1744
1745         if (strncmp("G$", r->in.name.string, 2) == 0) {
1746                 const char *name2;
1747                 name = &r->in.name.string[2];
1748                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
1749                 secret_state->global = true;
1750
1751                 if (strlen(name) < 1) {
1752                         return NT_STATUS_INVALID_PARAMETER;
1753                 }
1754
1755                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
1756                 /* search for the secret record */
1757                 ret = gendb_search(secret_state->sam_ldb,
1758                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1759                                    "(&(cn=%s)(objectclass=secret))", 
1760                                    name2);
1761                 if (ret > 0) {
1762                         return NT_STATUS_OBJECT_NAME_COLLISION;
1763                 }
1764                 
1765                 if (ret == -1) {
1766                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
1767                                  name2, ldb_errstring(secret_state->sam_ldb)));
1768                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1769                 }
1770
1771                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1772                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
1773                         return NT_STATUS_NO_MEMORY;
1774                 }
1775                 
1776                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
1777         
1778         } else {
1779                 secret_state->global = false;
1780
1781                 name = r->in.name.string;
1782                 if (strlen(name) < 1) {
1783                         return NT_STATUS_INVALID_PARAMETER;
1784                 }
1785
1786                 secret_state->sam_ldb = talloc_reference(secret_state, 
1787                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
1788                 /* search for the secret record */
1789                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
1790                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
1791                                    &msgs, attrs,
1792                                    "(&(cn=%s)(objectclass=secret))", 
1793                                    ldb_binary_encode_string(mem_ctx, name));
1794                 if (ret > 0) {
1795                         return NT_STATUS_OBJECT_NAME_COLLISION;
1796                 }
1797                 
1798                 if (ret == -1) {
1799                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
1800                                  name, ldb_errstring(secret_state->sam_ldb)));
1801                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1802                 }
1803
1804                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
1805                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
1806         } 
1807
1808         /* pull in all the template attributes.  Note this is always from the global samdb */
1809         ret = samdb_copy_template(secret_state->policy->sam_ldb, msg, 
1810                                   "secret", &errstr);
1811         if (ret != 0) {
1812                 DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n",
1813                          errstr));
1814                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1815         }
1816
1817         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
1818         
1819         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
1820
1821         /* create the secret */
1822         ret = ldb_add(secret_state->sam_ldb, msg);
1823         if (ret != 0) {
1824                 DEBUG(0,("Failed to create secret record %s: %s\n",
1825                          ldb_dn_get_linearized(msg->dn), 
1826                          ldb_errstring(secret_state->sam_ldb)));
1827                 return NT_STATUS_ACCESS_DENIED;
1828         }
1829
1830         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1831         if (!handle) {
1832                 return NT_STATUS_NO_MEMORY;
1833         }
1834         
1835         handle->data = talloc_steal(handle, secret_state);
1836         
1837         secret_state->access_mask = r->in.access_mask;
1838         secret_state->policy = talloc_reference(secret_state, policy_state);
1839         
1840         *r->out.sec_handle = handle->wire_handle;
1841         
1842         return NT_STATUS_OK;
1843 }
1844
1845
1846 /* 
1847   lsa_OpenSecret 
1848 */
1849 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1850                                struct lsa_OpenSecret *r)
1851 {
1852         struct dcesrv_handle *policy_handle;
1853         
1854         struct lsa_policy_state *policy_state;
1855         struct lsa_secret_state *secret_state;
1856         struct dcesrv_handle *handle;
1857         struct ldb_message **msgs;
1858         const char *attrs[] = {
1859                 NULL
1860         };
1861
1862         const char *name;
1863
1864         int ret;
1865
1866         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1867         ZERO_STRUCTP(r->out.sec_handle);
1868         policy_state = policy_handle->data;
1869
1870         if (!r->in.name.string) {
1871                 return NT_STATUS_INVALID_PARAMETER;
1872         }
1873         
1874         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
1875         {
1876         case SECURITY_SYSTEM:
1877         case SECURITY_ADMINISTRATOR:
1878                 break;
1879         default:
1880                 /* Users and annonymous are not allowed to access secrets */
1881                 return NT_STATUS_ACCESS_DENIED;
1882         }
1883
1884         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1885         if (!secret_state) {
1886                 return NT_STATUS_NO_MEMORY;
1887         }
1888         secret_state->policy = policy_state;
1889
1890         if (strncmp("G$", r->in.name.string, 2) == 0) {
1891                 name = &r->in.name.string[2];
1892                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
1893                 secret_state->global = true;
1894
1895                 if (strlen(name) < 1) {
1896                         return NT_STATUS_INVALID_PARAMETER;
1897                 }
1898
1899                 /* search for the secret record */
1900                 ret = gendb_search(secret_state->sam_ldb,
1901                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1902                                    "(&(cn=%s Secret)(objectclass=secret))", 
1903                                    ldb_binary_encode_string(mem_ctx, name));
1904                 if (ret == 0) {
1905                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1906                 }
1907                 
1908                 if (ret != 1) {
1909                         DEBUG(0,("Found %d records matching DN %s\n", ret,
1910                                  ldb_dn_get_linearized(policy_state->system_dn)));
1911                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1912                 }
1913         
1914         } else {
1915                 secret_state->global = false;
1916                 secret_state->sam_ldb = talloc_reference(secret_state, 
1917                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
1918
1919                 name = r->in.name.string;
1920                 if (strlen(name) < 1) {
1921                         return NT_STATUS_INVALID_PARAMETER;
1922                 }
1923
1924                 /* search for the secret record */
1925                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
1926                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
1927                                    &msgs, attrs,
1928                                    "(&(cn=%s)(objectclass=secret))", 
1929                                    ldb_binary_encode_string(mem_ctx, name));
1930                 if (ret == 0) {
1931                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1932                 }
1933                 
1934                 if (ret != 1) {
1935                         DEBUG(0,("Found %d records matching CN=%s\n", 
1936                                  ret, ldb_binary_encode_string(mem_ctx, name)));
1937                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1938                 }
1939         } 
1940
1941         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
1942         
1943         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1944         if (!handle) {
1945                 return NT_STATUS_NO_MEMORY;
1946         }
1947         
1948         handle->data = talloc_steal(handle, secret_state);
1949         
1950         secret_state->access_mask = r->in.access_mask;
1951         secret_state->policy = talloc_reference(secret_state, policy_state);
1952         
1953         *r->out.sec_handle = handle->wire_handle;
1954         
1955         return NT_STATUS_OK;
1956 }
1957
1958
1959 /* 
1960   lsa_SetSecret 
1961 */
1962 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1963                               struct lsa_SetSecret *r)
1964 {
1965
1966         struct dcesrv_handle *h;
1967         struct lsa_secret_state *secret_state;
1968         struct ldb_message *msg;
1969         DATA_BLOB session_key;
1970         DATA_BLOB crypt_secret, secret;
1971         struct ldb_val val;
1972         int ret;
1973         NTSTATUS status = NT_STATUS_OK;
1974
1975         struct timeval now = timeval_current();
1976         NTTIME nt_now = timeval_to_nttime(&now);
1977
1978         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
1979
1980         secret_state = h->data;
1981
1982         msg = ldb_msg_new(mem_ctx);
1983         if (msg == NULL) {
1984                 return NT_STATUS_NO_MEMORY;
1985         }
1986
1987         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
1988         if (!msg->dn) {
1989                 return NT_STATUS_NO_MEMORY;
1990         }
1991         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
1992         if (!NT_STATUS_IS_OK(status)) {
1993                 return status;
1994         }
1995
1996         if (r->in.old_val) {
1997                 /* Decrypt */
1998                 crypt_secret.data = r->in.old_val->data;
1999                 crypt_secret.length = r->in.old_val->size;
2000                 
2001                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2002                 if (!NT_STATUS_IS_OK(status)) {
2003                         return status;
2004                 }
2005                 
2006                 val.data = secret.data;
2007                 val.length = secret.length;
2008                 
2009                 /* set value */
2010                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2011                                         mem_ctx, msg, "priorValue", &val) != 0) {
2012                         return NT_STATUS_NO_MEMORY; 
2013                 }
2014                 
2015                 /* set old value mtime */
2016                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2017                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2018                         return NT_STATUS_NO_MEMORY; 
2019                 }
2020
2021                 if (!r->in.new_val) {
2022                         /* set old value mtime */
2023                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2024                                                  mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2025                                 return NT_STATUS_NO_MEMORY; 
2026                         }
2027                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
2028                                                  mem_ctx, msg, "currentValue")) {
2029                                 return NT_STATUS_NO_MEMORY;
2030                         }
2031                 }
2032         }
2033
2034         if (r->in.new_val) {
2035                 /* Decrypt */
2036                 crypt_secret.data = r->in.new_val->data;
2037                 crypt_secret.length = r->in.new_val->size;
2038                 
2039                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2040                 if (!NT_STATUS_IS_OK(status)) {
2041                         return status;
2042                 }
2043                 
2044                 val.data = secret.data;
2045                 val.length = secret.length;
2046                 
2047                 /* set value */
2048                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2049                                         mem_ctx, msg, "currentValue", &val) != 0) {
2050                         return NT_STATUS_NO_MEMORY; 
2051                 }
2052                 
2053                 /* set new value mtime */
2054                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2055                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2056                         return NT_STATUS_NO_MEMORY; 
2057                 }
2058                 
2059                 /* If the old value is not set, then migrate the
2060                  * current value to the old value */
2061                 if (!r->in.old_val) {
2062                         const struct ldb_val *new_val;
2063                         NTTIME last_set_time;
2064                         struct ldb_message **res;
2065                         const char *attrs[] = {
2066                                 "currentValue",
2067                                 "lastSetTime",
2068                                 NULL
2069                         };
2070                         
2071                         /* search for the secret record */
2072                         ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2073                                               secret_state->secret_dn, &res, attrs);
2074                         if (ret == 0) {
2075                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2076                         }
2077                         
2078                         if (ret != 1) {
2079                                 DEBUG(0,("Found %d records matching dn=%s\n", ret,
2080                                          ldb_dn_get_linearized(secret_state->secret_dn)));
2081                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2082                         }
2083
2084                         new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2085                         last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2086                         
2087                         if (new_val) {
2088                                 /* set value */
2089                                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2090                                                         mem_ctx, msg, "priorValue", 
2091                                                         new_val) != 0) {
2092                                         return NT_STATUS_NO_MEMORY; 
2093                                 }
2094                         }
2095                         
2096                         /* set new value mtime */
2097                         if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2098                                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2099                                                          mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2100                                         return NT_STATUS_NO_MEMORY; 
2101                                 }
2102                         }
2103                 }
2104         }
2105
2106         /* modify the samdb record */
2107         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2108         if (ret != 0) {
2109                 /* we really need samdb.c to return NTSTATUS */
2110                 return NT_STATUS_UNSUCCESSFUL;
2111         }
2112
2113         return NT_STATUS_OK;
2114 }
2115
2116
2117 /* 
2118   lsa_QuerySecret 
2119 */
2120 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2121                                 struct lsa_QuerySecret *r)
2122 {
2123         struct dcesrv_handle *h;
2124         struct lsa_secret_state *secret_state;
2125         struct ldb_message *msg;
2126         DATA_BLOB session_key;
2127         DATA_BLOB crypt_secret, secret;
2128         int ret;
2129         struct ldb_message **res;
2130         const char *attrs[] = {
2131                 "currentValue",
2132                 "priorValue",
2133                 "lastSetTime",
2134                 "priorSetTime", 
2135                 NULL
2136         };
2137
2138         NTSTATUS nt_status;
2139
2140         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2141
2142         /* Ensure user is permitted to read this... */
2143         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2144         {
2145         case SECURITY_SYSTEM:
2146         case SECURITY_ADMINISTRATOR:
2147                 break;
2148         default:
2149                 /* Users and annonymous are not allowed to read secrets */
2150                 return NT_STATUS_ACCESS_DENIED;
2151         }
2152
2153         secret_state = h->data;
2154
2155         /* pull all the user attributes */
2156         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2157                               secret_state->secret_dn, &res, attrs);
2158         if (ret != 1) {
2159                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2160         }
2161         msg = res[0];
2162         
2163         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2164         if (!NT_STATUS_IS_OK(nt_status)) {
2165                 return nt_status;
2166         }
2167         
2168         if (r->in.old_val) {
2169                 const struct ldb_val *prior_val;
2170                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2171                 if (!r->out.old_val) {
2172                         return NT_STATUS_NO_MEMORY;
2173                 }
2174                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2175                 
2176                 if (prior_val && prior_val->length) {
2177                         secret.data = prior_val->data;
2178                         secret.length = prior_val->length;
2179                 
2180                         /* Encrypt */
2181                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2182                         if (!crypt_secret.length) {
2183                                 return NT_STATUS_NO_MEMORY;
2184                         }
2185                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2186                         if (!r->out.old_val->buf) {
2187                                 return NT_STATUS_NO_MEMORY;
2188                         }
2189                         r->out.old_val->buf->size = crypt_secret.length;
2190                         r->out.old_val->buf->length = crypt_secret.length;
2191                         r->out.old_val->buf->data = crypt_secret.data;
2192                 }
2193         }
2194         
2195         if (r->in.old_mtime) {
2196                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2197                 if (!r->out.old_mtime) {
2198                         return NT_STATUS_NO_MEMORY;
2199                 }
2200                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2201         }
2202         
2203         if (r->in.new_val) {
2204                 const struct ldb_val *new_val;
2205                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2206                 if (!r->out.new_val) {
2207                         return NT_STATUS_NO_MEMORY;
2208                 }
2209
2210                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2211                 
2212                 if (new_val && new_val->length) {
2213                         secret.data = new_val->data;
2214                         secret.length = new_val->length;
2215                 
2216                         /* Encrypt */
2217                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2218                         if (!crypt_secret.length) {
2219                                 return NT_STATUS_NO_MEMORY;
2220                         }
2221                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2222                         if (!r->out.new_val->buf) {
2223                                 return NT_STATUS_NO_MEMORY;
2224                         }
2225                         r->out.new_val->buf->length = crypt_secret.length;
2226                         r->out.new_val->buf->size = crypt_secret.length;
2227                         r->out.new_val->buf->data = crypt_secret.data;
2228                 }
2229         }
2230         
2231         if (r->in.new_mtime) {
2232                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2233                 if (!r->out.new_mtime) {
2234                         return NT_STATUS_NO_MEMORY;
2235                 }
2236                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2237         }
2238         
2239         return NT_STATUS_OK;
2240 }
2241
2242
2243 /* 
2244   lsa_LookupPrivValue
2245 */
2246 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2247                                     TALLOC_CTX *mem_ctx,
2248                                     struct lsa_LookupPrivValue *r)
2249 {
2250         struct dcesrv_handle *h;
2251         struct lsa_policy_state *state;
2252         int id;
2253
2254         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2255
2256         state = h->data;
2257
2258         id = sec_privilege_id(r->in.name->string);
2259         if (id == -1) {
2260                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2261         }
2262
2263         r->out.luid->low = id;
2264         r->out.luid->high = 0;
2265
2266         return NT_STATUS_OK;    
2267 }
2268
2269
2270 /* 
2271   lsa_LookupPrivName 
2272 */
2273 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2274                                    TALLOC_CTX *mem_ctx,
2275                                    struct lsa_LookupPrivName *r)
2276 {
2277         struct dcesrv_handle *h;
2278         struct lsa_policy_state *state;
2279         const char *privname;
2280
2281         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2282
2283         state = h->data;
2284
2285         if (r->in.luid->high != 0) {
2286                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2287         }
2288
2289         privname = sec_privilege_name(r->in.luid->low);
2290         if (privname == NULL) {
2291                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2292         }
2293
2294         r->out.name = talloc(mem_ctx, struct lsa_StringLarge);
2295         if (r->out.name == NULL) {
2296                 return NT_STATUS_NO_MEMORY;
2297         }
2298         r->out.name->string = privname;
2299
2300         return NT_STATUS_OK;    
2301 }
2302
2303
2304 /* 
2305   lsa_LookupPrivDisplayName
2306 */
2307 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2308                                           TALLOC_CTX *mem_ctx,
2309                                           struct lsa_LookupPrivDisplayName *r)
2310 {
2311         struct dcesrv_handle *h;
2312         struct lsa_policy_state *state;
2313         int id;
2314
2315         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2316
2317         state = h->data;
2318
2319         id = sec_privilege_id(r->in.name->string);
2320         if (id == -1) {
2321                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2322         }
2323         
2324         r->out.disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2325         if (r->out.disp_name == NULL) {
2326                 return NT_STATUS_NO_MEMORY;
2327         }
2328
2329         r->out.disp_name->string = sec_privilege_display_name(id, r->in.language_id);
2330         if (r->out.disp_name->string == NULL) {
2331                 return NT_STATUS_INTERNAL_ERROR;
2332         }
2333
2334         return NT_STATUS_OK;
2335 }
2336
2337
2338 /* 
2339   lsa_EnumAccountsWithUserRight
2340 */
2341 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2342                                               TALLOC_CTX *mem_ctx,
2343                                               struct lsa_EnumAccountsWithUserRight *r)
2344 {
2345         struct dcesrv_handle *h;
2346         struct lsa_policy_state *state;
2347         int ret, i;
2348         struct ldb_message **res;
2349         const char * const attrs[] = { "objectSid", NULL};
2350         const char *privname;
2351
2352         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2353
2354         state = h->data;
2355
2356         if (r->in.name == NULL) {
2357                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2358         } 
2359
2360         privname = r->in.name->string;
2361         if (sec_privilege_id(privname) == -1) {
2362                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2363         }
2364
2365         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
2366                            "privilege=%s", privname);
2367         if (ret == -1) {
2368                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2369         }
2370         if (ret == 0) {
2371                 return NT_STATUS_NO_MORE_ENTRIES;
2372         }
2373
2374         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2375         if (r->out.sids->sids == NULL) {
2376                 return NT_STATUS_NO_MEMORY;
2377         }
2378         for (i=0;i<ret;i++) {
2379                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2380                                                                 res[i], "objectSid");
2381                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2382         }
2383         r->out.sids->num_sids = ret;
2384
2385         return NT_STATUS_OK;
2386 }
2387
2388
2389 /* 
2390   lsa_AddAccountRights
2391 */
2392 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2393                                      TALLOC_CTX *mem_ctx,
2394                                      struct lsa_AddAccountRights *r)
2395 {
2396         struct dcesrv_handle *h;
2397         struct lsa_policy_state *state;
2398
2399         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2400
2401         state = h->data;
2402
2403         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2404                                           LDB_FLAG_MOD_ADD,
2405                                           r->in.sid, r->in.rights);
2406 }
2407
2408
2409 /* 
2410   lsa_RemoveAccountRights
2411 */
2412 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2413                                         TALLOC_CTX *mem_ctx,
2414                                         struct lsa_RemoveAccountRights *r)
2415 {
2416         struct dcesrv_handle *h;
2417         struct lsa_policy_state *state;
2418
2419         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2420
2421         state = h->data;
2422
2423         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2424                                           LDB_FLAG_MOD_DELETE,
2425                                           r->in.sid, r->in.rights);
2426 }
2427
2428
2429 /* 
2430   lsa_StorePrivateData
2431 */
2432 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2433                        struct lsa_StorePrivateData *r)
2434 {
2435         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2436 }
2437
2438
2439 /* 
2440   lsa_RetrievePrivateData
2441 */
2442 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2443                        struct lsa_RetrievePrivateData *r)
2444 {
2445         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2446 }
2447
2448
2449 /* 
2450   lsa_GetUserName
2451 */
2452 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2453                                 struct lsa_GetUserName *r)
2454 {
2455         NTSTATUS status = NT_STATUS_OK;
2456         const char *account_name;
2457         const char *authority_name;
2458         struct lsa_String *_account_name;
2459         struct lsa_StringPointer *_authority_name = NULL;
2460
2461         /* this is what w2k3 does */
2462         r->out.account_name = r->in.account_name;
2463         r->out.authority_name = r->in.authority_name;
2464
2465         if (r->in.account_name && r->in.account_name->string) {
2466                 return NT_STATUS_INVALID_PARAMETER;
2467         }
2468
2469         if (r->in.authority_name &&
2470             r->in.authority_name->string &&
2471             r->in.authority_name->string->string) {
2472                 return NT_STATUS_INVALID_PARAMETER;
2473         }
2474
2475         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
2476         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
2477
2478         _account_name = talloc(mem_ctx, struct lsa_String);
2479         NT_STATUS_HAVE_NO_MEMORY(_account_name);
2480         _account_name->string = account_name;
2481
2482         if (r->in.authority_name) {
2483                 _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
2484                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
2485                 _authority_name->string = talloc(mem_ctx, struct lsa_String);
2486                 NT_STATUS_HAVE_NO_MEMORY(_authority_name->string);
2487                 _authority_name->string->string = authority_name;
2488         }
2489
2490         r->out.account_name = _account_name;
2491         r->out.authority_name = _authority_name;
2492
2493         return status;
2494 }
2495
2496 /*
2497   lsa_SetInfoPolicy2
2498 */
2499 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
2500                                    TALLOC_CTX *mem_ctx,
2501                                    struct lsa_SetInfoPolicy2 *r)
2502 {
2503         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2504 }
2505
2506 /*
2507   lsa_QueryDomainInformationPolicy
2508 */
2509 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2510                                                  TALLOC_CTX *mem_ctx,
2511                                                  struct lsa_QueryDomainInformationPolicy *r)
2512 {
2513         r->out.info = talloc(mem_ctx, union lsa_DomainInformationPolicy);
2514         if (!r->out.info) {
2515                 return NT_STATUS_NO_MEMORY;
2516         }
2517
2518         switch (r->in.level) {
2519         case LSA_DOMAIN_INFO_POLICY_EFS:
2520                 talloc_free(r->out.info);
2521                 r->out.info = NULL;
2522                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2523         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
2524         {
2525                 struct lsa_DomainInfoKerberos *k = &r->out.info->kerberos_info;
2526                 struct smb_krb5_context *smb_krb5_context;
2527                 int ret = smb_krb5_init_context(mem_ctx, 
2528                                                         dce_call->event_ctx, 
2529                                                         dce_call->conn->dce_ctx->lp_ctx,
2530                                                         &smb_krb5_context);
2531                 if (ret != 0) {
2532                         talloc_free(r->out.info);
2533                         r->out.info = NULL;
2534                         return NT_STATUS_INTERNAL_ERROR;
2535                 }
2536                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
2537                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
2538                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
2539                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
2540                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
2541                 talloc_free(smb_krb5_context);
2542                 return NT_STATUS_OK;
2543         }
2544         default:
2545                 talloc_free(r->out.info);
2546                 r->out.info = NULL;
2547                 return NT_STATUS_INVALID_INFO_CLASS;
2548         }
2549 }
2550
2551 /*
2552   lsa_SetDomInfoPolicy
2553 */
2554 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2555                                               TALLOC_CTX *mem_ctx,
2556                                               struct lsa_SetDomainInformationPolicy *r)
2557 {
2558         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2559 }
2560
2561 /*
2562   lsa_TestCall
2563 */
2564 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
2565                              TALLOC_CTX *mem_ctx,
2566                              struct lsa_TestCall *r)
2567 {
2568         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2569 }
2570
2571 /* 
2572   lsa_CREDRWRITE 
2573 */
2574 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2575                        struct lsa_CREDRWRITE *r)
2576 {
2577         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2578 }
2579
2580
2581 /* 
2582   lsa_CREDRREAD 
2583 */
2584 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2585                        struct lsa_CREDRREAD *r)
2586 {
2587         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2588 }
2589
2590
2591 /* 
2592   lsa_CREDRENUMERATE 
2593 */
2594 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2595                        struct lsa_CREDRENUMERATE *r)
2596 {
2597         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2598 }
2599
2600
2601 /* 
2602   lsa_CREDRWRITEDOMAINCREDENTIALS 
2603 */
2604 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2605                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
2606 {
2607         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2608 }
2609
2610
2611 /* 
2612   lsa_CREDRREADDOMAINCREDENTIALS 
2613 */
2614 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2615                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
2616 {
2617         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2618 }
2619
2620
2621 /* 
2622   lsa_CREDRDELETE 
2623 */
2624 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2625                        struct lsa_CREDRDELETE *r)
2626 {
2627         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2628 }
2629
2630
2631 /* 
2632   lsa_CREDRGETTARGETINFO 
2633 */
2634 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2635                        struct lsa_CREDRGETTARGETINFO *r)
2636 {
2637         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2638 }
2639
2640
2641 /* 
2642   lsa_CREDRPROFILELOADED 
2643 */
2644 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2645                        struct lsa_CREDRPROFILELOADED *r)
2646 {
2647         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2648 }
2649
2650
2651 /* 
2652   lsa_CREDRGETSESSIONTYPES 
2653 */
2654 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2655                        struct lsa_CREDRGETSESSIONTYPES *r)
2656 {
2657         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2658 }
2659
2660
2661 /* 
2662   lsa_LSARREGISTERAUDITEVENT 
2663 */
2664 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2665                        struct lsa_LSARREGISTERAUDITEVENT *r)
2666 {
2667         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2668 }
2669
2670
2671 /* 
2672   lsa_LSARGENAUDITEVENT 
2673 */
2674 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2675                        struct lsa_LSARGENAUDITEVENT *r)
2676 {
2677         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2678 }
2679
2680
2681 /* 
2682   lsa_LSARUNREGISTERAUDITEVENT 
2683 */
2684 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2685                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
2686 {
2687         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2688 }
2689
2690
2691 /* 
2692   lsa_lsaRQueryForestTrustInformation 
2693 */
2694 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2695                        struct lsa_lsaRQueryForestTrustInformation *r)
2696 {
2697         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2698 }
2699
2700
2701 /* 
2702   lsa_LSARSETFORESTTRUSTINFORMATION 
2703 */
2704 static NTSTATUS dcesrv_lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2705                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
2706 {
2707         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2708 }
2709
2710
2711 /* 
2712   lsa_CREDRRENAME 
2713 */
2714 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2715                        struct lsa_CREDRRENAME *r)
2716 {
2717         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2718 }
2719
2720
2721
2722 /* 
2723   lsa_LSAROPENPOLICYSCE 
2724 */
2725 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2726                        struct lsa_LSAROPENPOLICYSCE *r)
2727 {
2728         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2729 }
2730
2731
2732 /* 
2733   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
2734 */
2735 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2736                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
2737 {
2738         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2739 }
2740
2741
2742 /* 
2743   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
2744 */
2745 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2746                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
2747 {
2748         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2749 }
2750
2751
2752 /* 
2753   lsa_LSARADTREPORTSECURITYEVENT 
2754 */
2755 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2756                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
2757 {
2758         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2759 }
2760
2761
2762 /* include the generated boilerplate */
2763 #include "librpc/gen_ndr/ndr_lsa_s.c"
2764
2765
2766
2767 /*****************************************
2768 NOTE! The remaining calls below were
2769 removed in w2k3, so the DCESRV_FAULT()
2770 replies are the correct implementation. Do
2771 not try and fill these in with anything else
2772 ******************************************/
2773
2774 /* 
2775   dssetup_DsRoleDnsNameToFlatName 
2776 */
2777 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2778                                         struct dssetup_DsRoleDnsNameToFlatName *r)
2779 {
2780         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2781 }
2782
2783
2784 /* 
2785   dssetup_DsRoleDcAsDc 
2786 */
2787 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2788                              struct dssetup_DsRoleDcAsDc *r)
2789 {
2790         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2791 }
2792
2793
2794 /* 
2795   dssetup_DsRoleDcAsReplica 
2796 */
2797 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2798                                   struct dssetup_DsRoleDcAsReplica *r)
2799 {
2800         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2801 }
2802
2803
2804 /* 
2805   dssetup_DsRoleDemoteDc 
2806 */
2807 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2808                                struct dssetup_DsRoleDemoteDc *r)
2809 {
2810         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2811 }
2812
2813
2814 /* 
2815   dssetup_DsRoleGetDcOperationProgress 
2816 */
2817 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2818                                              struct dssetup_DsRoleGetDcOperationProgress *r)
2819 {
2820         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2821 }
2822
2823
2824 /* 
2825   dssetup_DsRoleGetDcOperationResults 
2826 */
2827 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2828                                             struct dssetup_DsRoleGetDcOperationResults *r)
2829 {
2830         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2831 }
2832
2833
2834 /* 
2835   dssetup_DsRoleCancel 
2836 */
2837 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2838                              struct dssetup_DsRoleCancel *r)
2839 {
2840         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2841 }
2842
2843
2844 /* 
2845   dssetup_DsRoleServerSaveStateForUpgrade 
2846 */
2847 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2848                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
2849 {
2850         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2851 }
2852
2853
2854 /* 
2855   dssetup_DsRoleUpgradeDownlevelServer 
2856 */
2857 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2858                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
2859 {
2860         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2861 }
2862
2863
2864 /* 
2865   dssetup_DsRoleAbortDownlevelServerUpgrade 
2866 */
2867 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2868                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
2869 {
2870         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2871 }
2872
2873
2874 /* include the generated boilerplate */
2875 #include "librpc/gen_ndr/ndr_dssetup_s.c"
2876
2877 NTSTATUS dcerpc_server_lsa_init(void)
2878 {
2879         NTSTATUS ret;
2880         
2881         ret = dcerpc_server_dssetup_init();
2882         if (!NT_STATUS_IS_OK(ret)) {
2883                 return ret;
2884         }
2885         ret = dcerpc_server_lsarpc_init();
2886         if (!NT_STATUS_IS_OK(ret)) {
2887                 return ret;
2888         }
2889         return ret;
2890 }