Revert "s4:netr_DsRAddressToSitenames[Ex]W calls - implement them correctly with...
[ddiss/samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    Copyright (C) Matthias Dieter Wallnöfer            2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc.h"
35 #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 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
992                                          struct ldb_context *sam_ctx,
993                                          struct netr_DomainTrustList *trusts,
994                                          uint32_t trust_flags);
995
996 /*
997   netr_GetAnyDCName
998 */
999 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1000                        struct netr_GetAnyDCName *r)
1001 {
1002         struct netr_DomainTrustList *trusts;
1003         struct ldb_context *sam_ctx;
1004         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1005         uint32_t i;
1006         WERROR werr;
1007
1008         *r->out.dcname = NULL;
1009
1010         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1011                 /* if the domainname parameter wasn't set assume our domain */
1012                 r->in.domainname = lp_workgroup(lp_ctx);
1013         }
1014
1015         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1016                                 dce_call->conn->auth_state.session_info);
1017         if (sam_ctx == NULL) {
1018                 return WERR_DS_UNAVAILABLE;
1019         }
1020
1021         if (strcasecmp(r->in.domainname, lp_workgroup(lp_ctx)) == 0) {
1022                 /* well we asked for a DC of our own domain */
1023                 if (samdb_is_pdc(sam_ctx)) {
1024                         /* we are the PDC of the specified domain */
1025                         return WERR_NO_SUCH_DOMAIN;
1026                 }
1027
1028                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1029                                                 lp_netbios_name(lp_ctx));
1030                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1031
1032                 return WERR_OK;
1033         }
1034
1035         /* Okay, now we have to consider the trusted domains */
1036
1037         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1038         W_ERROR_HAVE_NO_MEMORY(trusts);
1039
1040         trusts->count = 0;
1041
1042         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1043                                           NETR_TRUST_FLAG_INBOUND
1044                                           | NETR_TRUST_FLAG_OUTBOUND);
1045         W_ERROR_NOT_OK_RETURN(werr);
1046
1047         for (i = 0; i < trusts->count; i++) {
1048                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1049                         /* FIXME: Here we need to find a DC for the specified
1050                          * trusted domain. */
1051
1052                         /* return WERR_OK; */
1053                         return WERR_NO_SUCH_DOMAIN;
1054                 }
1055         }
1056
1057         return WERR_NO_SUCH_DOMAIN;
1058 }
1059
1060
1061 /*
1062   netr_DatabaseRedo
1063 */
1064 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1065                        struct netr_DatabaseRedo *r)
1066 {
1067         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1068 }
1069
1070
1071 /*
1072   netr_NetrEnumerateTurstedDomains
1073 */
1074 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1075                        struct netr_NetrEnumerateTrustedDomains *r)
1076 {
1077         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1078 }
1079
1080
1081 /*
1082   netr_LogonGetCapabilities
1083 */
1084 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1085                        struct netr_LogonGetCapabilities *r)
1086 {
1087         /* we don't support AES yet */
1088         return NT_STATUS_NOT_IMPLEMENTED;
1089 }
1090
1091
1092 /*
1093   netr_NETRLOGONSETSERVICEBITS
1094 */
1095 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1096                        struct netr_NETRLOGONSETSERVICEBITS *r)
1097 {
1098         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1099 }
1100
1101
1102 /*
1103   netr_LogonGetTrustRid
1104 */
1105 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1106                        struct netr_LogonGetTrustRid *r)
1107 {
1108         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1109 }
1110
1111
1112 /*
1113   netr_NETRLOGONCOMPUTESERVERDIGEST
1114 */
1115 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1116                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1117 {
1118         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1119 }
1120
1121
1122 /*
1123   netr_NETRLOGONCOMPUTECLIENTDIGEST
1124 */
1125 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1126                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1127 {
1128         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1129 }
1130
1131
1132
1133 /*
1134   netr_DsRGetSiteName
1135 */
1136 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1137                                   struct netr_DsRGetSiteName *r)
1138 {
1139         struct ldb_context *sam_ctx;
1140         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1141
1142         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1143                                 dce_call->conn->auth_state.session_info);
1144         if (sam_ctx == NULL) {
1145                 return WERR_DS_UNAVAILABLE;
1146         }
1147
1148         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1149         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1150
1151         return WERR_OK;
1152 }
1153
1154
1155 /*
1156   fill in a netr_OneDomainInfo from a ldb search result
1157 */
1158 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1159                                      struct loadparm_context *lp_ctx,
1160                                      struct ldb_context *sam_ctx,
1161                                      struct ldb_message *res,
1162                                      struct netr_OneDomainInfo *info,
1163                                      bool is_local, bool is_trust_list)
1164 {
1165         ZERO_STRUCTP(info);
1166
1167         if (is_trust_list) {
1168                 /* w2k8 only fills this on trusted domains */
1169                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1170                 info->trust_extension.length = 16;
1171                 info->trust_extension.info->flags =
1172                         NETR_TRUST_FLAG_TREEROOT |
1173                         NETR_TRUST_FLAG_IN_FOREST |
1174                         NETR_TRUST_FLAG_PRIMARY |
1175                         NETR_TRUST_FLAG_NATIVE;
1176
1177                 info->trust_extension.info->parent_index = 0; /* should be index into array
1178                                                                  of parent */
1179                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1180                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1181         }
1182
1183         if (is_trust_list) {
1184                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1185                 info->dns_forestname.string = NULL;
1186         } else {
1187                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1188                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1189                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1190                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1191         }
1192
1193         if (is_local) {
1194                 info->domainname.string = lp_workgroup(lp_ctx);
1195                 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1196                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1197                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1198         } else {
1199                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1200                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1201                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1202                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1203         }
1204         if (!is_trust_list) {
1205                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1206         }
1207
1208         return NT_STATUS_OK;
1209 }
1210
1211 /*
1212   netr_LogonGetDomainInfo
1213   this is called as part of the ADS domain logon procedure.
1214
1215   It has an important role in convaying details about the client, such
1216   as Operating System, Version, Service Pack etc.
1217 */
1218 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1219         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1220 {
1221         struct netlogon_creds_CredentialState *creds;
1222         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1223                 "securityIdentifier", "trustPartner", NULL };
1224         const char * const attrs2[] = { "dNSHostName",
1225                 "msDS-SupportedEncryptionTypes", NULL };
1226         const char * const attrs3[] = { NULL };
1227         const char *temp_str, *temp_str2;
1228         const char *old_dns_hostname;
1229         struct ldb_context *sam_ctx;
1230         struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1231         struct ldb_dn *workstation_dn;
1232         struct netr_DomainInformation *domain_info;
1233         struct netr_LsaPolicyInformation *lsa_policy_info;
1234         struct netr_OsVersionInfoEx *os_version;
1235         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1236         bool update_dns_hostname = true;
1237         int ret, ret3, i;
1238         NTSTATUS status;
1239
1240         status = dcesrv_netr_creds_server_step_check(dce_call,
1241                                                      mem_ctx,
1242                                                      r->in.computer_name,
1243                                                      r->in.credential,
1244                                                      r->out.return_authenticator,
1245                                                      &creds);
1246         if (!NT_STATUS_IS_OK(status)) {
1247                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1248         }
1249         NT_STATUS_NOT_OK_RETURN(status);
1250
1251         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1252                 dce_call->conn->dce_ctx->lp_ctx,
1253                 system_session(dce_call->conn->dce_ctx->lp_ctx));
1254         if (sam_ctx == NULL) {
1255                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1256         }
1257
1258         switch (r->in.level) {
1259         case 1: /* Domain information */
1260
1261                 /*
1262                  * Updates the DNS hostname when the client wishes that the
1263                  * server should handle this for him
1264                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1265                  * See MS-NRPC section 3.5.4.3.9
1266                  */
1267                 if ((r->in.query->workstation_info->workstation_flags
1268                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1269                         update_dns_hostname = false;
1270                 }
1271
1272                 /*
1273                  * Checks that the computer name parameter without possible "$"
1274                  * matches as prefix with the DNS hostname in the workstation
1275                  * info structure.
1276                  */
1277                 temp_str = talloc_strndup(mem_ctx,
1278                                           r->in.computer_name,
1279                                           strcspn(r->in.computer_name, "$"));
1280                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1281                 temp_str2 = talloc_strndup(mem_ctx,
1282                                            r->in.query->workstation_info->dns_hostname,
1283                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1284                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1285                 if (strcasecmp(temp_str, temp_str2) != 0) {
1286                         update_dns_hostname = false;
1287                 }
1288
1289                 /*
1290                  * Check that the DNS hostname when it should be updated
1291                  * will be used only by maximum one host.
1292                  */
1293                 ret = gendb_search(sam_ctx, mem_ctx,
1294                                    ldb_get_default_basedn(sam_ctx),
1295                                    &res0, attrs3, "(dNSHostName=%s)",
1296                                    r->in.query->workstation_info->dns_hostname);
1297                 if (ret < 0) {
1298                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1299                 }
1300                 if (ret >= 1) {
1301                         update_dns_hostname = false;
1302                 }
1303
1304                 talloc_free(res0);
1305
1306                 /* Prepare the workstation DN */
1307                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1308                         dom_sid_string(mem_ctx, creds->sid));
1309                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1310
1311                 /* Lookup for attributes in workstation object */
1312                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1313                         &res1, attrs2);
1314                 if (ret != 1) {
1315                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1316                 }
1317
1318                 /* Gets the old DNS hostname */
1319                 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1320                         NULL);
1321
1322                 /* Gets host informations and put them in our directory */
1323                 new_msg = ldb_msg_new(mem_ctx);
1324                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1325
1326                 new_msg->dn = workstation_dn;
1327
1328                 /* Deletes old OS version values */
1329                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1330                         "operatingSystemServicePack");
1331                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1332                         "operatingSystemVersion");
1333
1334                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1335                         DEBUG(3,("Impossible to update samdb: %s\n",
1336                                 ldb_errstring(sam_ctx)));
1337                 }
1338
1339                 talloc_free(new_msg);
1340
1341                 new_msg = ldb_msg_new(mem_ctx);
1342                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1343
1344                 new_msg->dn = workstation_dn;
1345
1346                 /* Sets the OS name */
1347                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1348                         "operatingSystem",
1349                         r->in.query->workstation_info->os_name.string);
1350
1351                 /*
1352                  * Sets informations from "os_version". On a empty structure
1353                  * the values are cleared.
1354                  */
1355                 if (r->in.query->workstation_info->os_version.os != NULL) {
1356                         os_version = &r->in.query->workstation_info->os_version.os->os;
1357
1358                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1359                                              "operatingSystemServicePack",
1360                                              os_version->CSDVersion);
1361
1362                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1363                                 "operatingSystemVersion",
1364                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1365                                         os_version->MajorVersion,
1366                                         os_version->MinorVersion,
1367                                         os_version->BuildNumber
1368                                 )
1369                         );
1370                 }
1371
1372                 /*
1373                  * If the boolean "update_dns_hostname" remained true, then we
1374                  * are fine to start the update.
1375                  */
1376                 if (update_dns_hostname) {
1377                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1378                                 "dNSHostname",
1379                         r->in.query->workstation_info->dns_hostname);
1380
1381                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1382                                 "servicePrincipalName",
1383                                 talloc_asprintf(mem_ctx, "HOST/%s",
1384                                 r->in.computer_name)
1385                         );
1386                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1387                                 "servicePrincipalName",
1388                                 talloc_asprintf(mem_ctx, "HOST/%s",
1389                                 r->in.query->workstation_info->dns_hostname)
1390                         );
1391                 }
1392
1393                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1394                         DEBUG(3,("Impossible to update samdb: %s\n",
1395                                 ldb_errstring(sam_ctx)));
1396                 }
1397
1398                 talloc_free(new_msg);
1399
1400                 /* Writes back the domain information */
1401
1402                 /* We need to do two searches. The first will pull our primary
1403                    domain and the second will pull any trusted domains. Our
1404                    primary domain is also a "trusted" domain, so we need to
1405                    put the primary domain into the lists of returned trusts as
1406                    well. */
1407                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1408                         &res2, attrs);
1409                 if (ret != 1) {
1410                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1411                 }
1412
1413                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1414                         "(objectClass=trustedDomain)");
1415                 if (ret3 == -1) {
1416                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1417                 }
1418
1419                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1420                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1421
1422                 ZERO_STRUCTP(domain_info);
1423
1424                 /* Informations about the local and trusted domains */
1425
1426                 status = fill_one_domain_info(mem_ctx,
1427                         dce_call->conn->dce_ctx->lp_ctx,
1428                         sam_ctx, res2[0], &domain_info->primary_domain,
1429                         true, false);
1430                 NT_STATUS_NOT_OK_RETURN(status);
1431
1432                 domain_info->trusted_domain_count = ret3 + 1;
1433                 domain_info->trusted_domains = talloc_array(mem_ctx,
1434                         struct netr_OneDomainInfo,
1435                         domain_info->trusted_domain_count);
1436                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1437
1438                 for (i=0;i<ret3;i++) {
1439                         status = fill_one_domain_info(mem_ctx,
1440                                 dce_call->conn->dce_ctx->lp_ctx,
1441                                 sam_ctx, res3[i],
1442                                 &domain_info->trusted_domains[i],
1443                                 false, true);
1444                         NT_STATUS_NOT_OK_RETURN(status);
1445                 }
1446
1447                 status = fill_one_domain_info(mem_ctx,
1448                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1449                         &domain_info->trusted_domains[i], true, true);
1450                 NT_STATUS_NOT_OK_RETURN(status);
1451
1452                 /* Sets the supported encryption types */
1453                 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1454                         "msDS-SupportedEncryptionTypes",
1455                         default_supported_enc_types);
1456
1457                 /* Other host domain informations */
1458
1459                 lsa_policy_info = talloc(mem_ctx,
1460                         struct netr_LsaPolicyInformation);
1461                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1462                 ZERO_STRUCTP(lsa_policy_info);
1463
1464                 domain_info->lsa_policy = *lsa_policy_info;
1465
1466                 /* The DNS hostname is only returned back when there is a chance
1467                  * for a change. */
1468                 if ((r->in.query->workstation_info->workstation_flags
1469                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1470                         domain_info->dns_hostname.string = old_dns_hostname;
1471                 } else {
1472                         domain_info->dns_hostname.string = NULL;
1473                 }
1474
1475                 domain_info->workstation_flags =
1476                         r->in.query->workstation_info->workstation_flags;
1477
1478                 r->out.info->domain_info = domain_info;
1479         break;
1480         case 2: /* LSA policy information - not used at the moment */
1481                 lsa_policy_info = talloc(mem_ctx,
1482                         struct netr_LsaPolicyInformation);
1483                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1484                 ZERO_STRUCTP(lsa_policy_info);
1485
1486                 r->out.info->lsa_policy_info = lsa_policy_info;
1487         break;
1488         default:
1489                 return NT_STATUS_INVALID_LEVEL;
1490         break;
1491         }
1492
1493         return NT_STATUS_OK;
1494 }
1495
1496
1497
1498 /*
1499   netr_ServerPasswordGet
1500 */
1501 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1502                        struct netr_ServerPasswordGet *r)
1503 {
1504         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1505 }
1506
1507
1508 /*
1509   netr_NETRLOGONSENDTOSAM
1510 */
1511 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1512                        struct netr_NETRLOGONSENDTOSAM *r)
1513 {
1514         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1515 }
1516
1517
1518 /*
1519   netr_DsRAddressToSitenamesW
1520 */
1521 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1522                        struct netr_DsRAddressToSitenamesW *r)
1523 {
1524         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1525 }
1526
1527
1528 /*
1529   netr_DsRGetDCNameEx2
1530 */
1531 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1532                                           TALLOC_CTX *mem_ctx,
1533                                           struct netr_DsRGetDCNameEx2 *r)
1534 {
1535         struct ldb_context *sam_ctx;
1536         struct netr_DsRGetDCNameInfo *info;
1537         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1538         struct socket_address *addr;
1539         const char *server_site_name;
1540         char *guid_str;
1541         struct netlogon_samlogon_response response;
1542         NTSTATUS status;
1543
1544         ZERO_STRUCTP(r->out.info);
1545
1546         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1547                                 dce_call->conn->auth_state.session_info);
1548         if (sam_ctx == NULL) {
1549                 return WERR_DS_UNAVAILABLE;
1550         }
1551
1552         addr = dce_call->conn->transport.get_peer_addr(dce_call->conn, mem_ctx);
1553         W_ERROR_HAVE_NO_MEMORY(addr);
1554
1555         /* "server_unc" is ignored by w2k3 */
1556
1557         /* Proof server site parameter "site_name" if it was specified */
1558         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1559         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1560         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1561                                                      server_site_name) != 0)) {
1562                 return WERR_NO_SUCH_DOMAIN;
1563         }
1564
1565         /* TODO: the flags are ignored for now */
1566
1567         guid_str = r->in.domain_guid != NULL ?
1568                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1569
1570         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1571                                                  r->in.domain_name,
1572                                                  r->in.domain_name,
1573                                                  NULL, guid_str,
1574                                                  r->in.client_account,
1575                                                  r->in.mask, addr->addr,
1576                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1577                                                  lp_ctx, &response);
1578         if (!NT_STATUS_IS_OK(status)) {
1579                 return ntstatus_to_werror(status);
1580         }
1581
1582         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1583         W_ERROR_HAVE_NO_MEMORY(info);
1584         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s",
1585                                                  response.data.nt5_ex.pdc_dns_name);
1586         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1587         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1588                                            response.data.nt5_ex.sockaddr.pdc_ip);
1589         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1590         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1591         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1592         info->domain_name      = response.data.nt5_ex.dns_domain;
1593         info->forest_name      = response.data.nt5_ex.forest;
1594         info->dc_flags         = response.data.nt5_ex.server_type;
1595         info->dc_site_name     = response.data.nt5_ex.server_site;
1596         info->client_site_name = response.data.nt5_ex.client_site;
1597
1598         *r->out.info = info;
1599
1600         return WERR_OK;
1601 }
1602
1603 /*
1604   netr_DsRGetDCNameEx
1605 */
1606 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1607                                   struct netr_DsRGetDCNameEx *r)
1608 {
1609         struct netr_DsRGetDCNameEx2 r2;
1610         WERROR werr;
1611
1612         ZERO_STRUCT(r2);
1613
1614         r2.in.server_unc = r->in.server_unc;
1615         r2.in.client_account = NULL;
1616         r2.in.mask = 0;
1617         r2.in.domain_guid = r->in.domain_guid;
1618         r2.in.domain_name = r->in.domain_name;
1619         r2.in.site_name = r->in.site_name;
1620         r2.in.flags = r->in.flags;
1621         r2.out.info = r->out.info;
1622
1623         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1624
1625         return werr;
1626 }
1627
1628 /*
1629   netr_DsRGetDCName
1630 */
1631 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1632                                 struct netr_DsRGetDCName *r)
1633 {
1634         struct netr_DsRGetDCNameEx2 r2;
1635         WERROR werr;
1636
1637         ZERO_STRUCT(r2);
1638
1639         r2.in.server_unc = r->in.server_unc;
1640         r2.in.client_account = NULL;
1641         r2.in.mask = 0;
1642         r2.in.domain_name = r->in.domain_name;
1643         r2.in.domain_guid = r->in.domain_guid;
1644
1645         r2.in.site_name = NULL; /* should fill in from site GUID */
1646         r2.in.flags = r->in.flags;
1647         r2.out.info = r->out.info;
1648
1649         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1650
1651         return werr;
1652 }
1653 /*
1654   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1655 */
1656 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1657                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1658 {
1659         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1660 }
1661
1662
1663 /*
1664   netr_NetrEnumerateTrustedDomainsEx
1665 */
1666 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1667                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1668 {
1669         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1670 }
1671
1672
1673 /*
1674   netr_DsRAddressToSitenamesExW
1675 */
1676 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1677                                                    struct netr_DsRAddressToSitenamesExW *r)
1678 {
1679         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1680         int i;
1681
1682         /* we should map the provided IPs to site names, once we have
1683          * sites support
1684          */
1685         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1686         W_ERROR_HAVE_NO_MEMORY(ctr);
1687
1688         *r->out.ctr = ctr;
1689
1690         ctr->count = r->in.count;
1691         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1692         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1693         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1694         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1695
1696         for (i=0; i<ctr->count; i++) {
1697                 /* FIXME: Hardcoded site name */
1698                 ctr->sitename[i].string   = "Default-First-Site-Name";
1699                 ctr->subnetname[i].string = NULL;
1700         }
1701
1702         return WERR_OK;
1703 }
1704
1705
1706 /*
1707   netr_DsrGetDcSiteCoverageW
1708 */
1709 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1710                        struct netr_DsrGetDcSiteCoverageW *r)
1711 {
1712         struct ldb_context *sam_ctx;
1713         struct DcSitesCtr *ctr;
1714         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1715
1716         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1717                                 dce_call->conn->auth_state.session_info);
1718         if (sam_ctx == NULL) {
1719                 return WERR_DS_UNAVAILABLE;
1720         }
1721
1722         ctr = talloc(mem_ctx, struct DcSitesCtr);
1723         W_ERROR_HAVE_NO_MEMORY(ctr);
1724
1725         *r->out.ctr = ctr;
1726
1727         /* For now only return our default site */
1728         ctr->num_sites = 1;
1729         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1730         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1731         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1732         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1733
1734         return WERR_OK;
1735 }
1736
1737
1738 #define GET_CHECK_STR(dest, mem, msg, attr) \
1739 do {\
1740         const char *s; \
1741         s = samdb_result_string(msg, attr, NULL); \
1742         if (!s) { \
1743                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1744                           "without flatname\n", \
1745                           ldb_dn_get_linearized(msg->dn))); \
1746                 continue; \
1747         } \
1748         dest = talloc_strdup(mem, s); \
1749         W_ERROR_HAVE_NO_MEMORY(dest); \
1750 } while(0)
1751
1752
1753 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1754                                          struct ldb_context *sam_ctx,
1755                                          struct netr_DomainTrustList *trusts,
1756                                          uint32_t trust_flags)
1757 {
1758         struct ldb_dn *system_dn;
1759         struct ldb_message **dom_res = NULL;
1760         const char *trust_attrs[] = { "flatname", "trustPartner",
1761                                       "securityIdentifier", "trustDirection",
1762                                       "trustType", "trustAttributes", NULL };
1763         uint32_t n;
1764         int i;
1765         int ret;
1766
1767         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1768                              NETR_TRUST_FLAG_OUTBOUND))) {
1769                 return WERR_INVALID_FLAGS;
1770         }
1771
1772         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1773                                     ldb_get_default_basedn(sam_ctx),
1774                                     "(&(objectClass=container)(cn=System))");
1775         if (!system_dn) {
1776                 return WERR_GENERAL_FAILURE;
1777         }
1778
1779         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1780                            &dom_res, trust_attrs,
1781                            "(objectclass=trustedDomain)");
1782
1783         for (i = 0; i < ret; i++) {
1784                 unsigned int trust_dir;
1785                 uint32_t flags = 0;
1786
1787                 trust_dir = samdb_result_uint(dom_res[i],
1788                                               "trustDirection", 0);
1789
1790                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1791                         flags |= NETR_TRUST_FLAG_INBOUND;
1792                 }
1793                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1794                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1795                 }
1796
1797                 if (!(flags & trust_flags)) {
1798                         /* this trust direction was not requested */
1799                         continue;
1800                 }
1801
1802                 n = trusts->count;
1803                 trusts->array = talloc_realloc(trusts, trusts->array,
1804                                                struct netr_DomainTrust,
1805                                                n + 1);
1806                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1807
1808                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1809                               dom_res[i], "flatname");
1810                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1811                               dom_res[i], "trustPartner");
1812
1813                 trusts->array[n].trust_flags = flags;
1814                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1815                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1816                         /* TODO: find if we have parent in the list */
1817                         trusts->array[n].parent_index = 0;
1818                 }
1819
1820                 trusts->array[n].trust_type =
1821                                 samdb_result_uint(dom_res[i],
1822                                                   "trustType", 0);
1823                 trusts->array[n].trust_attributes =
1824                                 samdb_result_uint(dom_res[i],
1825                                                   "trustAttributes", 0);
1826
1827                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1828                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1829                         struct dom_sid zero_sid;
1830                         ZERO_STRUCT(zero_sid);
1831                         trusts->array[n].sid =
1832                                 dom_sid_dup(trusts, &zero_sid);
1833                 } else {
1834                         trusts->array[n].sid =
1835                                 samdb_result_dom_sid(trusts, dom_res[i],
1836                                                      "securityIdentifier");
1837                 }
1838                 trusts->array[n].guid = GUID_zero();
1839
1840                 trusts->count = n + 1;
1841         }
1842
1843         talloc_free(dom_res);
1844         return WERR_OK;
1845 }
1846
1847 /*
1848   netr_DsrEnumerateDomainTrusts
1849 */
1850 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1851                                                    TALLOC_CTX *mem_ctx,
1852                                                    struct netr_DsrEnumerateDomainTrusts *r)
1853 {
1854         struct netr_DomainTrustList *trusts;
1855         struct ldb_context *sam_ctx;
1856         int ret;
1857         struct ldb_message **dom_res;
1858         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1859         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1860         const char *dnsdomain = lp_dnsdomain(lp_ctx);
1861         const char *p;
1862         WERROR werr;
1863
1864         if (r->in.trust_flags & 0xFFFFFE00) {
1865                 return WERR_INVALID_FLAGS;
1866         }
1867
1868         /* TODO: turn to hard check once we are sure this is 100% correct */
1869         if (!r->in.server_name) {
1870                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1871                           "But received NULL!\n", dnsdomain));
1872         } else {
1873                 p = strchr(r->in.server_name, '.');
1874                 if (!p) {
1875                         DEBUG(3, ("Invalid domain! Expected name in domain "
1876                                   "[%s]. But received [%s]!\n",
1877                                   dnsdomain, r->in.server_name));
1878                         p = r->in.server_name;
1879                 } else {
1880                         p++;
1881                 }
1882                 if (strcasecmp(p, dnsdomain)) {
1883                         DEBUG(3, ("Invalid domain! Expected name in domain "
1884                                   "[%s]. But received [%s]!\n",
1885                                   dnsdomain, r->in.server_name));
1886                 }
1887         }
1888
1889         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1890         W_ERROR_HAVE_NO_MEMORY(trusts);
1891
1892         trusts->count = 0;
1893         r->out.trusts = trusts;
1894
1895         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1896                                 dce_call->conn->auth_state.session_info);
1897         if (sam_ctx == NULL) {
1898                 return WERR_GENERAL_FAILURE;
1899         }
1900
1901         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1902             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1903
1904                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1905                                                   trusts, r->in.trust_flags);
1906                 W_ERROR_NOT_OK_RETURN(werr);
1907         }
1908
1909         /* NOTE: we currently are always the root of the forest */
1910         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1911                 int n = trusts->count;
1912
1913                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1914                                       &dom_res, dom_attrs);
1915                 if (ret != 1) {
1916                         return WERR_GENERAL_FAILURE;
1917                 }
1918
1919                 trusts->count = n + 1;
1920                 trusts->array = talloc_realloc(trusts, trusts->array,
1921                                                struct netr_DomainTrust,
1922                                                trusts->count);
1923                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1924
1925                 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1926                 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1927                 trusts->array[n].trust_flags =
1928                         NETR_TRUST_FLAG_NATIVE |
1929                         NETR_TRUST_FLAG_TREEROOT |
1930                         NETR_TRUST_FLAG_IN_FOREST |
1931                         NETR_TRUST_FLAG_PRIMARY;
1932                 /* we are always the root domain for now */
1933                 trusts->array[n].parent_index = 0;
1934                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1935                 trusts->array[n].trust_attributes = 0;
1936                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1937                                                             dom_res[0],
1938                                                             "objectSid");
1939                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1940                                                           "objectGUID");
1941                 talloc_free(dom_res);
1942         }
1943
1944         return WERR_OK;
1945 }
1946
1947
1948 /*
1949   netr_DsrDeregisterDNSHostRecords
1950 */
1951 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1952                        struct netr_DsrDeregisterDNSHostRecords *r)
1953 {
1954         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1955 }
1956
1957
1958 /*
1959   netr_ServerTrustPasswordsGet
1960 */
1961 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1962                        struct netr_ServerTrustPasswordsGet *r)
1963 {
1964         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1965 }
1966
1967
1968 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
1969                                       struct ldb_context *sam_ctx,
1970                                       struct loadparm_context *lp_ctx,
1971                                       struct lsa_ForestTrustInformation *info)
1972 {
1973         struct lsa_ForestTrustDomainInfo *domain_info;
1974         struct lsa_ForestTrustRecord *e;
1975         struct ldb_message **dom_res;
1976         const char * const dom_attrs[] = { "objectSid", NULL };
1977         int ret;
1978
1979         /* we need to provide 2 entries:
1980          * 1. the Root Forest name
1981          * 2. the Domain Information
1982          */
1983
1984         info->count = 2;
1985         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
1986         W_ERROR_HAVE_NO_MEMORY(info->entries);
1987
1988         /* Forest root info */
1989         e = talloc(info, struct lsa_ForestTrustRecord);
1990         W_ERROR_HAVE_NO_MEMORY(e);
1991
1992         e->flags = 0;
1993         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
1994         e->time = 0; /* so far always 0 in trces. */
1995         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
1996                                                                        mem_ctx);
1997         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
1998
1999         info->entries[0] = e;
2000
2001         /* Domain info */
2002         e = talloc(info, struct lsa_ForestTrustRecord);
2003         W_ERROR_HAVE_NO_MEMORY(e);
2004
2005         /* get our own domain info */
2006         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2007         if (ret != 1) {
2008                 return WERR_GENERAL_FAILURE;
2009         }
2010
2011         /* TODO: check if disabled and set flags accordingly */
2012         e->flags = 0;
2013         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2014         e->time = 0; /* so far always 0 in traces. */
2015
2016         domain_info = &e->forest_trust_data.domain_info;
2017         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2018                                                        "objectSid");
2019         domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
2020         domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
2021
2022         info->entries[1] = e;
2023
2024         talloc_free(dom_res);
2025
2026         return WERR_OK;
2027 }
2028
2029 /*
2030   netr_DsRGetForestTrustInformation
2031 */
2032 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2033                                                        TALLOC_CTX *mem_ctx,
2034                                                        struct netr_DsRGetForestTrustInformation *r)
2035 {
2036         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2037         struct lsa_ForestTrustInformation *info, **info_ptr;
2038         struct ldb_context *sam_ctx;
2039         WERROR werr;
2040
2041         if (r->in.flags & 0xFFFFFFFE) {
2042                 return WERR_INVALID_FLAGS;
2043         }
2044
2045         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2046                                 dce_call->conn->auth_state.session_info);
2047         if (sam_ctx == NULL) {
2048                 return WERR_GENERAL_FAILURE;
2049         }
2050
2051         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2052                 if (!samdb_is_pdc(sam_ctx)) {
2053                         return WERR_NERR_NOTPRIMARY;
2054                 }
2055
2056                 if (r->in.trusted_domain_name == NULL) {
2057                         return WERR_INVALID_FLAGS;
2058                 }
2059
2060                 /* TODO: establish an schannel connection with
2061                  * r->in.trusted_domain_name and perform a
2062                  * netr_GetForestTrustInformation call against it */
2063
2064                 /* for now return not implementd */
2065                 return WERR_CALL_NOT_IMPLEMENTED;
2066         }
2067
2068         /* TODO: check r->in.server_name is our name */
2069
2070         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2071         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2072
2073         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2074         W_ERROR_HAVE_NO_MEMORY(info);
2075
2076         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2077         W_ERROR_NOT_OK_RETURN(werr);
2078
2079         *info_ptr = info;
2080         r->out.forest_trust_info = info_ptr;
2081
2082         return WERR_OK;
2083 }
2084
2085
2086 /*
2087   netr_GetForestTrustInformation
2088 */
2089 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2090                                                       TALLOC_CTX *mem_ctx,
2091                                                       struct netr_GetForestTrustInformation *r)
2092 {
2093         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2094         struct netlogon_creds_CredentialState *creds;
2095         struct lsa_ForestTrustInformation *info, **info_ptr;
2096         struct ldb_context *sam_ctx;
2097         NTSTATUS status;
2098         WERROR werr;
2099
2100         status = dcesrv_netr_creds_server_step_check(dce_call,
2101                                                      mem_ctx,
2102                                                      r->in.computer_name,
2103                                                      r->in.credential,
2104                                                      r->out.return_authenticator,
2105                                                      &creds);
2106         if (!NT_STATUS_IS_OK(status)) {
2107                 return status;
2108         }
2109
2110         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2111             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2112                 return NT_STATUS_NOT_IMPLEMENTED;
2113         }
2114
2115         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2116                                 dce_call->conn->auth_state.session_info);
2117         if (sam_ctx == NULL) {
2118                 return NT_STATUS_UNSUCCESSFUL;
2119         }
2120
2121         /* TODO: check r->in.server_name is our name */
2122
2123         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2124         if (!info_ptr) {
2125                 return NT_STATUS_NO_MEMORY;
2126         }
2127         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2128         if (!info) {
2129                 return NT_STATUS_NO_MEMORY;
2130         }
2131
2132         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2133         if (!W_ERROR_IS_OK(werr)) {
2134                 return werror_to_ntstatus(werr);
2135         }
2136
2137         *info_ptr = info;
2138         r->out.forest_trust_info = info_ptr;
2139
2140         return NT_STATUS_OK;
2141 }
2142
2143
2144 /*
2145   netr_ServerGetTrustInfo
2146 */
2147 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2148                        struct netr_ServerGetTrustInfo *r)
2149 {
2150         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2151 }
2152
2153
2154 /* include the generated boilerplate */
2155 #include "librpc/gen_ndr/ndr_netlogon_s.c"