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