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