s4:dsdb/common/util.c - add a call which determines centrally the forest DNS domainname
[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         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_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
716                                              lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
717                                              r->in.computer_name, &creds);
718         if (!NT_STATUS_IS_OK(nt_status)) {
719                 return nt_status;
720         }
721
722         if (!dce_call->conn->auth_state.auth_info ||
723             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
724                 return NT_STATUS_ACCESS_DENIED;
725         }
726         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
727 }
728
729 /*
730   netr_LogonSamLogonWithFlags
731
732 */
733 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
734                                             struct netr_LogonSamLogonWithFlags *r)
735 {
736         NTSTATUS nt_status;
737         struct netlogon_creds_CredentialState *creds;
738         struct netr_LogonSamLogonEx r2;
739
740         struct netr_Authenticator *return_authenticator;
741
742         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
743         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
744
745         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
746                                                         mem_ctx,
747                                                         r->in.computer_name,
748                                                         r->in.credential, return_authenticator,
749                                                         &creds);
750         NT_STATUS_NOT_OK_RETURN(nt_status);
751
752         ZERO_STRUCT(r2);
753
754         r2.in.server_name       = r->in.server_name;
755         r2.in.computer_name     = r->in.computer_name;
756         r2.in.logon_level       = r->in.logon_level;
757         r2.in.logon             = r->in.logon;
758         r2.in.validation_level  = r->in.validation_level;
759         r2.in.flags             = r->in.flags;
760         r2.out.validation       = r->out.validation;
761         r2.out.authoritative    = r->out.authoritative;
762         r2.out.flags            = r->out.flags;
763
764         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
765
766         r->out.return_authenticator     = return_authenticator;
767
768         return nt_status;
769 }
770
771 /*
772   netr_LogonSamLogon
773 */
774 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
775                                    struct netr_LogonSamLogon *r)
776 {
777         struct netr_LogonSamLogonWithFlags r2;
778         uint32_t flags = 0;
779         NTSTATUS status;
780
781         ZERO_STRUCT(r2);
782
783         r2.in.server_name = r->in.server_name;
784         r2.in.computer_name = r->in.computer_name;
785         r2.in.credential  = r->in.credential;
786         r2.in.return_authenticator = r->in.return_authenticator;
787         r2.in.logon_level = r->in.logon_level;
788         r2.in.logon = r->in.logon;
789         r2.in.validation_level = r->in.validation_level;
790         r2.in.flags = &flags;
791         r2.out.validation = r->out.validation;
792         r2.out.authoritative = r->out.authoritative;
793         r2.out.flags = &flags;
794
795         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
796
797         r->out.return_authenticator = r2.out.return_authenticator;
798
799         return status;
800 }
801
802
803 /*
804   netr_LogonSamLogoff
805 */
806 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
807                        struct netr_LogonSamLogoff *r)
808 {
809         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
810 }
811
812
813
814 /*
815   netr_DatabaseDeltas
816 */
817 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
818                        struct netr_DatabaseDeltas *r)
819 {
820         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
821 }
822
823
824 /*
825   netr_DatabaseSync2
826 */
827 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
828                        struct netr_DatabaseSync2 *r)
829 {
830         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
831         return NT_STATUS_NOT_IMPLEMENTED;
832 }
833
834
835 /*
836   netr_DatabaseSync
837 */
838 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
839                        struct netr_DatabaseSync *r)
840 {
841         struct netr_DatabaseSync2 r2;
842         NTSTATUS status;
843
844         ZERO_STRUCT(r2);
845
846         r2.in.logon_server = r->in.logon_server;
847         r2.in.computername = r->in.computername;
848         r2.in.credential = r->in.credential;
849         r2.in.database_id = r->in.database_id;
850         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
851         r2.in.sync_context = r->in.sync_context;
852         r2.out.sync_context = r->out.sync_context;
853         r2.out.delta_enum_array = r->out.delta_enum_array;
854         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
855
856         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
857
858         return status;
859 }
860
861
862 /*
863   netr_AccountDeltas
864 */
865 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
866                        struct netr_AccountDeltas *r)
867 {
868         /* w2k3 returns "NOT IMPLEMENTED" for this call */
869         return NT_STATUS_NOT_IMPLEMENTED;
870 }
871
872
873 /*
874   netr_AccountSync
875 */
876 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
877                        struct netr_AccountSync *r)
878 {
879         /* w2k3 returns "NOT IMPLEMENTED" for this call */
880         return NT_STATUS_NOT_IMPLEMENTED;
881 }
882
883
884 /*
885   netr_GetDcName
886 */
887 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
888                        struct netr_GetDcName *r)
889 {
890         const char * const attrs[] = { NULL };
891         struct ldb_context *sam_ctx;
892         struct ldb_message **res;
893         struct ldb_dn *domain_dn;
894         int ret;
895         const char *dcname;
896
897         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
898                                 dce_call->conn->dce_ctx->lp_ctx,
899                                 dce_call->conn->auth_state.session_info);
900         if (sam_ctx == NULL) {
901                 return WERR_DS_UNAVAILABLE;
902         }
903
904         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
905                                        r->in.domainname);
906         if (domain_dn == NULL) {
907                 return WERR_DS_UNAVAILABLE;
908         }
909
910         ret = gendb_search_dn(sam_ctx, mem_ctx,
911                               domain_dn, &res, attrs);
912         if (ret != 1) {
913                 return WERR_NO_SUCH_DOMAIN;
914         }
915
916         /* TODO: - return real IP address
917          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
918          */
919         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
920                                  lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
921         W_ERROR_HAVE_NO_MEMORY(dcname);
922
923         *r->out.dcname = dcname;
924         return WERR_OK;
925 }
926
927
928 /*
929   netr_LogonControl2Ex
930 */
931 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
932                        struct netr_LogonControl2Ex *r)
933 {
934         return WERR_NOT_SUPPORTED;
935 }
936
937
938 /*
939   netr_LogonControl
940 */
941 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
942                        struct netr_LogonControl *r)
943 {
944         struct netr_LogonControl2Ex r2;
945         WERROR werr;
946
947         if (r->in.level == 0x00000001) {
948                 ZERO_STRUCT(r2);
949
950                 r2.in.logon_server = r->in.logon_server;
951                 r2.in.function_code = r->in.function_code;
952                 r2.in.level = r->in.level;
953                 r2.in.data = NULL;
954                 r2.out.query = r->out.query;
955
956                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
957         } else if (r->in.level == 0x00000002) {
958                 werr = WERR_NOT_SUPPORTED;
959         } else {
960                 werr = WERR_UNKNOWN_LEVEL;
961         }
962
963         return werr;
964 }
965
966
967 /*
968   netr_LogonControl2
969 */
970 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
971                        struct netr_LogonControl2 *r)
972 {
973         struct netr_LogonControl2Ex r2;
974         WERROR werr;
975
976         ZERO_STRUCT(r2);
977
978         r2.in.logon_server = r->in.logon_server;
979         r2.in.function_code = r->in.function_code;
980         r2.in.level = r->in.level;
981         r2.in.data = r->in.data;
982         r2.out.query = r->out.query;
983
984         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
985
986         return werr;
987 }
988
989
990 /*
991   netr_GetAnyDCName
992 */
993 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
994                        struct netr_GetAnyDCName *r)
995 {
996         struct netr_GetDcName r2;
997         WERROR werr;
998
999         ZERO_STRUCT(r2);
1000
1001         r2.in.logon_server      = r->in.logon_server;
1002         r2.in.domainname        = r->in.domainname;
1003         r2.out.dcname           = r->out.dcname;
1004
1005         werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
1006
1007         return werr;
1008 }
1009
1010
1011 /*
1012   netr_DatabaseRedo
1013 */
1014 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1015                        struct netr_DatabaseRedo *r)
1016 {
1017         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1018 }
1019
1020
1021 /*
1022   netr_NetrEnumerateTurstedDomains
1023 */
1024 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1025                        struct netr_NetrEnumerateTrustedDomains *r)
1026 {
1027         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1028 }
1029
1030
1031 /*
1032   netr_LogonGetCapabilities
1033 */
1034 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1035                        struct netr_LogonGetCapabilities *r)
1036 {
1037         /* we don't support AES yet */
1038         return NT_STATUS_NOT_IMPLEMENTED;
1039 }
1040
1041
1042 /*
1043   netr_NETRLOGONSETSERVICEBITS
1044 */
1045 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1046                        struct netr_NETRLOGONSETSERVICEBITS *r)
1047 {
1048         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1049 }
1050
1051
1052 /*
1053   netr_LogonGetTrustRid
1054 */
1055 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1056                        struct netr_LogonGetTrustRid *r)
1057 {
1058         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1059 }
1060
1061
1062 /*
1063   netr_NETRLOGONCOMPUTESERVERDIGEST
1064 */
1065 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1066                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1067 {
1068         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1069 }
1070
1071
1072 /*
1073   netr_NETRLOGONCOMPUTECLIENTDIGEST
1074 */
1075 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1076                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1077 {
1078         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1079 }
1080
1081
1082
1083 /*
1084   netr_DsRGetSiteName
1085 */
1086 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1087                                   struct netr_DsRGetSiteName *r)
1088 {
1089         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1090 }
1091
1092
1093 /*
1094   fill in a netr_OneDomainInfo from a ldb search result
1095 */
1096 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1097                                      struct loadparm_context *lp_ctx,
1098                                      struct ldb_context *sam_ctx,
1099                                      struct ldb_message *res,
1100                                      struct netr_OneDomainInfo *info,
1101                                      bool is_local, bool is_trust_list)
1102 {
1103         ZERO_STRUCTP(info);
1104
1105         if (is_trust_list) {
1106                 /* w2k8 only fills this on trusted domains */
1107                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1108                 info->trust_extension.length = 16;
1109                 info->trust_extension.info->flags =
1110                         NETR_TRUST_FLAG_TREEROOT |
1111                         NETR_TRUST_FLAG_IN_FOREST |
1112                         NETR_TRUST_FLAG_PRIMARY |
1113                         NETR_TRUST_FLAG_NATIVE;
1114
1115                 info->trust_extension.info->parent_index = 0; /* should be index into array
1116                                                                  of parent */
1117                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1118                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1119         }
1120
1121         if (is_trust_list) {
1122                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1123                 info->dns_forestname.string = NULL;
1124         } else {
1125                 char *p;
1126                 /* TODO: we need a common function for pulling the forest */
1127                 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1128                 if (!info->dns_forestname.string) {
1129                         return NT_STATUS_NO_SUCH_DOMAIN;
1130                 }
1131                 p = strchr(info->dns_forestname.string, '/');
1132                 if (p) {
1133                         *p = '\0';
1134                 }
1135                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1136
1137         }
1138
1139         if (is_local) {
1140                 info->domainname.string = lp_sam_name(lp_ctx);
1141                 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1142                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1143                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1144         } else {
1145                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1146                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1147                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1148                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1149         }
1150         if (!is_trust_list) {
1151                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1152         }
1153
1154         return NT_STATUS_OK;
1155 }
1156
1157 /*
1158   netr_LogonGetDomainInfo
1159   this is called as part of the ADS domain logon procedure.
1160
1161   It has an important role in convaying details about the client, such
1162   as Operating System, Version, Service Pack etc.
1163 */
1164 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1165         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1166 {
1167         struct netlogon_creds_CredentialState *creds;
1168         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1169                 "securityIdentifier", "trustPartner", NULL };
1170         const char * const attrs2[] = { "dNSHostName",
1171                 "msDS-SupportedEncryptionTypes", NULL };
1172         const char * const attrs3[] = { NULL };
1173         const char *temp_str, *temp_str2;
1174         const char *old_dns_hostname;
1175         struct ldb_context *sam_ctx;
1176         struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1177         struct ldb_dn *workstation_dn;
1178         struct netr_DomainInformation *domain_info;
1179         struct netr_LsaPolicyInformation *lsa_policy_info;
1180         struct netr_OsVersionInfoEx *os_version;
1181         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1182         bool update_dns_hostname = true;
1183         int ret, ret3, i;
1184         NTSTATUS status;
1185
1186         status = dcesrv_netr_creds_server_step_check(dce_call,
1187                                                      mem_ctx,
1188                                                      r->in.computer_name,
1189                                                      r->in.credential,
1190                                                      r->out.return_authenticator,
1191                                                      &creds);
1192         if (!NT_STATUS_IS_OK(status)) {
1193                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1194         }
1195         NT_STATUS_NOT_OK_RETURN(status);
1196
1197         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1198                 dce_call->conn->dce_ctx->lp_ctx,
1199                 system_session(dce_call->conn->dce_ctx->lp_ctx));
1200         if (sam_ctx == NULL) {
1201                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1202         }
1203
1204         switch (r->in.level) {
1205         case 1: /* Domain information */
1206
1207                 /*
1208                  * Updates the DNS hostname when the client wishes that the
1209                  * server should handle this for him
1210                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1211                  * See MS-NRPC section 3.5.4.3.9
1212                  */
1213                 if ((r->in.query->workstation_info->workstation_flags
1214                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1215                         update_dns_hostname = false;
1216                 }
1217
1218                 /*
1219                  * Checks that the computer name parameter without possible "$"
1220                  * matches as prefix with the DNS hostname in the workstation
1221                  * info structure.
1222                  */
1223                 temp_str = talloc_strndup(mem_ctx,
1224                                           r->in.computer_name,
1225                                           strcspn(r->in.computer_name, "$"));
1226                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1227                 temp_str2 = talloc_strndup(mem_ctx,
1228                                            r->in.query->workstation_info->dns_hostname,
1229                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1230                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1231                 if (strcasecmp(temp_str, temp_str2) != 0) {
1232                         update_dns_hostname = false;
1233                 }
1234
1235                 /*
1236                  * Check that the DNS hostname when it should be updated
1237                  * will be used only by maximum one host.
1238                  */
1239                 ret = gendb_search(sam_ctx, mem_ctx,
1240                                    ldb_get_default_basedn(sam_ctx),
1241                                    &res0, attrs3, "(dNSHostName=%s)",
1242                                    r->in.query->workstation_info->dns_hostname);
1243                 if (ret < 0) {
1244                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1245                 }
1246                 if (ret >= 1) {
1247                         update_dns_hostname = false;
1248                 }
1249
1250                 talloc_free(res0);
1251
1252                 /* Prepare the workstation DN */
1253                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1254                         dom_sid_string(mem_ctx, creds->sid));
1255                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1256
1257                 /* Lookup for attributes in workstation object */
1258                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1259                         &res1, attrs2);
1260                 if (ret != 1) {
1261                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1262                 }
1263
1264                 /* Gets the old DNS hostname */
1265                 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1266                         NULL);
1267
1268                 /* Gets host informations and put them in our directory */
1269                 new_msg = ldb_msg_new(mem_ctx);
1270                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1271
1272                 new_msg->dn = workstation_dn;
1273
1274                 /* Deletes old OS version values */
1275                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1276                         "operatingSystemServicePack");
1277                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1278                         "operatingSystemVersion");
1279
1280                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1281                         DEBUG(3,("Impossible to update samdb: %s\n",
1282                                 ldb_errstring(sam_ctx)));
1283                 }
1284
1285                 talloc_free(new_msg);
1286
1287                 new_msg = ldb_msg_new(mem_ctx);
1288                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1289
1290                 new_msg->dn = workstation_dn;
1291
1292                 /* Sets the OS name */
1293                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1294                         "operatingSystem",
1295                         r->in.query->workstation_info->os_name.string);
1296
1297                 /*
1298                  * Sets informations from "os_version". On a empty structure
1299                  * the values are cleared.
1300                  */
1301                 if (r->in.query->workstation_info->os_version.os != NULL) {
1302                         os_version = &r->in.query->workstation_info->os_version.os->os;
1303
1304                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1305                                              "operatingSystemServicePack",
1306                                              os_version->CSDVersion);
1307
1308                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1309                                 "operatingSystemVersion",
1310                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1311                                         os_version->MajorVersion,
1312                                         os_version->MinorVersion,
1313                                         os_version->BuildNumber
1314                                 )
1315                         );
1316                 }
1317
1318                 /*
1319                  * If the boolean "update_dns_hostname" remained true, then we
1320                  * are fine to start the update.
1321                  */
1322                 if (update_dns_hostname) {
1323                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1324                                 "dNSHostname",
1325                         r->in.query->workstation_info->dns_hostname);
1326
1327                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1328                                 "servicePrincipalName",
1329                                 talloc_asprintf(mem_ctx, "HOST/%s",
1330                                 r->in.computer_name)
1331                         );
1332                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1333                                 "servicePrincipalName",
1334                                 talloc_asprintf(mem_ctx, "HOST/%s",
1335                                 r->in.query->workstation_info->dns_hostname)
1336                         );
1337                 }
1338
1339                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1340                         DEBUG(3,("Impossible to update samdb: %s\n",
1341                                 ldb_errstring(sam_ctx)));
1342                 }
1343
1344                 talloc_free(new_msg);
1345
1346                 /* Writes back the domain information */
1347
1348                 /* We need to do two searches. The first will pull our primary
1349                    domain and the second will pull any trusted domains. Our
1350                    primary domain is also a "trusted" domain, so we need to
1351                    put the primary domain into the lists of returned trusts as
1352                    well. */
1353                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1354                         &res2, attrs);
1355                 if (ret != 1) {
1356                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1357                 }
1358
1359                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1360                         "(objectClass=trustedDomain)");
1361                 if (ret3 == -1) {
1362                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1363                 }
1364
1365                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1366                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1367
1368                 ZERO_STRUCTP(domain_info);
1369
1370                 /* Informations about the local and trusted domains */
1371
1372                 status = fill_one_domain_info(mem_ctx,
1373                         dce_call->conn->dce_ctx->lp_ctx,
1374                         sam_ctx, res2[0], &domain_info->primary_domain,
1375                         true, false);
1376                 NT_STATUS_NOT_OK_RETURN(status);
1377
1378                 domain_info->trusted_domain_count = ret3 + 1;
1379                 domain_info->trusted_domains = talloc_array(mem_ctx,
1380                         struct netr_OneDomainInfo,
1381                         domain_info->trusted_domain_count);
1382                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1383
1384                 for (i=0;i<ret3;i++) {
1385                         status = fill_one_domain_info(mem_ctx,
1386                                 dce_call->conn->dce_ctx->lp_ctx,
1387                                 sam_ctx, res3[i],
1388                                 &domain_info->trusted_domains[i],
1389                                 false, true);
1390                         NT_STATUS_NOT_OK_RETURN(status);
1391                 }
1392
1393                 status = fill_one_domain_info(mem_ctx,
1394                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1395                         &domain_info->trusted_domains[i], true, true);
1396                 NT_STATUS_NOT_OK_RETURN(status);
1397
1398                 /* Sets the supported encryption types */
1399                 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1400                         "msDS-SupportedEncryptionTypes",
1401                         default_supported_enc_types);
1402
1403                 /* Other host domain informations */
1404
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                 domain_info->lsa_policy = *lsa_policy_info;
1411
1412                 /* The DNS hostname is only returned back when there is a chance
1413                  * for a change. */
1414                 if ((r->in.query->workstation_info->workstation_flags
1415                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1416                         domain_info->dns_hostname.string = old_dns_hostname;
1417                 } else {
1418                         domain_info->dns_hostname.string = NULL;
1419                 }
1420
1421                 domain_info->workstation_flags =
1422                         r->in.query->workstation_info->workstation_flags;
1423
1424                 r->out.info->domain_info = domain_info;
1425         break;
1426         case 2: /* LSA policy information - not used at the moment */
1427                 lsa_policy_info = talloc(mem_ctx,
1428                         struct netr_LsaPolicyInformation);
1429                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1430                 ZERO_STRUCTP(lsa_policy_info);
1431
1432                 r->out.info->lsa_policy_info = lsa_policy_info;
1433         break;
1434         default:
1435                 return NT_STATUS_INVALID_LEVEL;
1436         break;
1437         }
1438
1439         return NT_STATUS_OK;
1440 }
1441
1442
1443
1444 /*
1445   netr_ServerPasswordGet
1446 */
1447 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1448                        struct netr_ServerPasswordGet *r)
1449 {
1450         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1451 }
1452
1453
1454 /*
1455   netr_NETRLOGONSENDTOSAM
1456 */
1457 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1458                        struct netr_NETRLOGONSENDTOSAM *r)
1459 {
1460         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1461 }
1462
1463
1464 /*
1465   netr_DsRAddressToSitenamesW
1466 */
1467 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1468                        struct netr_DsRAddressToSitenamesW *r)
1469 {
1470         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1471 }
1472
1473
1474 /*
1475   netr_DsRGetDCNameEx2
1476 */
1477 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1478                                           TALLOC_CTX *mem_ctx,
1479                                           struct netr_DsRGetDCNameEx2 *r)
1480 {
1481         const char * const attrs[] = { "objectGUID", NULL };
1482         struct ldb_context *sam_ctx;
1483         struct ldb_message **res;
1484         struct ldb_dn *domain_dn;
1485         int ret;
1486         struct netr_DsRGetDCNameInfo *info;
1487         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1488
1489         ZERO_STRUCTP(r->out.info);
1490
1491         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1492                                 dce_call->conn->auth_state.session_info);
1493         if (sam_ctx == NULL) {
1494                 return WERR_DS_UNAVAILABLE;
1495         }
1496
1497         /* Windows 7 sends the domain name in the form the user typed, so we
1498          * have to cope  with both the short and long form here */
1499         if (r->in.domain_name != NULL &&
1500             !lp_is_my_domain_or_realm(lp_ctx, r->in.domain_name)) {
1501                 return WERR_NO_SUCH_DOMAIN;
1502         }
1503
1504         domain_dn = ldb_get_default_basedn(sam_ctx);
1505         if (domain_dn == NULL) {
1506                 return WERR_DS_UNAVAILABLE;
1507         }
1508
1509         ret = gendb_search_dn(sam_ctx, mem_ctx,
1510                               domain_dn, &res, attrs);
1511         if (ret != 1) {
1512                 return WERR_GENERAL_FAILURE;
1513         }
1514
1515         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1516         W_ERROR_HAVE_NO_MEMORY(info);
1517
1518         /* TODO: - return real IP address
1519          *       - check all r->in.* parameters
1520          *       (server_unc is ignored by w2k3!)
1521          */
1522         info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1523                                        lp_netbios_name(lp_ctx),
1524                                        lp_dnsdomain(lp_ctx));
1525         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1526
1527         info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1528         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1529
1530         info->dc_address_type = DS_ADDRESS_TYPE_INET;
1531         info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1532         info->domain_name = lp_dnsdomain(lp_ctx);
1533         info->forest_name = lp_dnsdomain(lp_ctx);
1534         info->dc_flags  = DS_DNS_FOREST_ROOT |
1535                           DS_DNS_DOMAIN |
1536                           DS_DNS_CONTROLLER |
1537                           DS_SERVER_WRITABLE |
1538                           DS_SERVER_CLOSEST |
1539                           DS_SERVER_TIMESERV |
1540                           DS_SERVER_KDC |
1541                           DS_SERVER_DS |
1542                           DS_SERVER_LDAP |
1543                           DS_SERVER_GC |
1544                           DS_SERVER_PDC;
1545
1546         info->dc_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1547         W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1548
1549         /* FIXME: Hardcoded site name */
1550         info->client_site_name = talloc_strdup(mem_ctx,
1551                                                "Default-First-Site-Name");
1552         W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1553
1554         *r->out.info = info;
1555
1556         return WERR_OK;
1557 }
1558
1559 /*
1560   netr_DsRGetDCNameEx
1561 */
1562 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1563                                   struct netr_DsRGetDCNameEx *r)
1564 {
1565         struct netr_DsRGetDCNameEx2 r2;
1566         WERROR werr;
1567
1568         ZERO_STRUCT(r2);
1569
1570         r2.in.server_unc = r->in.server_unc;
1571         r2.in.client_account = NULL;
1572         r2.in.mask = 0;
1573         r2.in.domain_guid = r->in.domain_guid;
1574         r2.in.domain_name = r->in.domain_name;
1575         r2.in.site_name = r->in.site_name;
1576         r2.in.flags = r->in.flags;
1577         r2.out.info = r->out.info;
1578
1579         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1580
1581         return werr;
1582 }
1583
1584 /*
1585   netr_DsRGetDCName
1586 */
1587 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1588                                 struct netr_DsRGetDCName *r)
1589 {
1590         struct netr_DsRGetDCNameEx2 r2;
1591         WERROR werr;
1592
1593         ZERO_STRUCT(r2);
1594
1595         r2.in.server_unc = r->in.server_unc;
1596         r2.in.client_account = NULL;
1597         r2.in.mask = 0;
1598         r2.in.domain_name = r->in.domain_name;
1599         r2.in.domain_guid = r->in.domain_guid;
1600
1601         r2.in.site_name = NULL; /* should fill in from site GUID */
1602         r2.in.flags = r->in.flags;
1603         r2.out.info = r->out.info;
1604
1605         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1606
1607         return werr;
1608 }
1609 /*
1610   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1611 */
1612 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1613                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1614 {
1615         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1616 }
1617
1618
1619 /*
1620   netr_NetrEnumerateTrustedDomainsEx
1621 */
1622 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1623                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1624 {
1625         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1626 }
1627
1628
1629 /*
1630   netr_DsRAddressToSitenamesExW
1631 */
1632 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1633                                                    struct netr_DsRAddressToSitenamesExW *r)
1634 {
1635         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1636         int i;
1637
1638         /* we should map the provided IPs to site names, once we have
1639          * sites support
1640          */
1641         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1642         W_ERROR_HAVE_NO_MEMORY(ctr);
1643
1644         *r->out.ctr = ctr;
1645
1646         ctr->count = r->in.count;
1647         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1648         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1649         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1650         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1651
1652         for (i=0; i<ctr->count; i++) {
1653                 /* FIXME: Hardcoded site name */
1654                 ctr->sitename[i].string   = "Default-First-Site-Name";
1655                 ctr->subnetname[i].string = NULL;
1656         }
1657
1658         return WERR_OK;
1659 }
1660
1661
1662 /*
1663   netr_DsrGetDcSiteCoverageW
1664 */
1665 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1666                        struct netr_DsrGetDcSiteCoverageW *r)
1667 {
1668         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1669 }
1670
1671
1672 #define GET_CHECK_STR(dest, mem, msg, attr) \
1673 do {\
1674         const char *s; \
1675         s = samdb_result_string(msg, attr, NULL); \
1676         if (!s) { \
1677                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1678                           "without flatname\n", \
1679                           ldb_dn_get_linearized(msg->dn))); \
1680                 continue; \
1681         } \
1682         dest = talloc_strdup(mem, s); \
1683         W_ERROR_HAVE_NO_MEMORY(dest); \
1684 } while(0)
1685
1686
1687 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1688                                          struct ldb_context *sam_ctx,
1689                                          struct netr_DomainTrustList *trusts,
1690                                          uint32_t trust_flags)
1691 {
1692         struct ldb_dn *system_dn;
1693         struct ldb_message **dom_res = NULL;
1694         const char *trust_attrs[] = { "flatname", "trustPartner",
1695                                       "securityIdentifier", "trustDirection",
1696                                       "trustType", "trustAttributes", NULL };
1697         int i, n;
1698         int ret;
1699
1700         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1701                              NETR_TRUST_FLAG_OUTBOUND))) {
1702                 return WERR_INVALID_FLAGS;
1703         }
1704
1705         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1706                                     ldb_get_default_basedn(sam_ctx),
1707                                     "(&(objectClass=container)(cn=System))");
1708         if (!system_dn) {
1709                 return WERR_GENERAL_FAILURE;
1710         }
1711
1712         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1713                            &dom_res, trust_attrs,
1714                            "(objectclass=trustedDomain)");
1715
1716         for (i = 0; i < ret; i++) {
1717                 unsigned int trust_dir;
1718                 uint32_t flags = 0;
1719
1720                 trust_dir = samdb_result_uint(dom_res[i],
1721                                               "trustDirection", 0);
1722
1723                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1724                         flags |= NETR_TRUST_FLAG_INBOUND;
1725                 }
1726                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1727                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1728                 }
1729
1730                 if (!(flags & trust_flags)) {
1731                         /* this trust direction was not requested */
1732                         continue;
1733                 }
1734
1735                 n = trusts->count;
1736                 trusts->array = talloc_realloc(trusts, trusts->array,
1737                                                struct netr_DomainTrust,
1738                                                n + 1);
1739                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1740
1741                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1742                               dom_res[i], "flatname");
1743                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1744                               dom_res[i], "trustPartner");
1745
1746                 trusts->array[n].trust_flags = flags;
1747                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1748                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1749                         /* TODO: find if we have parent in the list */
1750                         trusts->array[n].parent_index = 0;
1751                 }
1752
1753                 trusts->array[n].trust_type =
1754                                 samdb_result_uint(dom_res[i],
1755                                                   "trustType", 0);
1756                 trusts->array[n].trust_attributes =
1757                                 samdb_result_uint(dom_res[i],
1758                                                   "trustAttributes", 0);
1759
1760                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1761                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1762                         struct dom_sid zero_sid;
1763                         ZERO_STRUCT(zero_sid);
1764                         trusts->array[n].sid =
1765                                 dom_sid_dup(trusts, &zero_sid);
1766                 } else {
1767                         trusts->array[n].sid =
1768                                 samdb_result_dom_sid(trusts, dom_res[i],
1769                                                      "securityIdentifier");
1770                 }
1771                 trusts->array[n].guid = GUID_zero();
1772
1773                 trusts->count = n + 1;
1774         }
1775
1776         talloc_free(dom_res);
1777         return WERR_OK;
1778 }
1779
1780 /*
1781   netr_DsrEnumerateDomainTrusts
1782 */
1783 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1784                                                    TALLOC_CTX *mem_ctx,
1785                                                    struct netr_DsrEnumerateDomainTrusts *r)
1786 {
1787         struct netr_DomainTrustList *trusts;
1788         struct ldb_context *sam_ctx;
1789         int ret;
1790         struct ldb_message **dom_res;
1791         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1792         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1793         const char *dnsdomain = lp_dnsdomain(lp_ctx);
1794         const char *p;
1795         WERROR werr;
1796
1797         if (r->in.trust_flags & 0xFFFFFE00) {
1798                 return WERR_INVALID_FLAGS;
1799         }
1800
1801         /* TODO: turn to hard check once we are sure this is 100% correct */
1802         if (!r->in.server_name) {
1803                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1804                           "But received NULL!\n", dnsdomain));
1805         } else {
1806                 p = strchr(r->in.server_name, '.');
1807                 if (!p) {
1808                         DEBUG(3, ("Invalid domain! Expected name in domain "
1809                                   "[%s]. But received [%s]!\n",
1810                                   dnsdomain, r->in.server_name));
1811                         p = r->in.server_name;
1812                 } else {
1813                         p++;
1814                 }
1815                 if (strcasecmp(p, dnsdomain)) {
1816                         DEBUG(3, ("Invalid domain! Expected name in domain "
1817                                   "[%s]. But received [%s]!\n",
1818                                   dnsdomain, r->in.server_name));
1819                 }
1820         }
1821
1822         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1823         W_ERROR_HAVE_NO_MEMORY(trusts);
1824
1825         trusts->count = 0;
1826         r->out.trusts = trusts;
1827
1828         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1829                                 dce_call->conn->auth_state.session_info);
1830         if (sam_ctx == NULL) {
1831                 return WERR_GENERAL_FAILURE;
1832         }
1833
1834         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1835             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1836
1837                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1838                                                   trusts, r->in.trust_flags);
1839                 W_ERROR_NOT_OK_RETURN(werr);
1840         }
1841
1842         /* NOTE: we currently are always the root of the forest */
1843         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1844                 int n = trusts->count;
1845
1846                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1847                                       &dom_res, dom_attrs);
1848                 if (ret != 1) {
1849                         return WERR_GENERAL_FAILURE;
1850                 }
1851
1852                 trusts->count = n + 1;
1853                 trusts->array = talloc_realloc(trusts, trusts->array,
1854                                                struct netr_DomainTrust,
1855                                                trusts->count);
1856                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1857
1858                 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1859                 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1860                 trusts->array[n].trust_flags =
1861                         NETR_TRUST_FLAG_NATIVE |
1862                         NETR_TRUST_FLAG_TREEROOT |
1863                         NETR_TRUST_FLAG_IN_FOREST |
1864                         NETR_TRUST_FLAG_PRIMARY;
1865                 /* we are always the root domain for now */
1866                 trusts->array[n].parent_index = 0;
1867                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1868                 trusts->array[n].trust_attributes = 0;
1869                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1870                                                             dom_res[0],
1871                                                             "objectSid");
1872                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1873                                                           "objectGUID");
1874                 talloc_free(dom_res);
1875         }
1876
1877         return WERR_OK;
1878 }
1879
1880
1881 /*
1882   netr_DsrDeregisterDNSHostRecords
1883 */
1884 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1885                        struct netr_DsrDeregisterDNSHostRecords *r)
1886 {
1887         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1888 }
1889
1890
1891 /*
1892   netr_ServerTrustPasswordsGet
1893 */
1894 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1895                        struct netr_ServerTrustPasswordsGet *r)
1896 {
1897         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1898 }
1899
1900
1901 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
1902                                       struct ldb_context *sam_ctx,
1903                                       struct loadparm_context *lp_ctx,
1904                                       struct lsa_ForestTrustInformation *info)
1905 {
1906         struct lsa_ForestTrustDomainInfo *domain_info;
1907         struct lsa_ForestTrustRecord *e;
1908         struct ldb_message **dom_res;
1909         const char * const dom_attrs[] = { "objectSid", NULL };
1910         int ret;
1911
1912         /* we need to provide 2 entries:
1913          * 1. the Root Forest name
1914          * 2. the Domain Information
1915          */
1916
1917         info->count = 2;
1918         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
1919         W_ERROR_HAVE_NO_MEMORY(info->entries);
1920
1921         /* Forest root info */
1922         e = talloc(info, struct lsa_ForestTrustRecord);
1923         W_ERROR_HAVE_NO_MEMORY(e);
1924
1925         e->flags = 0;
1926         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
1927         e->time = 0; /* so far always 0 in trces. */
1928         e->forest_trust_data.top_level_name.string = lp_dnsdomain(lp_ctx);
1929
1930         info->entries[0] = e;
1931
1932         /* Domain info */
1933         e = talloc(info, struct lsa_ForestTrustRecord);
1934         W_ERROR_HAVE_NO_MEMORY(e);
1935
1936         /* get our own domain info */
1937         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
1938         if (ret != 1) {
1939                 return WERR_GENERAL_FAILURE;
1940         }
1941
1942         /* TODO: check if disabled and set flags accordingly */
1943         e->flags = 0;
1944         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
1945         e->time = 0; /* so far always 0 in traces. */
1946
1947         domain_info = &e->forest_trust_data.domain_info;
1948         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
1949                                                        "objectSid");
1950         domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
1951         domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
1952
1953         info->entries[1] = e;
1954
1955         talloc_free(dom_res);
1956
1957         return WERR_OK;
1958 }
1959
1960 /*
1961   netr_DsRGetForestTrustInformation
1962 */
1963 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
1964                                                        TALLOC_CTX *mem_ctx,
1965                                                        struct netr_DsRGetForestTrustInformation *r)
1966 {
1967         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1968         struct lsa_ForestTrustInformation *info, **info_ptr;
1969         struct ldb_context *sam_ctx;
1970         WERROR werr;
1971
1972         if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
1973                 return WERR_CALL_NOT_IMPLEMENTED;
1974         }
1975
1976         if (r->in.flags & 0xFFFFFFFE) {
1977                 return WERR_INVALID_FLAGS;
1978         }
1979
1980         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1981                                 dce_call->conn->auth_state.session_info);
1982         if (sam_ctx == NULL) {
1983                 return WERR_GENERAL_FAILURE;
1984         }
1985
1986         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
1987                 if (!samdb_is_pdc(sam_ctx)) {
1988                         return WERR_NERR_NOTPRIMARY;
1989                 }
1990
1991                 if (r->in.trusted_domain_name == NULL) {
1992                         return WERR_INVALID_FLAGS;
1993                 }
1994
1995                 /* TODO: establish an schannel connection with
1996                  * r->in.trusted_domain_name and perform a
1997                  * netr_GetForestTrustInformation call against it */
1998
1999                 /* for now return not implementd */
2000                 return WERR_CALL_NOT_IMPLEMENTED;
2001         }
2002
2003         /* TODO: check r->in.server_name is our name */
2004
2005         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2006         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2007
2008         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2009         W_ERROR_HAVE_NO_MEMORY(info);
2010
2011         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2012         W_ERROR_NOT_OK_RETURN(werr);
2013
2014         *info_ptr = info;
2015         r->out.forest_trust_info = info_ptr;
2016
2017         return WERR_OK;
2018 }
2019
2020
2021 /*
2022   netr_GetForestTrustInformation
2023 */
2024 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2025                                                       TALLOC_CTX *mem_ctx,
2026                                                       struct netr_GetForestTrustInformation *r)
2027 {
2028         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2029         struct netlogon_creds_CredentialState *creds;
2030         struct lsa_ForestTrustInformation *info, **info_ptr;
2031         struct ldb_context *sam_ctx;
2032         NTSTATUS status;
2033         WERROR werr;
2034
2035         if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
2036                 return NT_STATUS_NOT_IMPLEMENTED;
2037         }
2038
2039         status = dcesrv_netr_creds_server_step_check(dce_call,
2040                                                      mem_ctx,
2041                                                      r->in.computer_name,
2042                                                      r->in.credential,
2043                                                      r->out.return_authenticator,
2044                                                      &creds);
2045         if (!NT_STATUS_IS_OK(status)) {
2046                 return status;
2047         }
2048
2049         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2050             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2051                 return NT_STATUS_NOT_IMPLEMENTED;
2052         }
2053
2054         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2055                                 dce_call->conn->auth_state.session_info);
2056         if (sam_ctx == NULL) {
2057                 return NT_STATUS_UNSUCCESSFUL;
2058         }
2059
2060         /* TODO: check r->in.server_name is our name */
2061
2062         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2063         if (!info_ptr) {
2064                 return NT_STATUS_NO_MEMORY;
2065         }
2066         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2067         if (!info) {
2068                 return NT_STATUS_NO_MEMORY;
2069         }
2070
2071         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2072         if (!W_ERROR_IS_OK(werr)) {
2073                 return werror_to_ntstatus(werr);
2074         }
2075
2076         *info_ptr = info;
2077         r->out.forest_trust_info = info_ptr;
2078
2079         return NT_STATUS_OK;
2080 }
2081
2082
2083 /*
2084   netr_ServerGetTrustInfo
2085 */
2086 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087                        struct netr_ServerGetTrustInfo *r)
2088 {
2089         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2090 }
2091
2092
2093 /* include the generated boilerplate */
2094 #include "librpc/gen_ndr/ndr_netlogon_s.c"