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