s4:netlogon - Put the "supported encryption types" more back in the "LogonGetDomainIn...
[ira/wip.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 "rpc_server/common/common.h"
27 #include "lib/ldb/include/ldb.h"
28 #include "auth/auth.h"
29 #include "auth/auth_sam_reply.h"
30 #include "dsdb/samdb/samdb.h"
31 #include "../libds/common/flags.h"
32 #include "rpc_server/samr/proto.h"
33 #include "../lib/util/util_ldb.h"
34 #include "libcli/auth/libcli_auth.h"
35 #include "auth/gensec/schannel.h"
36 #include "libcli/security/security.h"
37 #include "param/param.h"
38 #include "lib/messaging/irpc.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
40 #include "librpc/gen_ndr/ndr_netlogon.h"
41
42 struct netlogon_server_pipe_state {
43         struct netr_Credential client_challenge;
44         struct netr_Credential server_challenge;
45 };
46
47
48 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
49                                         struct netr_ServerReqChallenge *r)
50 {
51         struct netlogon_server_pipe_state *pipe_state =
52                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
53
54         ZERO_STRUCTP(r->out.return_credentials);
55
56         /* destroyed on pipe shutdown */
57
58         if (pipe_state) {
59                 talloc_free(pipe_state);
60                 dce_call->context->private_data = NULL;
61         }
62         
63         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
64         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
65
66         pipe_state->client_challenge = *r->in.credentials;
67
68         generate_random_buffer(pipe_state->server_challenge.data, 
69                                sizeof(pipe_state->server_challenge.data));
70
71         *r->out.return_credentials = pipe_state->server_challenge;
72
73         dce_call->context->private_data = pipe_state;
74
75         return NT_STATUS_OK;
76 }
77
78 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
79                                          struct netr_ServerAuthenticate3 *r)
80 {
81         struct netlogon_server_pipe_state *pipe_state =
82                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
83         struct netlogon_creds_CredentialState *creds;
84         struct ldb_context *schannel_ldb;
85         struct ldb_context *sam_ctx;
86         struct samr_Password *mach_pwd;
87         uint32_t user_account_control;
88         int num_records;
89         struct ldb_message **msgs;
90         NTSTATUS nt_status;
91         const char *attrs[] = {"unicodePwd", "userAccountControl", 
92                                "objectSid", NULL};
93
94         const char *trust_dom_attrs[] = {"flatname", NULL};
95         const char *account_name;
96
97         ZERO_STRUCTP(r->out.return_credentials);
98         *r->out.rid = 0;
99
100         /*
101          * According to Microsoft (see bugid #6099)
102          * Windows 7 looks at the negotiate_flags
103          * returned in this structure *even if the
104          * call fails with access denied!
105          */
106         *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
107                                   NETLOGON_NEG_PERSISTENT_SAMREPL |
108                                   NETLOGON_NEG_ARCFOUR |
109                                   NETLOGON_NEG_PROMOTION_COUNT |
110                                   NETLOGON_NEG_CHANGELOG_BDC |
111                                   NETLOGON_NEG_FULL_SYNC_REPL |
112                                   NETLOGON_NEG_MULTIPLE_SIDS |
113                                   NETLOGON_NEG_REDO |
114                                   NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
115                                   NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
116                                   NETLOGON_NEG_GENERIC_PASSTHROUGH |
117                                   NETLOGON_NEG_CONCURRENT_RPC |
118                                   NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
119                                   NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
120                                   NETLOGON_NEG_STRONG_KEYS |
121                                   NETLOGON_NEG_TRANSITIVE_TRUSTS |
122                                   NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
123                                   NETLOGON_NEG_PASSWORD_SET2 |
124                                   NETLOGON_NEG_GETDOMAININFO |
125                                   NETLOGON_NEG_CROSS_FOREST_TRUSTS |
126                                   NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
127                                   NETLOGON_NEG_RODC_PASSTHROUGH |
128                                   NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
129                                   NETLOGON_NEG_AUTHENTICATED_RPC;
130
131         if (!pipe_state) {
132                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
133                 return NT_STATUS_ACCESS_DENIED;
134         }
135
136         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, 
137                                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
138         if (sam_ctx == NULL) {
139                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
140         }
141
142         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
143                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
144                 const char *flatname;
145                 if (!encoded_account) {
146                         return NT_STATUS_NO_MEMORY;
147                 }
148
149                 /* Kill the trailing dot */
150                 if (encoded_account[strlen(encoded_account)-1] == '.') {
151                         encoded_account[strlen(encoded_account)-1] = '\0';
152                 }
153
154                 /* pull the user attributes */
155                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
156                                            trust_dom_attrs,
157                                            "(&(trustPartner=%s)(objectclass=trustedDomain))", 
158                                            encoded_account);
159                 
160                 if (num_records == 0) {
161                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n", 
162                                  encoded_account));
163                         return NT_STATUS_ACCESS_DENIED;
164                 }
165                 
166                 if (num_records > 1) {
167                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
168                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
169                 }
170                 
171                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
172                 if (!flatname) {
173                         /* No flatname for this trust - we can't proceed */
174                         return NT_STATUS_ACCESS_DENIED;
175                 }
176                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
177
178                 if (!account_name) {
179                         return NT_STATUS_NO_MEMORY;
180                 }
181                 
182         } else {
183                 account_name = r->in.account_name;
184         }
185         
186         /* pull the user attributes */
187         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
188                                    "(&(sAMAccountName=%s)(objectclass=user))", 
189                                    ldb_binary_encode_string(mem_ctx, account_name));
190
191         if (num_records == 0) {
192                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
193                          r->in.account_name));
194                 return NT_STATUS_ACCESS_DENIED;
195         }
196
197         if (num_records > 1) {
198                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
199                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
200         }
201
202         
203         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
204
205         if (user_account_control & UF_ACCOUNTDISABLE) {
206                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
207                 return NT_STATUS_ACCESS_DENIED;
208         }
209
210         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
211                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
212                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
213                         return NT_STATUS_ACCESS_DENIED;
214                 }
215         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || 
216                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
217                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
218                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
219                         
220                         return NT_STATUS_ACCESS_DENIED;
221                 }
222         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
223                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
224                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
225                         return NT_STATUS_ACCESS_DENIED;
226                 }
227         } else {
228                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", 
229                           r->in.secure_channel_type));
230                 return NT_STATUS_ACCESS_DENIED;
231         }
232
233         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], 
234                                                 "objectSid", 0);
235
236         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
237         if (mach_pwd == NULL) {
238                 return NT_STATUS_ACCESS_DENIED;
239         }
240
241         creds = netlogon_creds_server_init(mem_ctx,     
242                                            r->in.account_name,
243                                            r->in.computer_name,
244                                            r->in.secure_channel_type,
245                                            &pipe_state->client_challenge, 
246                                            &pipe_state->server_challenge, 
247                                            mach_pwd,
248                                            r->in.credentials,
249                                            r->out.return_credentials,
250                                            *r->in.negotiate_flags);
251         
252         if (!creds) {
253                 return NT_STATUS_ACCESS_DENIED;
254         }
255
256         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
257
258         schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
259         if (!schannel_ldb) {
260                 return NT_STATUS_ACCESS_DENIED;
261         }
262
263         nt_status = schannel_store_session_key_ldb(schannel_ldb, mem_ctx, creds);
264         talloc_free(schannel_ldb);
265
266         return nt_status;
267 }
268                                                  
269 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
270                                         struct netr_ServerAuthenticate *r)
271 {
272         struct netr_ServerAuthenticate3 a;
273         uint32_t rid;
274         /* TODO: 
275          * negotiate_flags is used as an [in] parameter
276          * so it need to be initialised.
277          *
278          * (I think ... = 0; seems wrong here --metze)
279          */
280         uint32_t negotiate_flags_in = 0;
281         uint32_t negotiate_flags_out = 0;
282
283         a.in.server_name                = r->in.server_name;
284         a.in.account_name               = r->in.account_name;
285         a.in.secure_channel_type        = r->in.secure_channel_type;
286         a.in.computer_name              = r->in.computer_name;
287         a.in.credentials                = r->in.credentials;
288         a.in.negotiate_flags            = &negotiate_flags_in;
289
290         a.out.return_credentials        = r->out.return_credentials;
291         a.out.rid                       = &rid;
292         a.out.negotiate_flags           = &negotiate_flags_out;
293
294         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
295 }
296
297 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
298                                          struct netr_ServerAuthenticate2 *r)
299 {
300         struct netr_ServerAuthenticate3 r3;
301         uint32_t rid = 0;
302
303         r3.in.server_name = r->in.server_name;
304         r3.in.account_name = r->in.account_name;
305         r3.in.secure_channel_type = r->in.secure_channel_type;
306         r3.in.computer_name = r->in.computer_name;
307         r3.in.credentials = r->in.credentials;
308         r3.out.return_credentials = r->out.return_credentials;
309         r3.in.negotiate_flags = r->in.negotiate_flags;
310         r3.out.negotiate_flags = r->out.negotiate_flags;
311         r3.out.rid = &rid;
312         
313         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
314 }
315
316 /*
317   Validate an incoming authenticator against the credentials for the remote machine.
318
319   The credentials are (re)read and from the schannel database, and
320   written back after the caclulations are performed.
321
322   The creds_out parameter (if not NULL) returns the credentials, if
323   the caller needs some of that information.
324
325 */
326 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
327                                                     TALLOC_CTX *mem_ctx, 
328                                                     const char *computer_name,
329                                                     struct netr_Authenticator *received_authenticator,
330                                                     struct netr_Authenticator *return_authenticator,
331                                                     struct netlogon_creds_CredentialState **creds_out) 
332 {
333         NTSTATUS nt_status;
334         struct ldb_context *ldb;
335         bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
336         bool schannel_in_use = dce_call->conn->auth_state.auth_info
337                 && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
338                 && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY 
339                     || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
340
341         ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
342         if (!ldb) {
343                 return NT_STATUS_ACCESS_DENIED;
344         }
345         nt_status = schannel_creds_server_step_check_ldb(ldb, mem_ctx,
346                                                          computer_name,
347                                                          schannel_global_required,
348                                                          schannel_in_use,
349                                                          received_authenticator,
350                                                          return_authenticator, creds_out);
351         talloc_free(ldb);
352         return nt_status;
353 }
354
355 /* 
356   Change the machine account password for the currently connected
357   client.  Supplies only the NT#.
358 */
359
360 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
361                                        struct netr_ServerPasswordSet *r)
362 {
363         struct netlogon_creds_CredentialState *creds;
364         struct ldb_context *sam_ctx;
365         NTSTATUS nt_status;
366
367         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
368                                                         mem_ctx, 
369                                                         r->in.computer_name, 
370                                                         r->in.credential, r->out.return_authenticator,
371                                                         &creds);
372         NT_STATUS_NOT_OK_RETURN(nt_status);
373
374         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
375         if (sam_ctx == NULL) {
376                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
377         }
378
379         netlogon_creds_des_decrypt(creds, r->in.new_password);
380
381         /* Using the sid for the account as the key, set the password */
382         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, 
383                                            creds->sid,
384                                            NULL, /* Don't have plaintext */
385                                            NULL, r->in.new_password,
386                                            true, /* Password change */
387                                            NULL, NULL);
388         return nt_status;
389 }
390
391 /* 
392   Change the machine account password for the currently connected
393   client.  Supplies new plaintext.
394 */
395 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
396                                        struct netr_ServerPasswordSet2 *r)
397 {
398         struct netlogon_creds_CredentialState *creds;
399         struct ldb_context *sam_ctx;
400         NTSTATUS nt_status;
401         DATA_BLOB new_password;
402
403         struct samr_CryptPassword password_buf;
404
405         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
406                                                         mem_ctx, 
407                                                         r->in.computer_name, 
408                                                         r->in.credential, r->out.return_authenticator,
409                                                         &creds);
410         NT_STATUS_NOT_OK_RETURN(nt_status);
411
412         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
413         if (sam_ctx == NULL) {
414                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
415         }
416
417         memcpy(password_buf.data, r->in.new_password->data, 512);
418         SIVAL(password_buf.data, 512, r->in.new_password->length);
419         netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
420
421         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
422                 DEBUG(3,("samr: failed to decode password buffer\n"));
423                 return NT_STATUS_WRONG_PASSWORD;
424         }
425                 
426         /* Using the sid for the account as the key, set the password */
427         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
428                                            creds->sid,
429                                            &new_password, /* we have plaintext */
430                                            NULL, NULL,
431                                            true, /* Password change */
432                                            NULL, NULL);
433         return nt_status;
434 }
435
436
437 /* 
438   netr_LogonUasLogon 
439 */
440 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
441                                  struct netr_LogonUasLogon *r)
442 {
443         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
444 }
445
446
447 /* 
448   netr_LogonUasLogoff 
449 */
450 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
451                        struct netr_LogonUasLogoff *r)
452 {
453         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
454 }
455
456
457 /* 
458   netr_LogonSamLogon_base
459
460   This version of the function allows other wrappers to say 'do not check the credentials'
461
462   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
463 */
464 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
465                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
466 {
467         struct auth_context *auth_context;
468         struct auth_usersupplied_info *user_info;
469         struct auth_serversupplied_info *server_info;
470         NTSTATUS nt_status;
471         static const char zeros[16];
472         struct netr_SamBaseInfo *sam;
473         struct netr_SamInfo2 *sam2;
474         struct netr_SamInfo3 *sam3;
475         struct netr_SamInfo6 *sam6;
476         
477         user_info = talloc(mem_ctx, struct auth_usersupplied_info);
478         NT_STATUS_HAVE_NO_MEMORY(user_info);
479
480         user_info->flags = 0;
481         user_info->mapped_state = false;
482         user_info->remote_host = NULL;
483
484         switch (r->in.logon_level) {
485         case NetlogonInteractiveInformation:
486         case NetlogonServiceInformation:
487         case NetlogonInteractiveTransitiveInformation:
488         case NetlogonServiceTransitiveInformation:
489                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
490                         netlogon_creds_arcfour_crypt(creds, 
491                                             r->in.logon->password->lmpassword.hash,
492                                             sizeof(r->in.logon->password->lmpassword.hash));
493                         netlogon_creds_arcfour_crypt(creds, 
494                                             r->in.logon->password->ntpassword.hash,
495                                             sizeof(r->in.logon->password->ntpassword.hash));
496                 } else {
497                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
498                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
499                 }
500
501                 /* TODO: we need to deny anonymous access here */
502                 nt_status = auth_context_create(mem_ctx, 
503                                                 dce_call->event_ctx, dce_call->msg_ctx,
504                                                 dce_call->conn->dce_ctx->lp_ctx,
505                                                 &auth_context);
506                 NT_STATUS_NOT_OK_RETURN(nt_status);
507
508                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
509                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
510                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
511                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
512                 
513                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
514                 user_info->password_state = AUTH_PASSWORD_HASH;
515
516                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
517                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
518                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
519
520                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
521                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
522                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
523
524                 break;
525         case NetlogonNetworkInformation:
526         case NetlogonNetworkTransitiveInformation:
527
528                 /* TODO: we need to deny anonymous access here */
529                 nt_status = auth_context_create(mem_ctx, 
530                                                 dce_call->event_ctx, dce_call->msg_ctx,
531                                                 dce_call->conn->dce_ctx->lp_ctx,
532                                                 &auth_context);
533                 NT_STATUS_NOT_OK_RETURN(nt_status);
534
535                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
536                 NT_STATUS_NOT_OK_RETURN(nt_status);
537
538                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
539                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
540                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
541                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
542                 
543                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
544                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
545                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
546         
547                 break;
548
549                 
550         case NetlogonGenericInformation:
551         {
552                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
553                         netlogon_creds_arcfour_crypt(creds, 
554                                             r->in.logon->generic->data, r->in.logon->generic->length);
555                 } else {
556                         /* Using DES to verify kerberos tickets makes no sense */
557                         return NT_STATUS_INVALID_PARAMETER;
558                 }
559
560                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
561                         NTSTATUS status;
562                         struct server_id *kdc;
563                         struct kdc_check_generic_kerberos check;
564                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
565                         NT_STATUS_HAVE_NO_MEMORY(generic);
566                         *r->out.authoritative = 1;
567                         
568                         /* TODO: Describe and deal with these flags */
569                         *r->out.flags = 0;
570
571                         r->out.validation->generic = generic;
572         
573                         kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
574                         if ((kdc == NULL) || (kdc[0].id == 0)) {
575                                 return NT_STATUS_NO_LOGON_SERVERS;
576                         }
577                         
578                         check.in.generic_request = 
579                                 data_blob_const(r->in.logon->generic->data,
580                                                 r->in.logon->generic->length);
581                         
582                         status = irpc_call(dce_call->msg_ctx, kdc[0],
583                                            &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
584                                            &check, mem_ctx);
585                         if (!NT_STATUS_IS_OK(status)) {
586                                 return status;
587                         }
588                         generic->length = check.out.generic_reply.length;
589                         generic->data = check.out.generic_reply.data;
590                         return NT_STATUS_OK;
591                 }
592
593                 /* Until we get an implemetnation of these other packages */
594                 return NT_STATUS_INVALID_PARAMETER;
595         }
596         default:
597                 return NT_STATUS_INVALID_PARAMETER;
598         }
599         
600         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
601         NT_STATUS_NOT_OK_RETURN(nt_status);
602
603         nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
604         NT_STATUS_NOT_OK_RETURN(nt_status);
605
606         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
607         /* It appears that level 6 is not individually encrypted */
608         if ((r->in.validation_level != 6) &&
609             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
610                 /* This key is sent unencrypted without the ARCFOUR flag set */
611                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
612                         netlogon_creds_arcfour_crypt(creds, 
613                                             sam->key.key, 
614                                             sizeof(sam->key.key));
615                 }
616         }
617
618         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
619         /* It appears that level 6 is not individually encrypted */
620         if ((r->in.validation_level != 6) &&
621             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
622                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
623                         netlogon_creds_arcfour_crypt(creds, 
624                                             sam->LMSessKey.key, 
625                                             sizeof(sam->LMSessKey.key));
626                 } else {
627                         netlogon_creds_des_encrypt_LMKey(creds, 
628                                                 &sam->LMSessKey);
629                 }
630         }
631
632         switch (r->in.validation_level) {
633         case 2:
634                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
635                 NT_STATUS_HAVE_NO_MEMORY(sam2);
636                 sam2->base = *sam;
637                 r->out.validation->sam2 = sam2;
638                 break;
639
640         case 3:
641                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
642                 NT_STATUS_HAVE_NO_MEMORY(sam3);
643                 sam3->base = *sam;
644                 r->out.validation->sam3 = sam3;
645                 break;
646
647         case 6:
648                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
649                 NT_STATUS_HAVE_NO_MEMORY(sam6);
650                 sam6->base = *sam;
651                 sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
652                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s", 
653                                                          sam->account_name.string, sam6->forest.string);
654                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
655                 r->out.validation->sam6 = sam6;
656                 break;
657
658         default:
659                 break;
660         }
661
662         *r->out.authoritative = 1;
663
664         /* TODO: Describe and deal with these flags */
665         *r->out.flags = 0;
666
667         return NT_STATUS_OK;
668 }
669
670 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
671                                      struct netr_LogonSamLogonEx *r) 
672 {
673         NTSTATUS nt_status;
674         struct netlogon_creds_CredentialState *creds;
675         struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
676         if (!ldb) {
677                 return NT_STATUS_ACCESS_DENIED;
678         }
679         
680         nt_status = schannel_fetch_session_key_ldb(ldb, mem_ctx, r->in.computer_name, &creds);
681         if (!NT_STATUS_IS_OK(nt_status)) {
682                 return nt_status;
683         }
684
685         if (!dce_call->conn->auth_state.auth_info ||
686             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
687                 return NT_STATUS_ACCESS_DENIED;
688         }
689         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
690 }
691
692 /* 
693   netr_LogonSamLogonWithFlags
694
695 */
696 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
697                                             struct netr_LogonSamLogonWithFlags *r)
698 {
699         NTSTATUS nt_status;
700         struct netlogon_creds_CredentialState *creds;
701         struct netr_LogonSamLogonEx r2;
702
703         struct netr_Authenticator *return_authenticator;
704
705         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
706         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
707
708         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
709                                                         mem_ctx, 
710                                                         r->in.computer_name, 
711                                                         r->in.credential, return_authenticator,
712                                                         &creds);
713         NT_STATUS_NOT_OK_RETURN(nt_status);
714
715         ZERO_STRUCT(r2);
716
717         r2.in.server_name       = r->in.server_name;
718         r2.in.computer_name     = r->in.computer_name;
719         r2.in.logon_level       = r->in.logon_level;
720         r2.in.logon             = r->in.logon;
721         r2.in.validation_level  = r->in.validation_level;
722         r2.in.flags             = r->in.flags;
723         r2.out.validation       = r->out.validation;
724         r2.out.authoritative    = r->out.authoritative;
725         r2.out.flags            = r->out.flags;
726
727         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
728
729         r->out.return_authenticator     = return_authenticator;
730
731         return nt_status;
732 }
733
734 /* 
735   netr_LogonSamLogon
736 */
737 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
738                                    struct netr_LogonSamLogon *r)
739 {
740         struct netr_LogonSamLogonWithFlags r2;
741         uint32_t flags = 0;
742         NTSTATUS status;
743
744         ZERO_STRUCT(r2);
745
746         r2.in.server_name = r->in.server_name;
747         r2.in.computer_name = r->in.computer_name;
748         r2.in.credential  = r->in.credential;
749         r2.in.return_authenticator = r->in.return_authenticator;
750         r2.in.logon_level = r->in.logon_level;
751         r2.in.logon = r->in.logon;
752         r2.in.validation_level = r->in.validation_level;
753         r2.in.flags = &flags;
754         r2.out.validation = r->out.validation;
755         r2.out.authoritative = r->out.authoritative;
756         r2.out.flags = &flags;
757
758         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
759
760         r->out.return_authenticator = r2.out.return_authenticator;
761
762         return status;
763 }
764
765
766 /* 
767   netr_LogonSamLogoff 
768 */
769 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
770                        struct netr_LogonSamLogoff *r)
771 {
772         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
773 }
774
775
776
777 /* 
778   netr_DatabaseDeltas 
779 */
780 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
781                        struct netr_DatabaseDeltas *r)
782 {
783         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
784 }
785
786
787 /* 
788   netr_DatabaseSync2 
789 */
790 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
791                        struct netr_DatabaseSync2 *r)
792 {
793         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
794         return NT_STATUS_NOT_IMPLEMENTED;
795 }
796
797
798 /* 
799   netr_DatabaseSync 
800 */
801 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
802                        struct netr_DatabaseSync *r)
803 {
804         struct netr_DatabaseSync2 r2;
805         NTSTATUS status;
806
807         ZERO_STRUCT(r2);
808
809         r2.in.logon_server = r->in.logon_server;
810         r2.in.computername = r->in.computername;
811         r2.in.credential = r->in.credential;
812         r2.in.database_id = r->in.database_id;
813         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
814         r2.in.sync_context = r->in.sync_context;
815         r2.out.sync_context = r->out.sync_context;
816         r2.out.delta_enum_array = r->out.delta_enum_array;
817         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
818
819         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
820
821         return status;
822 }
823
824
825 /* 
826   netr_AccountDeltas 
827 */
828 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
829                        struct netr_AccountDeltas *r)
830 {
831         /* w2k3 returns "NOT IMPLEMENTED" for this call */
832         return NT_STATUS_NOT_IMPLEMENTED;
833 }
834
835
836 /* 
837   netr_AccountSync 
838 */
839 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
840                        struct netr_AccountSync *r)
841 {
842         /* w2k3 returns "NOT IMPLEMENTED" for this call */
843         return NT_STATUS_NOT_IMPLEMENTED;
844 }
845
846
847 /* 
848   netr_GetDcName 
849 */
850 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
851                        struct netr_GetDcName *r)
852 {
853         const char * const attrs[] = { NULL };
854         struct ldb_context *sam_ctx;
855         struct ldb_message **res;
856         struct ldb_dn *domain_dn;
857         int ret;
858         const char *dcname;
859
860         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
861                                 dce_call->conn->dce_ctx->lp_ctx,
862                                 dce_call->conn->auth_state.session_info);
863         if (sam_ctx == NULL) {
864                 return WERR_DS_UNAVAILABLE;
865         }
866
867         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
868                                        r->in.domainname);
869         if (domain_dn == NULL) {
870                 return WERR_DS_UNAVAILABLE;
871         }
872
873         ret = gendb_search_dn(sam_ctx, mem_ctx,
874                               domain_dn, &res, attrs);
875         if (ret != 1) {
876                 return WERR_NO_SUCH_DOMAIN;
877         }
878
879         /* TODO: - return real IP address
880          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
881          */
882         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
883                                  lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
884         W_ERROR_HAVE_NO_MEMORY(dcname);
885
886         *r->out.dcname = dcname;
887         return WERR_OK;
888 }
889
890
891 /* 
892   netr_LogonControl2Ex 
893 */
894 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
895                        struct netr_LogonControl2Ex *r)
896 {
897         return WERR_NOT_SUPPORTED;
898 }
899
900
901 /* 
902   netr_LogonControl 
903 */
904 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
905                        struct netr_LogonControl *r)
906 {
907         struct netr_LogonControl2Ex r2;
908         WERROR werr;
909
910         if (r->in.level == 0x00000001) {
911                 ZERO_STRUCT(r2);
912
913                 r2.in.logon_server = r->in.logon_server;
914                 r2.in.function_code = r->in.function_code;
915                 r2.in.level = r->in.level;
916                 r2.in.data = NULL;
917                 r2.out.query = r->out.query;
918
919                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
920         } else if (r->in.level == 0x00000002) {
921                 werr = WERR_NOT_SUPPORTED;
922         } else {
923                 werr = WERR_UNKNOWN_LEVEL;
924         }
925
926         return werr;
927 }
928
929
930 /* 
931   netr_LogonControl2 
932 */
933 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
934                        struct netr_LogonControl2 *r)
935 {
936         struct netr_LogonControl2Ex r2;
937         WERROR werr;
938
939         ZERO_STRUCT(r2);
940
941         r2.in.logon_server = r->in.logon_server;
942         r2.in.function_code = r->in.function_code;
943         r2.in.level = r->in.level;
944         r2.in.data = r->in.data;
945         r2.out.query = r->out.query;
946
947         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
948
949         return werr;
950 }
951
952
953 /* 
954   netr_GetAnyDCName 
955 */
956 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
957                        struct netr_GetAnyDCName *r)
958 {
959         struct netr_GetDcName r2;
960         WERROR werr;
961
962         ZERO_STRUCT(r2);
963
964         r2.in.logon_server      = r->in.logon_server;
965         r2.in.domainname        = r->in.domainname;
966         r2.out.dcname           = r->out.dcname;
967
968         werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
969
970         return werr;
971 }
972
973
974 /* 
975   netr_DatabaseRedo 
976 */
977 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
978                        struct netr_DatabaseRedo *r)
979 {
980         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
981 }
982
983
984 /* 
985   netr_NetrEnumerateTurstedDomains
986 */
987 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
988                        struct netr_NetrEnumerateTrustedDomains *r)
989 {
990         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
991 }
992
993
994 /* 
995   netr_LogonGetCapabilities
996 */
997 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
998                        struct netr_LogonGetCapabilities *r)
999 {
1000         /* we don't support AES yet */
1001         return NT_STATUS_NOT_IMPLEMENTED;
1002 }
1003
1004
1005 /* 
1006   netr_NETRLOGONSETSERVICEBITS 
1007 */
1008 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1009                        struct netr_NETRLOGONSETSERVICEBITS *r)
1010 {
1011         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1012 }
1013
1014
1015 /*
1016   netr_LogonGetTrustRid
1017 */
1018 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1019                        struct netr_LogonGetTrustRid *r)
1020 {
1021         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1022 }
1023
1024
1025 /* 
1026   netr_NETRLOGONCOMPUTESERVERDIGEST 
1027 */
1028 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1029                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1030 {
1031         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1032 }
1033
1034
1035 /* 
1036   netr_NETRLOGONCOMPUTECLIENTDIGEST 
1037 */
1038 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1039                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1040 {
1041         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1042 }
1043
1044
1045
1046 /* 
1047   netr_DsRGetSiteName
1048 */
1049 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1050                                   struct netr_DsRGetSiteName *r)
1051 {
1052         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1053 }
1054
1055
1056 /*
1057   fill in a netr_OneDomainInfo from a ldb search result
1058 */
1059 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1060                                      struct loadparm_context *lp_ctx,
1061                                      struct ldb_context *sam_ctx,
1062                                      struct ldb_message *res,
1063                                      struct netr_OneDomainInfo *info,
1064                                      bool is_local, bool is_trust_list)
1065 {
1066         ZERO_STRUCTP(info);
1067
1068         info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1069         info->trust_extension.length = 16;
1070         info->trust_extension.info->flags = 
1071                 NETR_TRUST_FLAG_TREEROOT |
1072                 NETR_TRUST_FLAG_IN_FOREST | 
1073                 NETR_TRUST_FLAG_PRIMARY;
1074
1075         info->trust_extension.info->parent_index = 0; /* should be index into array
1076                                                          of parent */
1077         info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1078         info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
1079
1080         if (is_trust_list) {
1081                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1082                 info->dns_forestname.string = NULL;
1083         } else {
1084                 char *p;
1085                 /* TODO: we need a common function for pulling the forest */
1086                 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1087                 if (!info->dns_forestname.string) {
1088                         return NT_STATUS_NO_SUCH_DOMAIN;                
1089                 }
1090                 p = strchr(info->dns_forestname.string, '/');
1091                 if (p) {
1092                         *p = '\0';
1093                 }
1094         }
1095
1096         if (is_local) {
1097                 info->domainname.string = lp_sam_name(lp_ctx);
1098                 info->dns_domainname.string = lp_realm(lp_ctx);
1099                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1100                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1101         } else {
1102                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1103                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1104                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1105                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1106         }
1107
1108         return NT_STATUS_OK;
1109 }
1110
1111 /* 
1112   netr_LogonGetDomainInfo
1113   this is called as part of the ADS domain logon procedure.
1114
1115   It has an important role in convaying details about the client, such
1116   as Operating System, Version, Service Pack etc.
1117 */
1118 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1119         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1120 {
1121         struct netlogon_creds_CredentialState *creds;
1122         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1123                 "securityIdentifier", "trustPartner", NULL };
1124         const char *temp_str;
1125         const char *old_dns_hostname;
1126         struct ldb_context *sam_ctx;
1127         struct ldb_message **res1, **res2, *new_msg;
1128         struct ldb_dn *workstation_dn;
1129         struct netr_DomainInformation *domain_info;
1130         struct netr_LsaPolicyInformation *lsa_policy_info;
1131         struct netr_OsVersionInfoEx *os_version;
1132         uint32_t default_supported_enc_types =
1133                 ENC_CRC32|ENC_RSA_MD5|ENC_RC4_HMAC_MD5;
1134         int ret1, ret2, i;
1135         NTSTATUS status;
1136
1137         status = dcesrv_netr_creds_server_step_check(dce_call,
1138                                                      mem_ctx, 
1139                                                      r->in.computer_name, 
1140                                                      r->in.credential, 
1141                                                      r->out.return_authenticator,
1142                                                      &creds);
1143         if (!NT_STATUS_IS_OK(status)) {
1144                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1145         }
1146         NT_STATUS_NOT_OK_RETURN(status);
1147
1148         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1149                 dce_call->conn->dce_ctx->lp_ctx,
1150                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
1151         if (sam_ctx == NULL) {
1152                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1153         }
1154
1155         switch (r->in.level) {
1156         case 1: /* Domain information */
1157
1158                 /* TODO: check NTSTATUS results - and fail also on SAMDB
1159                  * errors (needs some testing against Windows Server 2008) */
1160
1161                 /*
1162                  * Check that the computer name parameter matches as prefix with
1163                  * the DNS hostname in the workstation info structure.
1164                  */
1165                 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
1166                         strcspn(r->in.query->workstation_info->dns_hostname,
1167                         "."));
1168                 if (strcasecmp(r->in.computer_name, temp_str) != 0)
1169                         return NT_STATUS_INVALID_PARAMETER;
1170
1171                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1172                         dom_sid_string(mem_ctx, creds->sid));
1173                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1174
1175                 /* Gets the old DNS hostname */
1176                 old_dns_hostname = samdb_search_string(sam_ctx, mem_ctx,
1177                                                         workstation_dn,
1178                                                         "dNSHostName",
1179                                                         NULL);
1180
1181                 /* Gets host informations and put them in our directory */
1182                 new_msg = ldb_msg_new(mem_ctx);
1183                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1184
1185                 new_msg->dn = workstation_dn;
1186
1187                 /* Deletes old OS version values */
1188                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1189                         "operatingSystemServicePack");
1190                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1191                         "operatingSystemVersion");
1192
1193                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1194                         DEBUG(3,("Impossible to update samdb: %s\n",
1195                                 ldb_errstring(sam_ctx)));
1196                 }
1197
1198                 talloc_free(new_msg);
1199
1200                 new_msg = ldb_msg_new(mem_ctx);
1201                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1202
1203                 new_msg->dn = workstation_dn;
1204
1205                 /* Sets the OS name */
1206                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1207                         "operatingSystem",
1208                         r->in.query->workstation_info->os_name.string);
1209
1210                 /*
1211                  * Sets informations from "os_version". On a empty structure
1212                  * the values are cleared.
1213                  */
1214                 if (r->in.query->workstation_info->os_version.os != NULL) {
1215                         os_version = &r->in.query->workstation_info->os_version.os->os;
1216
1217                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1218                                              "operatingSystemServicePack",
1219                                              os_version->CSDVersion);
1220
1221                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1222                                 "operatingSystemVersion",
1223                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1224                                         os_version->MajorVersion,
1225                                         os_version->MinorVersion,
1226                                         os_version->BuildNumber
1227                                 )
1228                         );
1229                 }
1230
1231                 /*
1232                  * Updates the "dNSHostname" and the "servicePrincipalName"s
1233                  * since the client wishes that the server should handle this
1234                  * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1235                  * See MS-NRPC section 3.5.4.3.9
1236                  */
1237                 if ((r->in.query->workstation_info->workstation_flags
1238                         & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1239
1240                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1241                                 "dNSHostname",
1242                                 r->in.query->workstation_info->dns_hostname);
1243                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1244                                 "servicePrincipalName",
1245                                 talloc_asprintf(mem_ctx, "HOST/%s",
1246                                 r->in.computer_name)
1247                         );
1248                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1249                                 "servicePrincipalName",
1250                                 talloc_asprintf(mem_ctx, "HOST/%s",
1251                                 r->in.query->workstation_info->dns_hostname)
1252                         );
1253                 }
1254
1255                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1256                         DEBUG(3,("Impossible to update samdb: %s\n",
1257                                 ldb_errstring(sam_ctx)));
1258                 }
1259
1260                 talloc_free(new_msg);
1261
1262                 /* Writes back the domain information */
1263
1264                 /* We need to do two searches. The first will pull our primary
1265                    domain and the second will pull any trusted domains. Our
1266                    primary domain is also a "trusted" domain, so we need to
1267                    put the primary domain into the lists of returned trusts as
1268                    well. */
1269                 ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1270                         &res1, attrs);
1271                 if (ret1 != 1) {
1272                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1273                 }
1274
1275                 ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs,
1276                         "(objectClass=trustedDomain)");
1277                 if (ret2 == -1) {
1278                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1279                 }
1280
1281                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1282                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1283
1284                 ZERO_STRUCTP(domain_info);
1285
1286                 /* Informations about the local and trusted domains */
1287
1288                 status = fill_one_domain_info(mem_ctx,
1289                         dce_call->conn->dce_ctx->lp_ctx,
1290                         sam_ctx, res1[0], &domain_info->primary_domain,
1291                         true, false);
1292                 NT_STATUS_NOT_OK_RETURN(status);
1293
1294                 domain_info->trusted_domain_count = ret2 + 1;
1295                 domain_info->trusted_domains = talloc_array(mem_ctx,
1296                         struct netr_OneDomainInfo,
1297                         domain_info->trusted_domain_count);
1298                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1299
1300                 for (i=0;i<ret2;i++) {
1301                         status = fill_one_domain_info(mem_ctx,
1302                                 dce_call->conn->dce_ctx->lp_ctx,
1303                                 sam_ctx, res2[i],
1304                                 &domain_info->trusted_domains[i],
1305                                 false, true);
1306                         NT_STATUS_NOT_OK_RETURN(status);
1307                 }
1308
1309                 status = fill_one_domain_info(mem_ctx,
1310                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0],
1311                         &domain_info->trusted_domains[i], true, true);
1312                 NT_STATUS_NOT_OK_RETURN(status);
1313
1314                 /* Sets the supported encryption types */
1315                 domain_info->supported_enc_types = samdb_search_uint(
1316                         sam_ctx, mem_ctx,
1317                         default_supported_enc_types, workstation_dn,
1318                         "msDS-SupportedEncryptionTypes", NULL);
1319
1320                 /* Other host domain informations */
1321
1322                 lsa_policy_info = talloc(mem_ctx,
1323                         struct netr_LsaPolicyInformation);
1324                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1325                 ZERO_STRUCTP(lsa_policy_info);
1326
1327                 domain_info->lsa_policy = *lsa_policy_info;
1328
1329                 domain_info->dns_hostname.string = old_dns_hostname;
1330                 domain_info->workstation_flags =
1331                         r->in.query->workstation_info->workstation_flags;
1332
1333                 r->out.info->domain_info = domain_info;
1334         break;
1335         case 2: /* LSA policy information - not used at the moment */
1336                 lsa_policy_info = talloc(mem_ctx,
1337                         struct netr_LsaPolicyInformation);
1338                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1339                 ZERO_STRUCTP(lsa_policy_info);
1340
1341                 r->out.info->lsa_policy_info = lsa_policy_info;
1342         break;
1343         default:
1344                 return NT_STATUS_INVALID_LEVEL;
1345         break;
1346         }
1347
1348         return NT_STATUS_OK;
1349 }
1350
1351
1352
1353 /*
1354   netr_ServerPasswordGet
1355 */
1356 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1357                        struct netr_ServerPasswordGet *r)
1358 {
1359         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1360 }
1361
1362
1363 /* 
1364   netr_NETRLOGONSENDTOSAM 
1365 */
1366 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1367                        struct netr_NETRLOGONSENDTOSAM *r)
1368 {
1369         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1370 }
1371
1372
1373 /* 
1374   netr_DsRAddressToSitenamesW 
1375 */
1376 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1377                        struct netr_DsRAddressToSitenamesW *r)
1378 {
1379         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1380 }
1381
1382
1383 /* 
1384   netr_DsRGetDCNameEx2
1385 */
1386 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1387                                    struct netr_DsRGetDCNameEx2 *r)
1388 {
1389         const char * const attrs[] = { "objectGUID", NULL };
1390         struct ldb_context *sam_ctx;
1391         struct ldb_message **res;
1392         struct ldb_dn *domain_dn;
1393         int ret;
1394         struct netr_DsRGetDCNameInfo *info;
1395
1396         ZERO_STRUCTP(r->out.info);
1397
1398         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1399         if (sam_ctx == NULL) {
1400                 return WERR_DS_UNAVAILABLE;
1401         }
1402
1403         /* Win7-beta will send the domain name in the form the user typed, so we have to cope
1404            with both the short and long form here */
1405         if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx, 
1406                                                                 r->in.domain_name)) {
1407                 return WERR_NO_SUCH_DOMAIN;
1408         }
1409
1410         domain_dn = ldb_get_default_basedn(sam_ctx);
1411         if (domain_dn == NULL) {
1412                 return WERR_DS_UNAVAILABLE;
1413         }
1414
1415         ret = gendb_search_dn(sam_ctx, mem_ctx,
1416                               domain_dn, &res, attrs);
1417         if (ret != 1) {
1418         }
1419
1420         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1421         W_ERROR_HAVE_NO_MEMORY(info);
1422
1423         /* TODO: - return real IP address
1424          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1425          */
1426         info->dc_unc                    = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1427                                                           lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), 
1428                                                           lp_realm(dce_call->conn->dce_ctx->lp_ctx));
1429         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1430         info->dc_address                = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1431         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1432         info->dc_address_type           = DS_ADDRESS_TYPE_INET;
1433         info->domain_guid               = samdb_result_guid(res[0], "objectGUID");
1434         info->domain_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1435         info->forest_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1436         info->dc_flags                  = DS_DNS_FOREST |
1437                                           DS_DNS_DOMAIN |
1438                                           DS_DNS_CONTROLLER |
1439                                           DS_SERVER_WRITABLE |
1440                                           DS_SERVER_CLOSEST |
1441                                           DS_SERVER_TIMESERV |
1442                                           DS_SERVER_KDC |
1443                                           DS_SERVER_DS |
1444                                           DS_SERVER_LDAP |
1445                                           DS_SERVER_GC |
1446                                           DS_SERVER_PDC;
1447         info->dc_site_name      = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1448         W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1449         info->client_site_name  = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1450         W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1451
1452         *r->out.info = info;
1453
1454         return WERR_OK;
1455 }
1456
1457 /* 
1458   netr_DsRGetDCNameEx
1459 */
1460 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1461                                   struct netr_DsRGetDCNameEx *r)
1462 {
1463         struct netr_DsRGetDCNameEx2 r2;
1464         WERROR werr;
1465
1466         ZERO_STRUCT(r2);
1467
1468         r2.in.server_unc = r->in.server_unc;
1469         r2.in.client_account = NULL;
1470         r2.in.mask = 0;
1471         r2.in.domain_guid = r->in.domain_guid;
1472         r2.in.domain_name = r->in.domain_name;
1473         r2.in.site_name = r->in.site_name;
1474         r2.in.flags = r->in.flags;
1475         r2.out.info = r->out.info;
1476
1477         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1478
1479         return werr;
1480 }
1481
1482 /* 
1483   netr_DsRGetDCName
1484 */
1485 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1486                                 struct netr_DsRGetDCName *r)
1487 {
1488         struct netr_DsRGetDCNameEx2 r2;
1489         WERROR werr;
1490
1491         ZERO_STRUCT(r2);
1492
1493         r2.in.server_unc = r->in.server_unc;
1494         r2.in.client_account = NULL;
1495         r2.in.mask = 0;
1496         r2.in.domain_name = r->in.domain_name;
1497         r2.in.domain_guid = r->in.domain_guid;
1498         
1499         r2.in.site_name = NULL; /* should fill in from site GUID */
1500         r2.in.flags = r->in.flags;
1501         r2.out.info = r->out.info;
1502
1503         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1504
1505         return werr;
1506 }
1507 /* 
1508   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
1509 */
1510 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1511                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1512 {
1513         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1514 }
1515
1516
1517 /*
1518   netr_NetrEnumerateTrustedDomainsEx
1519 */
1520 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1521                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1522 {
1523         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1524 }
1525
1526
1527 /* 
1528   netr_DsRAddressToSitenamesExW 
1529 */
1530 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1531                        struct netr_DsRAddressToSitenamesExW *r)
1532 {
1533         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1534 }
1535
1536
1537 /* 
1538   netr_DsrGetDcSiteCoverageW
1539 */
1540 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1541                        struct netr_DsrGetDcSiteCoverageW *r)
1542 {
1543         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1544 }
1545
1546
1547 /* 
1548   netr_DsrEnumerateDomainTrusts 
1549 */
1550 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1551                                               struct netr_DsrEnumerateDomainTrusts *r)
1552 {
1553         struct netr_DomainTrustList *trusts;
1554         struct ldb_context *sam_ctx;
1555         int ret;
1556         struct ldb_message **dom_res;
1557         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1558
1559         ZERO_STRUCT(r->out);
1560
1561         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1562         if (sam_ctx == NULL) {
1563                 return WERR_GENERAL_FAILURE;
1564         }
1565
1566         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1567                               &dom_res, dom_attrs);
1568         if (ret == -1) {
1569                 return WERR_GENERAL_FAILURE;            
1570         }
1571         if (ret != 1) {
1572                 return WERR_GENERAL_FAILURE;
1573         }
1574
1575         trusts = talloc(mem_ctx, struct netr_DomainTrustList);
1576         W_ERROR_HAVE_NO_MEMORY(trusts);
1577
1578         trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
1579         W_ERROR_HAVE_NO_MEMORY(trusts->array);
1580
1581         trusts->count = 1; /* ?? */
1582
1583         r->out.trusts = trusts;
1584
1585         /* TODO: add filtering by trust_flags, and correct trust_type
1586            and attributes */
1587         trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1588         trusts->array[0].dns_name     = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1589         trusts->array[0].trust_flags =
1590                 NETR_TRUST_FLAG_TREEROOT | 
1591                 NETR_TRUST_FLAG_IN_FOREST | 
1592                 NETR_TRUST_FLAG_PRIMARY;
1593         trusts->array[0].parent_index = 0;
1594         trusts->array[0].trust_type = 2;
1595         trusts->array[0].trust_attributes = 0;
1596         trusts->array[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1597         trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1598
1599         return WERR_OK;
1600 }
1601
1602
1603 /*
1604   netr_DsrDeregisterDNSHostRecords
1605 */
1606 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1607                        struct netr_DsrDeregisterDNSHostRecords *r)
1608 {
1609         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1610 }
1611
1612
1613 /*
1614   netr_ServerTrustPasswordsGet
1615 */
1616 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1617                        struct netr_ServerTrustPasswordsGet *r)
1618 {
1619         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1620 }
1621
1622
1623 /* 
1624   netr_DsRGetForestTrustInformation 
1625 */
1626 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1627                        struct netr_DsRGetForestTrustInformation *r)
1628 {
1629         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1630 }
1631
1632
1633 /*
1634   netr_GetForestTrustInformation
1635 */
1636 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1637                        struct netr_GetForestTrustInformation *r)
1638 {
1639         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1640 }
1641
1642
1643 /*
1644   netr_ServerGetTrustInfo
1645 */
1646 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1647                        struct netr_ServerGetTrustInfo *r)
1648 {
1649         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1650 }
1651
1652
1653 /* include the generated boilerplate */
1654 #include "librpc/gen_ndr/ndr_netlogon_s.c"