s4:netlogon RPC - "LogonGetDomainInfo" - make the call compatible with >= Windows...
[ddiss/samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    Copyright (C) Matthias Dieter Wallnöfer            2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc.h"
35
36 struct netlogon_server_pipe_state {
37         struct netr_Credential client_challenge;
38         struct netr_Credential server_challenge;
39 };
40
41 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
42                                         struct netr_ServerReqChallenge *r)
43 {
44         struct netlogon_server_pipe_state *pipe_state =
45                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
46
47         ZERO_STRUCTP(r->out.return_credentials);
48
49         /* destroyed on pipe shutdown */
50
51         if (pipe_state) {
52                 talloc_free(pipe_state);
53                 dce_call->context->private_data = NULL;
54         }
55
56         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
57         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
58
59         pipe_state->client_challenge = *r->in.credentials;
60
61         generate_random_buffer(pipe_state->server_challenge.data,
62                                sizeof(pipe_state->server_challenge.data));
63
64         *r->out.return_credentials = pipe_state->server_challenge;
65
66         dce_call->context->private_data = pipe_state;
67
68         return NT_STATUS_OK;
69 }
70
71 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
72                                          struct netr_ServerAuthenticate3 *r)
73 {
74         struct netlogon_server_pipe_state *pipe_state =
75                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
76         struct netlogon_creds_CredentialState *creds;
77         struct ldb_context *sam_ctx;
78         struct samr_Password *mach_pwd;
79         uint32_t user_account_control;
80         int num_records;
81         struct ldb_message **msgs;
82         NTSTATUS nt_status;
83         const char *attrs[] = {"unicodePwd", "userAccountControl",
84                                "objectSid", NULL};
85
86         const char *trust_dom_attrs[] = {"flatname", NULL};
87         const char *account_name;
88
89         ZERO_STRUCTP(r->out.return_credentials);
90         *r->out.rid = 0;
91
92         /*
93          * According to Microsoft (see bugid #6099)
94          * Windows 7 looks at the negotiate_flags
95          * returned in this structure *even if the
96          * call fails with access denied!
97          */
98         *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
99                                   NETLOGON_NEG_PERSISTENT_SAMREPL |
100                                   NETLOGON_NEG_ARCFOUR |
101                                   NETLOGON_NEG_PROMOTION_COUNT |
102                                   NETLOGON_NEG_CHANGELOG_BDC |
103                                   NETLOGON_NEG_FULL_SYNC_REPL |
104                                   NETLOGON_NEG_MULTIPLE_SIDS |
105                                   NETLOGON_NEG_REDO |
106                                   NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
107                                   NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
108                                   NETLOGON_NEG_GENERIC_PASSTHROUGH |
109                                   NETLOGON_NEG_CONCURRENT_RPC |
110                                   NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
111                                   NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
112                                   NETLOGON_NEG_STRONG_KEYS |
113                                   NETLOGON_NEG_TRANSITIVE_TRUSTS |
114                                   NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
115                                   NETLOGON_NEG_PASSWORD_SET2 |
116                                   NETLOGON_NEG_GETDOMAININFO |
117                                   NETLOGON_NEG_CROSS_FOREST_TRUSTS |
118                                   NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
119                                   NETLOGON_NEG_RODC_PASSTHROUGH |
120                                   NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
121                                   NETLOGON_NEG_AUTHENTICATED_RPC;
122
123         if (!pipe_state) {
124                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
125                 return NT_STATUS_ACCESS_DENIED;
126         }
127
128         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
129                                 system_session(dce_call->conn->dce_ctx->lp_ctx));
130         if (sam_ctx == NULL) {
131                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
132         }
133
134         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
135                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
136                 const char *flatname;
137                 if (!encoded_account) {
138                         return NT_STATUS_NO_MEMORY;
139                 }
140
141                 /* Kill the trailing dot */
142                 if (encoded_account[strlen(encoded_account)-1] == '.') {
143                         encoded_account[strlen(encoded_account)-1] = '\0';
144                 }
145
146                 /* pull the user attributes */
147                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
148                                            trust_dom_attrs,
149                                            "(&(trustPartner=%s)(objectclass=trustedDomain))",
150                                            encoded_account);
151
152                 if (num_records == 0) {
153                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
154                                  encoded_account));
155                         return NT_STATUS_ACCESS_DENIED;
156                 }
157
158                 if (num_records > 1) {
159                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
160                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
161                 }
162
163                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
164                 if (!flatname) {
165                         /* No flatname for this trust - we can't proceed */
166                         return NT_STATUS_ACCESS_DENIED;
167                 }
168                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
169
170                 if (!account_name) {
171                         return NT_STATUS_NO_MEMORY;
172                 }
173
174         } else {
175                 account_name = r->in.account_name;
176         }
177
178         /* pull the user attributes */
179         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
180                                    "(&(sAMAccountName=%s)(objectclass=user))",
181                                    ldb_binary_encode_string(mem_ctx, account_name));
182
183         if (num_records == 0) {
184                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
185                          r->in.account_name));
186                 return NT_STATUS_ACCESS_DENIED;
187         }
188
189         if (num_records > 1) {
190                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
191                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
192         }
193
194         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
195
196         if (user_account_control & UF_ACCOUNTDISABLE) {
197                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
198                 return NT_STATUS_ACCESS_DENIED;
199         }
200
201         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
202                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
203                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
204                         return NT_STATUS_ACCESS_DENIED;
205                 }
206         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
207                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
208                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
209                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
210
211                         return NT_STATUS_ACCESS_DENIED;
212                 }
213         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
214                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
215                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
216                         return NT_STATUS_ACCESS_DENIED;
217                 }
218         } else {
219                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
220                           r->in.secure_channel_type));
221                 return NT_STATUS_ACCESS_DENIED;
222         }
223
224         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
225                                                 "objectSid", 0);
226
227         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
228         if (mach_pwd == NULL) {
229                 return NT_STATUS_ACCESS_DENIED;
230         }
231
232         creds = netlogon_creds_server_init(mem_ctx,
233                                            r->in.account_name,
234                                            r->in.computer_name,
235                                            r->in.secure_channel_type,
236                                            &pipe_state->client_challenge,
237                                            &pipe_state->server_challenge,
238                                            mach_pwd,
239                                            r->in.credentials,
240                                            r->out.return_credentials,
241                                            *r->in.negotiate_flags);
242
243         if (!creds) {
244                 return NT_STATUS_ACCESS_DENIED;
245         }
246
247         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
248
249         nt_status = schannel_save_creds_state(mem_ctx,
250                                               lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
251                                               lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
252                                               creds);
253
254         return nt_status;
255 }
256
257 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
258                                         struct netr_ServerAuthenticate *r)
259 {
260         struct netr_ServerAuthenticate3 a;
261         uint32_t rid;
262         /* TODO:
263          * negotiate_flags is used as an [in] parameter
264          * so it need to be initialised.
265          *
266          * (I think ... = 0; seems wrong here --metze)
267          */
268         uint32_t negotiate_flags_in = 0;
269         uint32_t negotiate_flags_out = 0;
270
271         a.in.server_name                = r->in.server_name;
272         a.in.account_name               = r->in.account_name;
273         a.in.secure_channel_type        = r->in.secure_channel_type;
274         a.in.computer_name              = r->in.computer_name;
275         a.in.credentials                = r->in.credentials;
276         a.in.negotiate_flags            = &negotiate_flags_in;
277
278         a.out.return_credentials        = r->out.return_credentials;
279         a.out.rid                       = &rid;
280         a.out.negotiate_flags           = &negotiate_flags_out;
281
282         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
283 }
284
285 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
286                                          struct netr_ServerAuthenticate2 *r)
287 {
288         struct netr_ServerAuthenticate3 r3;
289         uint32_t rid = 0;
290
291         r3.in.server_name = r->in.server_name;
292         r3.in.account_name = r->in.account_name;
293         r3.in.secure_channel_type = r->in.secure_channel_type;
294         r3.in.computer_name = r->in.computer_name;
295         r3.in.credentials = r->in.credentials;
296         r3.out.return_credentials = r->out.return_credentials;
297         r3.in.negotiate_flags = r->in.negotiate_flags;
298         r3.out.negotiate_flags = r->out.negotiate_flags;
299         r3.out.rid = &rid;
300
301         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
302 }
303
304 /*
305  * NOTE: The following functions are nearly identical to the ones available in
306  * source3/rpc_server/srv_nelog_nt.c
307  * The reason we keep 2 copies is that they use different structures to
308  * represent the auth_info and the decrpc pipes.
309  */
310
311 /*
312  * If schannel is required for this call test that it actually is available.
313  */
314 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
315                                         const char *computer_name,
316                                         bool integrity, bool privacy)
317 {
318
319         if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
320                 if (!privacy && !integrity) {
321                         return NT_STATUS_OK;
322                 }
323
324                 if ((!privacy && integrity) &&
325                     auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
326                         return NT_STATUS_OK;
327                 }
328
329                 if ((privacy || integrity) &&
330                     auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
331                         return NT_STATUS_OK;
332                 }
333         }
334
335         /* test didn't pass */
336         DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
337                   computer_name));
338
339         return NT_STATUS_ACCESS_DENIED;
340 }
341
342 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
343                                                     TALLOC_CTX *mem_ctx,
344                                                     const char *computer_name,
345                                                     struct netr_Authenticator *received_authenticator,
346                                                     struct netr_Authenticator *return_authenticator,
347                                                     struct netlogon_creds_CredentialState **creds_out)
348 {
349         NTSTATUS nt_status;
350         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
351         bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
352
353         if (schannel_global_required) {
354                 nt_status = schannel_check_required(auth_info,
355                                                     computer_name,
356                                                     true, false);
357                 if (!NT_STATUS_IS_OK(nt_status)) {
358                         return nt_status;
359                 }
360         }
361
362         nt_status = schannel_check_creds_state(mem_ctx,
363                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_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         nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
621         NT_STATUS_NOT_OK_RETURN(nt_status);
622
623         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
624         /* It appears that level 6 is not individually encrypted */
625         if ((r->in.validation_level != 6) &&
626             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
627                 /* This key is sent unencrypted without the ARCFOUR flag set */
628                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
629                         netlogon_creds_arcfour_crypt(creds,
630                                             sam->key.key,
631                                             sizeof(sam->key.key));
632                 }
633         }
634
635         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
636         /* It appears that level 6 is not individually encrypted */
637         if ((r->in.validation_level != 6) &&
638             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
639                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
640                         netlogon_creds_arcfour_crypt(creds,
641                                             sam->LMSessKey.key,
642                                             sizeof(sam->LMSessKey.key));
643                 } else {
644                         netlogon_creds_des_encrypt_LMKey(creds,
645                                                 &sam->LMSessKey);
646                 }
647         }
648
649         switch (r->in.validation_level) {
650         case 2:
651                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
652                 NT_STATUS_HAVE_NO_MEMORY(sam2);
653                 sam2->base = *sam;
654                 r->out.validation->sam2 = sam2;
655                 break;
656
657         case 3:
658                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
659                 NT_STATUS_HAVE_NO_MEMORY(sam3);
660                 sam3->base = *sam;
661                 r->out.validation->sam3 = sam3;
662                 break;
663
664         case 6:
665                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
666                 NT_STATUS_HAVE_NO_MEMORY(sam6);
667                 sam6->base = *sam;
668                 sam6->forest.string = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
669                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
670                                                          sam->account_name.string, sam6->forest.string);
671                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
672                 r->out.validation->sam6 = sam6;
673                 break;
674
675         default:
676                 break;
677         }
678
679         *r->out.authoritative = 1;
680
681         /* TODO: Describe and deal with these flags */
682         *r->out.flags = 0;
683
684         return NT_STATUS_OK;
685 }
686
687 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
688                                      struct netr_LogonSamLogonEx *r)
689 {
690         NTSTATUS nt_status;
691         struct netlogon_creds_CredentialState *creds;
692
693         nt_status = schannel_get_creds_state(mem_ctx,
694                                              lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
695                                              lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
696                                              r->in.computer_name, &creds);
697         if (!NT_STATUS_IS_OK(nt_status)) {
698                 return nt_status;
699         }
700
701         if (!dce_call->conn->auth_state.auth_info ||
702             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
703                 return NT_STATUS_ACCESS_DENIED;
704         }
705         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
706 }
707
708 /*
709   netr_LogonSamLogonWithFlags
710
711 */
712 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
713                                             struct netr_LogonSamLogonWithFlags *r)
714 {
715         NTSTATUS nt_status;
716         struct netlogon_creds_CredentialState *creds;
717         struct netr_LogonSamLogonEx r2;
718
719         struct netr_Authenticator *return_authenticator;
720
721         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
722         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
723
724         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
725                                                         mem_ctx,
726                                                         r->in.computer_name,
727                                                         r->in.credential, return_authenticator,
728                                                         &creds);
729         NT_STATUS_NOT_OK_RETURN(nt_status);
730
731         ZERO_STRUCT(r2);
732
733         r2.in.server_name       = r->in.server_name;
734         r2.in.computer_name     = r->in.computer_name;
735         r2.in.logon_level       = r->in.logon_level;
736         r2.in.logon             = r->in.logon;
737         r2.in.validation_level  = r->in.validation_level;
738         r2.in.flags             = r->in.flags;
739         r2.out.validation       = r->out.validation;
740         r2.out.authoritative    = r->out.authoritative;
741         r2.out.flags            = r->out.flags;
742
743         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
744
745         r->out.return_authenticator     = return_authenticator;
746
747         return nt_status;
748 }
749
750 /*
751   netr_LogonSamLogon
752 */
753 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
754                                    struct netr_LogonSamLogon *r)
755 {
756         struct netr_LogonSamLogonWithFlags r2;
757         uint32_t flags = 0;
758         NTSTATUS status;
759
760         ZERO_STRUCT(r2);
761
762         r2.in.server_name = r->in.server_name;
763         r2.in.computer_name = r->in.computer_name;
764         r2.in.credential  = r->in.credential;
765         r2.in.return_authenticator = r->in.return_authenticator;
766         r2.in.logon_level = r->in.logon_level;
767         r2.in.logon = r->in.logon;
768         r2.in.validation_level = r->in.validation_level;
769         r2.in.flags = &flags;
770         r2.out.validation = r->out.validation;
771         r2.out.authoritative = r->out.authoritative;
772         r2.out.flags = &flags;
773
774         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
775
776         r->out.return_authenticator = r2.out.return_authenticator;
777
778         return status;
779 }
780
781
782 /*
783   netr_LogonSamLogoff
784 */
785 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
786                        struct netr_LogonSamLogoff *r)
787 {
788         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
789 }
790
791
792
793 /*
794   netr_DatabaseDeltas
795 */
796 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
797                        struct netr_DatabaseDeltas *r)
798 {
799         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
800 }
801
802
803 /*
804   netr_DatabaseSync2
805 */
806 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
807                        struct netr_DatabaseSync2 *r)
808 {
809         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
810         return NT_STATUS_NOT_IMPLEMENTED;
811 }
812
813
814 /*
815   netr_DatabaseSync
816 */
817 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
818                        struct netr_DatabaseSync *r)
819 {
820         struct netr_DatabaseSync2 r2;
821         NTSTATUS status;
822
823         ZERO_STRUCT(r2);
824
825         r2.in.logon_server = r->in.logon_server;
826         r2.in.computername = r->in.computername;
827         r2.in.credential = r->in.credential;
828         r2.in.database_id = r->in.database_id;
829         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
830         r2.in.sync_context = r->in.sync_context;
831         r2.out.sync_context = r->out.sync_context;
832         r2.out.delta_enum_array = r->out.delta_enum_array;
833         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
834
835         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
836
837         return status;
838 }
839
840
841 /*
842   netr_AccountDeltas
843 */
844 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
845                        struct netr_AccountDeltas *r)
846 {
847         /* w2k3 returns "NOT IMPLEMENTED" for this call */
848         return NT_STATUS_NOT_IMPLEMENTED;
849 }
850
851
852 /*
853   netr_AccountSync
854 */
855 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
856                        struct netr_AccountSync *r)
857 {
858         /* w2k3 returns "NOT IMPLEMENTED" for this call */
859         return NT_STATUS_NOT_IMPLEMENTED;
860 }
861
862
863 /*
864   netr_GetDcName
865 */
866 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
867                        struct netr_GetDcName *r)
868 {
869         const char * const attrs[] = { NULL };
870         struct ldb_context *sam_ctx;
871         struct ldb_message **res;
872         struct ldb_dn *domain_dn;
873         int ret;
874         const char *dcname;
875
876         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
877                                 dce_call->conn->dce_ctx->lp_ctx,
878                                 dce_call->conn->auth_state.session_info);
879         if (sam_ctx == NULL) {
880                 return WERR_DS_UNAVAILABLE;
881         }
882
883         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
884                                        r->in.domainname);
885         if (domain_dn == NULL) {
886                 return WERR_DS_UNAVAILABLE;
887         }
888
889         ret = gendb_search_dn(sam_ctx, mem_ctx,
890                               domain_dn, &res, attrs);
891         if (ret != 1) {
892                 return WERR_NO_SUCH_DOMAIN;
893         }
894
895         /* TODO: - return real IP address
896          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
897          */
898         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
899                                  lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
900         W_ERROR_HAVE_NO_MEMORY(dcname);
901
902         *r->out.dcname = dcname;
903         return WERR_OK;
904 }
905
906
907 /*
908   netr_LogonControl2Ex
909 */
910 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
911                        struct netr_LogonControl2Ex *r)
912 {
913         return WERR_NOT_SUPPORTED;
914 }
915
916
917 /*
918   netr_LogonControl
919 */
920 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
921                        struct netr_LogonControl *r)
922 {
923         struct netr_LogonControl2Ex r2;
924         WERROR werr;
925
926         if (r->in.level == 0x00000001) {
927                 ZERO_STRUCT(r2);
928
929                 r2.in.logon_server = r->in.logon_server;
930                 r2.in.function_code = r->in.function_code;
931                 r2.in.level = r->in.level;
932                 r2.in.data = NULL;
933                 r2.out.query = r->out.query;
934
935                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
936         } else if (r->in.level == 0x00000002) {
937                 werr = WERR_NOT_SUPPORTED;
938         } else {
939                 werr = WERR_UNKNOWN_LEVEL;
940         }
941
942         return werr;
943 }
944
945
946 /*
947   netr_LogonControl2
948 */
949 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
950                        struct netr_LogonControl2 *r)
951 {
952         struct netr_LogonControl2Ex r2;
953         WERROR werr;
954
955         ZERO_STRUCT(r2);
956
957         r2.in.logon_server = r->in.logon_server;
958         r2.in.function_code = r->in.function_code;
959         r2.in.level = r->in.level;
960         r2.in.data = r->in.data;
961         r2.out.query = r->out.query;
962
963         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
964
965         return werr;
966 }
967
968
969 /*
970   netr_GetAnyDCName
971 */
972 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973                        struct netr_GetAnyDCName *r)
974 {
975         struct netr_GetDcName r2;
976         WERROR werr;
977
978         ZERO_STRUCT(r2);
979
980         r2.in.logon_server      = r->in.logon_server;
981         r2.in.domainname        = r->in.domainname;
982         r2.out.dcname           = r->out.dcname;
983
984         werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
985
986         return werr;
987 }
988
989
990 /*
991   netr_DatabaseRedo
992 */
993 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
994                        struct netr_DatabaseRedo *r)
995 {
996         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
997 }
998
999
1000 /*
1001   netr_NetrEnumerateTurstedDomains
1002 */
1003 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1004                        struct netr_NetrEnumerateTrustedDomains *r)
1005 {
1006         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1007 }
1008
1009
1010 /*
1011   netr_LogonGetCapabilities
1012 */
1013 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1014                        struct netr_LogonGetCapabilities *r)
1015 {
1016         /* we don't support AES yet */
1017         return NT_STATUS_NOT_IMPLEMENTED;
1018 }
1019
1020
1021 /*
1022   netr_NETRLOGONSETSERVICEBITS
1023 */
1024 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1025                        struct netr_NETRLOGONSETSERVICEBITS *r)
1026 {
1027         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1028 }
1029
1030
1031 /*
1032   netr_LogonGetTrustRid
1033 */
1034 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1035                        struct netr_LogonGetTrustRid *r)
1036 {
1037         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1038 }
1039
1040
1041 /*
1042   netr_NETRLOGONCOMPUTESERVERDIGEST
1043 */
1044 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1045                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1046 {
1047         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1048 }
1049
1050
1051 /*
1052   netr_NETRLOGONCOMPUTECLIENTDIGEST
1053 */
1054 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1055                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1056 {
1057         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1058 }
1059
1060
1061
1062 /*
1063   netr_DsRGetSiteName
1064 */
1065 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1066                                   struct netr_DsRGetSiteName *r)
1067 {
1068         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1069 }
1070
1071
1072 /*
1073   fill in a netr_OneDomainInfo from a ldb search result
1074 */
1075 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1076                                      struct loadparm_context *lp_ctx,
1077                                      struct ldb_context *sam_ctx,
1078                                      struct ldb_message *res,
1079                                      struct netr_OneDomainInfo *info,
1080                                      bool is_local, bool is_trust_list)
1081 {
1082         ZERO_STRUCTP(info);
1083
1084         if (is_trust_list) {
1085                 /* w2k8 only fills this on trusted domains */
1086                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1087                 info->trust_extension.length = 16;
1088                 info->trust_extension.info->flags =
1089                         NETR_TRUST_FLAG_TREEROOT |
1090                         NETR_TRUST_FLAG_IN_FOREST |
1091                         NETR_TRUST_FLAG_PRIMARY |
1092                         NETR_TRUST_FLAG_NATIVE;
1093
1094                 info->trust_extension.info->parent_index = 0; /* should be index into array
1095                                                                  of parent */
1096                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1097                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1098         }
1099
1100         if (is_trust_list) {
1101                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1102                 info->dns_forestname.string = NULL;
1103         } else {
1104                 char *p;
1105                 /* TODO: we need a common function for pulling the forest */
1106                 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1107                 if (!info->dns_forestname.string) {
1108                         return NT_STATUS_NO_SUCH_DOMAIN;
1109                 }
1110                 p = strchr(info->dns_forestname.string, '/');
1111                 if (p) {
1112                         *p = '\0';
1113                 }
1114                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1115
1116         }
1117
1118         if (is_local) {
1119                 info->domainname.string = lp_sam_name(lp_ctx);
1120                 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1121                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1122                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1123         } else {
1124                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1125                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1126                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1127                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1128         }
1129         if (!is_trust_list) {
1130                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1131         }
1132
1133         return NT_STATUS_OK;
1134 }
1135
1136 /*
1137   netr_LogonGetDomainInfo
1138   this is called as part of the ADS domain logon procedure.
1139
1140   It has an important role in convaying details about the client, such
1141   as Operating System, Version, Service Pack etc.
1142 */
1143 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1144         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1145 {
1146         struct netlogon_creds_CredentialState *creds;
1147         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1148                 "securityIdentifier", "trustPartner", NULL };
1149         const char * const attrs2[] = { "dNSHostName",
1150                 "msDS-SupportedEncryptionTypes", NULL };
1151         const char * const attrs3[] = { NULL };
1152         const char *temp_str, *temp_str2;
1153         const char *old_dns_hostname;
1154         struct ldb_context *sam_ctx;
1155         struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1156         struct ldb_dn *workstation_dn;
1157         struct netr_DomainInformation *domain_info;
1158         struct netr_LsaPolicyInformation *lsa_policy_info;
1159         struct netr_OsVersionInfoEx *os_version;
1160         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1161         bool update_dns_hostname = true;
1162         int ret, ret3, i;
1163         NTSTATUS status;
1164
1165         status = dcesrv_netr_creds_server_step_check(dce_call,
1166                                                      mem_ctx,
1167                                                      r->in.computer_name,
1168                                                      r->in.credential,
1169                                                      r->out.return_authenticator,
1170                                                      &creds);
1171         if (!NT_STATUS_IS_OK(status)) {
1172                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1173         }
1174         NT_STATUS_NOT_OK_RETURN(status);
1175
1176         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1177                 dce_call->conn->dce_ctx->lp_ctx,
1178                 system_session(dce_call->conn->dce_ctx->lp_ctx));
1179         if (sam_ctx == NULL) {
1180                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1181         }
1182
1183         switch (r->in.level) {
1184         case 1: /* Domain information */
1185
1186                 /*
1187                  * Updates the DNS hostname when the client wishes that the
1188                  * server should handle this for him
1189                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1190                  * See MS-NRPC section 3.5.4.3.9
1191                  */
1192                 if ((r->in.query->workstation_info->workstation_flags
1193                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1194                         update_dns_hostname = false;
1195                 }
1196
1197                 /*
1198                  * Checks that the computer name parameter without possible "$"
1199                  * matches as prefix with the DNS hostname in the workstation
1200                  * info structure.
1201                  */
1202                 temp_str = talloc_strndup(mem_ctx,
1203                                           r->in.computer_name,
1204                                           strcspn(r->in.computer_name, "$"));
1205                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1206                 temp_str2 = talloc_strndup(mem_ctx,
1207                                            r->in.query->workstation_info->dns_hostname,
1208                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1209                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1210                 if (strcasecmp(temp_str, temp_str2) != 0) {
1211                         update_dns_hostname = false;
1212                 }
1213
1214                 /*
1215                  * Check that the DNS hostname when it should be updated
1216                  * will be used only by maximum one host.
1217                  */
1218                 ret = gendb_search(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1219                                    &res0, attrs3, "(dNSHostName=%s)",
1220                                    r->in.query->workstation_info->dns_hostname);
1221                 if (ret < 0) {
1222                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1223                 }
1224                 if (ret >= 1) {
1225                         update_dns_hostname = false;
1226                 }
1227
1228                 talloc_free(res0);
1229
1230                 /* Prepare the workstation DN */
1231                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1232                         dom_sid_string(mem_ctx, creds->sid));
1233                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1234
1235                 /* Lookup for attributes in workstation object */
1236                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1237                         &res1, attrs2);
1238                 if (ret != 1) {
1239                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1240                 }
1241
1242                 /* Gets the old DNS hostname */
1243                 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1244                         NULL);
1245
1246                 /* Gets host informations and put them in our directory */
1247                 new_msg = ldb_msg_new(mem_ctx);
1248                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1249
1250                 new_msg->dn = workstation_dn;
1251
1252                 /* Deletes old OS version values */
1253                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1254                         "operatingSystemServicePack");
1255                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1256                         "operatingSystemVersion");
1257
1258                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1259                         DEBUG(3,("Impossible to update samdb: %s\n",
1260                                 ldb_errstring(sam_ctx)));
1261                 }
1262
1263                 talloc_free(new_msg);
1264
1265                 new_msg = ldb_msg_new(mem_ctx);
1266                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1267
1268                 new_msg->dn = workstation_dn;
1269
1270                 /* Sets the OS name */
1271                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1272                         "operatingSystem",
1273                         r->in.query->workstation_info->os_name.string);
1274
1275                 /*
1276                  * Sets informations from "os_version". On a empty structure
1277                  * the values are cleared.
1278                  */
1279                 if (r->in.query->workstation_info->os_version.os != NULL) {
1280                         os_version = &r->in.query->workstation_info->os_version.os->os;
1281
1282                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1283                                              "operatingSystemServicePack",
1284                                              os_version->CSDVersion);
1285
1286                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1287                                 "operatingSystemVersion",
1288                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1289                                         os_version->MajorVersion,
1290                                         os_version->MinorVersion,
1291                                         os_version->BuildNumber
1292                                 )
1293                         );
1294                 }
1295
1296                 /*
1297                  * If the boolean "update_dns_hostname" remained true, then we
1298                  * are fine to start the update.
1299                  */
1300                 if (update_dns_hostname) {
1301                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1302                                 "dNSHostname",
1303                         r->in.query->workstation_info->dns_hostname);
1304
1305                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1306                                 "servicePrincipalName",
1307                                 talloc_asprintf(mem_ctx, "HOST/%s",
1308                                 r->in.computer_name)
1309                         );
1310                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1311                                 "servicePrincipalName",
1312                                 talloc_asprintf(mem_ctx, "HOST/%s",
1313                                 r->in.query->workstation_info->dns_hostname)
1314                         );
1315                 }
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                 /* Writes back the domain information */
1325
1326                 /* We need to do two searches. The first will pull our primary
1327                    domain and the second will pull any trusted domains. Our
1328                    primary domain is also a "trusted" domain, so we need to
1329                    put the primary domain into the lists of returned trusts as
1330                    well. */
1331                 ret = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1332                         &res2, attrs);
1333                 if (ret != 1) {
1334                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1335                 }
1336
1337                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1338                         "(objectClass=trustedDomain)");
1339                 if (ret3 == -1) {
1340                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1341                 }
1342
1343                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1344                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1345
1346                 ZERO_STRUCTP(domain_info);
1347
1348                 /* Informations about the local and trusted domains */
1349
1350                 status = fill_one_domain_info(mem_ctx,
1351                         dce_call->conn->dce_ctx->lp_ctx,
1352                         sam_ctx, res2[0], &domain_info->primary_domain,
1353                         true, false);
1354                 NT_STATUS_NOT_OK_RETURN(status);
1355
1356                 domain_info->trusted_domain_count = ret3 + 1;
1357                 domain_info->trusted_domains = talloc_array(mem_ctx,
1358                         struct netr_OneDomainInfo,
1359                         domain_info->trusted_domain_count);
1360                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1361
1362                 for (i=0;i<ret3;i++) {
1363                         status = fill_one_domain_info(mem_ctx,
1364                                 dce_call->conn->dce_ctx->lp_ctx,
1365                                 sam_ctx, res3[i],
1366                                 &domain_info->trusted_domains[i],
1367                                 false, true);
1368                         NT_STATUS_NOT_OK_RETURN(status);
1369                 }
1370
1371                 status = fill_one_domain_info(mem_ctx,
1372                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1373                         &domain_info->trusted_domains[i], true, true);
1374                 NT_STATUS_NOT_OK_RETURN(status);
1375
1376                 /* Sets the supported encryption types */
1377                 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1378                         "msDS-SupportedEncryptionTypes",
1379                         default_supported_enc_types);
1380
1381                 /* Other host domain informations */
1382
1383                 lsa_policy_info = talloc(mem_ctx,
1384                         struct netr_LsaPolicyInformation);
1385                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1386                 ZERO_STRUCTP(lsa_policy_info);
1387
1388                 domain_info->lsa_policy = *lsa_policy_info;
1389
1390                 /* The DNS hostname is only returned back when there is a chance
1391                  * for a change. */
1392                 if ((r->in.query->workstation_info->workstation_flags
1393                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1394                         domain_info->dns_hostname.string = old_dns_hostname;
1395                 } else {
1396                         domain_info->dns_hostname.string = NULL;
1397                 }
1398
1399                 domain_info->workstation_flags =
1400                         r->in.query->workstation_info->workstation_flags;
1401
1402                 r->out.info->domain_info = domain_info;
1403         break;
1404         case 2: /* LSA policy information - not used at the moment */
1405                 lsa_policy_info = talloc(mem_ctx,
1406                         struct netr_LsaPolicyInformation);
1407                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1408                 ZERO_STRUCTP(lsa_policy_info);
1409
1410                 r->out.info->lsa_policy_info = lsa_policy_info;
1411         break;
1412         default:
1413                 return NT_STATUS_INVALID_LEVEL;
1414         break;
1415         }
1416
1417         return NT_STATUS_OK;
1418 }
1419
1420
1421
1422 /*
1423   netr_ServerPasswordGet
1424 */
1425 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1426                        struct netr_ServerPasswordGet *r)
1427 {
1428         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1429 }
1430
1431
1432 /*
1433   netr_NETRLOGONSENDTOSAM
1434 */
1435 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1436                        struct netr_NETRLOGONSENDTOSAM *r)
1437 {
1438         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1439 }
1440
1441
1442 /*
1443   netr_DsRAddressToSitenamesW
1444 */
1445 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1446                        struct netr_DsRAddressToSitenamesW *r)
1447 {
1448         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1449 }
1450
1451
1452 /*
1453   netr_DsRGetDCNameEx2
1454 */
1455 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1456                                           TALLOC_CTX *mem_ctx,
1457                                           struct netr_DsRGetDCNameEx2 *r)
1458 {
1459         const char * const attrs[] = { "objectGUID", NULL };
1460         struct ldb_context *sam_ctx;
1461         struct ldb_message **res;
1462         struct ldb_dn *domain_dn;
1463         int ret;
1464         struct netr_DsRGetDCNameInfo *info;
1465         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1466
1467         ZERO_STRUCTP(r->out.info);
1468
1469         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1470                                 dce_call->conn->auth_state.session_info);
1471         if (sam_ctx == NULL) {
1472                 return WERR_DS_UNAVAILABLE;
1473         }
1474
1475         /* Windows 7 sends the domain name in the form the user typed, so we
1476          * have to cope  with both the short and long form here */
1477         if (r->in.domain_name != NULL &&
1478             !lp_is_my_domain_or_realm(lp_ctx, r->in.domain_name)) {
1479                 return WERR_NO_SUCH_DOMAIN;
1480         }
1481
1482         domain_dn = ldb_get_default_basedn(sam_ctx);
1483         if (domain_dn == NULL) {
1484                 return WERR_DS_UNAVAILABLE;
1485         }
1486
1487         ret = gendb_search_dn(sam_ctx, mem_ctx,
1488                               domain_dn, &res, attrs);
1489         if (ret != 1) {
1490                 return WERR_GENERAL_FAILURE;
1491         }
1492
1493         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1494         W_ERROR_HAVE_NO_MEMORY(info);
1495
1496         /* TODO: - return real IP address
1497          *       - check all r->in.* parameters
1498          *       (server_unc is ignored by w2k3!)
1499          */
1500         info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1501                                        lp_netbios_name(lp_ctx),
1502                                        lp_dnsdomain(lp_ctx));
1503         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1504
1505         info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1506         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1507
1508         info->dc_address_type = DS_ADDRESS_TYPE_INET;
1509         info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1510         info->domain_name = lp_dnsdomain(lp_ctx);
1511         info->forest_name = lp_dnsdomain(lp_ctx);
1512         info->dc_flags  = DS_DNS_FOREST_ROOT |
1513                           DS_DNS_DOMAIN |
1514                           DS_DNS_CONTROLLER |
1515                           DS_SERVER_WRITABLE |
1516                           DS_SERVER_CLOSEST |
1517                           DS_SERVER_TIMESERV |
1518                           DS_SERVER_KDC |
1519                           DS_SERVER_DS |
1520                           DS_SERVER_LDAP |
1521                           DS_SERVER_GC |
1522                           DS_SERVER_PDC;
1523
1524         info->dc_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1525         W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1526
1527         /* FIXME: Hardcoded site name */
1528         info->client_site_name = talloc_strdup(mem_ctx,
1529                                                "Default-First-Site-Name");
1530         W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1531
1532         *r->out.info = info;
1533
1534         return WERR_OK;
1535 }
1536
1537 /*
1538   netr_DsRGetDCNameEx
1539 */
1540 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1541                                   struct netr_DsRGetDCNameEx *r)
1542 {
1543         struct netr_DsRGetDCNameEx2 r2;
1544         WERROR werr;
1545
1546         ZERO_STRUCT(r2);
1547
1548         r2.in.server_unc = r->in.server_unc;
1549         r2.in.client_account = NULL;
1550         r2.in.mask = 0;
1551         r2.in.domain_guid = r->in.domain_guid;
1552         r2.in.domain_name = r->in.domain_name;
1553         r2.in.site_name = r->in.site_name;
1554         r2.in.flags = r->in.flags;
1555         r2.out.info = r->out.info;
1556
1557         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1558
1559         return werr;
1560 }
1561
1562 /*
1563   netr_DsRGetDCName
1564 */
1565 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1566                                 struct netr_DsRGetDCName *r)
1567 {
1568         struct netr_DsRGetDCNameEx2 r2;
1569         WERROR werr;
1570
1571         ZERO_STRUCT(r2);
1572
1573         r2.in.server_unc = r->in.server_unc;
1574         r2.in.client_account = NULL;
1575         r2.in.mask = 0;
1576         r2.in.domain_name = r->in.domain_name;
1577         r2.in.domain_guid = r->in.domain_guid;
1578
1579         r2.in.site_name = NULL; /* should fill in from site GUID */
1580         r2.in.flags = r->in.flags;
1581         r2.out.info = r->out.info;
1582
1583         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1584
1585         return werr;
1586 }
1587 /*
1588   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1589 */
1590 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1591                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1592 {
1593         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1594 }
1595
1596
1597 /*
1598   netr_NetrEnumerateTrustedDomainsEx
1599 */
1600 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1601                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1602 {
1603         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1604 }
1605
1606
1607 /*
1608   netr_DsRAddressToSitenamesExW
1609 */
1610 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1611                                                    struct netr_DsRAddressToSitenamesExW *r)
1612 {
1613         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1614         int i;
1615
1616         /* we should map the provided IPs to site names, once we have
1617          * sites support
1618          */
1619         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1620         W_ERROR_HAVE_NO_MEMORY(ctr);
1621
1622         *r->out.ctr = ctr;
1623
1624         ctr->count = r->in.count;
1625         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1626         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1627         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1628         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1629
1630         for (i=0; i<ctr->count; i++) {
1631                 /* FIXME: Hardcoded site name */
1632                 ctr->sitename[i].string   = "Default-First-Site-Name";
1633                 ctr->subnetname[i].string = NULL;
1634         }
1635
1636         return WERR_OK;
1637 }
1638
1639
1640 /*
1641   netr_DsrGetDcSiteCoverageW
1642 */
1643 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1644                        struct netr_DsrGetDcSiteCoverageW *r)
1645 {
1646         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1647 }
1648
1649
1650 #define GET_CHECK_STR(dest, mem, msg, attr) \
1651 do {\
1652         const char *s; \
1653         s = samdb_result_string(msg, attr, NULL); \
1654         if (!s) { \
1655                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1656                           "without flatname\n", \
1657                           ldb_dn_get_linearized(msg->dn))); \
1658                 continue; \
1659         } \
1660         dest = talloc_strdup(mem, s); \
1661         W_ERROR_HAVE_NO_MEMORY(dest); \
1662 } while(0)
1663
1664
1665 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1666                                          struct ldb_context *sam_ctx,
1667                                          struct netr_DomainTrustList *trusts,
1668                                          uint32_t trust_flags)
1669 {
1670         struct ldb_dn *system_dn;
1671         struct ldb_message **dom_res = NULL;
1672         const char *trust_attrs[] = { "flatname", "trustPartner",
1673                                       "securityIdentifier", "trustDirection",
1674                                       "trustType", "trustAttributes", NULL };
1675         int i, n;
1676         int ret;
1677
1678         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1679                              NETR_TRUST_FLAG_OUTBOUND))) {
1680                 return WERR_INVALID_FLAGS;
1681         }
1682
1683         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1684                                     ldb_get_default_basedn(sam_ctx),
1685                                     "(&(objectClass=container)(cn=System))");
1686         if (!system_dn) {
1687                 return WERR_GENERAL_FAILURE;
1688         }
1689
1690         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1691                            &dom_res, trust_attrs,
1692                            "(objectclass=trustedDomain)");
1693
1694         for (i = 0; i < ret; i++) {
1695                 unsigned int trust_dir;
1696                 uint32_t flags = 0;
1697
1698                 trust_dir = samdb_result_uint(dom_res[i],
1699                                               "trustDirection", 0);
1700
1701                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1702                         flags |= NETR_TRUST_FLAG_INBOUND;
1703                 }
1704                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1705                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1706                 }
1707
1708                 if (!(flags & trust_flags)) {
1709                         /* this trust direction was not requested */
1710                         continue;
1711                 }
1712
1713                 n = trusts->count;
1714                 trusts->array = talloc_realloc(trusts, trusts->array,
1715                                                struct netr_DomainTrust,
1716                                                n + 1);
1717                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1718
1719                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1720                               dom_res[i], "flatname");
1721                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1722                               dom_res[i], "trustPartner");
1723
1724                 trusts->array[n].trust_flags = flags;
1725                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1726                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1727                         /* TODO: find if we have parent in the list */
1728                         trusts->array[n].parent_index = 0;
1729                 }
1730
1731                 trusts->array[n].trust_type =
1732                                 samdb_result_uint(dom_res[i],
1733                                                   "trustType", 0);
1734                 trusts->array[n].trust_attributes =
1735                                 samdb_result_uint(dom_res[i],
1736                                                   "trustAttributes", 0);
1737
1738                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1739                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1740                         struct dom_sid zero_sid;
1741                         ZERO_STRUCT(zero_sid);
1742                         trusts->array[n].sid =
1743                                 dom_sid_dup(trusts, &zero_sid);
1744                 } else {
1745                         trusts->array[n].sid =
1746                                 samdb_result_dom_sid(trusts, dom_res[i],
1747                                                      "securityIdentifier");
1748                 }
1749                 trusts->array[n].guid = GUID_zero();
1750
1751                 trusts->count = n + 1;
1752         }
1753
1754         talloc_free(dom_res);
1755         return WERR_OK;
1756 }
1757
1758 /*
1759   netr_DsrEnumerateDomainTrusts
1760 */
1761 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1762                                                    TALLOC_CTX *mem_ctx,
1763                                                    struct netr_DsrEnumerateDomainTrusts *r)
1764 {
1765         struct netr_DomainTrustList *trusts;
1766         struct ldb_context *sam_ctx;
1767         int ret;
1768         struct ldb_message **dom_res;
1769         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1770         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1771         const char *dnsdomain = lp_dnsdomain(lp_ctx);
1772         const char *p;
1773         WERROR werr;
1774
1775         if (r->in.trust_flags & 0xFFFFFE00) {
1776                 return WERR_INVALID_FLAGS;
1777         }
1778
1779         /* TODO: turn to hard check once we are sure this is 100% correct */
1780         if (!r->in.server_name) {
1781                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1782                           "But received NULL!\n", dnsdomain));
1783         } else {
1784                 p = strchr(r->in.server_name, '.');
1785                 if (!p) {
1786                         DEBUG(3, ("Invalid domain! Expected name in domain "
1787                                   "[%s]. But received [%s]!\n",
1788                                   dnsdomain, r->in.server_name));
1789                         p = r->in.server_name;
1790                 } else {
1791                         p++;
1792                 }
1793                 if (strcasecmp(p, dnsdomain)) {
1794                         DEBUG(3, ("Invalid domain! Expected name in domain "
1795                                   "[%s]. But received [%s]!\n",
1796                                   dnsdomain, r->in.server_name));
1797                 }
1798         }
1799
1800         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1801         W_ERROR_HAVE_NO_MEMORY(trusts);
1802
1803         trusts->count = 0;
1804         r->out.trusts = trusts;
1805
1806         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1807                                 dce_call->conn->auth_state.session_info);
1808         if (sam_ctx == NULL) {
1809                 return WERR_GENERAL_FAILURE;
1810         }
1811
1812         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1813             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1814
1815                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1816                                                   trusts, r->in.trust_flags);
1817                 W_ERROR_NOT_OK_RETURN(werr);
1818         }
1819
1820         /* NOTE: we currently are always the root of the forest */
1821         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1822                 int n = trusts->count;
1823
1824                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1825                                       &dom_res, dom_attrs);
1826                 if (ret != 1) {
1827                         return WERR_GENERAL_FAILURE;
1828                 }
1829
1830                 trusts->count = n + 1;
1831                 trusts->array = talloc_realloc(trusts, trusts->array,
1832                                                struct netr_DomainTrust,
1833                                                trusts->count);
1834                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1835
1836                 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1837                 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1838                 trusts->array[n].trust_flags =
1839                         NETR_TRUST_FLAG_NATIVE |
1840                         NETR_TRUST_FLAG_TREEROOT |
1841                         NETR_TRUST_FLAG_IN_FOREST |
1842                         NETR_TRUST_FLAG_PRIMARY;
1843                 /* we are always the root domain for now */
1844                 trusts->array[n].parent_index = 0;
1845                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1846                 trusts->array[n].trust_attributes = 0;
1847                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1848                                                             dom_res[0],
1849                                                             "objectSid");
1850                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1851                                                           "objectGUID");
1852                 talloc_free(dom_res);
1853         }
1854
1855         return WERR_OK;
1856 }
1857
1858
1859 /*
1860   netr_DsrDeregisterDNSHostRecords
1861 */
1862 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1863                        struct netr_DsrDeregisterDNSHostRecords *r)
1864 {
1865         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1866 }
1867
1868
1869 /*
1870   netr_ServerTrustPasswordsGet
1871 */
1872 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1873                        struct netr_ServerTrustPasswordsGet *r)
1874 {
1875         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1876 }
1877
1878
1879 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
1880                                       struct ldb_context *sam_ctx,
1881                                       struct loadparm_context *lp_ctx,
1882                                       struct lsa_ForestTrustInformation *info)
1883 {
1884         struct lsa_ForestTrustDomainInfo *domain_info;
1885         struct lsa_ForestTrustRecord *e;
1886         struct ldb_message **dom_res;
1887         const char * const dom_attrs[] = { "objectSid", NULL };
1888         int ret;
1889
1890         /* we need to provide 2 entries:
1891          * 1. the Root Forest name
1892          * 2. the Domain Information
1893          */
1894
1895         info->count = 2;
1896         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
1897         W_ERROR_HAVE_NO_MEMORY(info->entries);
1898
1899         /* Forest root info */
1900         e = talloc(info, struct lsa_ForestTrustRecord);
1901         W_ERROR_HAVE_NO_MEMORY(e);
1902
1903         e->flags = 0;
1904         e->level = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
1905         e->time = 0; /* so far always 0 in trces. */
1906         e->forest_trust_data.top_level_name.string = lp_dnsdomain(lp_ctx);
1907
1908         info->entries[0] = e;
1909
1910         /* Domain info */
1911         e = talloc(info, struct lsa_ForestTrustRecord);
1912         W_ERROR_HAVE_NO_MEMORY(e);
1913
1914         /* get our own domain info */
1915         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
1916         if (ret != 1) {
1917                 return WERR_GENERAL_FAILURE;
1918         }
1919
1920         /* TODO: check if disabled and set flags accordingly */
1921         e->flags = 0;
1922         e->level = LSA_FOREST_TRUST_DOMAIN_INFO;
1923         e->time = 0; /* so far always 0 in traces. */
1924
1925         domain_info = &e->forest_trust_data.domain_info;
1926         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
1927                                                        "objectSid");
1928         domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
1929         domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
1930
1931         info->entries[1] = e;
1932
1933         talloc_free(dom_res);
1934
1935         return WERR_OK;
1936 }
1937
1938 /*
1939   netr_DsRGetForestTrustInformation
1940 */
1941 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
1942                                                        TALLOC_CTX *mem_ctx,
1943                                                        struct netr_DsRGetForestTrustInformation *r)
1944 {
1945         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1946         struct lsa_ForestTrustInformation *info, **info_ptr;
1947         struct ldb_context *sam_ctx;
1948         WERROR werr;
1949
1950         if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
1951                 return WERR_CALL_NOT_IMPLEMENTED;
1952         }
1953
1954         if (r->in.flags & 0xFFFFFFFE) {
1955                 return WERR_INVALID_FLAGS;
1956         }
1957
1958         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1959                                 dce_call->conn->auth_state.session_info);
1960         if (sam_ctx == NULL) {
1961                 return WERR_GENERAL_FAILURE;
1962         }
1963
1964         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
1965                 if (!samdb_is_pdc(sam_ctx)) {
1966                         return WERR_NERR_NOTPRIMARY;
1967                 }
1968
1969                 if (r->in.trusted_domain_name == NULL) {
1970                         return WERR_INVALID_FLAGS;
1971                 }
1972
1973                 /* TODO: establish an schannel connection with
1974                  * r->in.trusted_domain_name and perform a
1975                  * netr_GetForestTrustInformation call against it */
1976
1977                 /* for now return not implementd */
1978                 return WERR_CALL_NOT_IMPLEMENTED;
1979         }
1980
1981         /* TODO: check r->in.server_name is our name */
1982
1983         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
1984         W_ERROR_HAVE_NO_MEMORY(info_ptr);
1985
1986         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
1987         W_ERROR_HAVE_NO_MEMORY(info);
1988
1989         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
1990         W_ERROR_NOT_OK_RETURN(werr);
1991
1992         *info_ptr = info;
1993         r->out.forest_trust_info = info_ptr;
1994
1995         return WERR_OK;
1996 }
1997
1998
1999 /*
2000   netr_GetForestTrustInformation
2001 */
2002 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2003                                                       TALLOC_CTX *mem_ctx,
2004                                                       struct netr_GetForestTrustInformation *r)
2005 {
2006         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2007         struct netlogon_creds_CredentialState *creds;
2008         struct lsa_ForestTrustInformation *info, **info_ptr;
2009         struct ldb_context *sam_ctx;
2010         NTSTATUS status;
2011         WERROR werr;
2012
2013         if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
2014                 return NT_STATUS_NOT_IMPLEMENTED;
2015         }
2016
2017         status = dcesrv_netr_creds_server_step_check(dce_call,
2018                                                      mem_ctx,
2019                                                      r->in.computer_name,
2020                                                      r->in.credential,
2021                                                      r->out.return_authenticator,
2022                                                      &creds);
2023         if (!NT_STATUS_IS_OK(status)) {
2024                 return status;
2025         }
2026
2027         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2028             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2029                 return NT_STATUS_NOT_IMPLEMENTED;
2030         }
2031
2032         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2033                                 dce_call->conn->auth_state.session_info);
2034         if (sam_ctx == NULL) {
2035                 return NT_STATUS_UNSUCCESSFUL;
2036         }
2037
2038         /* TODO: check r->in.server_name is our name */
2039
2040         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2041         if (!info_ptr) {
2042                 return NT_STATUS_NO_MEMORY;
2043         }
2044         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2045         if (!info) {
2046                 return NT_STATUS_NO_MEMORY;
2047         }
2048
2049         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2050         if (!W_ERROR_IS_OK(werr)) {
2051                 return werror_to_ntstatus(werr);
2052         }
2053
2054         *info_ptr = info;
2055         r->out.forest_trust_info = info_ptr;
2056
2057         return NT_STATUS_OK;
2058 }
2059
2060
2061 /*
2062   netr_ServerGetTrustInfo
2063 */
2064 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2065                        struct netr_ServerGetTrustInfo *r)
2066 {
2067         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2068 }
2069
2070
2071 /* include the generated boilerplate */
2072 #include "librpc/gen_ndr/ndr_netlogon_s.c"