2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "rpc_server/common/common.h"
26 struct server_pipe_state {
28 struct netr_Credential client_challenge;
29 struct netr_Credential server_challenge;
32 char *computer_name; /* for logging only */
35 struct creds_CredentialState *creds;
38 static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di)
40 dce_call->conn->private = NULL;
45 /* this function is called when the client disconnects the endpoint */
46 static void netlogon_unbind(struct dcesrv_connection *conn, const struct dcesrv_interface *di)
48 struct server_pipe_state *pipe_state = conn->private;
51 talloc_destroy(pipe_state->mem_ctx);
56 #define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
57 #define DCESRV_INTERFACE_NETLOGON_UNBIND netlogon_unbind
60 netr_ServerReqChallenge
62 NTSTATUS netr_ServerReqChallenge(
63 [in] unistr *server_name,
64 [in] unistr computer_name,
65 [in][out] netr_Credential credentials
69 static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
70 struct netr_ServerReqChallenge *r)
72 struct server_pipe_state *pipe_state = dce_call->conn->private;
73 TALLOC_CTX *pipe_mem_ctx;
75 ZERO_STRUCT(r->out.credentials);
77 /* destroyed on pipe shutdown */
80 talloc_destroy(pipe_state->mem_ctx);
81 dce_call->conn->private = NULL;
84 pipe_mem_ctx = talloc_init("internal netlogon pipe state for %s",
88 return NT_STATUS_NO_MEMORY;
91 pipe_state = talloc_p(pipe_mem_ctx, struct server_pipe_state);
93 talloc_destroy(pipe_mem_ctx);
94 return NT_STATUS_NO_MEMORY;
97 pipe_state->mem_ctx = pipe_mem_ctx;
98 pipe_state->authenticated = False;
99 pipe_state->creds = NULL;
100 pipe_state->account_name = NULL;
101 pipe_state->computer_name = NULL;
103 pipe_state->client_challenge = r->in.credentials;
105 generate_random_buffer(pipe_state->server_challenge.data,
106 sizeof(pipe_state->server_challenge.data),
109 r->out.credentials = pipe_state->server_challenge;
111 dce_call->conn->private = pipe_state;
118 netr_ServerAuthenticate
120 secure channel types:
122 const int SEC_CHAN_WKSTA = 2;
123 const int SEC_CHAN_DOMAIN = 4;
124 const int SEC_CHAN_BDC = 6;
126 NTSTATUS netr_ServerAuthenticate(
127 [in] unistr *server_name,
128 [in] unistr username,
129 [in] uint16 secure_channel_type,
130 [in] unistr computer_name,
131 [in,out] netr_Credential credentials
137 static NTSTATUS netr_ServerAuthenticateInternals(struct server_pipe_state *pipe_state,
139 const char *account_name,
140 const char *computer_name,
141 uint16 secure_channel_type,
143 const struct netr_Credential *client_credentials,
144 struct netr_Credential *server_credentials,
151 struct ldb_message **msgs;
154 const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
155 "userAccountControl", NULL
158 ZERO_STRUCTP(server_credentials);
164 DEBUG(1, ("No challange requested by client, cannot authenticate\n"));
165 return NT_STATUS_ACCESS_DENIED;
168 sam_ctx = samdb_connect();
169 if (sam_ctx == NULL) {
170 return NT_STATUS_INVALID_SYSTEM_SERVICE;
172 /* pull the user attributes */
173 num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
174 "(&(sAMAccountName=%s)(objectclass=user))",
177 if (num_records == 0) {
178 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
180 samdb_close(sam_ctx);
181 return NT_STATUS_NO_SUCH_USER;
184 if (num_records > 1) {
185 DEBUG(1,("Found %d records matching user [%s]\n", num_records, account_name));
186 samdb_close(sam_ctx);
187 return NT_STATUS_INTERNAL_DB_CORRUPTION;
190 acct_flags = samdb_result_acct_flags(msgs[0],
191 "userAccountControl");
193 if (acct_flags & ACB_DISABLED) {
194 DEBUG(1, ("Account [%s] is disabled\n", account_name));
195 return NT_STATUS_ACCESS_DENIED;
198 if (secure_channel_type == SEC_CHAN_WKSTA) {
199 if (!(acct_flags & ACB_WSTRUST)) {
200 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", acct_flags));
201 return NT_STATUS_ACCESS_DENIED;
203 } else if (secure_channel_type == SEC_CHAN_DOMAIN) {
204 if (!(acct_flags & ACB_DOMTRUST)) {
205 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", acct_flags));
206 return NT_STATUS_ACCESS_DENIED;
208 } else if (secure_channel_type == SEC_CHAN_BDC) {
209 if (!(acct_flags & ACB_SVRTRUST)) {
210 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", acct_flags));
211 return NT_STATUS_ACCESS_DENIED;
214 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", secure_channel_type));
215 return NT_STATUS_ACCESS_DENIED;
218 pipe_state->acct_flags = acct_flags;
219 pipe_state->sec_chan_type = secure_channel_type;
221 if (!NT_STATUS_IS_OK(nt_status = samdb_result_passwords(mem_ctx, msgs[0],
223 samdb_close(sam_ctx);
224 return NT_STATUS_ACCESS_DENIED;
227 samdb_close(sam_ctx);
229 if (!pipe_state->creds) {
230 pipe_state->creds = talloc_p(pipe_state->mem_ctx, struct creds_CredentialState);
231 if (!pipe_state->creds) {
232 return NT_STATUS_NO_MEMORY;
236 creds_server_init(pipe_state->creds, &pipe_state->client_challenge,
237 &pipe_state->server_challenge, mach_pwd,
240 if (!creds_server_check(pipe_state->creds, client_credentials)) {
241 return NT_STATUS_ACCESS_DENIED;
244 pipe_state->authenticated = True;
246 if (pipe_state->account_name) {
247 /* We don't want a memory leak on this long-lived talloc context */
248 talloc_free(pipe_state->mem_ctx, pipe_state->account_name);
251 pipe_state->account_name = talloc_strdup(pipe_state->mem_ctx, account_name);
253 if (pipe_state->computer_name) {
254 /* We don't want a memory leak on this long-lived talloc context */
255 talloc_free(pipe_state->mem_ctx, pipe_state->account_name);
258 pipe_state->computer_name = talloc_strdup(pipe_state->mem_ctx, computer_name);
261 *out_flags = NETLOGON_NEG_AUTH2_FLAGS;
268 static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
269 struct netr_ServerAuthenticate *r)
271 struct server_pipe_state *pipe_state = dce_call->conn->private;
273 return netr_ServerAuthenticateInternals(pipe_state,
277 r->in.secure_channel_type,
284 static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
285 struct netr_ServerAuthenticate2 *r)
287 struct server_pipe_state *pipe_state = dce_call->conn->private;
289 return netr_ServerAuthenticateInternals(pipe_state,
293 r->in.secure_channel_type,
294 *r->in.negotiate_flags,
297 r->out.negotiate_flags);
300 static BOOL netr_creds_server_step_check(struct server_pipe_state *pipe_state,
301 struct netr_Authenticator *received_authenticator,
302 struct netr_Authenticator *return_authenticator)
304 if (!pipe_state->authenticated) {
307 return creds_server_step_check(pipe_state->creds,
308 received_authenticator,
309 return_authenticator);
313 netr_ServerPasswordSet
315 NTSTATUS netr_ServerPasswordSet(
316 [in] unistr *server_name,
317 [in] unistr username,
318 [in] uint16 secure_channel_type,
319 [in] unistr computer_name,
320 [in] netr_Authenticator credential,
321 [in] netr_Password new_password,
322 [out] netr_Authenticator return_authenticator
326 static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
327 struct netr_ServerPasswordSet *r)
329 struct server_pipe_state *pipe_state = dce_call->conn->private;
333 int num_records_domain;
336 struct ldb_message **msgs;
337 struct ldb_message **msgs_domain;
339 struct samr_Hash newNtHash;
340 struct ldb_message mod, *msg_set_pw = &mod;
341 const char *domain_dn;
342 struct dom_sid *domain_sid;
344 const char *attrs[] = {"objectSid", NULL
347 const char **domain_attrs = attrs;
350 if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) {
351 return NT_STATUS_ACCESS_DENIED;
355 DEBUG(1, ("No challange requested by client, cannot authenticate\n"));
356 return NT_STATUS_ACCESS_DENIED;
359 sam_ctx = samdb_connect();
360 if (sam_ctx == NULL) {
361 return NT_STATUS_INVALID_SYSTEM_SERVICE;
363 /* pull the user attributes */
364 num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
365 "(&(sAMAccountName=%s)(objectclass=user))",
366 pipe_state->account_name);
368 if (num_records == 0) {
369 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
370 pipe_state->account_name));
371 samdb_close(sam_ctx);
372 return NT_STATUS_NO_SUCH_USER;
375 if (num_records > 1) {
376 DEBUG(1,("Found %d records matching user [%s]\n", num_records,
377 pipe_state->account_name));
378 samdb_close(sam_ctx);
379 return NT_STATUS_INTERNAL_DB_CORRUPTION;
382 domain_sid = dom_sid_parse_talloc(mem_ctx,
383 samdb_result_string(msgs[0],
387 samdb_close(sam_ctx);
388 return NT_STATUS_INTERNAL_DB_CORRUPTION;
391 sid_split_rid(domain_sid, NULL);
393 /* find the domain's DN */
394 num_records_domain = samdb_search(sam_ctx, mem_ctx, NULL,
395 &msgs_domain, domain_attrs,
396 "(&(objectSid=%s)(objectclass=domain))",
397 dom_sid_string(mem_ctx, domain_sid));
399 if (num_records_domain == 0) {
400 DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
401 dom_sid_string(mem_ctx, domain_sid)));
402 samdb_close(sam_ctx);
403 return NT_STATUS_NO_SUCH_USER;
406 if (num_records_domain > 1) {
407 DEBUG(1,("Found %d records matching domain [%s]\n", num_records_domain, dom_sid_string(mem_ctx, domain_sid)));
408 samdb_close(sam_ctx);
409 return NT_STATUS_INTERNAL_DB_CORRUPTION;
412 domain_dn = msgs_domain[0]->dn;
414 mod.dn = talloc_strdup(mem_ctx, msgs[0]->dn);
416 samdb_close(sam_ctx);
417 return NT_STATUS_NO_MEMORY;
420 creds_des_decrypt(pipe_state->creds, &r->in.new_password);
422 memcpy(newNtHash.hash, r->in.new_password.data, sizeof(newNtHash.hash));
424 /* set the password - samdb needs to know both the domain and user DNs,
425 so the domain password policy can be used */
426 nt_status = samdb_set_password(sam_ctx, mem_ctx,
427 msgs[0]->dn, domain_dn,
429 NULL, /* Don't have plaintext */
431 False /* This is not considered a password change */);
433 if (!NT_STATUS_IS_OK(nt_status)) {
434 samdb_close(sam_ctx);
438 /* mark all the message elements as LDB_FLAG_MOD_REPLACE,
439 unless they are already marked with some other flag */
440 for (i=0;i<mod.num_elements;i++) {
441 if (mod.elements[i].flags == 0) {
442 mod.elements[i].flags = LDB_FLAG_MOD_REPLACE;
446 ret = samdb_modify(sam_ctx, mem_ctx, msg_set_pw);
448 /* we really need samdb.c to return NTSTATUS */
450 samdb_close(sam_ctx);
451 return NT_STATUS_UNSUCCESSFUL;
454 samdb_close(sam_ctx);
462 static WERROR netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
463 struct netr_LogonUasLogon *r)
465 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
472 static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
473 struct netr_LogonUasLogoff *r)
475 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
485 static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
486 struct netr_LogonSamLogon *r)
488 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
495 static NTSTATUS netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
496 struct netr_LogonSamLogoff *r)
498 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
506 static NTSTATUS netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
507 struct netr_DatabaseDeltas *r)
509 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
516 static NTSTATUS netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
517 struct netr_DatabaseSync *r)
519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
526 static NTSTATUS netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
527 struct netr_AccountDeltas *r)
529 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
536 static NTSTATUS netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
537 struct netr_AccountSync *r)
539 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
546 static NTSTATUS netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
547 struct netr_GetDcName *r)
549 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
556 static WERROR netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
557 struct netr_LogonControl *r)
559 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
566 static WERROR netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
567 struct netr_GetAnyDCName *r)
569 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
576 static WERROR netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
577 struct netr_LogonControl2 *r)
579 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
586 static NTSTATUS netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
587 struct netr_DatabaseSync2 *r)
589 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
596 static NTSTATUS netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
597 struct netr_DatabaseRedo *r)
599 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
606 static WERROR netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
607 struct netr_LogonControl2Ex *r)
609 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
613 /* include the generated boilerplate */
614 #include "librpc/gen_ndr/ndr_netlogon_s.c"