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