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