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