tort: RPC-CRACKNAMES test case refactored
[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         int ret1, ret2, i;
1133         NTSTATUS status;
1134
1135         status = dcesrv_netr_creds_server_step_check(dce_call,
1136                                                      mem_ctx, 
1137                                                      r->in.computer_name, 
1138                                                      r->in.credential, 
1139                                                      r->out.return_authenticator,
1140                                                      &creds);
1141         if (!NT_STATUS_IS_OK(status)) {
1142                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1143         }
1144         NT_STATUS_NOT_OK_RETURN(status);
1145
1146         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1147                 dce_call->conn->dce_ctx->lp_ctx,
1148                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
1149         if (sam_ctx == NULL) {
1150                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1151         }
1152
1153         switch (r->in.level) {
1154         case 1: /* Domain information */
1155
1156                 /* TODO: check NTSTATUS results - and fail also on SAMDB
1157                  * errors (needs some testing against Windows Server 2008) */
1158
1159                 /*
1160                  * Check that the computer name parameter matches as prefix with
1161                  * the DNS hostname in the workstation info structure.
1162                  */
1163                 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
1164                         strcspn(r->in.query->workstation_info->dns_hostname,
1165                         "."));
1166                 if (strcasecmp(r->in.computer_name, temp_str) != 0)
1167                         return NT_STATUS_INVALID_PARAMETER;
1168
1169                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1170                         dom_sid_string(mem_ctx, creds->sid));
1171                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1172
1173                 /* Gets the old DNS hostname */
1174                 old_dns_hostname = samdb_search_string(sam_ctx, mem_ctx,
1175                                                         workstation_dn,
1176                                                         "dNSHostName",
1177                                                         NULL);
1178
1179                 /* Gets host informations and put them in our directory */
1180                 new_msg = ldb_msg_new(mem_ctx);
1181                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1182
1183                 new_msg->dn = workstation_dn;
1184
1185                 /* Deletes old OS version values */
1186                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1187                         "operatingSystemServicePack");
1188                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1189                         "operatingSystemVersion");
1190
1191                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1192                         DEBUG(3,("Impossible to update samdb: %s\n",
1193                                 ldb_errstring(sam_ctx)));
1194                 }
1195
1196                 talloc_free(new_msg);
1197
1198                 new_msg = ldb_msg_new(mem_ctx);
1199                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1200
1201                 new_msg->dn = workstation_dn;
1202
1203                 /* Sets the OS name */
1204                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1205                         "operatingSystem",
1206                         r->in.query->workstation_info->os_name.string);
1207
1208                 /*
1209                  * Sets informations from "os_version". On a empty structure
1210                  * the values are cleared.
1211                  */
1212                 if (r->in.query->workstation_info->os_version.os != NULL) {
1213                         os_version = &r->in.query->workstation_info->os_version.os->os;
1214
1215                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1216                                              "operatingSystemServicePack",
1217                                              os_version->CSDVersion);
1218
1219                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1220                                 "operatingSystemVersion",
1221                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1222                                         os_version->MajorVersion,
1223                                         os_version->MinorVersion,
1224                                         os_version->BuildNumber
1225                                 )
1226                         );
1227                 }
1228
1229                 /*
1230                  * Updates the "dNSHostname" and the "servicePrincipalName"s
1231                  * since the client wishes that the server should handle this
1232                  * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1233                  * See MS-NRPC section 3.5.4.3.9
1234                  */
1235                 if ((r->in.query->workstation_info->workstation_flags
1236                         & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1237
1238                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1239                                 "dNSHostname",
1240                                 r->in.query->workstation_info->dns_hostname);
1241                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1242                                 "servicePrincipalName",
1243                                 talloc_asprintf(mem_ctx, "HOST/%s",
1244                                 r->in.computer_name)
1245                         );
1246                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1247                                 "servicePrincipalName",
1248                                 talloc_asprintf(mem_ctx, "HOST/%s",
1249                                 r->in.query->workstation_info->dns_hostname)
1250                         );
1251                 }
1252
1253                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1254                         DEBUG(3,("Impossible to update samdb: %s\n",
1255                                 ldb_errstring(sam_ctx)));
1256                 }
1257
1258                 talloc_free(new_msg);
1259
1260                 /* Writes back the domain information */
1261
1262                 /* We need to do two searches. The first will pull our primary
1263                    domain and the second will pull any trusted domains. Our
1264                    primary domain is also a "trusted" domain, so we need to
1265                    put the primary domain into the lists of returned trusts as
1266                    well. */
1267                 ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1268                         &res1, attrs);
1269                 if (ret1 != 1) {
1270                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1271                 }
1272
1273                 ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs,
1274                         "(objectClass=trustedDomain)");
1275                 if (ret2 == -1) {
1276                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1277                 }
1278
1279                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1280                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1281
1282                 ZERO_STRUCTP(domain_info);
1283
1284                 /* Informations about the local and trusted domains */
1285
1286                 status = fill_one_domain_info(mem_ctx,
1287                         dce_call->conn->dce_ctx->lp_ctx,
1288                         sam_ctx, res1[0], &domain_info->primary_domain,
1289                         true, false);
1290                 NT_STATUS_NOT_OK_RETURN(status);
1291
1292                 domain_info->trusted_domain_count = ret2 + 1;
1293                 domain_info->trusted_domains = talloc_array(mem_ctx,
1294                         struct netr_OneDomainInfo,
1295                         domain_info->trusted_domain_count);
1296                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1297
1298                 for (i=0;i<ret2;i++) {
1299                         status = fill_one_domain_info(mem_ctx,
1300                                 dce_call->conn->dce_ctx->lp_ctx,
1301                                 sam_ctx, res2[i],
1302                                 &domain_info->trusted_domains[i],
1303                                 false, true);
1304                         NT_STATUS_NOT_OK_RETURN(status);
1305                 }
1306
1307                 status = fill_one_domain_info(mem_ctx,
1308                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0],
1309                         &domain_info->trusted_domains[i], true, true);
1310                 NT_STATUS_NOT_OK_RETURN(status);
1311
1312                 /* Other host domain informations */
1313
1314                 lsa_policy_info = talloc(mem_ctx,
1315                         struct netr_LsaPolicyInformation);
1316                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1317                 ZERO_STRUCTP(lsa_policy_info);
1318
1319                 domain_info->lsa_policy = *lsa_policy_info;
1320
1321                 domain_info->dns_hostname.string = old_dns_hostname;
1322                 domain_info->workstation_flags =
1323                         r->in.query->workstation_info->workstation_flags;
1324                 domain_info->supported_enc_types = 0; /* w2008 gives this 0 */
1325
1326                 r->out.info->domain_info = domain_info;
1327         break;
1328         case 2: /* LSA policy information - not used at the moment */
1329                 lsa_policy_info = talloc(mem_ctx,
1330                         struct netr_LsaPolicyInformation);
1331                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1332                 ZERO_STRUCTP(lsa_policy_info);
1333
1334                 r->out.info->lsa_policy_info = lsa_policy_info;
1335         break;
1336         default:
1337                 return NT_STATUS_INVALID_LEVEL;
1338         break;
1339         }
1340
1341         return NT_STATUS_OK;
1342 }
1343
1344
1345
1346 /*
1347   netr_ServerPasswordGet
1348 */
1349 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1350                        struct netr_ServerPasswordGet *r)
1351 {
1352         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1353 }
1354
1355
1356 /* 
1357   netr_NETRLOGONSENDTOSAM 
1358 */
1359 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1360                        struct netr_NETRLOGONSENDTOSAM *r)
1361 {
1362         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1363 }
1364
1365
1366 /* 
1367   netr_DsRAddressToSitenamesW 
1368 */
1369 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1370                        struct netr_DsRAddressToSitenamesW *r)
1371 {
1372         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1373 }
1374
1375
1376 /* 
1377   netr_DsRGetDCNameEx2
1378 */
1379 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1380                                    struct netr_DsRGetDCNameEx2 *r)
1381 {
1382         const char * const attrs[] = { "objectGUID", NULL };
1383         struct ldb_context *sam_ctx;
1384         struct ldb_message **res;
1385         struct ldb_dn *domain_dn;
1386         int ret;
1387         struct netr_DsRGetDCNameInfo *info;
1388
1389         ZERO_STRUCTP(r->out.info);
1390
1391         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1392         if (sam_ctx == NULL) {
1393                 return WERR_DS_UNAVAILABLE;
1394         }
1395
1396         /* Win7-beta will send the domain name in the form the user typed, so we have to cope
1397            with both the short and long form here */
1398         if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx, 
1399                                                                 r->in.domain_name)) {
1400                 return WERR_NO_SUCH_DOMAIN;
1401         }
1402
1403         domain_dn = ldb_get_default_basedn(sam_ctx);
1404         if (domain_dn == NULL) {
1405                 return WERR_DS_UNAVAILABLE;
1406         }
1407
1408         ret = gendb_search_dn(sam_ctx, mem_ctx,
1409                               domain_dn, &res, attrs);
1410         if (ret != 1) {
1411         }
1412
1413         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1414         W_ERROR_HAVE_NO_MEMORY(info);
1415
1416         /* TODO: - return real IP address
1417          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1418          */
1419         info->dc_unc                    = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1420                                                           lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), 
1421                                                           lp_realm(dce_call->conn->dce_ctx->lp_ctx));
1422         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1423         info->dc_address                = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1424         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1425         info->dc_address_type           = DS_ADDRESS_TYPE_INET;
1426         info->domain_guid               = samdb_result_guid(res[0], "objectGUID");
1427         info->domain_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1428         info->forest_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1429         info->dc_flags                  = DS_DNS_FOREST |
1430                                           DS_DNS_DOMAIN |
1431                                           DS_DNS_CONTROLLER |
1432                                           DS_SERVER_WRITABLE |
1433                                           DS_SERVER_CLOSEST |
1434                                           DS_SERVER_TIMESERV |
1435                                           DS_SERVER_KDC |
1436                                           DS_SERVER_DS |
1437                                           DS_SERVER_LDAP |
1438                                           DS_SERVER_GC |
1439                                           DS_SERVER_PDC;
1440         info->dc_site_name      = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1441         W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1442         info->client_site_name  = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1443         W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1444
1445         *r->out.info = info;
1446
1447         return WERR_OK;
1448 }
1449
1450 /* 
1451   netr_DsRGetDCNameEx
1452 */
1453 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1454                                   struct netr_DsRGetDCNameEx *r)
1455 {
1456         struct netr_DsRGetDCNameEx2 r2;
1457         WERROR werr;
1458
1459         ZERO_STRUCT(r2);
1460
1461         r2.in.server_unc = r->in.server_unc;
1462         r2.in.client_account = NULL;
1463         r2.in.mask = 0;
1464         r2.in.domain_guid = r->in.domain_guid;
1465         r2.in.domain_name = r->in.domain_name;
1466         r2.in.site_name = r->in.site_name;
1467         r2.in.flags = r->in.flags;
1468         r2.out.info = r->out.info;
1469
1470         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1471
1472         return werr;
1473 }
1474
1475 /* 
1476   netr_DsRGetDCName
1477 */
1478 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1479                                 struct netr_DsRGetDCName *r)
1480 {
1481         struct netr_DsRGetDCNameEx2 r2;
1482         WERROR werr;
1483
1484         ZERO_STRUCT(r2);
1485
1486         r2.in.server_unc = r->in.server_unc;
1487         r2.in.client_account = NULL;
1488         r2.in.mask = 0;
1489         r2.in.domain_name = r->in.domain_name;
1490         r2.in.domain_guid = r->in.domain_guid;
1491         
1492         r2.in.site_name = NULL; /* should fill in from site GUID */
1493         r2.in.flags = r->in.flags;
1494         r2.out.info = r->out.info;
1495
1496         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1497
1498         return werr;
1499 }
1500 /* 
1501   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
1502 */
1503 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1504                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1505 {
1506         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1507 }
1508
1509
1510 /*
1511   netr_NetrEnumerateTrustedDomainsEx
1512 */
1513 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1514                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1515 {
1516         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1517 }
1518
1519
1520 /* 
1521   netr_DsRAddressToSitenamesExW 
1522 */
1523 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1524                        struct netr_DsRAddressToSitenamesExW *r)
1525 {
1526         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1527 }
1528
1529
1530 /* 
1531   netr_DsrGetDcSiteCoverageW
1532 */
1533 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1534                        struct netr_DsrGetDcSiteCoverageW *r)
1535 {
1536         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1537 }
1538
1539
1540 /* 
1541   netr_DsrEnumerateDomainTrusts 
1542 */
1543 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1544                                               struct netr_DsrEnumerateDomainTrusts *r)
1545 {
1546         struct netr_DomainTrustList *trusts;
1547         struct ldb_context *sam_ctx;
1548         int ret;
1549         struct ldb_message **dom_res;
1550         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1551
1552         ZERO_STRUCT(r->out);
1553
1554         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1555         if (sam_ctx == NULL) {
1556                 return WERR_GENERAL_FAILURE;
1557         }
1558
1559         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1560                               &dom_res, dom_attrs);
1561         if (ret == -1) {
1562                 return WERR_GENERAL_FAILURE;            
1563         }
1564         if (ret != 1) {
1565                 return WERR_GENERAL_FAILURE;
1566         }
1567
1568         trusts = talloc(mem_ctx, struct netr_DomainTrustList);
1569         W_ERROR_HAVE_NO_MEMORY(trusts);
1570
1571         trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
1572         W_ERROR_HAVE_NO_MEMORY(trusts->array);
1573
1574         trusts->count = 1; /* ?? */
1575
1576         r->out.trusts = trusts;
1577
1578         /* TODO: add filtering by trust_flags, and correct trust_type
1579            and attributes */
1580         trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1581         trusts->array[0].dns_name     = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1582         trusts->array[0].trust_flags =
1583                 NETR_TRUST_FLAG_TREEROOT | 
1584                 NETR_TRUST_FLAG_IN_FOREST | 
1585                 NETR_TRUST_FLAG_PRIMARY;
1586         trusts->array[0].parent_index = 0;
1587         trusts->array[0].trust_type = 2;
1588         trusts->array[0].trust_attributes = 0;
1589         trusts->array[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1590         trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1591
1592         return WERR_OK;
1593 }
1594
1595
1596 /*
1597   netr_DsrDeregisterDNSHostRecords
1598 */
1599 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1600                        struct netr_DsrDeregisterDNSHostRecords *r)
1601 {
1602         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1603 }
1604
1605
1606 /*
1607   netr_ServerTrustPasswordsGet
1608 */
1609 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1610                        struct netr_ServerTrustPasswordsGet *r)
1611 {
1612         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1613 }
1614
1615
1616 /* 
1617   netr_DsRGetForestTrustInformation 
1618 */
1619 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1620                        struct netr_DsRGetForestTrustInformation *r)
1621 {
1622         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1623 }
1624
1625
1626 /*
1627   netr_GetForestTrustInformation
1628 */
1629 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1630                        struct netr_GetForestTrustInformation *r)
1631 {
1632         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1633 }
1634
1635
1636 /*
1637   netr_ServerGetTrustInfo
1638 */
1639 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1640                        struct netr_ServerGetTrustInfo *r)
1641 {
1642         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1643 }
1644
1645
1646 /* include the generated boilerplate */
1647 #include "librpc/gen_ndr/ndr_netlogon_s.c"