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