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