s4-auth Rework auth subsystem to remove struct auth_serversupplied_info
[sfrench/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         struct netr_OsVersionInfoEx *os_version;
1382         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1383         bool update_dns_hostname = true;
1384         int ret, ret3, i;
1385         NTSTATUS status;
1386
1387         status = dcesrv_netr_creds_server_step_check(dce_call,
1388                                                      mem_ctx,
1389                                                      r->in.computer_name,
1390                                                      r->in.credential,
1391                                                      r->out.return_authenticator,
1392                                                      &creds);
1393         if (!NT_STATUS_IS_OK(status)) {
1394                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1395         }
1396         NT_STATUS_NOT_OK_RETURN(status);
1397
1398         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1399                                 dce_call->conn->dce_ctx->lp_ctx,
1400                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1401         if (sam_ctx == NULL) {
1402                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1403         }
1404
1405         switch (r->in.level) {
1406         case 1: /* Domain information */
1407
1408                 if (r->in.query->workstation_info == NULL) {
1409                         return NT_STATUS_INVALID_PARAMETER;
1410                 }
1411
1412                 /* Prepares the workstation DN */
1413                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1414                                                 dom_sid_string(mem_ctx, creds->sid));
1415                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1416
1417                 /* Lookup for attributes in workstation object */
1418                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1419                                       attrs2);
1420                 if (ret != 1) {
1421                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1422                 }
1423
1424                 /* Gets the sam account name which is checked against the DNS
1425                  * hostname parameter. */
1426                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1427                                                                "sAMAccountName",
1428                                                                NULL);
1429                 if (sam_account_name == NULL) {
1430                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1431                 }
1432
1433                 /*
1434                  * Checks that the sam account name without a possible "$"
1435                  * matches as prefix with the DNS hostname in the workstation
1436                  * info structure.
1437                  */
1438                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1439                                          strcspn(sam_account_name, "$"));
1440                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1441                 if (r->in.query->workstation_info->dns_hostname != NULL) {
1442                         prefix2 = talloc_strndup(mem_ctx,
1443                                                  r->in.query->workstation_info->dns_hostname,
1444                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
1445                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
1446
1447                         if (strcasecmp(prefix1, prefix2) != 0) {
1448                                 update_dns_hostname = false;
1449                         }
1450                 } else {
1451                         update_dns_hostname = false;
1452                 }
1453
1454                 /* Gets the old DNS hostname */
1455                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1456                                                                "dNSHostName",
1457                                                                NULL);
1458
1459                 /*
1460                  * Updates the DNS hostname when the client wishes that the
1461                  * server should handle this for him
1462                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1463                  * obviously only checked when we do already have a
1464                  * "dNSHostName".
1465                  * See MS-NRPC section 3.5.4.3.9
1466                  */
1467                 if ((old_dns_hostname != NULL) &&
1468                     (r->in.query->workstation_info->workstation_flags
1469                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1470                         update_dns_hostname = false;
1471                 }
1472
1473                 /* Gets host informations and put them into our directory */
1474
1475                 new_msg = ldb_msg_new(mem_ctx);
1476                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1477
1478                 new_msg->dn = workstation_dn;
1479
1480                 /* Sets the OS name */
1481                 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1482                                            "operatingSystem",
1483                                            r->in.query->workstation_info->os_name.string);
1484                 if (ret != LDB_SUCCESS) {
1485                         return NT_STATUS_NO_MEMORY;
1486                 }
1487
1488                 /*
1489                  * Sets informations from "os_version". On an empty structure
1490                  * the values are cleared.
1491                  */
1492                 if (r->in.query->workstation_info->os_version.os != NULL) {
1493                         os_version = &r->in.query->workstation_info->os_version.os->os;
1494
1495                         ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1496                                                    "operatingSystemServicePack",
1497                                                    os_version->CSDVersion);
1498                         if (ret != LDB_SUCCESS) {
1499                                 return NT_STATUS_NO_MEMORY;
1500                         }
1501
1502                         ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1503                                                    "operatingSystemVersion",
1504                                                    talloc_asprintf(mem_ctx,
1505                                                    "%u.%u (%u)",
1506                                                    os_version->MajorVersion,
1507                                                    os_version->MinorVersion,
1508                                                    os_version->BuildNumber));
1509                         if (ret != LDB_SUCCESS) {
1510                                 return NT_STATUS_NO_MEMORY;
1511                         }
1512                 } else {
1513                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1514                                                    "operatingSystemServicePack");
1515                         if (ret != LDB_SUCCESS) {
1516                                 return NT_STATUS_NO_MEMORY;
1517                         }
1518
1519                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1520                                                    "operatingSystemVersion");
1521                         if (ret != LDB_SUCCESS) {
1522                                 return NT_STATUS_NO_MEMORY;
1523                         }
1524                 }
1525
1526                 /*
1527                  * If the boolean "update_dns_hostname" remained true, then we
1528                  * are fine to start the update.
1529                  */
1530                 if (update_dns_hostname) {
1531                         ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1532                                                    "dNSHostname",
1533                                                    r->in.query->workstation_info->dns_hostname);
1534                         if (ret != LDB_SUCCESS) {
1535                                 return NT_STATUS_NO_MEMORY;
1536                         }
1537
1538                         /* This manual "servicePrincipalName" generation is
1539                          * still needed! Since the update in the samldb LDB
1540                          * module does only work if the entries already exist
1541                          * which isn't always the case. */
1542                         ret = ldb_msg_add_string(new_msg,
1543                                                  "servicePrincipalName",
1544                                                  talloc_asprintf(new_msg, "HOST/%s",
1545                                                  r->in.computer_name));
1546                         if (ret != LDB_SUCCESS) {
1547                                 return NT_STATUS_NO_MEMORY;
1548                         }
1549
1550                         ret = ldb_msg_add_string(new_msg,
1551                                                  "servicePrincipalName",
1552                                                  talloc_asprintf(new_msg, "HOST/%s",
1553                                                  r->in.query->workstation_info->dns_hostname));
1554                         if (ret != LDB_SUCCESS) {
1555                                 return NT_STATUS_NO_MEMORY;
1556                         }
1557                 }
1558
1559                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1560                         DEBUG(3,("Impossible to update samdb: %s\n",
1561                                 ldb_errstring(sam_ctx)));
1562                 }
1563
1564                 talloc_free(new_msg);
1565
1566                 /* Writes back the domain information */
1567
1568                 /* We need to do two searches. The first will pull our primary
1569                    domain and the second will pull any trusted domains. Our
1570                    primary domain is also a "trusted" domain, so we need to
1571                    put the primary domain into the lists of returned trusts as
1572                    well. */
1573                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1574                         &res2, attrs);
1575                 if (ret != 1) {
1576                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1577                 }
1578
1579                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1580                         "(objectClass=trustedDomain)");
1581                 if (ret3 == -1) {
1582                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1583                 }
1584
1585                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1586                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1587
1588                 ZERO_STRUCTP(domain_info);
1589
1590                 /* Informations about the local and trusted domains */
1591
1592                 status = fill_one_domain_info(mem_ctx,
1593                         dce_call->conn->dce_ctx->lp_ctx,
1594                         sam_ctx, res2[0], &domain_info->primary_domain,
1595                         true, false);
1596                 NT_STATUS_NOT_OK_RETURN(status);
1597
1598                 domain_info->trusted_domain_count = ret3 + 1;
1599                 domain_info->trusted_domains = talloc_array(mem_ctx,
1600                         struct netr_OneDomainInfo,
1601                         domain_info->trusted_domain_count);
1602                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1603
1604                 for (i=0;i<ret3;i++) {
1605                         status = fill_one_domain_info(mem_ctx,
1606                                 dce_call->conn->dce_ctx->lp_ctx,
1607                                 sam_ctx, res3[i],
1608                                 &domain_info->trusted_domains[i],
1609                                 false, true);
1610                         NT_STATUS_NOT_OK_RETURN(status);
1611                 }
1612
1613                 status = fill_one_domain_info(mem_ctx,
1614                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1615                         &domain_info->trusted_domains[i], true, true);
1616                 NT_STATUS_NOT_OK_RETURN(status);
1617
1618                 /* Sets the supported encryption types */
1619                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1620                         "msDS-SupportedEncryptionTypes",
1621                         default_supported_enc_types);
1622
1623                 /* Other host domain informations */
1624
1625                 lsa_policy_info = talloc(mem_ctx,
1626                         struct netr_LsaPolicyInformation);
1627                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1628                 ZERO_STRUCTP(lsa_policy_info);
1629
1630                 domain_info->lsa_policy = *lsa_policy_info;
1631
1632                 /* The DNS hostname is only returned back when there is a chance
1633                  * for a change. */
1634                 if ((r->in.query->workstation_info->workstation_flags
1635                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1636                         domain_info->dns_hostname.string = old_dns_hostname;
1637                 } else {
1638                         domain_info->dns_hostname.string = NULL;
1639                 }
1640
1641                 domain_info->workstation_flags =
1642                         r->in.query->workstation_info->workstation_flags;
1643
1644                 r->out.info->domain_info = domain_info;
1645         break;
1646         case 2: /* LSA policy information - not used at the moment */
1647                 lsa_policy_info = talloc(mem_ctx,
1648                         struct netr_LsaPolicyInformation);
1649                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1650                 ZERO_STRUCTP(lsa_policy_info);
1651
1652                 r->out.info->lsa_policy_info = lsa_policy_info;
1653         break;
1654         default:
1655                 return NT_STATUS_INVALID_LEVEL;
1656         break;
1657         }
1658
1659         return NT_STATUS_OK;
1660 }
1661
1662
1663 /*
1664   netr_ServerPasswordGet
1665 */
1666 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1667                        struct netr_ServerPasswordGet *r)
1668 {
1669         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1670 }
1671
1672
1673 /*
1674   netr_NETRLOGONSENDTOSAM
1675 */
1676 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1677                        struct netr_NETRLOGONSENDTOSAM *r)
1678 {
1679         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1680 }
1681
1682
1683 /*
1684   netr_DsRGetDCNameEx2
1685 */
1686 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1687                                           TALLOC_CTX *mem_ctx,
1688                                           struct netr_DsRGetDCNameEx2 *r)
1689 {
1690         struct ldb_context *sam_ctx;
1691         struct netr_DsRGetDCNameInfo *info;
1692         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1693         const struct tsocket_address *remote_address;
1694         char *addr = NULL;
1695         const char *server_site_name;
1696         char *guid_str;
1697         struct netlogon_samlogon_response response;
1698         NTSTATUS status;
1699         const char *dc_name = NULL;
1700         const char *domain_name = NULL;
1701
1702         ZERO_STRUCTP(r->out.info);
1703
1704         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1705                                 dce_call->conn->auth_state.session_info, 0);
1706         if (sam_ctx == NULL) {
1707                 return WERR_DS_UNAVAILABLE;
1708         }
1709
1710         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1711         if (tsocket_address_is_inet(remote_address, "ip")) {
1712                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1713                 W_ERROR_HAVE_NO_MEMORY(addr);
1714         }
1715
1716         /* "server_unc" is ignored by w2k3 */
1717
1718         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1719                 return WERR_INVALID_FLAGS;
1720         }
1721
1722         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1723             r->in.flags & DS_PDC_REQUIRED &&
1724             r->in.flags & DS_KDC_REQUIRED) {
1725                 return WERR_INVALID_FLAGS;
1726         }
1727         if (r->in.flags & DS_IS_FLAT_NAME &&
1728             r->in.flags & DS_IS_DNS_NAME) {
1729                 return WERR_INVALID_FLAGS;
1730         }
1731         if (r->in.flags & DS_RETURN_DNS_NAME &&
1732             r->in.flags & DS_RETURN_FLAT_NAME) {
1733                 return WERR_INVALID_FLAGS;
1734         }
1735         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1736             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1737                 return WERR_INVALID_FLAGS;
1738         }
1739
1740         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1741             r->in.flags &
1742             (DS_DIRECTORY_SERVICE_REQUIRED |
1743              DS_DIRECTORY_SERVICE_PREFERRED |
1744              DS_GC_SERVER_REQUIRED |
1745              DS_PDC_REQUIRED |
1746              DS_KDC_REQUIRED)) {
1747                 return WERR_INVALID_FLAGS;
1748         }
1749
1750         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1751             r->in.site_name) {
1752                 return WERR_INVALID_FLAGS;
1753         }
1754
1755         /* Proof server site parameter "site_name" if it was specified */
1756         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1757         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1758         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1759                                                      server_site_name) != 0)) {
1760                 return WERR_NO_SUCH_DOMAIN;
1761         }
1762
1763         guid_str = r->in.domain_guid != NULL ?
1764                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1765
1766         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1767                                                  r->in.domain_name,
1768                                                  r->in.domain_name,
1769                                                  NULL, guid_str,
1770                                                  r->in.client_account,
1771                                                  r->in.mask, addr,
1772                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1773                                                  lp_ctx, &response, true);
1774         if (!NT_STATUS_IS_OK(status)) {
1775                 return ntstatus_to_werror(status);
1776         }
1777
1778         if (r->in.flags & DS_RETURN_DNS_NAME) {
1779                 dc_name = response.data.nt5_ex.pdc_dns_name;
1780                 domain_name = response.data.nt5_ex.dns_domain;
1781         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1782                 dc_name = response.data.nt5_ex.pdc_name;
1783                 domain_name = response.data.nt5_ex.domain_name;
1784         } else {
1785
1786                 /*
1787                  * TODO: autodetect what we need to return
1788                  * based on the given arguments
1789                  */
1790                 dc_name = response.data.nt5_ex.pdc_name;
1791                 domain_name = response.data.nt5_ex.domain_name;
1792         }
1793
1794         if (!dc_name || !dc_name[0]) {
1795                 return WERR_NO_SUCH_DOMAIN;
1796         }
1797
1798         if (!domain_name || !domain_name[0]) {
1799                 return WERR_NO_SUCH_DOMAIN;
1800         }
1801
1802         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1803         W_ERROR_HAVE_NO_MEMORY(info);
1804         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1805         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1806         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1807                                            response.data.nt5_ex.sockaddr.pdc_ip);
1808         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1809         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1810         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1811         info->domain_name      = domain_name;
1812         info->forest_name      = response.data.nt5_ex.forest;
1813         info->dc_flags         = response.data.nt5_ex.server_type;
1814         info->dc_site_name     = response.data.nt5_ex.server_site;
1815         info->client_site_name = response.data.nt5_ex.client_site;
1816
1817         *r->out.info = info;
1818
1819         return WERR_OK;
1820 }
1821
1822 /*
1823   netr_DsRGetDCNameEx
1824 */
1825 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1826                                   struct netr_DsRGetDCNameEx *r)
1827 {
1828         struct netr_DsRGetDCNameEx2 r2;
1829         WERROR werr;
1830
1831         ZERO_STRUCT(r2);
1832
1833         r2.in.server_unc = r->in.server_unc;
1834         r2.in.client_account = NULL;
1835         r2.in.mask = 0;
1836         r2.in.domain_guid = r->in.domain_guid;
1837         r2.in.domain_name = r->in.domain_name;
1838         r2.in.site_name = r->in.site_name;
1839         r2.in.flags = r->in.flags;
1840         r2.out.info = r->out.info;
1841
1842         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1843
1844         return werr;
1845 }
1846
1847 /*
1848   netr_DsRGetDCName
1849 */
1850 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1851                                 struct netr_DsRGetDCName *r)
1852 {
1853         struct netr_DsRGetDCNameEx2 r2;
1854         WERROR werr;
1855
1856         ZERO_STRUCT(r2);
1857
1858         r2.in.server_unc = r->in.server_unc;
1859         r2.in.client_account = NULL;
1860         r2.in.mask = 0;
1861         r2.in.domain_name = r->in.domain_name;
1862         r2.in.domain_guid = r->in.domain_guid;
1863
1864         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1865         r2.in.flags = r->in.flags;
1866         r2.out.info = r->out.info;
1867
1868         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1869
1870         return werr;
1871 }
1872 /*
1873   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1874 */
1875 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1876                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1877 {
1878         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1879 }
1880
1881
1882 /*
1883   netr_NetrEnumerateTrustedDomainsEx
1884 */
1885 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1886                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1887 {
1888         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1889 }
1890
1891
1892 /*
1893   netr_DsRAddressToSitenamesExW
1894 */
1895 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1896                                                    struct netr_DsRAddressToSitenamesExW *r)
1897 {
1898         struct ldb_context *sam_ctx;
1899         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1900         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1901         sa_family_t sin_family;
1902         struct sockaddr_in *addr;
1903 #ifdef HAVE_IPV6
1904         struct sockaddr_in6 *addr6;
1905         char addr_str[INET6_ADDRSTRLEN];
1906 #else
1907         char addr_str[INET_ADDRSTRLEN];
1908 #endif
1909         char *subnet_name;
1910         const char *res;
1911         uint32_t i;
1912
1913         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1914                                 dce_call->conn->auth_state.session_info, 0);
1915         if (sam_ctx == NULL) {
1916                 return WERR_DS_UNAVAILABLE;
1917         }
1918
1919         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1920         W_ERROR_HAVE_NO_MEMORY(ctr);
1921
1922         *r->out.ctr = ctr;
1923
1924         ctr->count = r->in.count;
1925         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1926         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1927         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1928         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1929
1930         for (i=0; i<ctr->count; i++) {
1931                 ctr->sitename[i].string = NULL;
1932                 ctr->subnetname[i].string = NULL;
1933
1934                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1935                         continue;
1936                 }
1937                 /* The first two byte of the buffer are reserved for the
1938                  * "sin_family" but for now only the first one is used. */
1939                 sin_family = r->in.addresses[i].buffer[0];
1940
1941                 switch (sin_family) {
1942                 case AF_INET:
1943                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1944                                 continue;
1945                         }
1946                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1947                         res = inet_ntop(AF_INET, &addr->sin_addr,
1948                                         addr_str, sizeof(addr_str));
1949                         break;
1950 #ifdef HAVE_IPV6
1951                 case AF_INET6:
1952                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1953                                 continue;
1954                         }
1955                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1956                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1957                                         addr_str, sizeof(addr_str));
1958                         break;
1959 #endif
1960                 default:
1961                         continue;
1962                 }
1963
1964                 if (res == NULL) {
1965                         continue;
1966                 }
1967
1968                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
1969                                                                    mem_ctx,
1970                                                                    addr_str,
1971                                                                    &subnet_name);
1972                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1973                 ctr->subnetname[i].string = subnet_name;
1974         }
1975
1976         return WERR_OK;
1977 }
1978
1979
1980 /*
1981   netr_DsRAddressToSitenamesW
1982 */
1983 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1984                        struct netr_DsRAddressToSitenamesW *r)
1985 {
1986         struct netr_DsRAddressToSitenamesExW r2;
1987         struct netr_DsRAddressToSitenamesWCtr *ctr;
1988         uint32_t i;
1989         WERROR werr;
1990
1991         ZERO_STRUCT(r2);
1992
1993         r2.in.server_name = r->in.server_name;
1994         r2.in.count = r->in.count;
1995         r2.in.addresses = r->in.addresses;
1996
1997         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1998         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1999
2000         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2001         W_ERROR_HAVE_NO_MEMORY(ctr);
2002
2003         *r->out.ctr = ctr;
2004
2005         ctr->count = r->in.count;
2006         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2007         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2008
2009         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2010
2011         for (i=0; i<ctr->count; i++) {
2012                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2013         }
2014
2015         return werr;
2016 }
2017
2018
2019 /*
2020   netr_DsrGetDcSiteCoverageW
2021 */
2022 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2023                        struct netr_DsrGetDcSiteCoverageW *r)
2024 {
2025         struct ldb_context *sam_ctx;
2026         struct DcSitesCtr *ctr;
2027         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2028
2029         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2030                                 dce_call->conn->auth_state.session_info, 0);
2031         if (sam_ctx == NULL) {
2032                 return WERR_DS_UNAVAILABLE;
2033         }
2034
2035         ctr = talloc(mem_ctx, struct DcSitesCtr);
2036         W_ERROR_HAVE_NO_MEMORY(ctr);
2037
2038         *r->out.ctr = ctr;
2039
2040         /* For now only return our default site */
2041         ctr->num_sites = 1;
2042         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2043         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2044         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2045         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2046
2047         return WERR_OK;
2048 }
2049
2050
2051 #define GET_CHECK_STR(dest, mem, msg, attr) \
2052 do {\
2053         const char *s; \
2054         s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
2055         if (!s) { \
2056                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
2057                           "without flatname\n", \
2058                           ldb_dn_get_linearized(msg->dn))); \
2059                 continue; \
2060         } \
2061         dest = talloc_strdup(mem, s); \
2062         W_ERROR_HAVE_NO_MEMORY(dest); \
2063 } while(0)
2064
2065
2066 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2067                                          struct ldb_context *sam_ctx,
2068                                          struct netr_DomainTrustList *trusts,
2069                                          uint32_t trust_flags)
2070 {
2071         struct ldb_dn *system_dn;
2072         struct ldb_message **dom_res = NULL;
2073         const char *trust_attrs[] = { "flatname", "trustPartner",
2074                                       "securityIdentifier", "trustDirection",
2075                                       "trustType", "trustAttributes", NULL };
2076         uint32_t n;
2077         int i;
2078         int ret;
2079
2080         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2081                              NETR_TRUST_FLAG_OUTBOUND))) {
2082                 return WERR_INVALID_FLAGS;
2083         }
2084
2085         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2086                                     ldb_get_default_basedn(sam_ctx),
2087                                     "(&(objectClass=container)(cn=System))");
2088         if (!system_dn) {
2089                 return WERR_GENERAL_FAILURE;
2090         }
2091
2092         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2093                            &dom_res, trust_attrs,
2094                            "(objectclass=trustedDomain)");
2095
2096         for (i = 0; i < ret; i++) {
2097                 unsigned int trust_dir;
2098                 uint32_t flags = 0;
2099
2100                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2101                                                       "trustDirection", 0);
2102
2103                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2104                         flags |= NETR_TRUST_FLAG_INBOUND;
2105                 }
2106                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2107                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2108                 }
2109
2110                 if (!(flags & trust_flags)) {
2111                         /* this trust direction was not requested */
2112                         continue;
2113                 }
2114
2115                 n = trusts->count;
2116                 trusts->array = talloc_realloc(trusts, trusts->array,
2117                                                struct netr_DomainTrust,
2118                                                n + 1);
2119                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2120
2121                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2122                               dom_res[i], "flatname");
2123                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2124                               dom_res[i], "trustPartner");
2125
2126                 trusts->array[n].trust_flags = flags;
2127                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2128                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2129                         /* TODO: find if we have parent in the list */
2130                         trusts->array[n].parent_index = 0;
2131                 }
2132
2133                 trusts->array[n].trust_type =
2134                                 ldb_msg_find_attr_as_uint(dom_res[i],
2135                                                   "trustType", 0);
2136                 trusts->array[n].trust_attributes =
2137                                 ldb_msg_find_attr_as_uint(dom_res[i],
2138                                                   "trustAttributes", 0);
2139
2140                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2141                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2142                         struct dom_sid zero_sid;
2143                         ZERO_STRUCT(zero_sid);
2144                         trusts->array[n].sid =
2145                                 dom_sid_dup(trusts, &zero_sid);
2146                 } else {
2147                         trusts->array[n].sid =
2148                                 samdb_result_dom_sid(trusts, dom_res[i],
2149                                                      "securityIdentifier");
2150                 }
2151                 trusts->array[n].guid = GUID_zero();
2152
2153                 trusts->count = n + 1;
2154         }
2155
2156         talloc_free(dom_res);
2157         return WERR_OK;
2158 }
2159
2160 /*
2161   netr_DsrEnumerateDomainTrusts
2162 */
2163 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2164                                                    TALLOC_CTX *mem_ctx,
2165                                                    struct netr_DsrEnumerateDomainTrusts *r)
2166 {
2167         struct netr_DomainTrustList *trusts;
2168         struct ldb_context *sam_ctx;
2169         int ret;
2170         struct ldb_message **dom_res;
2171         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2172         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2173         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2174         const char *p;
2175         WERROR werr;
2176
2177         if (r->in.trust_flags & 0xFFFFFE00) {
2178                 return WERR_INVALID_FLAGS;
2179         }
2180
2181         /* TODO: turn to hard check once we are sure this is 100% correct */
2182         if (!r->in.server_name) {
2183                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2184                           "But received NULL!\n", dnsdomain));
2185         } else {
2186                 p = strchr(r->in.server_name, '.');
2187                 if (!p) {
2188                         DEBUG(3, ("Invalid domain! Expected name in domain "
2189                                   "[%s]. But received [%s]!\n",
2190                                   dnsdomain, r->in.server_name));
2191                         p = r->in.server_name;
2192                 } else {
2193                         p++;
2194                 }
2195                 if (strcasecmp(p, dnsdomain)) {
2196                         DEBUG(3, ("Invalid domain! Expected name in domain "
2197                                   "[%s]. But received [%s]!\n",
2198                                   dnsdomain, r->in.server_name));
2199                 }
2200         }
2201
2202         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2203         W_ERROR_HAVE_NO_MEMORY(trusts);
2204
2205         trusts->count = 0;
2206         r->out.trusts = trusts;
2207
2208         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2209                                 dce_call->conn->auth_state.session_info, 0);
2210         if (sam_ctx == NULL) {
2211                 return WERR_GENERAL_FAILURE;
2212         }
2213
2214         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2215             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2216
2217                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2218                                                   trusts, r->in.trust_flags);
2219                 W_ERROR_NOT_OK_RETURN(werr);
2220         }
2221
2222         /* NOTE: we currently are always the root of the forest */
2223         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2224                 uint32_t n = trusts->count;
2225
2226                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2227                                       &dom_res, dom_attrs);
2228                 if (ret != 1) {
2229                         return WERR_GENERAL_FAILURE;
2230                 }
2231
2232                 trusts->count = n + 1;
2233                 trusts->array = talloc_realloc(trusts, trusts->array,
2234                                                struct netr_DomainTrust,
2235                                                trusts->count);
2236                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2237
2238                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2239                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2240                 trusts->array[n].trust_flags =
2241                         NETR_TRUST_FLAG_NATIVE |
2242                         NETR_TRUST_FLAG_TREEROOT |
2243                         NETR_TRUST_FLAG_IN_FOREST |
2244                         NETR_TRUST_FLAG_PRIMARY;
2245                 /* we are always the root domain for now */
2246                 trusts->array[n].parent_index = 0;
2247                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2248                 trusts->array[n].trust_attributes = 0;
2249                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2250                                                             dom_res[0],
2251                                                             "objectSid");
2252                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2253                                                           "objectGUID");
2254                 talloc_free(dom_res);
2255         }
2256
2257         return WERR_OK;
2258 }
2259
2260
2261 /*
2262   netr_DsrDeregisterDNSHostRecords
2263 */
2264 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2265                        struct netr_DsrDeregisterDNSHostRecords *r)
2266 {
2267         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2268 }
2269
2270
2271 /*
2272   netr_ServerTrustPasswordsGet
2273 */
2274 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2275                        struct netr_ServerTrustPasswordsGet *r)
2276 {
2277         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2278 }
2279
2280
2281 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2282                                       struct ldb_context *sam_ctx,
2283                                       struct loadparm_context *lp_ctx,
2284                                       struct lsa_ForestTrustInformation *info)
2285 {
2286         struct lsa_ForestTrustDomainInfo *domain_info;
2287         struct lsa_ForestTrustRecord *e;
2288         struct ldb_message **dom_res;
2289         const char * const dom_attrs[] = { "objectSid", NULL };
2290         int ret;
2291
2292         /* we need to provide 2 entries:
2293          * 1. the Root Forest name
2294          * 2. the Domain Information
2295          */
2296
2297         info->count = 2;
2298         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2299         W_ERROR_HAVE_NO_MEMORY(info->entries);
2300
2301         /* Forest root info */
2302         e = talloc(info, struct lsa_ForestTrustRecord);
2303         W_ERROR_HAVE_NO_MEMORY(e);
2304
2305         e->flags = 0;
2306         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2307         e->time = 0; /* so far always 0 in trces. */
2308         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2309                                                                        mem_ctx);
2310         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2311
2312         info->entries[0] = e;
2313
2314         /* Domain info */
2315         e = talloc(info, struct lsa_ForestTrustRecord);
2316         W_ERROR_HAVE_NO_MEMORY(e);
2317
2318         /* get our own domain info */
2319         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2320         if (ret != 1) {
2321                 return WERR_GENERAL_FAILURE;
2322         }
2323
2324         /* TODO: check if disabled and set flags accordingly */
2325         e->flags = 0;
2326         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2327         e->time = 0; /* so far always 0 in traces. */
2328
2329         domain_info = &e->forest_trust_data.domain_info;
2330         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2331                                                        "objectSid");
2332         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2333         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2334
2335         info->entries[1] = e;
2336
2337         talloc_free(dom_res);
2338
2339         return WERR_OK;
2340 }
2341
2342 /*
2343   netr_DsRGetForestTrustInformation
2344 */
2345 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2346                                                        TALLOC_CTX *mem_ctx,
2347                                                        struct netr_DsRGetForestTrustInformation *r)
2348 {
2349         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2350         struct lsa_ForestTrustInformation *info, **info_ptr;
2351         struct ldb_context *sam_ctx;
2352         WERROR werr;
2353
2354         if (r->in.flags & 0xFFFFFFFE) {
2355                 return WERR_INVALID_FLAGS;
2356         }
2357
2358         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2359                                 dce_call->conn->auth_state.session_info, 0);
2360         if (sam_ctx == NULL) {
2361                 return WERR_GENERAL_FAILURE;
2362         }
2363
2364         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2365                 if (!samdb_is_pdc(sam_ctx)) {
2366                         return WERR_NERR_NOTPRIMARY;
2367                 }
2368
2369                 if (r->in.trusted_domain_name == NULL) {
2370                         return WERR_INVALID_FLAGS;
2371                 }
2372
2373                 /* TODO: establish an schannel connection with
2374                  * r->in.trusted_domain_name and perform a
2375                  * netr_GetForestTrustInformation call against it */
2376
2377                 /* for now return not implementd */
2378                 return WERR_CALL_NOT_IMPLEMENTED;
2379         }
2380
2381         /* TODO: check r->in.server_name is our name */
2382
2383         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2384         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2385
2386         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2387         W_ERROR_HAVE_NO_MEMORY(info);
2388
2389         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2390         W_ERROR_NOT_OK_RETURN(werr);
2391
2392         *info_ptr = info;
2393         r->out.forest_trust_info = info_ptr;
2394
2395         return WERR_OK;
2396 }
2397
2398
2399 /*
2400   netr_GetForestTrustInformation
2401 */
2402 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2403                                                       TALLOC_CTX *mem_ctx,
2404                                                       struct netr_GetForestTrustInformation *r)
2405 {
2406         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2407         struct netlogon_creds_CredentialState *creds;
2408         struct lsa_ForestTrustInformation *info, **info_ptr;
2409         struct ldb_context *sam_ctx;
2410         NTSTATUS status;
2411         WERROR werr;
2412
2413         status = dcesrv_netr_creds_server_step_check(dce_call,
2414                                                      mem_ctx,
2415                                                      r->in.computer_name,
2416                                                      r->in.credential,
2417                                                      r->out.return_authenticator,
2418                                                      &creds);
2419         if (!NT_STATUS_IS_OK(status)) {
2420                 return status;
2421         }
2422
2423         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2424             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2425                 return NT_STATUS_NOT_IMPLEMENTED;
2426         }
2427
2428         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2429                                 dce_call->conn->auth_state.session_info, 0);
2430         if (sam_ctx == NULL) {
2431                 return NT_STATUS_UNSUCCESSFUL;
2432         }
2433
2434         /* TODO: check r->in.server_name is our name */
2435
2436         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2437         if (!info_ptr) {
2438                 return NT_STATUS_NO_MEMORY;
2439         }
2440         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2441         if (!info) {
2442                 return NT_STATUS_NO_MEMORY;
2443         }
2444
2445         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2446         if (!W_ERROR_IS_OK(werr)) {
2447                 return werror_to_ntstatus(werr);
2448         }
2449
2450         *info_ptr = info;
2451         r->out.forest_trust_info = info_ptr;
2452
2453         return NT_STATUS_OK;
2454 }
2455
2456
2457 /*
2458   netr_ServerGetTrustInfo
2459 */
2460 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2461                        struct netr_ServerGetTrustInfo *r)
2462 {
2463         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2464 }
2465
2466 /*
2467   netr_Unused47
2468 */
2469 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2470                                      struct netr_Unused47 *r)
2471 {
2472         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2473 }
2474
2475
2476 struct netr_dnsupdate_RODC_state {
2477         struct dcesrv_call_state *dce_call;
2478         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2479         struct dnsupdate_RODC *r2;
2480 };
2481
2482 /*
2483   called when the forwarded RODC dns update request is finished
2484  */
2485 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2486 {
2487         struct netr_dnsupdate_RODC_state *st =
2488                 tevent_req_callback_data(subreq,
2489                                          struct netr_dnsupdate_RODC_state);
2490         NTSTATUS status;
2491
2492         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2493         TALLOC_FREE(subreq);
2494         if (!NT_STATUS_IS_OK(status)) {
2495                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2496                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2497         }
2498
2499         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2500
2501         status = dcesrv_reply(st->dce_call);
2502         if (!NT_STATUS_IS_OK(status)) {
2503                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2504         }
2505 }
2506
2507 /*
2508   netr_DsrUpdateReadOnlyServerDnsRecords
2509 */
2510 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2511                                                               TALLOC_CTX *mem_ctx,
2512                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2513 {
2514         struct netlogon_creds_CredentialState *creds;
2515         NTSTATUS nt_status;
2516         struct dcerpc_binding_handle *binding_handle;
2517         struct netr_dnsupdate_RODC_state *st;
2518         struct tevent_req *subreq;
2519
2520         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2521                                                         mem_ctx,
2522                                                         r->in.computer_name,
2523                                                         r->in.credential,
2524                                                         r->out.return_authenticator,
2525                                                         &creds);
2526         NT_STATUS_NOT_OK_RETURN(nt_status);
2527
2528         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2529                 return NT_STATUS_ACCESS_DENIED;
2530         }
2531
2532         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2533         NT_STATUS_HAVE_NO_MEMORY(st);
2534
2535         st->dce_call = dce_call;
2536         st->r = r;
2537         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2538         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2539
2540         st->r2->in.dom_sid = creds->sid;
2541         st->r2->in.site_name = r->in.site_name;
2542         st->r2->in.dns_ttl = r->in.dns_ttl;
2543         st->r2->in.dns_names = r->in.dns_names;
2544         st->r2->out.dns_names = r->out.dns_names;
2545
2546         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2547                                                      "dnsupdate", &ndr_table_irpc);
2548         if (binding_handle == NULL) {
2549                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2550                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2551                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2552         }
2553
2554         /* forward the call */
2555         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2556                                               binding_handle, st->r2);
2557         NT_STATUS_HAVE_NO_MEMORY(subreq);
2558
2559         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2560
2561         /* setup the callback */
2562         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2563
2564         return NT_STATUS_OK;
2565 }
2566
2567
2568 /* include the generated boilerplate */
2569 #include "librpc/gen_ndr/ndr_netlogon_s.c"