s4:netlogon RPC server - "LogonGetDomainInfo" - check for NULL attributes
[ambi/samba-autobuild/.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-2010
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 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
535 {
536         switch (r->in.logon_level) {
537         case NetlogonInteractiveInformation:
538         case NetlogonServiceInformation:
539         case NetlogonInteractiveTransitiveInformation:
540         case NetlogonServiceTransitiveInformation:
541                 if (r->in.logon->password == NULL) {
542                         return NT_STATUS_INVALID_PARAMETER;
543                 }
544
545                 switch (r->in.validation_level) {
546                 case NetlogonValidationSamInfo:  /* 2 */
547                 case NetlogonValidationSamInfo2: /* 3 */
548                 case NetlogonValidationSamInfo4: /* 6 */
549                         break;
550                 default:
551                         return NT_STATUS_INVALID_INFO_CLASS;
552                 }
553
554                 break;
555         case NetlogonNetworkInformation:
556         case NetlogonNetworkTransitiveInformation:
557                 if (r->in.logon->network == NULL) {
558                         return NT_STATUS_INVALID_PARAMETER;
559                 }
560
561                 switch (r->in.validation_level) {
562                 case NetlogonValidationSamInfo:  /* 2 */
563                 case NetlogonValidationSamInfo2: /* 3 */
564                 case NetlogonValidationSamInfo4: /* 6 */
565                         break;
566                 default:
567                         return NT_STATUS_INVALID_INFO_CLASS;
568                 }
569
570                 break;
571
572         case NetlogonGenericInformation:
573                 if (r->in.logon->generic == NULL) {
574                         return NT_STATUS_INVALID_PARAMETER;
575                 }
576
577                 switch (r->in.validation_level) {
578                 /* TODO: case NetlogonValidationGenericInfo: 4 */
579                 case NetlogonValidationGenericInfo2: /* 5 */
580                         break;
581                 default:
582                         return NT_STATUS_INVALID_INFO_CLASS;
583                 }
584
585                 break;
586         default:
587                 return NT_STATUS_INVALID_PARAMETER;
588         }
589
590         return NT_STATUS_OK;
591 }
592
593 /*
594   netr_LogonSamLogon_base
595
596   This version of the function allows other wrappers to say 'do not check the credentials'
597
598   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
599 */
600 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
601                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
602 {
603         struct auth_context *auth_context;
604         struct auth_usersupplied_info *user_info;
605         struct auth_user_info_dc *user_info_dc;
606         NTSTATUS nt_status;
607         static const char zeros[16];
608         struct netr_SamBaseInfo *sam;
609         struct netr_SamInfo2 *sam2;
610         struct netr_SamInfo3 *sam3;
611         struct netr_SamInfo6 *sam6;
612
613         *r->out.authoritative = 1;
614
615         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
616         NT_STATUS_HAVE_NO_MEMORY(user_info);
617
618         switch (r->in.logon_level) {
619         case NetlogonInteractiveInformation:
620         case NetlogonServiceInformation:
621         case NetlogonInteractiveTransitiveInformation:
622         case NetlogonServiceTransitiveInformation:
623                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
624                         netlogon_creds_arcfour_crypt(creds,
625                                             r->in.logon->password->lmpassword.hash,
626                                             sizeof(r->in.logon->password->lmpassword.hash));
627                         netlogon_creds_arcfour_crypt(creds,
628                                             r->in.logon->password->ntpassword.hash,
629                                             sizeof(r->in.logon->password->ntpassword.hash));
630                 } else {
631                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
632                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
633                 }
634
635                 /* TODO: we need to deny anonymous access here */
636                 nt_status = auth_context_create(mem_ctx,
637                                                 dce_call->event_ctx, dce_call->msg_ctx,
638                                                 dce_call->conn->dce_ctx->lp_ctx,
639                                                 &auth_context);
640                 NT_STATUS_NOT_OK_RETURN(nt_status);
641
642                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
643                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
644                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
645                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
646
647                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
648                 user_info->password_state = AUTH_PASSWORD_HASH;
649
650                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
651                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
652                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
653
654                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
655                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
656                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
657
658                 break;
659         case NetlogonNetworkInformation:
660         case NetlogonNetworkTransitiveInformation:
661
662                 /* TODO: we need to deny anonymous access here */
663                 nt_status = auth_context_create(mem_ctx,
664                                                 dce_call->event_ctx, dce_call->msg_ctx,
665                                                 dce_call->conn->dce_ctx->lp_ctx,
666                                                 &auth_context);
667                 NT_STATUS_NOT_OK_RETURN(nt_status);
668
669                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
670                 NT_STATUS_NOT_OK_RETURN(nt_status);
671
672                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
673                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
674                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
675                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
676
677                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
678                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
679                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
680
681                 break;
682
683
684         case NetlogonGenericInformation:
685         {
686                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
687                         netlogon_creds_arcfour_crypt(creds,
688                                             r->in.logon->generic->data, r->in.logon->generic->length);
689                 } else {
690                         /* Using DES to verify kerberos tickets makes no sense */
691                         return NT_STATUS_INVALID_PARAMETER;
692                 }
693
694                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
695                         NTSTATUS status;
696                         struct dcerpc_binding_handle *irpc_handle;
697                         struct kdc_check_generic_kerberos check;
698                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
699                         NT_STATUS_HAVE_NO_MEMORY(generic);
700                         *r->out.authoritative = 1;
701
702                         /* TODO: Describe and deal with these flags */
703                         *r->out.flags = 0;
704
705                         r->out.validation->generic = generic;
706
707                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
708                                                                   dce_call->msg_ctx,
709                                                                   "kdc_server",
710                                                                   &ndr_table_irpc);
711                         if (irpc_handle == NULL) {
712                                 return NT_STATUS_NO_LOGON_SERVERS;
713                         }
714
715                         check.in.generic_request =
716                                 data_blob_const(r->in.logon->generic->data,
717                                                 r->in.logon->generic->length);
718
719                         status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
720                                                                      mem_ctx,
721                                                                      &check);
722                         if (!NT_STATUS_IS_OK(status)) {
723                                 return status;
724                         }
725                         generic->length = check.out.generic_reply.length;
726                         generic->data = check.out.generic_reply.data;
727                         return NT_STATUS_OK;
728                 }
729
730                 /* Until we get an implemetnation of these other packages */
731                 return NT_STATUS_INVALID_PARAMETER;
732         }
733         default:
734                 return NT_STATUS_INVALID_PARAMETER;
735         }
736
737         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
738         /* TODO: set *r->out.authoritative = 0 on specific errors */
739         NT_STATUS_NOT_OK_RETURN(nt_status);
740
741         switch (r->in.validation_level) {
742         case 2:
743                 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
744                 NT_STATUS_NOT_OK_RETURN(nt_status);
745
746                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
747                 NT_STATUS_HAVE_NO_MEMORY(sam2);
748                 sam2->base = *sam;
749
750                 /* And put into the talloc tree */
751                 talloc_steal(sam2, sam);
752                 r->out.validation->sam2 = sam2;
753
754                 sam = &sam2->base;
755                 break;
756
757         case 3:
758                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
759                                                               user_info_dc,
760                                                               &sam3);
761                 NT_STATUS_NOT_OK_RETURN(nt_status);
762
763                 r->out.validation->sam3 = sam3;
764
765                 sam = &sam3->base;
766                 break;
767
768         case 6:
769                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
770                                                            user_info_dc,
771                                                            &sam3);
772                 NT_STATUS_NOT_OK_RETURN(nt_status);
773
774                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
775                 NT_STATUS_HAVE_NO_MEMORY(sam6);
776                 sam6->base = sam3->base;
777                 sam = &sam6->base;
778                 sam6->sidcount = sam3->sidcount;
779                 sam6->sids = sam3->sids;
780
781                 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
782                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
783                                                          sam->account_name.string, sam6->dns_domainname.string);
784                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
785                 /* And put into the talloc tree */
786                 talloc_steal(sam6, sam3);
787
788                 r->out.validation->sam6 = sam6;
789                 break;
790
791         default:
792                 return NT_STATUS_INVALID_INFO_CLASS;
793         }
794
795         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
796         /* It appears that level 6 is not individually encrypted */
797         if ((r->in.validation_level != 6) &&
798             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
799                 /* This key is sent unencrypted without the ARCFOUR flag set */
800                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
801                         netlogon_creds_arcfour_crypt(creds,
802                                             sam->key.key,
803                                             sizeof(sam->key.key));
804                 }
805         }
806
807         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
808         /* It appears that level 6 is not individually encrypted */
809         if ((r->in.validation_level != 6) &&
810             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
811                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
812                         netlogon_creds_arcfour_crypt(creds,
813                                             sam->LMSessKey.key,
814                                             sizeof(sam->LMSessKey.key));
815                 } else {
816                         netlogon_creds_des_encrypt_LMKey(creds,
817                                                 &sam->LMSessKey);
818                 }
819         }
820
821         /* TODO: Describe and deal with these flags */
822         *r->out.flags = 0;
823
824         return NT_STATUS_OK;
825 }
826
827 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
828                                      struct netr_LogonSamLogonEx *r)
829 {
830         NTSTATUS nt_status;
831         struct netlogon_creds_CredentialState *creds;
832
833         *r->out.authoritative = 1;
834
835         nt_status = dcesrv_netr_LogonSamLogon_check(r);
836         if (!NT_STATUS_IS_OK(nt_status)) {
837                 return nt_status;
838         }
839
840         nt_status = schannel_get_creds_state(mem_ctx,
841                                              lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
842                                              r->in.computer_name, &creds);
843         if (!NT_STATUS_IS_OK(nt_status)) {
844                 return nt_status;
845         }
846
847         if (!dce_call->conn->auth_state.auth_info ||
848             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
849                 return NT_STATUS_ACCESS_DENIED;
850         }
851         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
852 }
853
854 /*
855   netr_LogonSamLogonWithFlags
856
857 */
858 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
859                                             struct netr_LogonSamLogonWithFlags *r)
860 {
861         NTSTATUS nt_status;
862         struct netlogon_creds_CredentialState *creds;
863         struct netr_LogonSamLogonEx r2;
864
865         struct netr_Authenticator *return_authenticator;
866
867         ZERO_STRUCT(r2);
868
869         r2.in.server_name       = r->in.server_name;
870         r2.in.computer_name     = r->in.computer_name;
871         r2.in.logon_level       = r->in.logon_level;
872         r2.in.logon             = r->in.logon;
873         r2.in.validation_level  = r->in.validation_level;
874         r2.in.flags             = r->in.flags;
875         r2.out.validation       = r->out.validation;
876         r2.out.authoritative    = r->out.authoritative;
877         r2.out.flags            = r->out.flags;
878
879         *r->out.authoritative = 1;
880
881         nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
882         if (!NT_STATUS_IS_OK(nt_status)) {
883                 return nt_status;
884         }
885
886         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
887         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
888
889         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
890                                                         mem_ctx,
891                                                         r->in.computer_name,
892                                                         r->in.credential, return_authenticator,
893                                                         &creds);
894         NT_STATUS_NOT_OK_RETURN(nt_status);
895
896         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
897
898         r->out.return_authenticator     = return_authenticator;
899
900         return nt_status;
901 }
902
903 /*
904   netr_LogonSamLogon
905 */
906 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
907                                    struct netr_LogonSamLogon *r)
908 {
909         struct netr_LogonSamLogonWithFlags r2;
910         uint32_t flags = 0;
911         NTSTATUS status;
912
913         ZERO_STRUCT(r2);
914
915         r2.in.server_name = r->in.server_name;
916         r2.in.computer_name = r->in.computer_name;
917         r2.in.credential  = r->in.credential;
918         r2.in.return_authenticator = r->in.return_authenticator;
919         r2.in.logon_level = r->in.logon_level;
920         r2.in.logon = r->in.logon;
921         r2.in.validation_level = r->in.validation_level;
922         r2.in.flags = &flags;
923         r2.out.validation = r->out.validation;
924         r2.out.authoritative = r->out.authoritative;
925         r2.out.flags = &flags;
926
927         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
928
929         r->out.return_authenticator = r2.out.return_authenticator;
930
931         return status;
932 }
933
934
935 /*
936   netr_LogonSamLogoff
937 */
938 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
939                        struct netr_LogonSamLogoff *r)
940 {
941         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
942 }
943
944
945
946 /*
947   netr_DatabaseDeltas
948 */
949 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
950                        struct netr_DatabaseDeltas *r)
951 {
952         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
953 }
954
955
956 /*
957   netr_DatabaseSync2
958 */
959 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
960                        struct netr_DatabaseSync2 *r)
961 {
962         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
963         return NT_STATUS_NOT_IMPLEMENTED;
964 }
965
966
967 /*
968   netr_DatabaseSync
969 */
970 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
971                        struct netr_DatabaseSync *r)
972 {
973         struct netr_DatabaseSync2 r2;
974         NTSTATUS status;
975
976         ZERO_STRUCT(r2);
977
978         r2.in.logon_server = r->in.logon_server;
979         r2.in.computername = r->in.computername;
980         r2.in.credential = r->in.credential;
981         r2.in.database_id = r->in.database_id;
982         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
983         r2.in.sync_context = r->in.sync_context;
984         r2.out.sync_context = r->out.sync_context;
985         r2.out.delta_enum_array = r->out.delta_enum_array;
986         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
987
988         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
989
990         return status;
991 }
992
993
994 /*
995   netr_AccountDeltas
996 */
997 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
998                        struct netr_AccountDeltas *r)
999 {
1000         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1001         return NT_STATUS_NOT_IMPLEMENTED;
1002 }
1003
1004
1005 /*
1006   netr_AccountSync
1007 */
1008 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1009                        struct netr_AccountSync *r)
1010 {
1011         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1012         return NT_STATUS_NOT_IMPLEMENTED;
1013 }
1014
1015
1016 /*
1017   netr_GetDcName
1018 */
1019 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1020                        struct netr_GetDcName *r)
1021 {
1022         const char * const attrs[] = { NULL };
1023         struct ldb_context *sam_ctx;
1024         struct ldb_message **res;
1025         struct ldb_dn *domain_dn;
1026         int ret;
1027         const char *dcname;
1028
1029         /*
1030          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1031          * that the domainname needs to be a valid netbios domain
1032          * name, if it is not NULL.
1033          */
1034         if (r->in.domainname) {
1035                 const char *dot = strchr(r->in.domainname, '.');
1036                 size_t len = strlen(r->in.domainname);
1037
1038                 if (dot || len > 15) {
1039                         return WERR_DCNOTFOUND;
1040                 }
1041
1042                 /*
1043                  * TODO: Should we also varify that only valid
1044                  *       netbios name characters are used?
1045                  */
1046         }
1047
1048         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1049                                 dce_call->conn->dce_ctx->lp_ctx,
1050                                 dce_call->conn->auth_state.session_info, 0);
1051         if (sam_ctx == NULL) {
1052                 return WERR_DS_UNAVAILABLE;
1053         }
1054
1055         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1056                                        r->in.domainname);
1057         if (domain_dn == NULL) {
1058                 return WERR_DS_UNAVAILABLE;
1059         }
1060
1061         ret = gendb_search_dn(sam_ctx, mem_ctx,
1062                               domain_dn, &res, attrs);
1063         if (ret != 1) {
1064                 return WERR_NO_SUCH_DOMAIN;
1065         }
1066
1067         /* TODO: - return real IP address
1068          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1069          */
1070         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1071                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1072         W_ERROR_HAVE_NO_MEMORY(dcname);
1073
1074         *r->out.dcname = dcname;
1075         return WERR_OK;
1076 }
1077
1078
1079 /*
1080   netr_LogonControl2Ex
1081 */
1082 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1083                        struct netr_LogonControl2Ex *r)
1084 {
1085         return WERR_NOT_SUPPORTED;
1086 }
1087
1088
1089 /*
1090   netr_LogonControl
1091 */
1092 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1093                        struct netr_LogonControl *r)
1094 {
1095         struct netr_LogonControl2Ex r2;
1096         WERROR werr;
1097
1098         if (r->in.level == 0x00000001) {
1099                 ZERO_STRUCT(r2);
1100
1101                 r2.in.logon_server = r->in.logon_server;
1102                 r2.in.function_code = r->in.function_code;
1103                 r2.in.level = r->in.level;
1104                 r2.in.data = NULL;
1105                 r2.out.query = r->out.query;
1106
1107                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1108         } else if (r->in.level == 0x00000002) {
1109                 werr = WERR_NOT_SUPPORTED;
1110         } else {
1111                 werr = WERR_UNKNOWN_LEVEL;
1112         }
1113
1114         return werr;
1115 }
1116
1117
1118 /*
1119   netr_LogonControl2
1120 */
1121 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1122                        struct netr_LogonControl2 *r)
1123 {
1124         struct netr_LogonControl2Ex r2;
1125         WERROR werr;
1126
1127         ZERO_STRUCT(r2);
1128
1129         r2.in.logon_server = r->in.logon_server;
1130         r2.in.function_code = r->in.function_code;
1131         r2.in.level = r->in.level;
1132         r2.in.data = r->in.data;
1133         r2.out.query = r->out.query;
1134
1135         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1136
1137         return werr;
1138 }
1139
1140 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1141                                          struct ldb_context *sam_ctx,
1142                                          struct netr_DomainTrustList *trusts,
1143                                          uint32_t trust_flags);
1144
1145 /*
1146   netr_GetAnyDCName
1147 */
1148 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1149                        struct netr_GetAnyDCName *r)
1150 {
1151         struct netr_DomainTrustList *trusts;
1152         struct ldb_context *sam_ctx;
1153         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1154         uint32_t i;
1155         WERROR werr;
1156
1157         *r->out.dcname = NULL;
1158
1159         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1160                 /* if the domainname parameter wasn't set assume our domain */
1161                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1162         }
1163
1164         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1165                                 dce_call->conn->auth_state.session_info, 0);
1166         if (sam_ctx == NULL) {
1167                 return WERR_DS_UNAVAILABLE;
1168         }
1169
1170         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1171                 /* well we asked for a DC of our own domain */
1172                 if (samdb_is_pdc(sam_ctx)) {
1173                         /* we are the PDC of the specified domain */
1174                         return WERR_NO_SUCH_DOMAIN;
1175                 }
1176
1177                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1178                                                 lpcfg_netbios_name(lp_ctx));
1179                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1180
1181                 return WERR_OK;
1182         }
1183
1184         /* Okay, now we have to consider the trusted domains */
1185
1186         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1187         W_ERROR_HAVE_NO_MEMORY(trusts);
1188
1189         trusts->count = 0;
1190
1191         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1192                                           NETR_TRUST_FLAG_INBOUND
1193                                           | NETR_TRUST_FLAG_OUTBOUND);
1194         W_ERROR_NOT_OK_RETURN(werr);
1195
1196         for (i = 0; i < trusts->count; i++) {
1197                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1198                         /* FIXME: Here we need to find a DC for the specified
1199                          * trusted domain. */
1200
1201                         /* return WERR_OK; */
1202                         return WERR_NO_SUCH_DOMAIN;
1203                 }
1204         }
1205
1206         return WERR_NO_SUCH_DOMAIN;
1207 }
1208
1209
1210 /*
1211   netr_DatabaseRedo
1212 */
1213 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1214                        struct netr_DatabaseRedo *r)
1215 {
1216         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1217 }
1218
1219
1220 /*
1221   netr_NetrEnumerateTrustedDomains
1222 */
1223 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1224                        struct netr_NetrEnumerateTrustedDomains *r)
1225 {
1226         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1227 }
1228
1229
1230 /*
1231   netr_LogonGetCapabilities
1232 */
1233 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1234                        struct netr_LogonGetCapabilities *r)
1235 {
1236         /* we don't support AES yet */
1237         return NT_STATUS_NOT_IMPLEMENTED;
1238 }
1239
1240
1241 /*
1242   netr_NETRLOGONSETSERVICEBITS
1243 */
1244 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1245                        struct netr_NETRLOGONSETSERVICEBITS *r)
1246 {
1247         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1248 }
1249
1250
1251 /*
1252   netr_LogonGetTrustRid
1253 */
1254 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1255                        struct netr_LogonGetTrustRid *r)
1256 {
1257         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1258 }
1259
1260
1261 /*
1262   netr_NETRLOGONCOMPUTESERVERDIGEST
1263 */
1264 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1265                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1266 {
1267         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1268 }
1269
1270
1271 /*
1272   netr_NETRLOGONCOMPUTECLIENTDIGEST
1273 */
1274 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1275                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1276 {
1277         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1278 }
1279
1280
1281
1282 /*
1283   netr_DsRGetSiteName
1284 */
1285 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1286                                   struct netr_DsRGetSiteName *r)
1287 {
1288         struct ldb_context *sam_ctx;
1289         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1290
1291         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1292                                 dce_call->conn->auth_state.session_info, 0);
1293         if (sam_ctx == NULL) {
1294                 return WERR_DS_UNAVAILABLE;
1295         }
1296
1297         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1298         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1299
1300         return WERR_OK;
1301 }
1302
1303
1304 /*
1305   fill in a netr_OneDomainInfo from a ldb search result
1306 */
1307 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1308                                      struct loadparm_context *lp_ctx,
1309                                      struct ldb_context *sam_ctx,
1310                                      struct ldb_message *res,
1311                                      struct netr_OneDomainInfo *info,
1312                                      bool is_local, bool is_trust_list)
1313 {
1314         ZERO_STRUCTP(info);
1315
1316         if (is_trust_list) {
1317                 /* w2k8 only fills this on trusted domains */
1318                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1319                 info->trust_extension.length = 16;
1320                 info->trust_extension.info->flags =
1321                         NETR_TRUST_FLAG_TREEROOT |
1322                         NETR_TRUST_FLAG_IN_FOREST |
1323                         NETR_TRUST_FLAG_PRIMARY |
1324                         NETR_TRUST_FLAG_NATIVE;
1325
1326                 info->trust_extension.info->parent_index = 0; /* should be index into array
1327                                                                  of parent */
1328                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1329                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1330         }
1331
1332         if (is_trust_list) {
1333                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1334                 info->dns_forestname.string = NULL;
1335         } else {
1336                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1337                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1338                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1339                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1340         }
1341
1342         if (is_local) {
1343                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1344                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1345                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1346                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1347         } else {
1348                 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1349                 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1350                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1351                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1352         }
1353         if (!is_trust_list) {
1354                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1355         }
1356
1357         return NT_STATUS_OK;
1358 }
1359
1360 /*
1361   netr_LogonGetDomainInfo
1362   this is called as part of the ADS domain logon procedure.
1363
1364   It has an important role in convaying details about the client, such
1365   as Operating System, Version, Service Pack etc.
1366 */
1367 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1368         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1369 {
1370         struct netlogon_creds_CredentialState *creds;
1371         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1372                 "securityIdentifier", "trustPartner", NULL };
1373         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1374                 "msDS-SupportedEncryptionTypes", NULL };
1375         const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1376         struct ldb_context *sam_ctx;
1377         struct ldb_message **res1, **res2, **res3, *new_msg;
1378         struct ldb_dn *workstation_dn;
1379         struct netr_DomainInformation *domain_info;
1380         struct netr_LsaPolicyInformation *lsa_policy_info;
1381         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1382         bool update_dns_hostname = true;
1383         int ret, ret3, i;
1384         NTSTATUS status;
1385
1386         status = dcesrv_netr_creds_server_step_check(dce_call,
1387                                                      mem_ctx,
1388                                                      r->in.computer_name,
1389                                                      r->in.credential,
1390                                                      r->out.return_authenticator,
1391                                                      &creds);
1392         if (!NT_STATUS_IS_OK(status)) {
1393                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1394         }
1395         NT_STATUS_NOT_OK_RETURN(status);
1396
1397         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1398                                 dce_call->conn->dce_ctx->lp_ctx,
1399                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1400         if (sam_ctx == NULL) {
1401                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1402         }
1403
1404         switch (r->in.level) {
1405         case 1: /* Domain information */
1406
1407                 if (r->in.query->workstation_info == NULL) {
1408                         return NT_STATUS_INVALID_PARAMETER;
1409                 }
1410
1411                 /* Prepares the workstation DN */
1412                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1413                                                 dom_sid_string(mem_ctx, creds->sid));
1414                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1415
1416                 /* Lookup for attributes in workstation object */
1417                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1418                                       attrs2);
1419                 if (ret != 1) {
1420                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1421                 }
1422
1423                 /* Gets the sam account name which is checked against the DNS
1424                  * hostname parameter. */
1425                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1426                                                                "sAMAccountName",
1427                                                                NULL);
1428                 if (sam_account_name == NULL) {
1429                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1430                 }
1431
1432                 /*
1433                  * Checks that the sam account name without a possible "$"
1434                  * matches as prefix with the DNS hostname in the workstation
1435                  * info structure.
1436                  */
1437                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1438                                          strcspn(sam_account_name, "$"));
1439                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1440                 if (r->in.query->workstation_info->dns_hostname != NULL) {
1441                         prefix2 = talloc_strndup(mem_ctx,
1442                                                  r->in.query->workstation_info->dns_hostname,
1443                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
1444                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
1445
1446                         if (strcasecmp(prefix1, prefix2) != 0) {
1447                                 update_dns_hostname = false;
1448                         }
1449                 } else {
1450                         update_dns_hostname = false;
1451                 }
1452
1453                 /* Gets the old DNS hostname */
1454                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1455                                                                "dNSHostName",
1456                                                                NULL);
1457
1458                 /*
1459                  * Updates the DNS hostname when the client wishes that the
1460                  * server should handle this for him
1461                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1462                  * obviously only checked when we do already have a
1463                  * "dNSHostName".
1464                  * See MS-NRPC section 3.5.4.3.9
1465                  */
1466                 if ((old_dns_hostname != NULL) &&
1467                     (r->in.query->workstation_info->workstation_flags
1468                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1469                         update_dns_hostname = false;
1470                 }
1471
1472                 /* Gets host information and put them into our directory */
1473
1474                 new_msg = ldb_msg_new(mem_ctx);
1475                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1476
1477                 new_msg->dn = workstation_dn;
1478
1479                 /* Sets the OS name */
1480
1481                 if (r->in.query->workstation_info->os_name.string == NULL) {
1482                         return NT_STATUS_INVALID_PARAMETER;
1483                 }
1484
1485                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1486                                          r->in.query->workstation_info->os_name.string);
1487                 if (ret != LDB_SUCCESS) {
1488                         return NT_STATUS_NO_MEMORY;
1489                 }
1490
1491                 /*
1492                  * Sets information from "os_version". On an empty structure
1493                  * the values are cleared.
1494                  */
1495                 if (r->in.query->workstation_info->os_version.os != NULL) {
1496                         struct netr_OsVersionInfoEx *os_version;
1497                         const char *os_version_str;
1498
1499                         os_version = &r->in.query->workstation_info->os_version.os->os;
1500
1501                         if (os_version->CSDVersion == NULL) {
1502                                 return NT_STATUS_INVALID_PARAMETER;
1503                         }
1504
1505                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1506                                                          os_version->MajorVersion,
1507                                                          os_version->MinorVersion,
1508                                                          os_version->BuildNumber);
1509                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1510
1511                         ret = ldb_msg_add_string(new_msg,
1512                                                  "operatingSystemServicePack",
1513                                                  os_version->CSDVersion);
1514                         if (ret != LDB_SUCCESS) {
1515                                 return NT_STATUS_NO_MEMORY;
1516                         }
1517
1518                         ret = ldb_msg_add_string(new_msg,
1519                                                  "operatingSystemVersion",
1520                                                  os_version_str);
1521                         if (ret != LDB_SUCCESS) {
1522                                 return NT_STATUS_NO_MEMORY;
1523                         }
1524                 } else {
1525                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1526                                                    "operatingSystemServicePack");
1527                         if (ret != LDB_SUCCESS) {
1528                                 return NT_STATUS_NO_MEMORY;
1529                         }
1530
1531                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1532                                                    "operatingSystemVersion");
1533                         if (ret != LDB_SUCCESS) {
1534                                 return NT_STATUS_NO_MEMORY;
1535                         }
1536                 }
1537
1538                 /*
1539                  * If the boolean "update_dns_hostname" remained true, then we
1540                  * are fine to start the update.
1541                  */
1542                 if (update_dns_hostname) {
1543                         ret = ldb_msg_add_string(new_msg,
1544                                                  "dNSHostname",
1545                                                  r->in.query->workstation_info->dns_hostname);
1546                         if (ret != LDB_SUCCESS) {
1547                                 return NT_STATUS_NO_MEMORY;
1548                         }
1549
1550                         /* This manual "servicePrincipalName" generation is
1551                          * still needed! Since the update in the samldb LDB
1552                          * module does only work if the entries already exist
1553                          * which isn't always the case. */
1554                         ret = ldb_msg_add_string(new_msg,
1555                                                  "servicePrincipalName",
1556                                                  talloc_asprintf(new_msg, "HOST/%s",
1557                                                  r->in.computer_name));
1558                         if (ret != LDB_SUCCESS) {
1559                                 return NT_STATUS_NO_MEMORY;
1560                         }
1561
1562                         ret = ldb_msg_add_string(new_msg,
1563                                                  "servicePrincipalName",
1564                                                  talloc_asprintf(new_msg, "HOST/%s",
1565                                                  r->in.query->workstation_info->dns_hostname));
1566                         if (ret != LDB_SUCCESS) {
1567                                 return NT_STATUS_NO_MEMORY;
1568                         }
1569                 }
1570
1571                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1572                         DEBUG(3,("Impossible to update samdb: %s\n",
1573                                 ldb_errstring(sam_ctx)));
1574                 }
1575
1576                 talloc_free(new_msg);
1577
1578                 /* Writes back the domain information */
1579
1580                 /* We need to do two searches. The first will pull our primary
1581                    domain and the second will pull any trusted domains. Our
1582                    primary domain is also a "trusted" domain, so we need to
1583                    put the primary domain into the lists of returned trusts as
1584                    well. */
1585                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1586                         &res2, attrs);
1587                 if (ret != 1) {
1588                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1589                 }
1590
1591                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1592                         "(objectClass=trustedDomain)");
1593                 if (ret3 == -1) {
1594                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1595                 }
1596
1597                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1598                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1599
1600                 ZERO_STRUCTP(domain_info);
1601
1602                 /* Informations about the local and trusted domains */
1603
1604                 status = fill_one_domain_info(mem_ctx,
1605                         dce_call->conn->dce_ctx->lp_ctx,
1606                         sam_ctx, res2[0], &domain_info->primary_domain,
1607                         true, false);
1608                 NT_STATUS_NOT_OK_RETURN(status);
1609
1610                 domain_info->trusted_domain_count = ret3 + 1;
1611                 domain_info->trusted_domains = talloc_array(mem_ctx,
1612                         struct netr_OneDomainInfo,
1613                         domain_info->trusted_domain_count);
1614                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1615
1616                 for (i=0;i<ret3;i++) {
1617                         status = fill_one_domain_info(mem_ctx,
1618                                 dce_call->conn->dce_ctx->lp_ctx,
1619                                 sam_ctx, res3[i],
1620                                 &domain_info->trusted_domains[i],
1621                                 false, true);
1622                         NT_STATUS_NOT_OK_RETURN(status);
1623                 }
1624
1625                 status = fill_one_domain_info(mem_ctx,
1626                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1627                         &domain_info->trusted_domains[i], true, true);
1628                 NT_STATUS_NOT_OK_RETURN(status);
1629
1630                 /* Sets the supported encryption types */
1631                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1632                         "msDS-SupportedEncryptionTypes",
1633                         default_supported_enc_types);
1634
1635                 /* Other host domain information */
1636
1637                 lsa_policy_info = talloc(mem_ctx,
1638                         struct netr_LsaPolicyInformation);
1639                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1640                 ZERO_STRUCTP(lsa_policy_info);
1641
1642                 domain_info->lsa_policy = *lsa_policy_info;
1643
1644                 /* The DNS hostname is only returned back when there is a chance
1645                  * for a change. */
1646                 if ((r->in.query->workstation_info->workstation_flags
1647                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1648                         domain_info->dns_hostname.string = old_dns_hostname;
1649                 } else {
1650                         domain_info->dns_hostname.string = NULL;
1651                 }
1652
1653                 domain_info->workstation_flags =
1654                         r->in.query->workstation_info->workstation_flags;
1655
1656                 r->out.info->domain_info = domain_info;
1657         break;
1658         case 2: /* LSA policy information - not used at the moment */
1659                 lsa_policy_info = talloc(mem_ctx,
1660                         struct netr_LsaPolicyInformation);
1661                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1662                 ZERO_STRUCTP(lsa_policy_info);
1663
1664                 r->out.info->lsa_policy_info = lsa_policy_info;
1665         break;
1666         default:
1667                 return NT_STATUS_INVALID_LEVEL;
1668         break;
1669         }
1670
1671         return NT_STATUS_OK;
1672 }
1673
1674
1675 /*
1676   netr_ServerPasswordGet
1677 */
1678 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1679                        struct netr_ServerPasswordGet *r)
1680 {
1681         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1682 }
1683
1684
1685 /*
1686   netr_NETRLOGONSENDTOSAM
1687 */
1688 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1689                        struct netr_NETRLOGONSENDTOSAM *r)
1690 {
1691         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1692 }
1693
1694
1695 /*
1696   netr_DsRGetDCNameEx2
1697 */
1698 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1699                                           TALLOC_CTX *mem_ctx,
1700                                           struct netr_DsRGetDCNameEx2 *r)
1701 {
1702         struct ldb_context *sam_ctx;
1703         struct netr_DsRGetDCNameInfo *info;
1704         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1705         const struct tsocket_address *remote_address;
1706         char *addr = NULL;
1707         const char *server_site_name;
1708         char *guid_str;
1709         struct netlogon_samlogon_response response;
1710         NTSTATUS status;
1711         const char *dc_name = NULL;
1712         const char *domain_name = NULL;
1713
1714         ZERO_STRUCTP(r->out.info);
1715
1716         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1717                                 dce_call->conn->auth_state.session_info, 0);
1718         if (sam_ctx == NULL) {
1719                 return WERR_DS_UNAVAILABLE;
1720         }
1721
1722         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1723         if (tsocket_address_is_inet(remote_address, "ip")) {
1724                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1725                 W_ERROR_HAVE_NO_MEMORY(addr);
1726         }
1727
1728         /* "server_unc" is ignored by w2k3 */
1729
1730         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1731                 return WERR_INVALID_FLAGS;
1732         }
1733
1734         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1735             r->in.flags & DS_PDC_REQUIRED &&
1736             r->in.flags & DS_KDC_REQUIRED) {
1737                 return WERR_INVALID_FLAGS;
1738         }
1739         if (r->in.flags & DS_IS_FLAT_NAME &&
1740             r->in.flags & DS_IS_DNS_NAME) {
1741                 return WERR_INVALID_FLAGS;
1742         }
1743         if (r->in.flags & DS_RETURN_DNS_NAME &&
1744             r->in.flags & DS_RETURN_FLAT_NAME) {
1745                 return WERR_INVALID_FLAGS;
1746         }
1747         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1748             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1749                 return WERR_INVALID_FLAGS;
1750         }
1751
1752         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1753             r->in.flags &
1754             (DS_DIRECTORY_SERVICE_REQUIRED |
1755              DS_DIRECTORY_SERVICE_PREFERRED |
1756              DS_GC_SERVER_REQUIRED |
1757              DS_PDC_REQUIRED |
1758              DS_KDC_REQUIRED)) {
1759                 return WERR_INVALID_FLAGS;
1760         }
1761
1762         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1763             r->in.site_name) {
1764                 return WERR_INVALID_FLAGS;
1765         }
1766
1767         /* Proof server site parameter "site_name" if it was specified */
1768         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1769         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1770         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1771                                                      server_site_name) != 0)) {
1772                 return WERR_NO_SUCH_DOMAIN;
1773         }
1774
1775         guid_str = r->in.domain_guid != NULL ?
1776                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1777
1778         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1779                                                  r->in.domain_name,
1780                                                  r->in.domain_name,
1781                                                  NULL, guid_str,
1782                                                  r->in.client_account,
1783                                                  r->in.mask, addr,
1784                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1785                                                  lp_ctx, &response, true);
1786         if (!NT_STATUS_IS_OK(status)) {
1787                 return ntstatus_to_werror(status);
1788         }
1789
1790         if (r->in.flags & DS_RETURN_DNS_NAME) {
1791                 dc_name = response.data.nt5_ex.pdc_dns_name;
1792                 domain_name = response.data.nt5_ex.dns_domain;
1793         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1794                 dc_name = response.data.nt5_ex.pdc_name;
1795                 domain_name = response.data.nt5_ex.domain_name;
1796         } else {
1797
1798                 /*
1799                  * TODO: autodetect what we need to return
1800                  * based on the given arguments
1801                  */
1802                 dc_name = response.data.nt5_ex.pdc_name;
1803                 domain_name = response.data.nt5_ex.domain_name;
1804         }
1805
1806         if (!dc_name || !dc_name[0]) {
1807                 return WERR_NO_SUCH_DOMAIN;
1808         }
1809
1810         if (!domain_name || !domain_name[0]) {
1811                 return WERR_NO_SUCH_DOMAIN;
1812         }
1813
1814         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1815         W_ERROR_HAVE_NO_MEMORY(info);
1816         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1817         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1818         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1819                                            response.data.nt5_ex.sockaddr.pdc_ip);
1820         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1821         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1822         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1823         info->domain_name      = domain_name;
1824         info->forest_name      = response.data.nt5_ex.forest;
1825         info->dc_flags         = response.data.nt5_ex.server_type;
1826         info->dc_site_name     = response.data.nt5_ex.server_site;
1827         info->client_site_name = response.data.nt5_ex.client_site;
1828
1829         *r->out.info = info;
1830
1831         return WERR_OK;
1832 }
1833
1834 /*
1835   netr_DsRGetDCNameEx
1836 */
1837 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1838                                   struct netr_DsRGetDCNameEx *r)
1839 {
1840         struct netr_DsRGetDCNameEx2 r2;
1841         WERROR werr;
1842
1843         ZERO_STRUCT(r2);
1844
1845         r2.in.server_unc = r->in.server_unc;
1846         r2.in.client_account = NULL;
1847         r2.in.mask = 0;
1848         r2.in.domain_guid = r->in.domain_guid;
1849         r2.in.domain_name = r->in.domain_name;
1850         r2.in.site_name = r->in.site_name;
1851         r2.in.flags = r->in.flags;
1852         r2.out.info = r->out.info;
1853
1854         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1855
1856         return werr;
1857 }
1858
1859 /*
1860   netr_DsRGetDCName
1861 */
1862 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1863                                 struct netr_DsRGetDCName *r)
1864 {
1865         struct netr_DsRGetDCNameEx2 r2;
1866         WERROR werr;
1867
1868         ZERO_STRUCT(r2);
1869
1870         r2.in.server_unc = r->in.server_unc;
1871         r2.in.client_account = NULL;
1872         r2.in.mask = 0;
1873         r2.in.domain_name = r->in.domain_name;
1874         r2.in.domain_guid = r->in.domain_guid;
1875
1876         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1877         r2.in.flags = r->in.flags;
1878         r2.out.info = r->out.info;
1879
1880         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1881
1882         return werr;
1883 }
1884 /*
1885   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1886 */
1887 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1888                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1889 {
1890         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1891 }
1892
1893
1894 /*
1895   netr_NetrEnumerateTrustedDomainsEx
1896 */
1897 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1898                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1899 {
1900         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1901 }
1902
1903
1904 /*
1905   netr_DsRAddressToSitenamesExW
1906 */
1907 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1908                                                    struct netr_DsRAddressToSitenamesExW *r)
1909 {
1910         struct ldb_context *sam_ctx;
1911         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1912         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1913         sa_family_t sin_family;
1914         struct sockaddr_in *addr;
1915 #ifdef HAVE_IPV6
1916         struct sockaddr_in6 *addr6;
1917         char addr_str[INET6_ADDRSTRLEN];
1918 #else
1919         char addr_str[INET_ADDRSTRLEN];
1920 #endif
1921         char *subnet_name;
1922         const char *res;
1923         uint32_t i;
1924
1925         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1926                                 dce_call->conn->auth_state.session_info, 0);
1927         if (sam_ctx == NULL) {
1928                 return WERR_DS_UNAVAILABLE;
1929         }
1930
1931         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1932         W_ERROR_HAVE_NO_MEMORY(ctr);
1933
1934         *r->out.ctr = ctr;
1935
1936         ctr->count = r->in.count;
1937         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1938         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1939         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1940         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1941
1942         for (i=0; i<ctr->count; i++) {
1943                 ctr->sitename[i].string = NULL;
1944                 ctr->subnetname[i].string = NULL;
1945
1946                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1947                         continue;
1948                 }
1949                 /* The first two byte of the buffer are reserved for the
1950                  * "sin_family" but for now only the first one is used. */
1951                 sin_family = r->in.addresses[i].buffer[0];
1952
1953                 switch (sin_family) {
1954                 case AF_INET:
1955                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1956                                 continue;
1957                         }
1958                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1959                         res = inet_ntop(AF_INET, &addr->sin_addr,
1960                                         addr_str, sizeof(addr_str));
1961                         break;
1962 #ifdef HAVE_IPV6
1963                 case AF_INET6:
1964                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1965                                 continue;
1966                         }
1967                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1968                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1969                                         addr_str, sizeof(addr_str));
1970                         break;
1971 #endif
1972                 default:
1973                         continue;
1974                 }
1975
1976                 if (res == NULL) {
1977                         continue;
1978                 }
1979
1980                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
1981                                                                    mem_ctx,
1982                                                                    addr_str,
1983                                                                    &subnet_name);
1984                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1985                 ctr->subnetname[i].string = subnet_name;
1986         }
1987
1988         return WERR_OK;
1989 }
1990
1991
1992 /*
1993   netr_DsRAddressToSitenamesW
1994 */
1995 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1996                        struct netr_DsRAddressToSitenamesW *r)
1997 {
1998         struct netr_DsRAddressToSitenamesExW r2;
1999         struct netr_DsRAddressToSitenamesWCtr *ctr;
2000         uint32_t i;
2001         WERROR werr;
2002
2003         ZERO_STRUCT(r2);
2004
2005         r2.in.server_name = r->in.server_name;
2006         r2.in.count = r->in.count;
2007         r2.in.addresses = r->in.addresses;
2008
2009         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2010         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2011
2012         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2013         W_ERROR_HAVE_NO_MEMORY(ctr);
2014
2015         *r->out.ctr = ctr;
2016
2017         ctr->count = r->in.count;
2018         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2019         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2020
2021         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2022
2023         for (i=0; i<ctr->count; i++) {
2024                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2025         }
2026
2027         return werr;
2028 }
2029
2030
2031 /*
2032   netr_DsrGetDcSiteCoverageW
2033 */
2034 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2035                        struct netr_DsrGetDcSiteCoverageW *r)
2036 {
2037         struct ldb_context *sam_ctx;
2038         struct DcSitesCtr *ctr;
2039         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2040
2041         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2042                                 dce_call->conn->auth_state.session_info, 0);
2043         if (sam_ctx == NULL) {
2044                 return WERR_DS_UNAVAILABLE;
2045         }
2046
2047         ctr = talloc(mem_ctx, struct DcSitesCtr);
2048         W_ERROR_HAVE_NO_MEMORY(ctr);
2049
2050         *r->out.ctr = ctr;
2051
2052         /* For now only return our default site */
2053         ctr->num_sites = 1;
2054         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2055         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2056         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2057         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2058
2059         return WERR_OK;
2060 }
2061
2062
2063 #define GET_CHECK_STR(dest, mem, msg, attr) \
2064 do {\
2065         const char *s; \
2066         s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
2067         if (!s) { \
2068                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
2069                           "without flatname\n", \
2070                           ldb_dn_get_linearized(msg->dn))); \
2071                 continue; \
2072         } \
2073         dest = talloc_strdup(mem, s); \
2074         W_ERROR_HAVE_NO_MEMORY(dest); \
2075 } while(0)
2076
2077
2078 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2079                                          struct ldb_context *sam_ctx,
2080                                          struct netr_DomainTrustList *trusts,
2081                                          uint32_t trust_flags)
2082 {
2083         struct ldb_dn *system_dn;
2084         struct ldb_message **dom_res = NULL;
2085         const char *trust_attrs[] = { "flatname", "trustPartner",
2086                                       "securityIdentifier", "trustDirection",
2087                                       "trustType", "trustAttributes", NULL };
2088         uint32_t n;
2089         int i;
2090         int ret;
2091
2092         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2093                              NETR_TRUST_FLAG_OUTBOUND))) {
2094                 return WERR_INVALID_FLAGS;
2095         }
2096
2097         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2098                                     ldb_get_default_basedn(sam_ctx),
2099                                     "(&(objectClass=container)(cn=System))");
2100         if (!system_dn) {
2101                 return WERR_GENERAL_FAILURE;
2102         }
2103
2104         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2105                            &dom_res, trust_attrs,
2106                            "(objectclass=trustedDomain)");
2107
2108         for (i = 0; i < ret; i++) {
2109                 unsigned int trust_dir;
2110                 uint32_t flags = 0;
2111
2112                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2113                                                       "trustDirection", 0);
2114
2115                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2116                         flags |= NETR_TRUST_FLAG_INBOUND;
2117                 }
2118                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2119                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2120                 }
2121
2122                 if (!(flags & trust_flags)) {
2123                         /* this trust direction was not requested */
2124                         continue;
2125                 }
2126
2127                 n = trusts->count;
2128                 trusts->array = talloc_realloc(trusts, trusts->array,
2129                                                struct netr_DomainTrust,
2130                                                n + 1);
2131                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2132
2133                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2134                               dom_res[i], "flatname");
2135                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2136                               dom_res[i], "trustPartner");
2137
2138                 trusts->array[n].trust_flags = flags;
2139                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2140                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2141                         /* TODO: find if we have parent in the list */
2142                         trusts->array[n].parent_index = 0;
2143                 }
2144
2145                 trusts->array[n].trust_type =
2146                                 ldb_msg_find_attr_as_uint(dom_res[i],
2147                                                   "trustType", 0);
2148                 trusts->array[n].trust_attributes =
2149                                 ldb_msg_find_attr_as_uint(dom_res[i],
2150                                                   "trustAttributes", 0);
2151
2152                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2153                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2154                         struct dom_sid zero_sid;
2155                         ZERO_STRUCT(zero_sid);
2156                         trusts->array[n].sid =
2157                                 dom_sid_dup(trusts, &zero_sid);
2158                 } else {
2159                         trusts->array[n].sid =
2160                                 samdb_result_dom_sid(trusts, dom_res[i],
2161                                                      "securityIdentifier");
2162                 }
2163                 trusts->array[n].guid = GUID_zero();
2164
2165                 trusts->count = n + 1;
2166         }
2167
2168         talloc_free(dom_res);
2169         return WERR_OK;
2170 }
2171
2172 /*
2173   netr_DsrEnumerateDomainTrusts
2174 */
2175 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2176                                                    TALLOC_CTX *mem_ctx,
2177                                                    struct netr_DsrEnumerateDomainTrusts *r)
2178 {
2179         struct netr_DomainTrustList *trusts;
2180         struct ldb_context *sam_ctx;
2181         int ret;
2182         struct ldb_message **dom_res;
2183         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2184         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2185         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2186         const char *p;
2187         WERROR werr;
2188
2189         if (r->in.trust_flags & 0xFFFFFE00) {
2190                 return WERR_INVALID_FLAGS;
2191         }
2192
2193         /* TODO: turn to hard check once we are sure this is 100% correct */
2194         if (!r->in.server_name) {
2195                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2196                           "But received NULL!\n", dnsdomain));
2197         } else {
2198                 p = strchr(r->in.server_name, '.');
2199                 if (!p) {
2200                         DEBUG(3, ("Invalid domain! Expected name in domain "
2201                                   "[%s]. But received [%s]!\n",
2202                                   dnsdomain, r->in.server_name));
2203                         p = r->in.server_name;
2204                 } else {
2205                         p++;
2206                 }
2207                 if (strcasecmp(p, dnsdomain)) {
2208                         DEBUG(3, ("Invalid domain! Expected name in domain "
2209                                   "[%s]. But received [%s]!\n",
2210                                   dnsdomain, r->in.server_name));
2211                 }
2212         }
2213
2214         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2215         W_ERROR_HAVE_NO_MEMORY(trusts);
2216
2217         trusts->count = 0;
2218         r->out.trusts = trusts;
2219
2220         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2221                                 dce_call->conn->auth_state.session_info, 0);
2222         if (sam_ctx == NULL) {
2223                 return WERR_GENERAL_FAILURE;
2224         }
2225
2226         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2227             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2228
2229                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2230                                                   trusts, r->in.trust_flags);
2231                 W_ERROR_NOT_OK_RETURN(werr);
2232         }
2233
2234         /* NOTE: we currently are always the root of the forest */
2235         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2236                 uint32_t n = trusts->count;
2237
2238                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2239                                       &dom_res, dom_attrs);
2240                 if (ret != 1) {
2241                         return WERR_GENERAL_FAILURE;
2242                 }
2243
2244                 trusts->count = n + 1;
2245                 trusts->array = talloc_realloc(trusts, trusts->array,
2246                                                struct netr_DomainTrust,
2247                                                trusts->count);
2248                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2249
2250                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2251                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2252                 trusts->array[n].trust_flags =
2253                         NETR_TRUST_FLAG_NATIVE |
2254                         NETR_TRUST_FLAG_TREEROOT |
2255                         NETR_TRUST_FLAG_IN_FOREST |
2256                         NETR_TRUST_FLAG_PRIMARY;
2257                 /* we are always the root domain for now */
2258                 trusts->array[n].parent_index = 0;
2259                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2260                 trusts->array[n].trust_attributes = 0;
2261                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2262                                                             dom_res[0],
2263                                                             "objectSid");
2264                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2265                                                           "objectGUID");
2266                 talloc_free(dom_res);
2267         }
2268
2269         return WERR_OK;
2270 }
2271
2272
2273 /*
2274   netr_DsrDeregisterDNSHostRecords
2275 */
2276 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2277                        struct netr_DsrDeregisterDNSHostRecords *r)
2278 {
2279         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2280 }
2281
2282
2283 /*
2284   netr_ServerTrustPasswordsGet
2285 */
2286 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2287                        struct netr_ServerTrustPasswordsGet *r)
2288 {
2289         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2290 }
2291
2292
2293 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2294                                       struct ldb_context *sam_ctx,
2295                                       struct loadparm_context *lp_ctx,
2296                                       struct lsa_ForestTrustInformation *info)
2297 {
2298         struct lsa_ForestTrustDomainInfo *domain_info;
2299         struct lsa_ForestTrustRecord *e;
2300         struct ldb_message **dom_res;
2301         const char * const dom_attrs[] = { "objectSid", NULL };
2302         int ret;
2303
2304         /* we need to provide 2 entries:
2305          * 1. the Root Forest name
2306          * 2. the Domain Information
2307          */
2308
2309         info->count = 2;
2310         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2311         W_ERROR_HAVE_NO_MEMORY(info->entries);
2312
2313         /* Forest root info */
2314         e = talloc(info, struct lsa_ForestTrustRecord);
2315         W_ERROR_HAVE_NO_MEMORY(e);
2316
2317         e->flags = 0;
2318         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2319         e->time = 0; /* so far always 0 in trces. */
2320         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2321                                                                        mem_ctx);
2322         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2323
2324         info->entries[0] = e;
2325
2326         /* Domain info */
2327         e = talloc(info, struct lsa_ForestTrustRecord);
2328         W_ERROR_HAVE_NO_MEMORY(e);
2329
2330         /* get our own domain info */
2331         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2332         if (ret != 1) {
2333                 return WERR_GENERAL_FAILURE;
2334         }
2335
2336         /* TODO: check if disabled and set flags accordingly */
2337         e->flags = 0;
2338         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2339         e->time = 0; /* so far always 0 in traces. */
2340
2341         domain_info = &e->forest_trust_data.domain_info;
2342         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2343                                                        "objectSid");
2344         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2345         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2346
2347         info->entries[1] = e;
2348
2349         talloc_free(dom_res);
2350
2351         return WERR_OK;
2352 }
2353
2354 /*
2355   netr_DsRGetForestTrustInformation
2356 */
2357 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2358                                                        TALLOC_CTX *mem_ctx,
2359                                                        struct netr_DsRGetForestTrustInformation *r)
2360 {
2361         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2362         struct lsa_ForestTrustInformation *info, **info_ptr;
2363         struct ldb_context *sam_ctx;
2364         WERROR werr;
2365
2366         if (r->in.flags & 0xFFFFFFFE) {
2367                 return WERR_INVALID_FLAGS;
2368         }
2369
2370         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2371                                 dce_call->conn->auth_state.session_info, 0);
2372         if (sam_ctx == NULL) {
2373                 return WERR_GENERAL_FAILURE;
2374         }
2375
2376         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2377                 if (!samdb_is_pdc(sam_ctx)) {
2378                         return WERR_NERR_NOTPRIMARY;
2379                 }
2380
2381                 if (r->in.trusted_domain_name == NULL) {
2382                         return WERR_INVALID_FLAGS;
2383                 }
2384
2385                 /* TODO: establish an schannel connection with
2386                  * r->in.trusted_domain_name and perform a
2387                  * netr_GetForestTrustInformation call against it */
2388
2389                 /* for now return not implementd */
2390                 return WERR_CALL_NOT_IMPLEMENTED;
2391         }
2392
2393         /* TODO: check r->in.server_name is our name */
2394
2395         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2396         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2397
2398         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2399         W_ERROR_HAVE_NO_MEMORY(info);
2400
2401         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2402         W_ERROR_NOT_OK_RETURN(werr);
2403
2404         *info_ptr = info;
2405         r->out.forest_trust_info = info_ptr;
2406
2407         return WERR_OK;
2408 }
2409
2410
2411 /*
2412   netr_GetForestTrustInformation
2413 */
2414 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2415                                                       TALLOC_CTX *mem_ctx,
2416                                                       struct netr_GetForestTrustInformation *r)
2417 {
2418         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2419         struct netlogon_creds_CredentialState *creds;
2420         struct lsa_ForestTrustInformation *info, **info_ptr;
2421         struct ldb_context *sam_ctx;
2422         NTSTATUS status;
2423         WERROR werr;
2424
2425         status = dcesrv_netr_creds_server_step_check(dce_call,
2426                                                      mem_ctx,
2427                                                      r->in.computer_name,
2428                                                      r->in.credential,
2429                                                      r->out.return_authenticator,
2430                                                      &creds);
2431         if (!NT_STATUS_IS_OK(status)) {
2432                 return status;
2433         }
2434
2435         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2436             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2437                 return NT_STATUS_NOT_IMPLEMENTED;
2438         }
2439
2440         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2441                                 dce_call->conn->auth_state.session_info, 0);
2442         if (sam_ctx == NULL) {
2443                 return NT_STATUS_UNSUCCESSFUL;
2444         }
2445
2446         /* TODO: check r->in.server_name is our name */
2447
2448         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2449         if (!info_ptr) {
2450                 return NT_STATUS_NO_MEMORY;
2451         }
2452         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2453         if (!info) {
2454                 return NT_STATUS_NO_MEMORY;
2455         }
2456
2457         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2458         if (!W_ERROR_IS_OK(werr)) {
2459                 return werror_to_ntstatus(werr);
2460         }
2461
2462         *info_ptr = info;
2463         r->out.forest_trust_info = info_ptr;
2464
2465         return NT_STATUS_OK;
2466 }
2467
2468
2469 /*
2470   netr_ServerGetTrustInfo
2471 */
2472 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2473                        struct netr_ServerGetTrustInfo *r)
2474 {
2475         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2476 }
2477
2478 /*
2479   netr_Unused47
2480 */
2481 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2482                                      struct netr_Unused47 *r)
2483 {
2484         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2485 }
2486
2487
2488 struct netr_dnsupdate_RODC_state {
2489         struct dcesrv_call_state *dce_call;
2490         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2491         struct dnsupdate_RODC *r2;
2492 };
2493
2494 /*
2495   called when the forwarded RODC dns update request is finished
2496  */
2497 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2498 {
2499         struct netr_dnsupdate_RODC_state *st =
2500                 tevent_req_callback_data(subreq,
2501                                          struct netr_dnsupdate_RODC_state);
2502         NTSTATUS status;
2503
2504         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2505         TALLOC_FREE(subreq);
2506         if (!NT_STATUS_IS_OK(status)) {
2507                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2508                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2509         }
2510
2511         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2512
2513         status = dcesrv_reply(st->dce_call);
2514         if (!NT_STATUS_IS_OK(status)) {
2515                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2516         }
2517 }
2518
2519 /*
2520   netr_DsrUpdateReadOnlyServerDnsRecords
2521 */
2522 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2523                                                               TALLOC_CTX *mem_ctx,
2524                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2525 {
2526         struct netlogon_creds_CredentialState *creds;
2527         NTSTATUS nt_status;
2528         struct dcerpc_binding_handle *binding_handle;
2529         struct netr_dnsupdate_RODC_state *st;
2530         struct tevent_req *subreq;
2531
2532         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2533                                                         mem_ctx,
2534                                                         r->in.computer_name,
2535                                                         r->in.credential,
2536                                                         r->out.return_authenticator,
2537                                                         &creds);
2538         NT_STATUS_NOT_OK_RETURN(nt_status);
2539
2540         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2541                 return NT_STATUS_ACCESS_DENIED;
2542         }
2543
2544         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2545         NT_STATUS_HAVE_NO_MEMORY(st);
2546
2547         st->dce_call = dce_call;
2548         st->r = r;
2549         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2550         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2551
2552         st->r2->in.dom_sid = creds->sid;
2553         st->r2->in.site_name = r->in.site_name;
2554         st->r2->in.dns_ttl = r->in.dns_ttl;
2555         st->r2->in.dns_names = r->in.dns_names;
2556         st->r2->out.dns_names = r->out.dns_names;
2557
2558         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2559                                                      "dnsupdate", &ndr_table_irpc);
2560         if (binding_handle == NULL) {
2561                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2562                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2563                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2564         }
2565
2566         /* forward the call */
2567         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2568                                               binding_handle, st->r2);
2569         NT_STATUS_HAVE_NO_MEMORY(subreq);
2570
2571         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2572
2573         /* setup the callback */
2574         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2575
2576         return NT_STATUS_OK;
2577 }
2578
2579
2580 /* include the generated boilerplate */
2581 #include "librpc/gen_ndr/ndr_netlogon_s.c"