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