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