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