diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-05-16 21:30:48 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:53:48 -0500 |
commit | 92dd542aa01f2c3b64ca104696c731919f4d7ec7 (patch) | |
tree | 1a1e2489c32f2b8c6b4eec31a7f8dc019ebda2ed /source4/rpc_server/netlogon | |
parent | 8b84f643bd50c83230b723eb35b0edafe5670fca (diff) | |
download | samba-92dd542aa01f2c3b64ca104696c731919f4d7ec7.tar.gz samba-92dd542aa01f2c3b64ca104696c731919f4d7ec7.tar.bz2 samba-92dd542aa01f2c3b64ca104696c731919f4d7ec7.zip |
r754: Implement the SetPassword operation on the netlogon pipe.
This involves allowing the password set code in samdb to take an
already hashed password, and some fixes to our torture code.
Andrew Bartlett
(This used to be commit f9f581b5804a20785df06cde157b23c952edc2ce)
Diffstat (limited to 'source4/rpc_server/netlogon')
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 141 |
1 files changed, 138 insertions, 3 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 87945ffef0..853a8b39e9 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -175,7 +175,7 @@ static NTSTATUS netr_ServerAuthenticateInternals(struct server_pipe_state *pipe_ account_name); if (num_records == 0) { - DEBUG(3,("Couldn't find user [%s] in passdb file.\n", + DEBUG(3,("Couldn't find user [%s] in samdb.\n", account_name)); samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; @@ -227,7 +227,7 @@ static NTSTATUS netr_ServerAuthenticateInternals(struct server_pipe_state *pipe_ samdb_close(sam_ctx); if (!pipe_state->creds) { - pipe_state->creds = talloc_p(mem_ctx, struct creds_CredentialState); + pipe_state->creds = talloc_p(pipe_state->mem_ctx, struct creds_CredentialState); if (!pipe_state->creds) { return NT_STATUS_NO_MEMORY; } @@ -297,6 +297,18 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL r->out.negotiate_flags); } +static BOOL netr_creds_server_step_check(struct server_pipe_state *pipe_state, + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator) +{ + if (!pipe_state->authenticated) { + return False; + } + return creds_server_step_check(pipe_state->creds, + received_authenticator, + return_authenticator); +} + /* netr_ServerPasswordSet @@ -314,10 +326,133 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerPasswordSet *r) { + struct server_pipe_state *pipe_state = dce_call->conn->private; - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + void *sam_ctx; + int num_records; + int num_records_domain; + int ret; + int i; + struct ldb_message **msgs; + struct ldb_message **msgs_domain; + NTSTATUS nt_status; + struct samr_Hash newNtHash; + struct ldb_message mod, *msg_set_pw = &mod; + const char *domain_dn; + struct dom_sid *domain_sid; + + const char *attrs[] = {"objectSid", NULL + }; + + const char **domain_attrs = attrs; + ZERO_STRUCT(mod); + + if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) { + return NT_STATUS_ACCESS_DENIED; + } + + if (!pipe_state) { + DEBUG(1, ("No challange requested by client, cannot authenticate\n")); + return NT_STATUS_ACCESS_DENIED; + } + + sam_ctx = samdb_connect(); + if (sam_ctx == NULL) { + return NT_STATUS_INVALID_SYSTEM_SERVICE; + } + /* pull the user attributes */ + num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs, + "(&(sAMAccountName=%s)(objectclass=user))", + pipe_state->account_name); + + if (num_records == 0) { + DEBUG(3,("Couldn't find user [%s] in samdb.\n", + pipe_state->account_name)); + samdb_close(sam_ctx); + return NT_STATUS_NO_SUCH_USER; + } + + if (num_records > 1) { + DEBUG(1,("Found %d records matching user [%s]\n", num_records, + pipe_state->account_name)); + samdb_close(sam_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + domain_sid = dom_sid_parse_talloc(mem_ctx, + samdb_result_string(msgs[0], + "objectSid", + NULL)); + if (!domain_sid) { + samdb_close(sam_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + sid_split_rid(domain_sid, NULL); + + /* find the domain's DN */ + num_records_domain = samdb_search(sam_ctx, mem_ctx, NULL, + &msgs_domain, domain_attrs, + "(&(objectSid=%s)(objectclass=domain))", + dom_sid_string(mem_ctx, domain_sid)); + + if (num_records_domain == 0) { + DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", + dom_sid_string(mem_ctx, domain_sid))); + samdb_close(sam_ctx); + return NT_STATUS_NO_SUCH_USER; + } + + if (num_records_domain > 1) { + DEBUG(1,("Found %d records matching domain [%s]\n", num_records_domain, dom_sid_string(mem_ctx, domain_sid))); + samdb_close(sam_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + domain_dn = msgs_domain[0]->dn; + + mod.dn = talloc_strdup(mem_ctx, msgs[0]->dn); + if (!mod.dn) { + samdb_close(sam_ctx); + return NT_STATUS_NO_MEMORY; + } + creds_des_decrypt(pipe_state->creds, &r->in.new_password); + + memcpy(newNtHash.hash, r->in.new_password.data, sizeof(newNtHash.hash)); + + /* set the password - samdb needs to know both the domain and user DNs, + so the domain password policy can be used */ + nt_status = samdb_set_password(sam_ctx, mem_ctx, + msgs[0]->dn, domain_dn, + msg_set_pw, + NULL, /* Don't have plaintext */ + NULL, &newNtHash, + False /* This is not considered a password change */); + + if (!NT_STATUS_IS_OK(nt_status)) { + samdb_close(sam_ctx); + return nt_status; + } + /* mark all the message elements as LDB_FLAG_MOD_REPLACE, + unless they are already marked with some other flag */ + for (i=0;i<mod.num_elements;i++) { + if (mod.elements[i].flags == 0) { + mod.elements[i].flags = LDB_FLAG_MOD_REPLACE; + } + } + + ret = samdb_modify(sam_ctx, mem_ctx, msg_set_pw); + if (ret != 0) { + /* we really need samdb.c to return NTSTATUS */ + + samdb_close(sam_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + + samdb_close(sam_ctx); + return NT_STATUS_OK; } |