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