s4:netlogon RPC server - "LogonGetDomainInfo" - always check the LDB return codes
[samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    Copyright (C) Matthias Dieter Wallnöfer            2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
40
41 struct netlogon_server_pipe_state {
42         struct netr_Credential client_challenge;
43         struct netr_Credential server_challenge;
44 };
45
46 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
47                                         struct netr_ServerReqChallenge *r)
48 {
49         struct netlogon_server_pipe_state *pipe_state =
50                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
51
52         ZERO_STRUCTP(r->out.return_credentials);
53
54         /* destroyed on pipe shutdown */
55
56         if (pipe_state) {
57                 talloc_free(pipe_state);
58                 dce_call->context->private_data = NULL;
59         }
60
61         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
62         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
63
64         pipe_state->client_challenge = *r->in.credentials;
65
66         generate_random_buffer(pipe_state->server_challenge.data,
67                                sizeof(pipe_state->server_challenge.data));
68
69         *r->out.return_credentials = pipe_state->server_challenge;
70
71         dce_call->context->private_data = pipe_state;
72
73         return NT_STATUS_OK;
74 }
75
76 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
77                                          struct netr_ServerAuthenticate3 *r)
78 {
79         struct netlogon_server_pipe_state *pipe_state =
80                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
81         struct netlogon_creds_CredentialState *creds;
82         struct ldb_context *sam_ctx;
83         struct samr_Password *mach_pwd;
84         uint32_t user_account_control;
85         int num_records;
86         struct ldb_message **msgs;
87         NTSTATUS nt_status;
88         const char *attrs[] = {"unicodePwd", "userAccountControl",
89                                "objectSid", NULL};
90
91         const char *trust_dom_attrs[] = {"flatname", NULL};
92         const char *account_name;
93
94         ZERO_STRUCTP(r->out.return_credentials);
95         *r->out.rid = 0;
96
97         /*
98          * According to Microsoft (see bugid #6099)
99          * Windows 7 looks at the negotiate_flags
100          * returned in this structure *even if the
101          * call fails with access denied!
102          */
103         *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
104                                   NETLOGON_NEG_PERSISTENT_SAMREPL |
105                                   NETLOGON_NEG_ARCFOUR |
106                                   NETLOGON_NEG_PROMOTION_COUNT |
107                                   NETLOGON_NEG_CHANGELOG_BDC |
108                                   NETLOGON_NEG_FULL_SYNC_REPL |
109                                   NETLOGON_NEG_MULTIPLE_SIDS |
110                                   NETLOGON_NEG_REDO |
111                                   NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
112                                   NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
113                                   NETLOGON_NEG_GENERIC_PASSTHROUGH |
114                                   NETLOGON_NEG_CONCURRENT_RPC |
115                                   NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
116                                   NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
117                                   NETLOGON_NEG_STRONG_KEYS |
118                                   NETLOGON_NEG_TRANSITIVE_TRUSTS |
119                                   NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
120                                   NETLOGON_NEG_PASSWORD_SET2 |
121                                   NETLOGON_NEG_GETDOMAININFO |
122                                   NETLOGON_NEG_CROSS_FOREST_TRUSTS |
123                                   NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
124                                   NETLOGON_NEG_RODC_PASSTHROUGH |
125                                   NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
126                                   NETLOGON_NEG_AUTHENTICATED_RPC;
127
128         switch (r->in.secure_channel_type) {
129         case SEC_CHAN_WKSTA:
130         case SEC_CHAN_DNS_DOMAIN:
131         case SEC_CHAN_DOMAIN:
132         case SEC_CHAN_BDC:
133         case SEC_CHAN_RODC:
134                 break;
135         default:
136                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
137                           r->in.secure_channel_type));
138                 return NT_STATUS_INVALID_PARAMETER;
139         }
140
141         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
142                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
143         if (sam_ctx == NULL) {
144                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
145         }
146
147         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
148                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
149                 const char *flatname;
150                 if (!encoded_account) {
151                         return NT_STATUS_NO_MEMORY;
152                 }
153
154                 /* Kill the trailing dot */
155                 if (encoded_account[strlen(encoded_account)-1] == '.') {
156                         encoded_account[strlen(encoded_account)-1] = '\0';
157                 }
158
159                 /* pull the user attributes */
160                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
161                                            trust_dom_attrs,
162                                            "(&(trustPartner=%s)(objectclass=trustedDomain))",
163                                            encoded_account);
164
165                 if (num_records == 0) {
166                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
167                                  encoded_account));
168                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
169                 }
170
171                 if (num_records > 1) {
172                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
173                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
174                 }
175
176                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
177                 if (!flatname) {
178                         /* No flatname for this trust - we can't proceed */
179                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
180                 }
181                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
182
183                 if (!account_name) {
184                         return NT_STATUS_NO_MEMORY;
185                 }
186
187         } else {
188                 account_name = r->in.account_name;
189         }
190
191         /* pull the user attributes */
192         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
193                                    "(&(sAMAccountName=%s)(objectclass=user))",
194                                    ldb_binary_encode_string(mem_ctx, account_name));
195
196         if (num_records == 0) {
197                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
198                          r->in.account_name));
199                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
200         }
201
202         if (num_records > 1) {
203                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
204                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
205         }
206
207         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
208
209         if (user_account_control & UF_ACCOUNTDISABLE) {
210                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
211                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
212         }
213
214         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
215                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
216                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
217                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
218                 }
219         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
220                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
221                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
222                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
223
224                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
225                 }
226         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
227                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
228                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
229                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
230                 }
231         } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
232                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
233                         DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
234                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
235                 }
236         } else {
237                 /* we should never reach this */
238                 return NT_STATUS_INTERNAL_ERROR;
239         }
240
241         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
242                                                 "objectSid", 0);
243
244         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
245         if (mach_pwd == NULL) {
246                 return NT_STATUS_ACCESS_DENIED;
247         }
248
249         if (!pipe_state) {
250                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
251                 return NT_STATUS_ACCESS_DENIED;
252         }
253
254         creds = netlogon_creds_server_init(mem_ctx,
255                                            r->in.account_name,
256                                            r->in.computer_name,
257                                            r->in.secure_channel_type,
258                                            &pipe_state->client_challenge,
259                                            &pipe_state->server_challenge,
260                                            mach_pwd,
261                                            r->in.credentials,
262                                            r->out.return_credentials,
263                                            *r->in.negotiate_flags);
264
265         if (!creds) {
266                 return NT_STATUS_ACCESS_DENIED;
267         }
268
269         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
270
271         nt_status = schannel_save_creds_state(mem_ctx,
272                                               lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
273                                               creds);
274
275         return nt_status;
276 }
277
278 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
279                                         struct netr_ServerAuthenticate *r)
280 {
281         struct netr_ServerAuthenticate3 a;
282         uint32_t rid;
283         /* TODO:
284          * negotiate_flags is used as an [in] parameter
285          * so it need to be initialised.
286          *
287          * (I think ... = 0; seems wrong here --metze)
288          */
289         uint32_t negotiate_flags_in = 0;
290         uint32_t negotiate_flags_out = 0;
291
292         a.in.server_name                = r->in.server_name;
293         a.in.account_name               = r->in.account_name;
294         a.in.secure_channel_type        = r->in.secure_channel_type;
295         a.in.computer_name              = r->in.computer_name;
296         a.in.credentials                = r->in.credentials;
297         a.in.negotiate_flags            = &negotiate_flags_in;
298
299         a.out.return_credentials        = r->out.return_credentials;
300         a.out.rid                       = &rid;
301         a.out.negotiate_flags           = &negotiate_flags_out;
302
303         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
304 }
305
306 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
307                                          struct netr_ServerAuthenticate2 *r)
308 {
309         struct netr_ServerAuthenticate3 r3;
310         uint32_t rid = 0;
311
312         r3.in.server_name = r->in.server_name;
313         r3.in.account_name = r->in.account_name;
314         r3.in.secure_channel_type = r->in.secure_channel_type;
315         r3.in.computer_name = r->in.computer_name;
316         r3.in.credentials = r->in.credentials;
317         r3.out.return_credentials = r->out.return_credentials;
318         r3.in.negotiate_flags = r->in.negotiate_flags;
319         r3.out.negotiate_flags = r->out.negotiate_flags;
320         r3.out.rid = &rid;
321
322         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
323 }
324
325 /*
326  * NOTE: The following functions are nearly identical to the ones available in
327  * source3/rpc_server/srv_nelog_nt.c
328  * The reason we keep 2 copies is that they use different structures to
329  * represent the auth_info and the decrpc pipes.
330  */
331
332 /*
333  * If schannel is required for this call test that it actually is available.
334  */
335 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
336                                         const char *computer_name,
337                                         bool integrity, bool privacy)
338 {
339
340         if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
341                 if (!privacy && !integrity) {
342                         return NT_STATUS_OK;
343                 }
344
345                 if ((!privacy && integrity) &&
346                     auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
347                         return NT_STATUS_OK;
348                 }
349
350                 if ((privacy || integrity) &&
351                     auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
352                         return NT_STATUS_OK;
353                 }
354         }
355
356         /* test didn't pass */
357         DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
358                   computer_name));
359
360         return NT_STATUS_ACCESS_DENIED;
361 }
362
363 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
364                                                     TALLOC_CTX *mem_ctx,
365                                                     const char *computer_name,
366                                                     struct netr_Authenticator *received_authenticator,
367                                                     struct netr_Authenticator *return_authenticator,
368                                                     struct netlogon_creds_CredentialState **creds_out)
369 {
370         NTSTATUS nt_status;
371         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
372         bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
373
374         if (schannel_global_required) {
375                 nt_status = schannel_check_required(auth_info,
376                                                     computer_name,
377                                                     true, false);
378                 if (!NT_STATUS_IS_OK(nt_status)) {
379                         return nt_status;
380                 }
381         }
382
383         nt_status = schannel_check_creds_state(mem_ctx,
384                                                lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
385                                                computer_name,
386                                                received_authenticator,
387                                                return_authenticator,
388                                                creds_out);
389         return nt_status;
390 }
391
392 /*
393   Change the machine account password for the currently connected
394   client.  Supplies only the NT#.
395 */
396
397 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
398                                        struct netr_ServerPasswordSet *r)
399 {
400         struct netlogon_creds_CredentialState *creds;
401         struct ldb_context *sam_ctx;
402         const char * const attrs[] = { "unicodePwd", NULL };
403         struct ldb_message **res;
404         struct samr_Password *oldNtHash;
405         NTSTATUS nt_status;
406         int ret;
407
408         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
409                                                         mem_ctx,
410                                                         r->in.computer_name,
411                                                         r->in.credential, r->out.return_authenticator,
412                                                         &creds);
413         NT_STATUS_NOT_OK_RETURN(nt_status);
414
415         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
416         if (sam_ctx == NULL) {
417                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
418         }
419
420         netlogon_creds_des_decrypt(creds, r->in.new_password);
421
422         /* fetch the old password hashes (the NT hash has to exist) */
423
424         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
425                            "(&(objectClass=user)(objectSid=%s))",
426                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
427         if (ret != 1) {
428                 return NT_STATUS_WRONG_PASSWORD;
429         }
430
431         nt_status = samdb_result_passwords(mem_ctx,
432                                            dce_call->conn->dce_ctx->lp_ctx,
433                                            res[0], NULL, &oldNtHash);
434         if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
435                 return NT_STATUS_WRONG_PASSWORD;
436         }
437
438         /* Using the sid for the account as the key, set the password */
439         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
440                                            creds->sid,
441                                            NULL, /* Don't have plaintext */
442                                            NULL, r->in.new_password,
443                                            NULL, oldNtHash, /* Password change */
444                                            NULL, NULL);
445         return nt_status;
446 }
447
448 /*
449   Change the machine account password for the currently connected
450   client.  Supplies new plaintext.
451 */
452 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
453                                        struct netr_ServerPasswordSet2 *r)
454 {
455         struct netlogon_creds_CredentialState *creds;
456         struct ldb_context *sam_ctx;
457         const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
458         struct ldb_message **res;
459         struct samr_Password *oldLmHash, *oldNtHash;
460         NTSTATUS nt_status;
461         DATA_BLOB new_password;
462         int ret;
463
464         struct samr_CryptPassword password_buf;
465
466         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
467                                                         mem_ctx,
468                                                         r->in.computer_name,
469                                                         r->in.credential, r->out.return_authenticator,
470                                                         &creds);
471         NT_STATUS_NOT_OK_RETURN(nt_status);
472
473         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
474         if (sam_ctx == NULL) {
475                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
476         }
477
478         memcpy(password_buf.data, r->in.new_password->data, 512);
479         SIVAL(password_buf.data, 512, r->in.new_password->length);
480         netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
481
482         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
483                 DEBUG(3,("samr: failed to decode password buffer\n"));
484                 return NT_STATUS_WRONG_PASSWORD;
485         }
486
487         /* fetch the old password hashes (at least one of both has to exist) */
488
489         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
490                            "(&(objectClass=user)(objectSid=%s))",
491                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
492         if (ret != 1) {
493                 return NT_STATUS_WRONG_PASSWORD;
494         }
495
496         nt_status = samdb_result_passwords(mem_ctx,
497                                            dce_call->conn->dce_ctx->lp_ctx,
498                                            res[0], &oldLmHash, &oldNtHash);
499         if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
500                 return NT_STATUS_WRONG_PASSWORD;
501         }
502
503         /* Using the sid for the account as the key, set the password */
504         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
505                                            creds->sid,
506                                            &new_password, /* we have plaintext */
507                                            NULL, NULL,
508                                            oldLmHash, oldNtHash, /* Password change */
509                                            NULL, NULL);
510         return nt_status;
511 }
512
513
514 /*
515   netr_LogonUasLogon
516 */
517 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
518                                  struct netr_LogonUasLogon *r)
519 {
520         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
521 }
522
523
524 /*
525   netr_LogonUasLogoff
526 */
527 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
528                        struct netr_LogonUasLogoff *r)
529 {
530         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
531 }
532
533
534 /*
535   netr_LogonSamLogon_base
536
537   This version of the function allows other wrappers to say 'do not check the credentials'
538
539   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
540 */
541 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
542                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
543 {
544         struct auth_context *auth_context;
545         struct auth_usersupplied_info *user_info;
546         struct auth_serversupplied_info *server_info;
547         NTSTATUS nt_status;
548         static const char zeros[16];
549         struct netr_SamBaseInfo *sam;
550         struct netr_SamInfo2 *sam2;
551         struct netr_SamInfo3 *sam3;
552         struct netr_SamInfo6 *sam6;
553
554         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
555         NT_STATUS_HAVE_NO_MEMORY(user_info);
556
557         switch (r->in.logon_level) {
558         case NetlogonInteractiveInformation:
559         case NetlogonServiceInformation:
560         case NetlogonInteractiveTransitiveInformation:
561         case NetlogonServiceTransitiveInformation:
562                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
563                         netlogon_creds_arcfour_crypt(creds,
564                                             r->in.logon->password->lmpassword.hash,
565                                             sizeof(r->in.logon->password->lmpassword.hash));
566                         netlogon_creds_arcfour_crypt(creds,
567                                             r->in.logon->password->ntpassword.hash,
568                                             sizeof(r->in.logon->password->ntpassword.hash));
569                 } else {
570                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
571                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
572                 }
573
574                 /* TODO: we need to deny anonymous access here */
575                 nt_status = auth_context_create(mem_ctx,
576                                                 dce_call->event_ctx, dce_call->msg_ctx,
577                                                 dce_call->conn->dce_ctx->lp_ctx,
578                                                 &auth_context);
579                 NT_STATUS_NOT_OK_RETURN(nt_status);
580
581                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
582                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
583                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
584                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
585
586                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
587                 user_info->password_state = AUTH_PASSWORD_HASH;
588
589                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
590                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
591                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
592
593                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
594                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
595                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
596
597                 break;
598         case NetlogonNetworkInformation:
599         case NetlogonNetworkTransitiveInformation:
600
601                 /* TODO: we need to deny anonymous access here */
602                 nt_status = auth_context_create(mem_ctx,
603                                                 dce_call->event_ctx, dce_call->msg_ctx,
604                                                 dce_call->conn->dce_ctx->lp_ctx,
605                                                 &auth_context);
606                 NT_STATUS_NOT_OK_RETURN(nt_status);
607
608                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
609                 NT_STATUS_NOT_OK_RETURN(nt_status);
610
611                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
612                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
613                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
614                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
615
616                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
617                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
618                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
619
620                 break;
621
622
623         case NetlogonGenericInformation:
624         {
625                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
626                         netlogon_creds_arcfour_crypt(creds,
627                                             r->in.logon->generic->data, r->in.logon->generic->length);
628                 } else {
629                         /* Using DES to verify kerberos tickets makes no sense */
630                         return NT_STATUS_INVALID_PARAMETER;
631                 }
632
633                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
634                         NTSTATUS status;
635                         struct dcerpc_binding_handle *irpc_handle;
636                         struct kdc_check_generic_kerberos check;
637                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
638                         NT_STATUS_HAVE_NO_MEMORY(generic);
639                         *r->out.authoritative = 1;
640
641                         /* TODO: Describe and deal with these flags */
642                         *r->out.flags = 0;
643
644                         r->out.validation->generic = generic;
645
646                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
647                                                                   dce_call->msg_ctx,
648                                                                   "kdc_server",
649                                                                   &ndr_table_irpc);
650                         if (irpc_handle == NULL) {
651                                 return NT_STATUS_NO_LOGON_SERVERS;
652                         }
653
654                         check.in.generic_request =
655                                 data_blob_const(r->in.logon->generic->data,
656                                                 r->in.logon->generic->length);
657
658                         status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
659                                                                      mem_ctx,
660                                                                      &check);
661                         if (!NT_STATUS_IS_OK(status)) {
662                                 return status;
663                         }
664                         generic->length = check.out.generic_reply.length;
665                         generic->data = check.out.generic_reply.data;
666                         return NT_STATUS_OK;
667                 }
668
669                 /* Until we get an implemetnation of these other packages */
670                 return NT_STATUS_INVALID_PARAMETER;
671         }
672         default:
673                 return NT_STATUS_INVALID_PARAMETER;
674         }
675
676         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
677         NT_STATUS_NOT_OK_RETURN(nt_status);
678
679         switch (r->in.validation_level) {
680         case 2:
681                 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
682                 NT_STATUS_NOT_OK_RETURN(nt_status);
683
684                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
685                 NT_STATUS_HAVE_NO_MEMORY(sam2);
686                 sam2->base = *sam;
687
688                 /* And put into the talloc tree */
689                 talloc_steal(sam2, sam);
690                 r->out.validation->sam2 = sam2;
691
692                 sam = &sam2->base;
693                 break;
694
695         case 3:
696                 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
697                                                               server_info,
698                                                               &sam3);
699                 NT_STATUS_NOT_OK_RETURN(nt_status);
700
701                 r->out.validation->sam3 = sam3;
702
703                 sam = &sam3->base;
704                 break;
705
706         case 6:
707                 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
708                                                            server_info,
709                                                            &sam3);
710                 NT_STATUS_NOT_OK_RETURN(nt_status);
711
712                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
713                 NT_STATUS_HAVE_NO_MEMORY(sam6);
714                 sam6->base = sam3->base;
715                 sam = &sam6->base;
716                 sam6->sidcount = sam3->sidcount;
717                 sam6->sids = sam3->sids;
718
719                 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
720                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
721                                                          sam->account_name.string, sam6->dns_domainname.string);
722                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
723                 /* And put into the talloc tree */
724                 talloc_steal(sam6, sam3);
725
726                 r->out.validation->sam6 = sam6;
727                 break;
728
729         default:
730                 break;
731         }
732
733         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
734         /* It appears that level 6 is not individually encrypted */
735         if ((r->in.validation_level != 6) &&
736             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
737                 /* This key is sent unencrypted without the ARCFOUR flag set */
738                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
739                         netlogon_creds_arcfour_crypt(creds,
740                                             sam->key.key,
741                                             sizeof(sam->key.key));
742                 }
743         }
744
745         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
746         /* It appears that level 6 is not individually encrypted */
747         if ((r->in.validation_level != 6) &&
748             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
749                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
750                         netlogon_creds_arcfour_crypt(creds,
751                                             sam->LMSessKey.key,
752                                             sizeof(sam->LMSessKey.key));
753                 } else {
754                         netlogon_creds_des_encrypt_LMKey(creds,
755                                                 &sam->LMSessKey);
756                 }
757         }
758
759         *r->out.authoritative = 1;
760
761         /* TODO: Describe and deal with these flags */
762         *r->out.flags = 0;
763
764         return NT_STATUS_OK;
765 }
766
767 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
768                                      struct netr_LogonSamLogonEx *r)
769 {
770         NTSTATUS nt_status;
771         struct netlogon_creds_CredentialState *creds;
772
773         nt_status = schannel_get_creds_state(mem_ctx,
774                                              lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
775                                              r->in.computer_name, &creds);
776         if (!NT_STATUS_IS_OK(nt_status)) {
777                 return nt_status;
778         }
779
780         if (!dce_call->conn->auth_state.auth_info ||
781             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
782                 return NT_STATUS_ACCESS_DENIED;
783         }
784         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
785 }
786
787 /*
788   netr_LogonSamLogonWithFlags
789
790 */
791 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
792                                             struct netr_LogonSamLogonWithFlags *r)
793 {
794         NTSTATUS nt_status;
795         struct netlogon_creds_CredentialState *creds;
796         struct netr_LogonSamLogonEx r2;
797
798         struct netr_Authenticator *return_authenticator;
799
800         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
801         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
802
803         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
804                                                         mem_ctx,
805                                                         r->in.computer_name,
806                                                         r->in.credential, return_authenticator,
807                                                         &creds);
808         NT_STATUS_NOT_OK_RETURN(nt_status);
809
810         ZERO_STRUCT(r2);
811
812         r2.in.server_name       = r->in.server_name;
813         r2.in.computer_name     = r->in.computer_name;
814         r2.in.logon_level       = r->in.logon_level;
815         r2.in.logon             = r->in.logon;
816         r2.in.validation_level  = r->in.validation_level;
817         r2.in.flags             = r->in.flags;
818         r2.out.validation       = r->out.validation;
819         r2.out.authoritative    = r->out.authoritative;
820         r2.out.flags            = r->out.flags;
821
822         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
823
824         r->out.return_authenticator     = return_authenticator;
825
826         return nt_status;
827 }
828
829 /*
830   netr_LogonSamLogon
831 */
832 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
833                                    struct netr_LogonSamLogon *r)
834 {
835         struct netr_LogonSamLogonWithFlags r2;
836         uint32_t flags = 0;
837         NTSTATUS status;
838
839         ZERO_STRUCT(r2);
840
841         r2.in.server_name = r->in.server_name;
842         r2.in.computer_name = r->in.computer_name;
843         r2.in.credential  = r->in.credential;
844         r2.in.return_authenticator = r->in.return_authenticator;
845         r2.in.logon_level = r->in.logon_level;
846         r2.in.logon = r->in.logon;
847         r2.in.validation_level = r->in.validation_level;
848         r2.in.flags = &flags;
849         r2.out.validation = r->out.validation;
850         r2.out.authoritative = r->out.authoritative;
851         r2.out.flags = &flags;
852
853         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
854
855         r->out.return_authenticator = r2.out.return_authenticator;
856
857         return status;
858 }
859
860
861 /*
862   netr_LogonSamLogoff
863 */
864 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
865                        struct netr_LogonSamLogoff *r)
866 {
867         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
868 }
869
870
871
872 /*
873   netr_DatabaseDeltas
874 */
875 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
876                        struct netr_DatabaseDeltas *r)
877 {
878         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
879 }
880
881
882 /*
883   netr_DatabaseSync2
884 */
885 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
886                        struct netr_DatabaseSync2 *r)
887 {
888         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
889         return NT_STATUS_NOT_IMPLEMENTED;
890 }
891
892
893 /*
894   netr_DatabaseSync
895 */
896 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
897                        struct netr_DatabaseSync *r)
898 {
899         struct netr_DatabaseSync2 r2;
900         NTSTATUS status;
901
902         ZERO_STRUCT(r2);
903
904         r2.in.logon_server = r->in.logon_server;
905         r2.in.computername = r->in.computername;
906         r2.in.credential = r->in.credential;
907         r2.in.database_id = r->in.database_id;
908         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
909         r2.in.sync_context = r->in.sync_context;
910         r2.out.sync_context = r->out.sync_context;
911         r2.out.delta_enum_array = r->out.delta_enum_array;
912         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
913
914         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
915
916         return status;
917 }
918
919
920 /*
921   netr_AccountDeltas
922 */
923 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
924                        struct netr_AccountDeltas *r)
925 {
926         /* w2k3 returns "NOT IMPLEMENTED" for this call */
927         return NT_STATUS_NOT_IMPLEMENTED;
928 }
929
930
931 /*
932   netr_AccountSync
933 */
934 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
935                        struct netr_AccountSync *r)
936 {
937         /* w2k3 returns "NOT IMPLEMENTED" for this call */
938         return NT_STATUS_NOT_IMPLEMENTED;
939 }
940
941
942 /*
943   netr_GetDcName
944 */
945 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
946                        struct netr_GetDcName *r)
947 {
948         const char * const attrs[] = { NULL };
949         struct ldb_context *sam_ctx;
950         struct ldb_message **res;
951         struct ldb_dn *domain_dn;
952         int ret;
953         const char *dcname;
954
955         /*
956          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
957          * that the domainname needs to be a valid netbios domain
958          * name, if it is not NULL.
959          */
960         if (r->in.domainname) {
961                 const char *dot = strchr(r->in.domainname, '.');
962                 size_t len = strlen(r->in.domainname);
963
964                 if (dot || len > 15) {
965                         return WERR_DCNOTFOUND;
966                 }
967
968                 /*
969                  * TODO: Should we also varify that only valid
970                  *       netbios name characters are used?
971                  */
972         }
973
974         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
975                                 dce_call->conn->dce_ctx->lp_ctx,
976                                 dce_call->conn->auth_state.session_info, 0);
977         if (sam_ctx == NULL) {
978                 return WERR_DS_UNAVAILABLE;
979         }
980
981         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
982                                        r->in.domainname);
983         if (domain_dn == NULL) {
984                 return WERR_DS_UNAVAILABLE;
985         }
986
987         ret = gendb_search_dn(sam_ctx, mem_ctx,
988                               domain_dn, &res, attrs);
989         if (ret != 1) {
990                 return WERR_NO_SUCH_DOMAIN;
991         }
992
993         /* TODO: - return real IP address
994          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
995          */
996         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
997                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
998         W_ERROR_HAVE_NO_MEMORY(dcname);
999
1000         *r->out.dcname = dcname;
1001         return WERR_OK;
1002 }
1003
1004
1005 /*
1006   netr_LogonControl2Ex
1007 */
1008 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1009                        struct netr_LogonControl2Ex *r)
1010 {
1011         return WERR_NOT_SUPPORTED;
1012 }
1013
1014
1015 /*
1016   netr_LogonControl
1017 */
1018 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1019                        struct netr_LogonControl *r)
1020 {
1021         struct netr_LogonControl2Ex r2;
1022         WERROR werr;
1023
1024         if (r->in.level == 0x00000001) {
1025                 ZERO_STRUCT(r2);
1026
1027                 r2.in.logon_server = r->in.logon_server;
1028                 r2.in.function_code = r->in.function_code;
1029                 r2.in.level = r->in.level;
1030                 r2.in.data = NULL;
1031                 r2.out.query = r->out.query;
1032
1033                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1034         } else if (r->in.level == 0x00000002) {
1035                 werr = WERR_NOT_SUPPORTED;
1036         } else {
1037                 werr = WERR_UNKNOWN_LEVEL;
1038         }
1039
1040         return werr;
1041 }
1042
1043
1044 /*
1045   netr_LogonControl2
1046 */
1047 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1048                        struct netr_LogonControl2 *r)
1049 {
1050         struct netr_LogonControl2Ex r2;
1051         WERROR werr;
1052
1053         ZERO_STRUCT(r2);
1054
1055         r2.in.logon_server = r->in.logon_server;
1056         r2.in.function_code = r->in.function_code;
1057         r2.in.level = r->in.level;
1058         r2.in.data = r->in.data;
1059         r2.out.query = r->out.query;
1060
1061         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1062
1063         return werr;
1064 }
1065
1066 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1067                                          struct ldb_context *sam_ctx,
1068                                          struct netr_DomainTrustList *trusts,
1069                                          uint32_t trust_flags);
1070
1071 /*
1072   netr_GetAnyDCName
1073 */
1074 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1075                        struct netr_GetAnyDCName *r)
1076 {
1077         struct netr_DomainTrustList *trusts;
1078         struct ldb_context *sam_ctx;
1079         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1080         uint32_t i;
1081         WERROR werr;
1082
1083         *r->out.dcname = NULL;
1084
1085         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1086                 /* if the domainname parameter wasn't set assume our domain */
1087                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1088         }
1089
1090         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1091                                 dce_call->conn->auth_state.session_info, 0);
1092         if (sam_ctx == NULL) {
1093                 return WERR_DS_UNAVAILABLE;
1094         }
1095
1096         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1097                 /* well we asked for a DC of our own domain */
1098                 if (samdb_is_pdc(sam_ctx)) {
1099                         /* we are the PDC of the specified domain */
1100                         return WERR_NO_SUCH_DOMAIN;
1101                 }
1102
1103                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1104                                                 lpcfg_netbios_name(lp_ctx));
1105                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1106
1107                 return WERR_OK;
1108         }
1109
1110         /* Okay, now we have to consider the trusted domains */
1111
1112         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1113         W_ERROR_HAVE_NO_MEMORY(trusts);
1114
1115         trusts->count = 0;
1116
1117         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1118                                           NETR_TRUST_FLAG_INBOUND
1119                                           | NETR_TRUST_FLAG_OUTBOUND);
1120         W_ERROR_NOT_OK_RETURN(werr);
1121
1122         for (i = 0; i < trusts->count; i++) {
1123                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1124                         /* FIXME: Here we need to find a DC for the specified
1125                          * trusted domain. */
1126
1127                         /* return WERR_OK; */
1128                         return WERR_NO_SUCH_DOMAIN;
1129                 }
1130         }
1131
1132         return WERR_NO_SUCH_DOMAIN;
1133 }
1134
1135
1136 /*
1137   netr_DatabaseRedo
1138 */
1139 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140                        struct netr_DatabaseRedo *r)
1141 {
1142         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1143 }
1144
1145
1146 /*
1147   netr_NetrEnumerateTrustedDomains
1148 */
1149 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150                        struct netr_NetrEnumerateTrustedDomains *r)
1151 {
1152         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1153 }
1154
1155
1156 /*
1157   netr_LogonGetCapabilities
1158 */
1159 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1160                        struct netr_LogonGetCapabilities *r)
1161 {
1162         /* we don't support AES yet */
1163         return NT_STATUS_NOT_IMPLEMENTED;
1164 }
1165
1166
1167 /*
1168   netr_NETRLOGONSETSERVICEBITS
1169 */
1170 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1171                        struct netr_NETRLOGONSETSERVICEBITS *r)
1172 {
1173         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1174 }
1175
1176
1177 /*
1178   netr_LogonGetTrustRid
1179 */
1180 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1181                        struct netr_LogonGetTrustRid *r)
1182 {
1183         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1184 }
1185
1186
1187 /*
1188   netr_NETRLOGONCOMPUTESERVERDIGEST
1189 */
1190 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1191                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1192 {
1193         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1194 }
1195
1196
1197 /*
1198   netr_NETRLOGONCOMPUTECLIENTDIGEST
1199 */
1200 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1201                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1202 {
1203         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1204 }
1205
1206
1207
1208 /*
1209   netr_DsRGetSiteName
1210 */
1211 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1212                                   struct netr_DsRGetSiteName *r)
1213 {
1214         struct ldb_context *sam_ctx;
1215         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1216
1217         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1218                                 dce_call->conn->auth_state.session_info, 0);
1219         if (sam_ctx == NULL) {
1220                 return WERR_DS_UNAVAILABLE;
1221         }
1222
1223         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1224         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1225
1226         return WERR_OK;
1227 }
1228
1229
1230 /*
1231   fill in a netr_OneDomainInfo from a ldb search result
1232 */
1233 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1234                                      struct loadparm_context *lp_ctx,
1235                                      struct ldb_context *sam_ctx,
1236                                      struct ldb_message *res,
1237                                      struct netr_OneDomainInfo *info,
1238                                      bool is_local, bool is_trust_list)
1239 {
1240         ZERO_STRUCTP(info);
1241
1242         if (is_trust_list) {
1243                 /* w2k8 only fills this on trusted domains */
1244                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1245                 info->trust_extension.length = 16;
1246                 info->trust_extension.info->flags =
1247                         NETR_TRUST_FLAG_TREEROOT |
1248                         NETR_TRUST_FLAG_IN_FOREST |
1249                         NETR_TRUST_FLAG_PRIMARY |
1250                         NETR_TRUST_FLAG_NATIVE;
1251
1252                 info->trust_extension.info->parent_index = 0; /* should be index into array
1253                                                                  of parent */
1254                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1255                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1256         }
1257
1258         if (is_trust_list) {
1259                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1260                 info->dns_forestname.string = NULL;
1261         } else {
1262                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1263                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1264                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1265                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1266         }
1267
1268         if (is_local) {
1269                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1270                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1271                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1272                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1273         } else {
1274                 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1275                 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1276                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1277                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1278         }
1279         if (!is_trust_list) {
1280                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1281         }
1282
1283         return NT_STATUS_OK;
1284 }
1285
1286 /*
1287   netr_LogonGetDomainInfo
1288   this is called as part of the ADS domain logon procedure.
1289
1290   It has an important role in convaying details about the client, such
1291   as Operating System, Version, Service Pack etc.
1292 */
1293 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1294         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1295 {
1296         struct netlogon_creds_CredentialState *creds;
1297         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1298                 "securityIdentifier", "trustPartner", NULL };
1299         const char * const attrs2[] = { "dNSHostName",
1300                 "msDS-SupportedEncryptionTypes", NULL };
1301         const char *temp_str, *temp_str2;
1302         const char *old_dns_hostname;
1303         struct ldb_context *sam_ctx;
1304         struct ldb_message **res1, **res2, **res3, *new_msg;
1305         struct ldb_dn *workstation_dn;
1306         struct netr_DomainInformation *domain_info;
1307         struct netr_LsaPolicyInformation *lsa_policy_info;
1308         struct netr_OsVersionInfoEx *os_version;
1309         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1310         bool update_dns_hostname = true;
1311         int ret, ret3, i;
1312         NTSTATUS status;
1313
1314         status = dcesrv_netr_creds_server_step_check(dce_call,
1315                                                      mem_ctx,
1316                                                      r->in.computer_name,
1317                                                      r->in.credential,
1318                                                      r->out.return_authenticator,
1319                                                      &creds);
1320         if (!NT_STATUS_IS_OK(status)) {
1321                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1322         }
1323         NT_STATUS_NOT_OK_RETURN(status);
1324
1325         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1326                                 dce_call->conn->dce_ctx->lp_ctx,
1327                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1328         if (sam_ctx == NULL) {
1329                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1330         }
1331
1332         switch (r->in.level) {
1333         case 1: /* Domain information */
1334
1335                 if (r->in.query->workstation_info == NULL) {
1336                         return NT_STATUS_INVALID_PARAMETER;
1337                 }
1338
1339                 /*
1340                  * Checks that the computer name parameter without possible "$"
1341                  * matches as prefix with the DNS hostname in the workstation
1342                  * info structure.
1343                  */
1344                 temp_str = talloc_strndup(mem_ctx,
1345                                           r->in.computer_name,
1346                                           strcspn(r->in.computer_name, "$"));
1347                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1348                 temp_str2 = talloc_strndup(mem_ctx,
1349                                            r->in.query->workstation_info->dns_hostname,
1350                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1351                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1352                 if (strcasecmp(temp_str, temp_str2) != 0) {
1353                         update_dns_hostname = false;
1354                 }
1355
1356                 /* Prepare the workstation DN */
1357                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1358                         dom_sid_string(mem_ctx, creds->sid));
1359                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1360
1361                 /* Lookup for attributes in workstation object */
1362                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1363                         &res1, attrs2);
1364                 if (ret != 1) {
1365                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1366                 }
1367
1368                 /* Gets the old DNS hostname */
1369                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1370                                                                "dNSHostName",
1371                                                                NULL);
1372
1373                 /*
1374                  * Updates the DNS hostname when the client wishes that the
1375                  * server should handle this for him
1376                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1377                  * obviously only checked when we do already have a
1378                  * "dNSHostName".
1379                  * See MS-NRPC section 3.5.4.3.9
1380                  */
1381                 if ((old_dns_hostname != NULL) &&
1382                     (r->in.query->workstation_info->workstation_flags
1383                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1384                         update_dns_hostname = false;
1385                 }
1386
1387                 /* Gets host informations and put them into our directory */
1388
1389                 new_msg = ldb_msg_new(mem_ctx);
1390                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1391
1392                 new_msg->dn = workstation_dn;
1393
1394                 /* Sets the OS name */
1395                 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1396                                            "operatingSystem",
1397                                            r->in.query->workstation_info->os_name.string);
1398                 if (ret != LDB_SUCCESS) {
1399                         return NT_STATUS_NO_MEMORY;
1400                 }
1401
1402                 /*
1403                  * Sets informations from "os_version". On an empty structure
1404                  * the values are cleared.
1405                  */
1406                 if (r->in.query->workstation_info->os_version.os != NULL) {
1407                         os_version = &r->in.query->workstation_info->os_version.os->os;
1408
1409                         ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1410                                                    "operatingSystemServicePack",
1411                                                    os_version->CSDVersion);
1412                         if (ret != LDB_SUCCESS) {
1413                                 return NT_STATUS_NO_MEMORY;
1414                         }
1415
1416                         ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1417                                                    "operatingSystemVersion",
1418                                                    talloc_asprintf(mem_ctx,
1419                                                    "%u.%u (%u)",
1420                                                    os_version->MajorVersion,
1421                                                    os_version->MinorVersion,
1422                                                    os_version->BuildNumber));
1423                         if (ret != LDB_SUCCESS) {
1424                                 return NT_STATUS_NO_MEMORY;
1425                         }
1426                 } else {
1427                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1428                                                    "operatingSystemServicePack");
1429                         if (ret != LDB_SUCCESS) {
1430                                 return NT_STATUS_NO_MEMORY;
1431                         }
1432
1433                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1434                                                    "operatingSystemVersion");
1435                         if (ret != LDB_SUCCESS) {
1436                                 return NT_STATUS_NO_MEMORY;
1437                         }
1438                 }
1439
1440                 /*
1441                  * If the boolean "update_dns_hostname" remained true, then we
1442                  * are fine to start the update.
1443                  */
1444                 if (update_dns_hostname) {
1445                         ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1446                                                    "dNSHostname",
1447                                                    r->in.query->workstation_info->dns_hostname);
1448                         if (ret != LDB_SUCCESS) {
1449                                 return NT_STATUS_NO_MEMORY;
1450                         }
1451
1452                         /* This manual "servicePrincipalName" generation is
1453                          * still needed! Since the update in the samldb LDB
1454                          * module does only work if the entries already exist
1455                          * which isn't always the case. */
1456                         ret = ldb_msg_add_string(new_msg,
1457                                                  "servicePrincipalName",
1458                                                  talloc_asprintf(new_msg, "HOST/%s",
1459                                                  r->in.computer_name));
1460                         if (ret != LDB_SUCCESS) {
1461                                 return NT_STATUS_NO_MEMORY;
1462                         }
1463
1464                         ret = ldb_msg_add_string(new_msg,
1465                                                  "servicePrincipalName",
1466                                                  talloc_asprintf(new_msg, "HOST/%s",
1467                                                  r->in.query->workstation_info->dns_hostname));
1468                         if (ret != LDB_SUCCESS) {
1469                                 return NT_STATUS_NO_MEMORY;
1470                         }
1471                 }
1472
1473                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1474                         DEBUG(3,("Impossible to update samdb: %s\n",
1475                                 ldb_errstring(sam_ctx)));
1476                 }
1477
1478                 talloc_free(new_msg);
1479
1480                 /* Writes back the domain information */
1481
1482                 /* We need to do two searches. The first will pull our primary
1483                    domain and the second will pull any trusted domains. Our
1484                    primary domain is also a "trusted" domain, so we need to
1485                    put the primary domain into the lists of returned trusts as
1486                    well. */
1487                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1488                         &res2, attrs);
1489                 if (ret != 1) {
1490                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1491                 }
1492
1493                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1494                         "(objectClass=trustedDomain)");
1495                 if (ret3 == -1) {
1496                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1497                 }
1498
1499                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1500                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1501
1502                 ZERO_STRUCTP(domain_info);
1503
1504                 /* Informations about the local and trusted domains */
1505
1506                 status = fill_one_domain_info(mem_ctx,
1507                         dce_call->conn->dce_ctx->lp_ctx,
1508                         sam_ctx, res2[0], &domain_info->primary_domain,
1509                         true, false);
1510                 NT_STATUS_NOT_OK_RETURN(status);
1511
1512                 domain_info->trusted_domain_count = ret3 + 1;
1513                 domain_info->trusted_domains = talloc_array(mem_ctx,
1514                         struct netr_OneDomainInfo,
1515                         domain_info->trusted_domain_count);
1516                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1517
1518                 for (i=0;i<ret3;i++) {
1519                         status = fill_one_domain_info(mem_ctx,
1520                                 dce_call->conn->dce_ctx->lp_ctx,
1521                                 sam_ctx, res3[i],
1522                                 &domain_info->trusted_domains[i],
1523                                 false, true);
1524                         NT_STATUS_NOT_OK_RETURN(status);
1525                 }
1526
1527                 status = fill_one_domain_info(mem_ctx,
1528                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1529                         &domain_info->trusted_domains[i], true, true);
1530                 NT_STATUS_NOT_OK_RETURN(status);
1531
1532                 /* Sets the supported encryption types */
1533                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1534                         "msDS-SupportedEncryptionTypes",
1535                         default_supported_enc_types);
1536
1537                 /* Other host domain informations */
1538
1539                 lsa_policy_info = talloc(mem_ctx,
1540                         struct netr_LsaPolicyInformation);
1541                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1542                 ZERO_STRUCTP(lsa_policy_info);
1543
1544                 domain_info->lsa_policy = *lsa_policy_info;
1545
1546                 /* The DNS hostname is only returned back when there is a chance
1547                  * for a change. */
1548                 if ((r->in.query->workstation_info->workstation_flags
1549                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1550                         domain_info->dns_hostname.string = old_dns_hostname;
1551                 } else {
1552                         domain_info->dns_hostname.string = NULL;
1553                 }
1554
1555                 domain_info->workstation_flags =
1556                         r->in.query->workstation_info->workstation_flags;
1557
1558                 r->out.info->domain_info = domain_info;
1559         break;
1560         case 2: /* LSA policy information - not used at the moment */
1561                 lsa_policy_info = talloc(mem_ctx,
1562                         struct netr_LsaPolicyInformation);
1563                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1564                 ZERO_STRUCTP(lsa_policy_info);
1565
1566                 r->out.info->lsa_policy_info = lsa_policy_info;
1567         break;
1568         default:
1569                 return NT_STATUS_INVALID_LEVEL;
1570         break;
1571         }
1572
1573         return NT_STATUS_OK;
1574 }
1575
1576
1577 /*
1578   netr_ServerPasswordGet
1579 */
1580 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1581                        struct netr_ServerPasswordGet *r)
1582 {
1583         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1584 }
1585
1586
1587 /*
1588   netr_NETRLOGONSENDTOSAM
1589 */
1590 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1591                        struct netr_NETRLOGONSENDTOSAM *r)
1592 {
1593         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1594 }
1595
1596
1597 /*
1598   netr_DsRGetDCNameEx2
1599 */
1600 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1601                                           TALLOC_CTX *mem_ctx,
1602                                           struct netr_DsRGetDCNameEx2 *r)
1603 {
1604         struct ldb_context *sam_ctx;
1605         struct netr_DsRGetDCNameInfo *info;
1606         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1607         const struct tsocket_address *remote_address;
1608         char *addr = NULL;
1609         const char *server_site_name;
1610         char *guid_str;
1611         struct netlogon_samlogon_response response;
1612         NTSTATUS status;
1613         const char *dc_name = NULL;
1614         const char *domain_name = NULL;
1615
1616         ZERO_STRUCTP(r->out.info);
1617
1618         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1619                                 dce_call->conn->auth_state.session_info, 0);
1620         if (sam_ctx == NULL) {
1621                 return WERR_DS_UNAVAILABLE;
1622         }
1623
1624         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1625         if (tsocket_address_is_inet(remote_address, "ip")) {
1626                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1627                 W_ERROR_HAVE_NO_MEMORY(addr);
1628         }
1629
1630         /* "server_unc" is ignored by w2k3 */
1631
1632         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1633                 return WERR_INVALID_FLAGS;
1634         }
1635
1636         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1637             r->in.flags & DS_PDC_REQUIRED &&
1638             r->in.flags & DS_KDC_REQUIRED) {
1639                 return WERR_INVALID_FLAGS;
1640         }
1641         if (r->in.flags & DS_IS_FLAT_NAME &&
1642             r->in.flags & DS_IS_DNS_NAME) {
1643                 return WERR_INVALID_FLAGS;
1644         }
1645         if (r->in.flags & DS_RETURN_DNS_NAME &&
1646             r->in.flags & DS_RETURN_FLAT_NAME) {
1647                 return WERR_INVALID_FLAGS;
1648         }
1649         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1650             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1651                 return WERR_INVALID_FLAGS;
1652         }
1653
1654         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1655             r->in.flags &
1656             (DS_DIRECTORY_SERVICE_REQUIRED |
1657              DS_DIRECTORY_SERVICE_PREFERRED |
1658              DS_GC_SERVER_REQUIRED |
1659              DS_PDC_REQUIRED |
1660              DS_KDC_REQUIRED)) {
1661                 return WERR_INVALID_FLAGS;
1662         }
1663
1664         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1665             r->in.site_name) {
1666                 return WERR_INVALID_FLAGS;
1667         }
1668
1669         /* Proof server site parameter "site_name" if it was specified */
1670         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1671         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1672         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1673                                                      server_site_name) != 0)) {
1674                 return WERR_NO_SUCH_DOMAIN;
1675         }
1676
1677         guid_str = r->in.domain_guid != NULL ?
1678                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1679
1680         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1681                                                  r->in.domain_name,
1682                                                  r->in.domain_name,
1683                                                  NULL, guid_str,
1684                                                  r->in.client_account,
1685                                                  r->in.mask, addr,
1686                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1687                                                  lp_ctx, &response, true);
1688         if (!NT_STATUS_IS_OK(status)) {
1689                 return ntstatus_to_werror(status);
1690         }
1691
1692         if (r->in.flags & DS_RETURN_DNS_NAME) {
1693                 dc_name = response.data.nt5_ex.pdc_dns_name;
1694                 domain_name = response.data.nt5_ex.dns_domain;
1695         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1696                 dc_name = response.data.nt5_ex.pdc_name;
1697                 domain_name = response.data.nt5_ex.domain_name;
1698         } else {
1699
1700                 /*
1701                  * TODO: autodetect what we need to return
1702                  * based on the given arguments
1703                  */
1704                 dc_name = response.data.nt5_ex.pdc_name;
1705                 domain_name = response.data.nt5_ex.domain_name;
1706         }
1707
1708         if (!dc_name || !dc_name[0]) {
1709                 return WERR_NO_SUCH_DOMAIN;
1710         }
1711
1712         if (!domain_name || !domain_name[0]) {
1713                 return WERR_NO_SUCH_DOMAIN;
1714         }
1715
1716         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1717         W_ERROR_HAVE_NO_MEMORY(info);
1718         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1719         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1720         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1721                                            response.data.nt5_ex.sockaddr.pdc_ip);
1722         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1723         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1724         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1725         info->domain_name      = domain_name;
1726         info->forest_name      = response.data.nt5_ex.forest;
1727         info->dc_flags         = response.data.nt5_ex.server_type;
1728         info->dc_site_name     = response.data.nt5_ex.server_site;
1729         info->client_site_name = response.data.nt5_ex.client_site;
1730
1731         *r->out.info = info;
1732
1733         return WERR_OK;
1734 }
1735
1736 /*
1737   netr_DsRGetDCNameEx
1738 */
1739 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1740                                   struct netr_DsRGetDCNameEx *r)
1741 {
1742         struct netr_DsRGetDCNameEx2 r2;
1743         WERROR werr;
1744
1745         ZERO_STRUCT(r2);
1746
1747         r2.in.server_unc = r->in.server_unc;
1748         r2.in.client_account = NULL;
1749         r2.in.mask = 0;
1750         r2.in.domain_guid = r->in.domain_guid;
1751         r2.in.domain_name = r->in.domain_name;
1752         r2.in.site_name = r->in.site_name;
1753         r2.in.flags = r->in.flags;
1754         r2.out.info = r->out.info;
1755
1756         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1757
1758         return werr;
1759 }
1760
1761 /*
1762   netr_DsRGetDCName
1763 */
1764 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1765                                 struct netr_DsRGetDCName *r)
1766 {
1767         struct netr_DsRGetDCNameEx2 r2;
1768         WERROR werr;
1769
1770         ZERO_STRUCT(r2);
1771
1772         r2.in.server_unc = r->in.server_unc;
1773         r2.in.client_account = NULL;
1774         r2.in.mask = 0;
1775         r2.in.domain_name = r->in.domain_name;
1776         r2.in.domain_guid = r->in.domain_guid;
1777
1778         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1779         r2.in.flags = r->in.flags;
1780         r2.out.info = r->out.info;
1781
1782         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1783
1784         return werr;
1785 }
1786 /*
1787   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1788 */
1789 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1790                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1791 {
1792         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1793 }
1794
1795
1796 /*
1797   netr_NetrEnumerateTrustedDomainsEx
1798 */
1799 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1800                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1801 {
1802         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1803 }
1804
1805
1806 /*
1807   netr_DsRAddressToSitenamesExW
1808 */
1809 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1810                                                    struct netr_DsRAddressToSitenamesExW *r)
1811 {
1812         struct ldb_context *sam_ctx;
1813         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1814         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1815         sa_family_t sin_family;
1816         struct sockaddr_in *addr;
1817 #ifdef HAVE_IPV6
1818         struct sockaddr_in6 *addr6;
1819         char addr_str[INET6_ADDRSTRLEN];
1820 #else
1821         char addr_str[INET_ADDRSTRLEN];
1822 #endif
1823         char *subnet_name;
1824         const char *res;
1825         uint32_t i;
1826
1827         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1828                                 dce_call->conn->auth_state.session_info, 0);
1829         if (sam_ctx == NULL) {
1830                 return WERR_DS_UNAVAILABLE;
1831         }
1832
1833         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1834         W_ERROR_HAVE_NO_MEMORY(ctr);
1835
1836         *r->out.ctr = ctr;
1837
1838         ctr->count = r->in.count;
1839         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1840         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1841         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1842         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1843
1844         for (i=0; i<ctr->count; i++) {
1845                 ctr->sitename[i].string = NULL;
1846                 ctr->subnetname[i].string = NULL;
1847
1848                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1849                         continue;
1850                 }
1851                 /* The first two byte of the buffer are reserved for the
1852                  * "sin_family" but for now only the first one is used. */
1853                 sin_family = r->in.addresses[i].buffer[0];
1854
1855                 switch (sin_family) {
1856                 case AF_INET:
1857                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1858                                 continue;
1859                         }
1860                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1861                         res = inet_ntop(AF_INET, &addr->sin_addr,
1862                                         addr_str, sizeof(addr_str));
1863                         break;
1864 #ifdef HAVE_IPV6
1865                 case AF_INET6:
1866                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1867                                 continue;
1868                         }
1869                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1870                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1871                                         addr_str, sizeof(addr_str));
1872                         break;
1873 #endif
1874                 default:
1875                         continue;
1876                 }
1877
1878                 if (res == NULL) {
1879                         continue;
1880                 }
1881
1882                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
1883                                                                    mem_ctx,
1884                                                                    addr_str,
1885                                                                    &subnet_name);
1886                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1887                 ctr->subnetname[i].string = subnet_name;
1888         }
1889
1890         return WERR_OK;
1891 }
1892
1893
1894 /*
1895   netr_DsRAddressToSitenamesW
1896 */
1897 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1898                        struct netr_DsRAddressToSitenamesW *r)
1899 {
1900         struct netr_DsRAddressToSitenamesExW r2;
1901         struct netr_DsRAddressToSitenamesWCtr *ctr;
1902         uint32_t i;
1903         WERROR werr;
1904
1905         ZERO_STRUCT(r2);
1906
1907         r2.in.server_name = r->in.server_name;
1908         r2.in.count = r->in.count;
1909         r2.in.addresses = r->in.addresses;
1910
1911         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1912         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1913
1914         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1915         W_ERROR_HAVE_NO_MEMORY(ctr);
1916
1917         *r->out.ctr = ctr;
1918
1919         ctr->count = r->in.count;
1920         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1921         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1922
1923         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1924
1925         for (i=0; i<ctr->count; i++) {
1926                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
1927         }
1928
1929         return werr;
1930 }
1931
1932
1933 /*
1934   netr_DsrGetDcSiteCoverageW
1935 */
1936 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1937                        struct netr_DsrGetDcSiteCoverageW *r)
1938 {
1939         struct ldb_context *sam_ctx;
1940         struct DcSitesCtr *ctr;
1941         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1942
1943         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1944                                 dce_call->conn->auth_state.session_info, 0);
1945         if (sam_ctx == NULL) {
1946                 return WERR_DS_UNAVAILABLE;
1947         }
1948
1949         ctr = talloc(mem_ctx, struct DcSitesCtr);
1950         W_ERROR_HAVE_NO_MEMORY(ctr);
1951
1952         *r->out.ctr = ctr;
1953
1954         /* For now only return our default site */
1955         ctr->num_sites = 1;
1956         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1957         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1958         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1959         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1960
1961         return WERR_OK;
1962 }
1963
1964
1965 #define GET_CHECK_STR(dest, mem, msg, attr) \
1966 do {\
1967         const char *s; \
1968         s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1969         if (!s) { \
1970                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1971                           "without flatname\n", \
1972                           ldb_dn_get_linearized(msg->dn))); \
1973                 continue; \
1974         } \
1975         dest = talloc_strdup(mem, s); \
1976         W_ERROR_HAVE_NO_MEMORY(dest); \
1977 } while(0)
1978
1979
1980 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1981                                          struct ldb_context *sam_ctx,
1982                                          struct netr_DomainTrustList *trusts,
1983                                          uint32_t trust_flags)
1984 {
1985         struct ldb_dn *system_dn;
1986         struct ldb_message **dom_res = NULL;
1987         const char *trust_attrs[] = { "flatname", "trustPartner",
1988                                       "securityIdentifier", "trustDirection",
1989                                       "trustType", "trustAttributes", NULL };
1990         uint32_t n;
1991         int i;
1992         int ret;
1993
1994         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1995                              NETR_TRUST_FLAG_OUTBOUND))) {
1996                 return WERR_INVALID_FLAGS;
1997         }
1998
1999         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2000                                     ldb_get_default_basedn(sam_ctx),
2001                                     "(&(objectClass=container)(cn=System))");
2002         if (!system_dn) {
2003                 return WERR_GENERAL_FAILURE;
2004         }
2005
2006         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2007                            &dom_res, trust_attrs,
2008                            "(objectclass=trustedDomain)");
2009
2010         for (i = 0; i < ret; i++) {
2011                 unsigned int trust_dir;
2012                 uint32_t flags = 0;
2013
2014                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2015                                                       "trustDirection", 0);
2016
2017                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2018                         flags |= NETR_TRUST_FLAG_INBOUND;
2019                 }
2020                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2021                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2022                 }
2023
2024                 if (!(flags & trust_flags)) {
2025                         /* this trust direction was not requested */
2026                         continue;
2027                 }
2028
2029                 n = trusts->count;
2030                 trusts->array = talloc_realloc(trusts, trusts->array,
2031                                                struct netr_DomainTrust,
2032                                                n + 1);
2033                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2034
2035                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2036                               dom_res[i], "flatname");
2037                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2038                               dom_res[i], "trustPartner");
2039
2040                 trusts->array[n].trust_flags = flags;
2041                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2042                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2043                         /* TODO: find if we have parent in the list */
2044                         trusts->array[n].parent_index = 0;
2045                 }
2046
2047                 trusts->array[n].trust_type =
2048                                 ldb_msg_find_attr_as_uint(dom_res[i],
2049                                                   "trustType", 0);
2050                 trusts->array[n].trust_attributes =
2051                                 ldb_msg_find_attr_as_uint(dom_res[i],
2052                                                   "trustAttributes", 0);
2053
2054                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2055                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2056                         struct dom_sid zero_sid;
2057                         ZERO_STRUCT(zero_sid);
2058                         trusts->array[n].sid =
2059                                 dom_sid_dup(trusts, &zero_sid);
2060                 } else {
2061                         trusts->array[n].sid =
2062                                 samdb_result_dom_sid(trusts, dom_res[i],
2063                                                      "securityIdentifier");
2064                 }
2065                 trusts->array[n].guid = GUID_zero();
2066
2067                 trusts->count = n + 1;
2068         }
2069
2070         talloc_free(dom_res);
2071         return WERR_OK;
2072 }
2073
2074 /*
2075   netr_DsrEnumerateDomainTrusts
2076 */
2077 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2078                                                    TALLOC_CTX *mem_ctx,
2079                                                    struct netr_DsrEnumerateDomainTrusts *r)
2080 {
2081         struct netr_DomainTrustList *trusts;
2082         struct ldb_context *sam_ctx;
2083         int ret;
2084         struct ldb_message **dom_res;
2085         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2086         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2087         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2088         const char *p;
2089         WERROR werr;
2090
2091         if (r->in.trust_flags & 0xFFFFFE00) {
2092                 return WERR_INVALID_FLAGS;
2093         }
2094
2095         /* TODO: turn to hard check once we are sure this is 100% correct */
2096         if (!r->in.server_name) {
2097                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2098                           "But received NULL!\n", dnsdomain));
2099         } else {
2100                 p = strchr(r->in.server_name, '.');
2101                 if (!p) {
2102                         DEBUG(3, ("Invalid domain! Expected name in domain "
2103                                   "[%s]. But received [%s]!\n",
2104                                   dnsdomain, r->in.server_name));
2105                         p = r->in.server_name;
2106                 } else {
2107                         p++;
2108                 }
2109                 if (strcasecmp(p, dnsdomain)) {
2110                         DEBUG(3, ("Invalid domain! Expected name in domain "
2111                                   "[%s]. But received [%s]!\n",
2112                                   dnsdomain, r->in.server_name));
2113                 }
2114         }
2115
2116         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2117         W_ERROR_HAVE_NO_MEMORY(trusts);
2118
2119         trusts->count = 0;
2120         r->out.trusts = trusts;
2121
2122         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2123                                 dce_call->conn->auth_state.session_info, 0);
2124         if (sam_ctx == NULL) {
2125                 return WERR_GENERAL_FAILURE;
2126         }
2127
2128         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2129             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2130
2131                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2132                                                   trusts, r->in.trust_flags);
2133                 W_ERROR_NOT_OK_RETURN(werr);
2134         }
2135
2136         /* NOTE: we currently are always the root of the forest */
2137         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2138                 uint32_t n = trusts->count;
2139
2140                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2141                                       &dom_res, dom_attrs);
2142                 if (ret != 1) {
2143                         return WERR_GENERAL_FAILURE;
2144                 }
2145
2146                 trusts->count = n + 1;
2147                 trusts->array = talloc_realloc(trusts, trusts->array,
2148                                                struct netr_DomainTrust,
2149                                                trusts->count);
2150                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2151
2152                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2153                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2154                 trusts->array[n].trust_flags =
2155                         NETR_TRUST_FLAG_NATIVE |
2156                         NETR_TRUST_FLAG_TREEROOT |
2157                         NETR_TRUST_FLAG_IN_FOREST |
2158                         NETR_TRUST_FLAG_PRIMARY;
2159                 /* we are always the root domain for now */
2160                 trusts->array[n].parent_index = 0;
2161                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2162                 trusts->array[n].trust_attributes = 0;
2163                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2164                                                             dom_res[0],
2165                                                             "objectSid");
2166                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2167                                                           "objectGUID");
2168                 talloc_free(dom_res);
2169         }
2170
2171         return WERR_OK;
2172 }
2173
2174
2175 /*
2176   netr_DsrDeregisterDNSHostRecords
2177 */
2178 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2179                        struct netr_DsrDeregisterDNSHostRecords *r)
2180 {
2181         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2182 }
2183
2184
2185 /*
2186   netr_ServerTrustPasswordsGet
2187 */
2188 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2189                        struct netr_ServerTrustPasswordsGet *r)
2190 {
2191         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2192 }
2193
2194
2195 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2196                                       struct ldb_context *sam_ctx,
2197                                       struct loadparm_context *lp_ctx,
2198                                       struct lsa_ForestTrustInformation *info)
2199 {
2200         struct lsa_ForestTrustDomainInfo *domain_info;
2201         struct lsa_ForestTrustRecord *e;
2202         struct ldb_message **dom_res;
2203         const char * const dom_attrs[] = { "objectSid", NULL };
2204         int ret;
2205
2206         /* we need to provide 2 entries:
2207          * 1. the Root Forest name
2208          * 2. the Domain Information
2209          */
2210
2211         info->count = 2;
2212         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2213         W_ERROR_HAVE_NO_MEMORY(info->entries);
2214
2215         /* Forest root info */
2216         e = talloc(info, struct lsa_ForestTrustRecord);
2217         W_ERROR_HAVE_NO_MEMORY(e);
2218
2219         e->flags = 0;
2220         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2221         e->time = 0; /* so far always 0 in trces. */
2222         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2223                                                                        mem_ctx);
2224         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2225
2226         info->entries[0] = e;
2227
2228         /* Domain info */
2229         e = talloc(info, struct lsa_ForestTrustRecord);
2230         W_ERROR_HAVE_NO_MEMORY(e);
2231
2232         /* get our own domain info */
2233         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2234         if (ret != 1) {
2235                 return WERR_GENERAL_FAILURE;
2236         }
2237
2238         /* TODO: check if disabled and set flags accordingly */
2239         e->flags = 0;
2240         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2241         e->time = 0; /* so far always 0 in traces. */
2242
2243         domain_info = &e->forest_trust_data.domain_info;
2244         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2245                                                        "objectSid");
2246         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2247         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2248
2249         info->entries[1] = e;
2250
2251         talloc_free(dom_res);
2252
2253         return WERR_OK;
2254 }
2255
2256 /*
2257   netr_DsRGetForestTrustInformation
2258 */
2259 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2260                                                        TALLOC_CTX *mem_ctx,
2261                                                        struct netr_DsRGetForestTrustInformation *r)
2262 {
2263         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2264         struct lsa_ForestTrustInformation *info, **info_ptr;
2265         struct ldb_context *sam_ctx;
2266         WERROR werr;
2267
2268         if (r->in.flags & 0xFFFFFFFE) {
2269                 return WERR_INVALID_FLAGS;
2270         }
2271
2272         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2273                                 dce_call->conn->auth_state.session_info, 0);
2274         if (sam_ctx == NULL) {
2275                 return WERR_GENERAL_FAILURE;
2276         }
2277
2278         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2279                 if (!samdb_is_pdc(sam_ctx)) {
2280                         return WERR_NERR_NOTPRIMARY;
2281                 }
2282
2283                 if (r->in.trusted_domain_name == NULL) {
2284                         return WERR_INVALID_FLAGS;
2285                 }
2286
2287                 /* TODO: establish an schannel connection with
2288                  * r->in.trusted_domain_name and perform a
2289                  * netr_GetForestTrustInformation call against it */
2290
2291                 /* for now return not implementd */
2292                 return WERR_CALL_NOT_IMPLEMENTED;
2293         }
2294
2295         /* TODO: check r->in.server_name is our name */
2296
2297         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2298         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2299
2300         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2301         W_ERROR_HAVE_NO_MEMORY(info);
2302
2303         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2304         W_ERROR_NOT_OK_RETURN(werr);
2305
2306         *info_ptr = info;
2307         r->out.forest_trust_info = info_ptr;
2308
2309         return WERR_OK;
2310 }
2311
2312
2313 /*
2314   netr_GetForestTrustInformation
2315 */
2316 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2317                                                       TALLOC_CTX *mem_ctx,
2318                                                       struct netr_GetForestTrustInformation *r)
2319 {
2320         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2321         struct netlogon_creds_CredentialState *creds;
2322         struct lsa_ForestTrustInformation *info, **info_ptr;
2323         struct ldb_context *sam_ctx;
2324         NTSTATUS status;
2325         WERROR werr;
2326
2327         status = dcesrv_netr_creds_server_step_check(dce_call,
2328                                                      mem_ctx,
2329                                                      r->in.computer_name,
2330                                                      r->in.credential,
2331                                                      r->out.return_authenticator,
2332                                                      &creds);
2333         if (!NT_STATUS_IS_OK(status)) {
2334                 return status;
2335         }
2336
2337         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2338             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2339                 return NT_STATUS_NOT_IMPLEMENTED;
2340         }
2341
2342         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2343                                 dce_call->conn->auth_state.session_info, 0);
2344         if (sam_ctx == NULL) {
2345                 return NT_STATUS_UNSUCCESSFUL;
2346         }
2347
2348         /* TODO: check r->in.server_name is our name */
2349
2350         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2351         if (!info_ptr) {
2352                 return NT_STATUS_NO_MEMORY;
2353         }
2354         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2355         if (!info) {
2356                 return NT_STATUS_NO_MEMORY;
2357         }
2358
2359         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2360         if (!W_ERROR_IS_OK(werr)) {
2361                 return werror_to_ntstatus(werr);
2362         }
2363
2364         *info_ptr = info;
2365         r->out.forest_trust_info = info_ptr;
2366
2367         return NT_STATUS_OK;
2368 }
2369
2370
2371 /*
2372   netr_ServerGetTrustInfo
2373 */
2374 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2375                        struct netr_ServerGetTrustInfo *r)
2376 {
2377         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2378 }
2379
2380 /*
2381   netr_Unused47
2382 */
2383 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2384                                      struct netr_Unused47 *r)
2385 {
2386         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2387 }
2388
2389
2390 struct netr_dnsupdate_RODC_state {
2391         struct dcesrv_call_state *dce_call;
2392         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2393         struct dnsupdate_RODC *r2;
2394 };
2395
2396 /*
2397   called when the forwarded RODC dns update request is finished
2398  */
2399 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2400 {
2401         struct netr_dnsupdate_RODC_state *st =
2402                 tevent_req_callback_data(subreq,
2403                                          struct netr_dnsupdate_RODC_state);
2404         NTSTATUS status;
2405
2406         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2407         TALLOC_FREE(subreq);
2408         if (!NT_STATUS_IS_OK(status)) {
2409                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2410                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2411         }
2412
2413         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2414
2415         status = dcesrv_reply(st->dce_call);
2416         if (!NT_STATUS_IS_OK(status)) {
2417                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2418         }
2419 }
2420
2421 /*
2422   netr_DsrUpdateReadOnlyServerDnsRecords
2423 */
2424 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2425                                                               TALLOC_CTX *mem_ctx,
2426                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2427 {
2428         struct netlogon_creds_CredentialState *creds;
2429         NTSTATUS nt_status;
2430         struct dcerpc_binding_handle *binding_handle;
2431         struct netr_dnsupdate_RODC_state *st;
2432         struct tevent_req *subreq;
2433
2434         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2435                                                         mem_ctx,
2436                                                         r->in.computer_name,
2437                                                         r->in.credential,
2438                                                         r->out.return_authenticator,
2439                                                         &creds);
2440         NT_STATUS_NOT_OK_RETURN(nt_status);
2441
2442         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2443                 return NT_STATUS_ACCESS_DENIED;
2444         }
2445
2446         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2447         NT_STATUS_HAVE_NO_MEMORY(st);
2448
2449         st->dce_call = dce_call;
2450         st->r = r;
2451         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2452         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2453
2454         st->r2->in.dom_sid = creds->sid;
2455         st->r2->in.site_name = r->in.site_name;
2456         st->r2->in.dns_ttl = r->in.dns_ttl;
2457         st->r2->in.dns_names = r->in.dns_names;
2458         st->r2->out.dns_names = r->out.dns_names;
2459
2460         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2461                                                      "dnsupdate", &ndr_table_irpc);
2462         if (binding_handle == NULL) {
2463                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2464                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2465                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2466         }
2467
2468         /* forward the call */
2469         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2470                                               binding_handle, st->r2);
2471         NT_STATUS_HAVE_NO_MEMORY(subreq);
2472
2473         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2474
2475         /* setup the callback */
2476         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2477
2478         return NT_STATUS_OK;
2479 }
2480
2481
2482 /* include the generated boilerplate */
2483 #include "librpc/gen_ndr/ndr_netlogon_s.c"