s4-netlogon: fixed breakage of dcesrv_netr_GetAnyDCName in sites patch
[amitay/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                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1023                                                 lp_netbios_name(lp_ctx));
1024                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1025
1026                 return WERR_OK;
1027         }
1028
1029         /* Okay, now we have to consider the trusted domains */
1030
1031         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1032         W_ERROR_HAVE_NO_MEMORY(trusts);
1033
1034         trusts->count = 0;
1035
1036         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1037                                           NETR_TRUST_FLAG_INBOUND
1038                                           | NETR_TRUST_FLAG_OUTBOUND);
1039         W_ERROR_NOT_OK_RETURN(werr);
1040
1041         for (i = 0; i < trusts->count; i++) {
1042                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1043                         /* FIXME: Here we need to find a DC for the specified
1044                          * trusted domain. */
1045
1046                         /* return WERR_OK; */
1047                         return WERR_NO_SUCH_DOMAIN;
1048                 }
1049         }
1050
1051         return WERR_NO_SUCH_DOMAIN;
1052 }
1053
1054
1055 /*
1056   netr_DatabaseRedo
1057 */
1058 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1059                        struct netr_DatabaseRedo *r)
1060 {
1061         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1062 }
1063
1064
1065 /*
1066   netr_NetrEnumerateTurstedDomains
1067 */
1068 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1069                        struct netr_NetrEnumerateTrustedDomains *r)
1070 {
1071         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1072 }
1073
1074
1075 /*
1076   netr_LogonGetCapabilities
1077 */
1078 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1079                        struct netr_LogonGetCapabilities *r)
1080 {
1081         /* we don't support AES yet */
1082         return NT_STATUS_NOT_IMPLEMENTED;
1083 }
1084
1085
1086 /*
1087   netr_NETRLOGONSETSERVICEBITS
1088 */
1089 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1090                        struct netr_NETRLOGONSETSERVICEBITS *r)
1091 {
1092         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1093 }
1094
1095
1096 /*
1097   netr_LogonGetTrustRid
1098 */
1099 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1100                        struct netr_LogonGetTrustRid *r)
1101 {
1102         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1103 }
1104
1105
1106 /*
1107   netr_NETRLOGONCOMPUTESERVERDIGEST
1108 */
1109 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1110                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1111 {
1112         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1113 }
1114
1115
1116 /*
1117   netr_NETRLOGONCOMPUTECLIENTDIGEST
1118 */
1119 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1120                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1121 {
1122         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1123 }
1124
1125
1126
1127 /*
1128   netr_DsRGetSiteName
1129 */
1130 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1131                                   struct netr_DsRGetSiteName *r)
1132 {
1133         struct ldb_context *sam_ctx;
1134         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1135
1136         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1137                                 dce_call->conn->auth_state.session_info);
1138         if (sam_ctx == NULL) {
1139                 return WERR_DS_UNAVAILABLE;
1140         }
1141
1142         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1143         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1144
1145         return WERR_OK;
1146 }
1147
1148
1149 /*
1150   fill in a netr_OneDomainInfo from a ldb search result
1151 */
1152 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1153                                      struct loadparm_context *lp_ctx,
1154                                      struct ldb_context *sam_ctx,
1155                                      struct ldb_message *res,
1156                                      struct netr_OneDomainInfo *info,
1157                                      bool is_local, bool is_trust_list)
1158 {
1159         ZERO_STRUCTP(info);
1160
1161         if (is_trust_list) {
1162                 /* w2k8 only fills this on trusted domains */
1163                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1164                 info->trust_extension.length = 16;
1165                 info->trust_extension.info->flags =
1166                         NETR_TRUST_FLAG_TREEROOT |
1167                         NETR_TRUST_FLAG_IN_FOREST |
1168                         NETR_TRUST_FLAG_PRIMARY |
1169                         NETR_TRUST_FLAG_NATIVE;
1170
1171                 info->trust_extension.info->parent_index = 0; /* should be index into array
1172                                                                  of parent */
1173                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1174                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1175         }
1176
1177         if (is_trust_list) {
1178                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1179                 info->dns_forestname.string = NULL;
1180         } else {
1181                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1182                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1183                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1184                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1185         }
1186
1187         if (is_local) {
1188                 info->domainname.string = lp_workgroup(lp_ctx);
1189                 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1190                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1191                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1192         } else {
1193                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1194                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1195                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1196                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1197         }
1198         if (!is_trust_list) {
1199                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1200         }
1201
1202         return NT_STATUS_OK;
1203 }
1204
1205 /*
1206   netr_LogonGetDomainInfo
1207   this is called as part of the ADS domain logon procedure.
1208
1209   It has an important role in convaying details about the client, such
1210   as Operating System, Version, Service Pack etc.
1211 */
1212 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1213         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1214 {
1215         struct netlogon_creds_CredentialState *creds;
1216         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1217                 "securityIdentifier", "trustPartner", NULL };
1218         const char * const attrs2[] = { "dNSHostName",
1219                 "msDS-SupportedEncryptionTypes", NULL };
1220         const char * const attrs3[] = { NULL };
1221         const char *temp_str, *temp_str2;
1222         const char *old_dns_hostname;
1223         struct ldb_context *sam_ctx;
1224         struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1225         struct ldb_dn *workstation_dn;
1226         struct netr_DomainInformation *domain_info;
1227         struct netr_LsaPolicyInformation *lsa_policy_info;
1228         struct netr_OsVersionInfoEx *os_version;
1229         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1230         bool update_dns_hostname = true;
1231         int ret, ret3, i;
1232         NTSTATUS status;
1233
1234         status = dcesrv_netr_creds_server_step_check(dce_call,
1235                                                      mem_ctx,
1236                                                      r->in.computer_name,
1237                                                      r->in.credential,
1238                                                      r->out.return_authenticator,
1239                                                      &creds);
1240         if (!NT_STATUS_IS_OK(status)) {
1241                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1242         }
1243         NT_STATUS_NOT_OK_RETURN(status);
1244
1245         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1246                 dce_call->conn->dce_ctx->lp_ctx,
1247                 system_session(dce_call->conn->dce_ctx->lp_ctx));
1248         if (sam_ctx == NULL) {
1249                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1250         }
1251
1252         switch (r->in.level) {
1253         case 1: /* Domain information */
1254
1255                 /*
1256                  * Updates the DNS hostname when the client wishes that the
1257                  * server should handle this for him
1258                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1259                  * See MS-NRPC section 3.5.4.3.9
1260                  */
1261                 if ((r->in.query->workstation_info->workstation_flags
1262                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1263                         update_dns_hostname = false;
1264                 }
1265
1266                 /*
1267                  * Checks that the computer name parameter without possible "$"
1268                  * matches as prefix with the DNS hostname in the workstation
1269                  * info structure.
1270                  */
1271                 temp_str = talloc_strndup(mem_ctx,
1272                                           r->in.computer_name,
1273                                           strcspn(r->in.computer_name, "$"));
1274                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1275                 temp_str2 = talloc_strndup(mem_ctx,
1276                                            r->in.query->workstation_info->dns_hostname,
1277                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1278                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1279                 if (strcasecmp(temp_str, temp_str2) != 0) {
1280                         update_dns_hostname = false;
1281                 }
1282
1283                 /*
1284                  * Check that the DNS hostname when it should be updated
1285                  * will be used only by maximum one host.
1286                  */
1287                 ret = gendb_search(sam_ctx, mem_ctx,
1288                                    ldb_get_default_basedn(sam_ctx),
1289                                    &res0, attrs3, "(dNSHostName=%s)",
1290                                    r->in.query->workstation_info->dns_hostname);
1291                 if (ret < 0) {
1292                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1293                 }
1294                 if (ret >= 1) {
1295                         update_dns_hostname = false;
1296                 }
1297
1298                 talloc_free(res0);
1299
1300                 /* Prepare the workstation DN */
1301                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1302                         dom_sid_string(mem_ctx, creds->sid));
1303                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1304
1305                 /* Lookup for attributes in workstation object */
1306                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1307                         &res1, attrs2);
1308                 if (ret != 1) {
1309                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1310                 }
1311
1312                 /* Gets the old DNS hostname */
1313                 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1314                         NULL);
1315
1316                 /* Gets host informations and put them in our directory */
1317                 new_msg = ldb_msg_new(mem_ctx);
1318                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1319
1320                 new_msg->dn = workstation_dn;
1321
1322                 /* Deletes old OS version values */
1323                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1324                         "operatingSystemServicePack");
1325                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1326                         "operatingSystemVersion");
1327
1328                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1329                         DEBUG(3,("Impossible to update samdb: %s\n",
1330                                 ldb_errstring(sam_ctx)));
1331                 }
1332
1333                 talloc_free(new_msg);
1334
1335                 new_msg = ldb_msg_new(mem_ctx);
1336                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1337
1338                 new_msg->dn = workstation_dn;
1339
1340                 /* Sets the OS name */
1341                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1342                         "operatingSystem",
1343                         r->in.query->workstation_info->os_name.string);
1344
1345                 /*
1346                  * Sets informations from "os_version". On a empty structure
1347                  * the values are cleared.
1348                  */
1349                 if (r->in.query->workstation_info->os_version.os != NULL) {
1350                         os_version = &r->in.query->workstation_info->os_version.os->os;
1351
1352                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1353                                              "operatingSystemServicePack",
1354                                              os_version->CSDVersion);
1355
1356                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1357                                 "operatingSystemVersion",
1358                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1359                                         os_version->MajorVersion,
1360                                         os_version->MinorVersion,
1361                                         os_version->BuildNumber
1362                                 )
1363                         );
1364                 }
1365
1366                 /*
1367                  * If the boolean "update_dns_hostname" remained true, then we
1368                  * are fine to start the update.
1369                  */
1370                 if (update_dns_hostname) {
1371                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1372                                 "dNSHostname",
1373                         r->in.query->workstation_info->dns_hostname);
1374
1375                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1376                                 "servicePrincipalName",
1377                                 talloc_asprintf(mem_ctx, "HOST/%s",
1378                                 r->in.computer_name)
1379                         );
1380                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1381                                 "servicePrincipalName",
1382                                 talloc_asprintf(mem_ctx, "HOST/%s",
1383                                 r->in.query->workstation_info->dns_hostname)
1384                         );
1385                 }
1386
1387                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1388                         DEBUG(3,("Impossible to update samdb: %s\n",
1389                                 ldb_errstring(sam_ctx)));
1390                 }
1391
1392                 talloc_free(new_msg);
1393
1394                 /* Writes back the domain information */
1395
1396                 /* We need to do two searches. The first will pull our primary
1397                    domain and the second will pull any trusted domains. Our
1398                    primary domain is also a "trusted" domain, so we need to
1399                    put the primary domain into the lists of returned trusts as
1400                    well. */
1401                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1402                         &res2, attrs);
1403                 if (ret != 1) {
1404                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1405                 }
1406
1407                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1408                         "(objectClass=trustedDomain)");
1409                 if (ret3 == -1) {
1410                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1411                 }
1412
1413                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1414                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1415
1416                 ZERO_STRUCTP(domain_info);
1417
1418                 /* Informations about the local and trusted domains */
1419
1420                 status = fill_one_domain_info(mem_ctx,
1421                         dce_call->conn->dce_ctx->lp_ctx,
1422                         sam_ctx, res2[0], &domain_info->primary_domain,
1423                         true, false);
1424                 NT_STATUS_NOT_OK_RETURN(status);
1425
1426                 domain_info->trusted_domain_count = ret3 + 1;
1427                 domain_info->trusted_domains = talloc_array(mem_ctx,
1428                         struct netr_OneDomainInfo,
1429                         domain_info->trusted_domain_count);
1430                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1431
1432                 for (i=0;i<ret3;i++) {
1433                         status = fill_one_domain_info(mem_ctx,
1434                                 dce_call->conn->dce_ctx->lp_ctx,
1435                                 sam_ctx, res3[i],
1436                                 &domain_info->trusted_domains[i],
1437                                 false, true);
1438                         NT_STATUS_NOT_OK_RETURN(status);
1439                 }
1440
1441                 status = fill_one_domain_info(mem_ctx,
1442                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1443                         &domain_info->trusted_domains[i], true, true);
1444                 NT_STATUS_NOT_OK_RETURN(status);
1445
1446                 /* Sets the supported encryption types */
1447                 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1448                         "msDS-SupportedEncryptionTypes",
1449                         default_supported_enc_types);
1450
1451                 /* Other host domain informations */
1452
1453                 lsa_policy_info = talloc(mem_ctx,
1454                         struct netr_LsaPolicyInformation);
1455                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1456                 ZERO_STRUCTP(lsa_policy_info);
1457
1458                 domain_info->lsa_policy = *lsa_policy_info;
1459
1460                 /* The DNS hostname is only returned back when there is a chance
1461                  * for a change. */
1462                 if ((r->in.query->workstation_info->workstation_flags
1463                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1464                         domain_info->dns_hostname.string = old_dns_hostname;
1465                 } else {
1466                         domain_info->dns_hostname.string = NULL;
1467                 }
1468
1469                 domain_info->workstation_flags =
1470                         r->in.query->workstation_info->workstation_flags;
1471
1472                 r->out.info->domain_info = domain_info;
1473         break;
1474         case 2: /* LSA policy information - not used at the moment */
1475                 lsa_policy_info = talloc(mem_ctx,
1476                         struct netr_LsaPolicyInformation);
1477                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1478                 ZERO_STRUCTP(lsa_policy_info);
1479
1480                 r->out.info->lsa_policy_info = lsa_policy_info;
1481         break;
1482         default:
1483                 return NT_STATUS_INVALID_LEVEL;
1484         break;
1485         }
1486
1487         return NT_STATUS_OK;
1488 }
1489
1490
1491
1492 /*
1493   netr_ServerPasswordGet
1494 */
1495 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1496                        struct netr_ServerPasswordGet *r)
1497 {
1498         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1499 }
1500
1501
1502 /*
1503   netr_NETRLOGONSENDTOSAM
1504 */
1505 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1506                        struct netr_NETRLOGONSENDTOSAM *r)
1507 {
1508         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1509 }
1510
1511
1512 /*
1513   netr_DsRGetDCNameEx2
1514 */
1515 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1516                                           TALLOC_CTX *mem_ctx,
1517                                           struct netr_DsRGetDCNameEx2 *r)
1518 {
1519         struct ldb_context *sam_ctx;
1520         struct netr_DsRGetDCNameInfo *info;
1521         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1522         struct socket_address *addr;
1523         const char *server_site_name;
1524         char *guid_str;
1525         struct netlogon_samlogon_response response;
1526         NTSTATUS status;
1527
1528         ZERO_STRUCTP(r->out.info);
1529
1530         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1531                                 dce_call->conn->auth_state.session_info);
1532         if (sam_ctx == NULL) {
1533                 return WERR_DS_UNAVAILABLE;
1534         }
1535
1536         addr = dce_call->conn->transport.get_peer_addr(dce_call->conn, mem_ctx);
1537         W_ERROR_HAVE_NO_MEMORY(addr);
1538
1539         /* "server_unc" is ignored by w2k3 */
1540
1541         /* Proof server site parameter "site_name" if it was specified */
1542         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1543         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1544         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1545                                                      server_site_name) != 0)) {
1546                 return WERR_NO_SUCH_DOMAIN;
1547         }
1548
1549         /* TODO: the flags are ignored for now */
1550
1551         guid_str = r->in.domain_guid != NULL ?
1552                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1553
1554         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1555                                                  r->in.domain_name,
1556                                                  r->in.domain_name,
1557                                                  NULL, guid_str,
1558                                                  r->in.client_account,
1559                                                  r->in.mask, addr->addr,
1560                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1561                                                  lp_ctx, &response);
1562         if (!NT_STATUS_IS_OK(status)) {
1563                 return ntstatus_to_werror(status);
1564         }
1565
1566         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1567         W_ERROR_HAVE_NO_MEMORY(info);
1568         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s",
1569                                                  response.data.nt5_ex.pdc_dns_name);
1570         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1571         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1572                                            response.data.nt5_ex.sockaddr.pdc_ip);
1573         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1574         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1575         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1576         info->domain_name      = response.data.nt5_ex.dns_domain;
1577         info->forest_name      = response.data.nt5_ex.forest;
1578         info->dc_flags         = response.data.nt5_ex.server_type;
1579         info->dc_site_name     = response.data.nt5_ex.server_site;
1580         info->client_site_name = response.data.nt5_ex.client_site;
1581
1582         *r->out.info = info;
1583
1584         return WERR_OK;
1585 }
1586
1587 /*
1588   netr_DsRGetDCNameEx
1589 */
1590 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1591                                   struct netr_DsRGetDCNameEx *r)
1592 {
1593         struct netr_DsRGetDCNameEx2 r2;
1594         WERROR werr;
1595
1596         ZERO_STRUCT(r2);
1597
1598         r2.in.server_unc = r->in.server_unc;
1599         r2.in.client_account = NULL;
1600         r2.in.mask = 0;
1601         r2.in.domain_guid = r->in.domain_guid;
1602         r2.in.domain_name = r->in.domain_name;
1603         r2.in.site_name = r->in.site_name;
1604         r2.in.flags = r->in.flags;
1605         r2.out.info = r->out.info;
1606
1607         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1608
1609         return werr;
1610 }
1611
1612 /*
1613   netr_DsRGetDCName
1614 */
1615 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1616                                 struct netr_DsRGetDCName *r)
1617 {
1618         struct netr_DsRGetDCNameEx2 r2;
1619         WERROR werr;
1620
1621         ZERO_STRUCT(r2);
1622
1623         r2.in.server_unc = r->in.server_unc;
1624         r2.in.client_account = NULL;
1625         r2.in.mask = 0;
1626         r2.in.domain_name = r->in.domain_name;
1627         r2.in.domain_guid = r->in.domain_guid;
1628
1629         r2.in.site_name = NULL; /* should fill in from site GUID */
1630         r2.in.flags = r->in.flags;
1631         r2.out.info = r->out.info;
1632
1633         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1634
1635         return werr;
1636 }
1637 /*
1638   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1639 */
1640 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1641                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1642 {
1643         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1644 }
1645
1646
1647 /*
1648   netr_NetrEnumerateTrustedDomainsEx
1649 */
1650 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1651                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1652 {
1653         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1654 }
1655
1656
1657 /*
1658   netr_DsRAddressToSitenamesExW
1659 */
1660 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1661                                                    struct netr_DsRAddressToSitenamesExW *r)
1662 {
1663         struct ldb_context *sam_ctx;
1664         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1665         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1666         uint16_t sin_family;
1667         struct sockaddr_in *addr;
1668         struct sockaddr_in6 *addr6;
1669         char addr_str[INET6_ADDRSTRLEN];
1670         char *subnet_name;
1671         const char *res;
1672         uint32_t i;
1673
1674         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1675                                 dce_call->conn->auth_state.session_info);
1676         if (sam_ctx == NULL) {
1677                 return WERR_DS_UNAVAILABLE;
1678         }
1679
1680         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1681         W_ERROR_HAVE_NO_MEMORY(ctr);
1682
1683         *r->out.ctr = ctr;
1684
1685         ctr->count = r->in.count;
1686         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1687         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1688         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1689         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1690
1691         for (i=0; i<ctr->count; i++) {
1692                 ctr->sitename[i].string = NULL;
1693                 ctr->subnetname[i].string = NULL;
1694
1695                 if (r->in.addresses[i].size < sizeof(sin_family)) {
1696                         continue;
1697                 }
1698                 sin_family = SVAL(r->in.addresses[i].buffer, 0);
1699
1700                 switch (sin_family) {
1701                 case AF_INET:
1702                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1703                                 continue;
1704                         }
1705                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1706                         res = inet_ntop(AF_INET, &addr->sin_addr,
1707                                         addr_str, sizeof(addr_str));
1708                         break;
1709                 case AF_INET6:
1710                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1711                                 continue;
1712                         }
1713                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1714                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1715                                         addr_str, sizeof(addr_str));
1716                         break;
1717                 default:
1718                         continue;
1719                 break;
1720                 }
1721
1722                 if (res == NULL) {
1723                         continue;
1724                 }
1725
1726                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
1727                                                                    mem_ctx,
1728                                                                    addr_str,
1729                                                                    &subnet_name);
1730                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1731                 ctr->subnetname[i].string = subnet_name;
1732         }
1733
1734         return WERR_OK;
1735 }
1736
1737
1738 /*
1739   netr_DsRAddressToSitenamesW
1740 */
1741 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1742                        struct netr_DsRAddressToSitenamesW *r)
1743 {
1744         struct netr_DsRAddressToSitenamesExW r2;
1745         struct netr_DsRAddressToSitenamesWCtr *ctr;
1746         uint32_t i;
1747         WERROR werr;
1748
1749         ZERO_STRUCT(r2);
1750
1751         r2.in.server_name = r->in.server_name;
1752         r2.in.count = r->in.count;
1753         r2.in.addresses = r->in.addresses;
1754
1755         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1756         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1757
1758         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1759
1760         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1761         W_ERROR_HAVE_NO_MEMORY(ctr);
1762
1763         *r->out.ctr = ctr;
1764
1765         ctr->count = r->in.count;
1766         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1767         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1768
1769         for (i=0; i<ctr->count; i++) {
1770                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
1771         }
1772
1773         return werr;
1774 }
1775
1776
1777 /*
1778   netr_DsrGetDcSiteCoverageW
1779 */
1780 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1781                        struct netr_DsrGetDcSiteCoverageW *r)
1782 {
1783         struct ldb_context *sam_ctx;
1784         struct DcSitesCtr *ctr;
1785         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1786
1787         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1788                                 dce_call->conn->auth_state.session_info);
1789         if (sam_ctx == NULL) {
1790                 return WERR_DS_UNAVAILABLE;
1791         }
1792
1793         ctr = talloc(mem_ctx, struct DcSitesCtr);
1794         W_ERROR_HAVE_NO_MEMORY(ctr);
1795
1796         *r->out.ctr = ctr;
1797
1798         /* For now only return our default site */
1799         ctr->num_sites = 1;
1800         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1801         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1802         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1803         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1804
1805         return WERR_OK;
1806 }
1807
1808
1809 #define GET_CHECK_STR(dest, mem, msg, attr) \
1810 do {\
1811         const char *s; \
1812         s = samdb_result_string(msg, attr, NULL); \
1813         if (!s) { \
1814                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1815                           "without flatname\n", \
1816                           ldb_dn_get_linearized(msg->dn))); \
1817                 continue; \
1818         } \
1819         dest = talloc_strdup(mem, s); \
1820         W_ERROR_HAVE_NO_MEMORY(dest); \
1821 } while(0)
1822
1823
1824 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1825                                          struct ldb_context *sam_ctx,
1826                                          struct netr_DomainTrustList *trusts,
1827                                          uint32_t trust_flags)
1828 {
1829         struct ldb_dn *system_dn;
1830         struct ldb_message **dom_res = NULL;
1831         const char *trust_attrs[] = { "flatname", "trustPartner",
1832                                       "securityIdentifier", "trustDirection",
1833                                       "trustType", "trustAttributes", NULL };
1834         uint32_t n;
1835         int i;
1836         int ret;
1837
1838         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1839                              NETR_TRUST_FLAG_OUTBOUND))) {
1840                 return WERR_INVALID_FLAGS;
1841         }
1842
1843         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1844                                     ldb_get_default_basedn(sam_ctx),
1845                                     "(&(objectClass=container)(cn=System))");
1846         if (!system_dn) {
1847                 return WERR_GENERAL_FAILURE;
1848         }
1849
1850         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1851                            &dom_res, trust_attrs,
1852                            "(objectclass=trustedDomain)");
1853
1854         for (i = 0; i < ret; i++) {
1855                 unsigned int trust_dir;
1856                 uint32_t flags = 0;
1857
1858                 trust_dir = samdb_result_uint(dom_res[i],
1859                                               "trustDirection", 0);
1860
1861                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1862                         flags |= NETR_TRUST_FLAG_INBOUND;
1863                 }
1864                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1865                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1866                 }
1867
1868                 if (!(flags & trust_flags)) {
1869                         /* this trust direction was not requested */
1870                         continue;
1871                 }
1872
1873                 n = trusts->count;
1874                 trusts->array = talloc_realloc(trusts, trusts->array,
1875                                                struct netr_DomainTrust,
1876                                                n + 1);
1877                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1878
1879                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1880                               dom_res[i], "flatname");
1881                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1882                               dom_res[i], "trustPartner");
1883
1884                 trusts->array[n].trust_flags = flags;
1885                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1886                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1887                         /* TODO: find if we have parent in the list */
1888                         trusts->array[n].parent_index = 0;
1889                 }
1890
1891                 trusts->array[n].trust_type =
1892                                 samdb_result_uint(dom_res[i],
1893                                                   "trustType", 0);
1894                 trusts->array[n].trust_attributes =
1895                                 samdb_result_uint(dom_res[i],
1896                                                   "trustAttributes", 0);
1897
1898                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1899                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1900                         struct dom_sid zero_sid;
1901                         ZERO_STRUCT(zero_sid);
1902                         trusts->array[n].sid =
1903                                 dom_sid_dup(trusts, &zero_sid);
1904                 } else {
1905                         trusts->array[n].sid =
1906                                 samdb_result_dom_sid(trusts, dom_res[i],
1907                                                      "securityIdentifier");
1908                 }
1909                 trusts->array[n].guid = GUID_zero();
1910
1911                 trusts->count = n + 1;
1912         }
1913
1914         talloc_free(dom_res);
1915         return WERR_OK;
1916 }
1917
1918 /*
1919   netr_DsrEnumerateDomainTrusts
1920 */
1921 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1922                                                    TALLOC_CTX *mem_ctx,
1923                                                    struct netr_DsrEnumerateDomainTrusts *r)
1924 {
1925         struct netr_DomainTrustList *trusts;
1926         struct ldb_context *sam_ctx;
1927         int ret;
1928         struct ldb_message **dom_res;
1929         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1930         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1931         const char *dnsdomain = lp_dnsdomain(lp_ctx);
1932         const char *p;
1933         WERROR werr;
1934
1935         if (r->in.trust_flags & 0xFFFFFE00) {
1936                 return WERR_INVALID_FLAGS;
1937         }
1938
1939         /* TODO: turn to hard check once we are sure this is 100% correct */
1940         if (!r->in.server_name) {
1941                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1942                           "But received NULL!\n", dnsdomain));
1943         } else {
1944                 p = strchr(r->in.server_name, '.');
1945                 if (!p) {
1946                         DEBUG(3, ("Invalid domain! Expected name in domain "
1947                                   "[%s]. But received [%s]!\n",
1948                                   dnsdomain, r->in.server_name));
1949                         p = r->in.server_name;
1950                 } else {
1951                         p++;
1952                 }
1953                 if (strcasecmp(p, dnsdomain)) {
1954                         DEBUG(3, ("Invalid domain! Expected name in domain "
1955                                   "[%s]. But received [%s]!\n",
1956                                   dnsdomain, r->in.server_name));
1957                 }
1958         }
1959
1960         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1961         W_ERROR_HAVE_NO_MEMORY(trusts);
1962
1963         trusts->count = 0;
1964         r->out.trusts = trusts;
1965
1966         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1967                                 dce_call->conn->auth_state.session_info);
1968         if (sam_ctx == NULL) {
1969                 return WERR_GENERAL_FAILURE;
1970         }
1971
1972         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1973             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1974
1975                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1976                                                   trusts, r->in.trust_flags);
1977                 W_ERROR_NOT_OK_RETURN(werr);
1978         }
1979
1980         /* NOTE: we currently are always the root of the forest */
1981         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1982                 int n = trusts->count;
1983
1984                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1985                                       &dom_res, dom_attrs);
1986                 if (ret != 1) {
1987                         return WERR_GENERAL_FAILURE;
1988                 }
1989
1990                 trusts->count = n + 1;
1991                 trusts->array = talloc_realloc(trusts, trusts->array,
1992                                                struct netr_DomainTrust,
1993                                                trusts->count);
1994                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1995
1996                 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1997                 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1998                 trusts->array[n].trust_flags =
1999                         NETR_TRUST_FLAG_NATIVE |
2000                         NETR_TRUST_FLAG_TREEROOT |
2001                         NETR_TRUST_FLAG_IN_FOREST |
2002                         NETR_TRUST_FLAG_PRIMARY;
2003                 /* we are always the root domain for now */
2004                 trusts->array[n].parent_index = 0;
2005                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2006                 trusts->array[n].trust_attributes = 0;
2007                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2008                                                             dom_res[0],
2009                                                             "objectSid");
2010                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2011                                                           "objectGUID");
2012                 talloc_free(dom_res);
2013         }
2014
2015         return WERR_OK;
2016 }
2017
2018
2019 /*
2020   netr_DsrDeregisterDNSHostRecords
2021 */
2022 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2023                        struct netr_DsrDeregisterDNSHostRecords *r)
2024 {
2025         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2026 }
2027
2028
2029 /*
2030   netr_ServerTrustPasswordsGet
2031 */
2032 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2033                        struct netr_ServerTrustPasswordsGet *r)
2034 {
2035         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2036 }
2037
2038
2039 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2040                                       struct ldb_context *sam_ctx,
2041                                       struct loadparm_context *lp_ctx,
2042                                       struct lsa_ForestTrustInformation *info)
2043 {
2044         struct lsa_ForestTrustDomainInfo *domain_info;
2045         struct lsa_ForestTrustRecord *e;
2046         struct ldb_message **dom_res;
2047         const char * const dom_attrs[] = { "objectSid", NULL };
2048         int ret;
2049
2050         /* we need to provide 2 entries:
2051          * 1. the Root Forest name
2052          * 2. the Domain Information
2053          */
2054
2055         info->count = 2;
2056         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2057         W_ERROR_HAVE_NO_MEMORY(info->entries);
2058
2059         /* Forest root info */
2060         e = talloc(info, struct lsa_ForestTrustRecord);
2061         W_ERROR_HAVE_NO_MEMORY(e);
2062
2063         e->flags = 0;
2064         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2065         e->time = 0; /* so far always 0 in trces. */
2066         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2067                                                                        mem_ctx);
2068         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2069
2070         info->entries[0] = e;
2071
2072         /* Domain info */
2073         e = talloc(info, struct lsa_ForestTrustRecord);
2074         W_ERROR_HAVE_NO_MEMORY(e);
2075
2076         /* get our own domain info */
2077         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2078         if (ret != 1) {
2079                 return WERR_GENERAL_FAILURE;
2080         }
2081
2082         /* TODO: check if disabled and set flags accordingly */
2083         e->flags = 0;
2084         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2085         e->time = 0; /* so far always 0 in traces. */
2086
2087         domain_info = &e->forest_trust_data.domain_info;
2088         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2089                                                        "objectSid");
2090         domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
2091         domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
2092
2093         info->entries[1] = e;
2094
2095         talloc_free(dom_res);
2096
2097         return WERR_OK;
2098 }
2099
2100 /*
2101   netr_DsRGetForestTrustInformation
2102 */
2103 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2104                                                        TALLOC_CTX *mem_ctx,
2105                                                        struct netr_DsRGetForestTrustInformation *r)
2106 {
2107         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2108         struct lsa_ForestTrustInformation *info, **info_ptr;
2109         struct ldb_context *sam_ctx;
2110         WERROR werr;
2111
2112         if (r->in.flags & 0xFFFFFFFE) {
2113                 return WERR_INVALID_FLAGS;
2114         }
2115
2116         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2117                                 dce_call->conn->auth_state.session_info);
2118         if (sam_ctx == NULL) {
2119                 return WERR_GENERAL_FAILURE;
2120         }
2121
2122         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2123                 if (!samdb_is_pdc(sam_ctx)) {
2124                         return WERR_NERR_NOTPRIMARY;
2125                 }
2126
2127                 if (r->in.trusted_domain_name == NULL) {
2128                         return WERR_INVALID_FLAGS;
2129                 }
2130
2131                 /* TODO: establish an schannel connection with
2132                  * r->in.trusted_domain_name and perform a
2133                  * netr_GetForestTrustInformation call against it */
2134
2135                 /* for now return not implementd */
2136                 return WERR_CALL_NOT_IMPLEMENTED;
2137         }
2138
2139         /* TODO: check r->in.server_name is our name */
2140
2141         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2142         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2143
2144         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2145         W_ERROR_HAVE_NO_MEMORY(info);
2146
2147         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2148         W_ERROR_NOT_OK_RETURN(werr);
2149
2150         *info_ptr = info;
2151         r->out.forest_trust_info = info_ptr;
2152
2153         return WERR_OK;
2154 }
2155
2156
2157 /*
2158   netr_GetForestTrustInformation
2159 */
2160 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2161                                                       TALLOC_CTX *mem_ctx,
2162                                                       struct netr_GetForestTrustInformation *r)
2163 {
2164         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2165         struct netlogon_creds_CredentialState *creds;
2166         struct lsa_ForestTrustInformation *info, **info_ptr;
2167         struct ldb_context *sam_ctx;
2168         NTSTATUS status;
2169         WERROR werr;
2170
2171         status = dcesrv_netr_creds_server_step_check(dce_call,
2172                                                      mem_ctx,
2173                                                      r->in.computer_name,
2174                                                      r->in.credential,
2175                                                      r->out.return_authenticator,
2176                                                      &creds);
2177         if (!NT_STATUS_IS_OK(status)) {
2178                 return status;
2179         }
2180
2181         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2182             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2183                 return NT_STATUS_NOT_IMPLEMENTED;
2184         }
2185
2186         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2187                                 dce_call->conn->auth_state.session_info);
2188         if (sam_ctx == NULL) {
2189                 return NT_STATUS_UNSUCCESSFUL;
2190         }
2191
2192         /* TODO: check r->in.server_name is our name */
2193
2194         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2195         if (!info_ptr) {
2196                 return NT_STATUS_NO_MEMORY;
2197         }
2198         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2199         if (!info) {
2200                 return NT_STATUS_NO_MEMORY;
2201         }
2202
2203         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2204         if (!W_ERROR_IS_OK(werr)) {
2205                 return werror_to_ntstatus(werr);
2206         }
2207
2208         *info_ptr = info;
2209         r->out.forest_trust_info = info_ptr;
2210
2211         return NT_STATUS_OK;
2212 }
2213
2214
2215 /*
2216   netr_ServerGetTrustInfo
2217 */
2218 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2219                        struct netr_ServerGetTrustInfo *r)
2220 {
2221         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2222 }
2223
2224
2225 /* include the generated boilerplate */
2226 #include "librpc/gen_ndr/ndr_netlogon_s.c"