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