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