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