102-srv_netlog_nt.c.diff [plain text]
Index: samba/source/rpc_server/srv_netlog_nt.c
===================================================================
--- samba/source/rpc_server/srv_netlog_nt.c.orig
+++ samba/source/rpc_server/srv_netlog_nt.c
@@ -25,6 +25,7 @@
/* This is the implementation of the netlogon pipe. */
#include "includes.h"
+#include "opendirectory.h"
extern userdom_struct current_user_info;
@@ -361,6 +362,7 @@ NTSTATUS _net_auth(pipes_struct *p, NET_
fstring remote_machine;
DOM_CHAL srv_chal_out;
+
if (!p->dc || !p->dc->challenge_sent) {
return NT_STATUS_ACCESS_DENIED;
}
@@ -370,7 +372,23 @@ NTSTATUS _net_auth(pipes_struct *p, NET_
rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
- status = get_md4pw((char *)p->dc->mach_pw, mach_acct, q_u->clnt_id.sec_chan);
+ if (lp_opendirectory()) {
+ tDirStatus dirStatus;
+ become_root();
+ dirStatus = opendirectory_cred_session_key(&p->dc->clnt_chal,
+ &p->dc->srv_chal, mach_acct,
+ p->dc->sess_key, 0);
+ unbecome_root();
+ DEBUG(4, ("_net_auth opendirectory_cred_session_key [%d]\n",
+ dirStatus));
+
+ status = (dirStatus == eDSNoErr) ? NT_STATUS_OK
+ : NT_STATUS_UNSUCCESSFUL;
+ } else {
+ status = get_md4pw((char *)p->dc->mach_pw, mach_acct,
+ q_u->clnt_id.sec_chan);
+ }
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("_net_auth: creds_server_check failed. Failed to "
"get password for machine account %s "
@@ -430,6 +448,7 @@ NTSTATUS _net_auth_2(pipes_struct *p, NE
fstring mach_acct;
fstring remote_machine;
DOM_CHAL srv_chal_out;
+ u_int32_t session_key_type = 0;
rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),
q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
@@ -438,10 +457,16 @@ NTSTATUS _net_auth_2(pipes_struct *p, NE
rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
+ if (q_u->clnt_flgs.neg_flags & NETLOGON_NEG_128BIT) {
+ DEBUG(4, ("_net_auth2: NETLOGON_NEG_128BIT auth attempt\n"));
+ session_key_type = 1;
+ }
+
if (!p->dc || !p->dc->challenge_sent) {
DEBUG(0,("_net_auth2: no challenge sent to client %s\n",
remote_machine ));
- return NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_ACCESS_DENIED;
+ goto exit_on_error;
}
if ( (lp_server_schannel() == True) &&
@@ -451,16 +476,42 @@ NTSTATUS _net_auth_2(pipes_struct *p, NE
DEBUG(0,("_net_auth2: schannel required but client failed "
"to offer it. Client was %s\n",
mach_acct ));
- return NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_ACCESS_DENIED;
+ goto exit_on_error;
+ }
+
+
+ if (lp_opendirectory()) {
+ //check acct_ctrl flags
+ tDirStatus dirStatus;
+ become_root();
+ dirStatus =
+ opendirectory_cred_session_key(&p->dc->clnt_chal,
+ &p->dc->srv_chal, mach_acct,
+ p->dc->sess_key, session_key_type);
+ unbecome_root();
+ DEBUG(4, ("_net_auth_2: "
+ "opendirectory_cred_session_key [%d] session_key_type[%d]\n",
+ dirStatus,session_key_type));
+
+ /* FIXME: there should be a proper error mapping from
+ * tDirStatus to NT_ERROR types -- jpeach
+ */
+ status = (dirStatus == eDSNoErr) ? NT_STATUS_OK
+ : NT_STATUS_UNSUCCESSFUL;
+
+ } else {
+ status = get_md4pw((char *)p->dc->mach_pw, mach_acct,
+ q_u->clnt_id.sec_chan);
}
- status = get_md4pw((char *)p->dc->mach_pw, mach_acct, q_u->clnt_id.sec_chan);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("_net_auth2: failed to get machine password for "
"account %s: %s\n",
mach_acct, nt_errstr(status) ));
/* always return NT_STATUS_ACCESS_DENIED */
- return NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_ACCESS_DENIED;
+ goto exit_on_error;
}
/* From the client / server challenges and md4 password, generate sess key */
@@ -476,31 +527,40 @@ NTSTATUS _net_auth_2(pipes_struct *p, NE
DEBUG(0,("_net_auth2: creds_server_check failed. Rejecting auth "
"request from client %s machine account %s\n",
remote_machine, mach_acct ));
- return NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_ACCESS_DENIED;
+ goto exit_on_error;
+ } else {
+ DEBUG(4, ("_net_auth2: creds_server_check - server validated client challenge session_key_type[%d]\n", session_key_type));
+ status = NT_STATUS_OK;
}
+exit_on_error:
+ /* set server capabalities on return */
srv_flgs.neg_flags = 0x000001ff;
if (lp_server_schannel() != False) {
srv_flgs.neg_flags |= NETLOGON_NEG_SCHANNEL;
}
-
+ if (session_key_type == 1) {
+ srv_flgs.neg_flags |= NETLOGON_NEG_128BIT;
+ }
/* set up the LSA AUTH 2 response */
- init_net_r_auth_2(r_u, &srv_chal_out, &srv_flgs, NT_STATUS_OK);
-
- fstrcpy(p->dc->mach_acct, mach_acct);
- fstrcpy(p->dc->remote_machine, remote_machine);
- fstrcpy(p->dc->domain, lp_workgroup() );
-
- p->dc->authenticated = True;
+ init_net_r_auth_2(r_u, &srv_chal_out, &srv_flgs, status);
- /* Store off the state so we can continue after client disconnect. */
- become_root();
- secrets_store_schannel_session_info(p->mem_ctx,
- remote_machine,
- p->dc);
- unbecome_root();
+ if (NT_STATUS_IS_OK(status)) {
+ fstrcpy(p->dc->mach_acct, mach_acct);
+ fstrcpy(p->dc->remote_machine, remote_machine);
+ fstrcpy(p->dc->domain, lp_workgroup() );
+ p->dc->authenticated = True;
+
+ /* Store off the state so we can continue after client disconnect. */
+ become_root();
+ secrets_store_schannel_session_info(p->mem_ctx,
+ remote_machine,
+ p->dc);
+ unbecome_root();
+ }
return r_u->status;
}
@@ -603,35 +663,52 @@ NTSTATUS _net_srv_pwset(pipes_struct *p,
DEBUG(100,("%02X ", pwd[i]));
DEBUG(100,("\n"));
- old_pw = pdb_get_nt_passwd(sampass);
-
- if (old_pw && memcmp(pwd, old_pw, 16) == 0) {
- /* Avoid backend modificiations and other fun if the
- client changed the password to the *same thing* */
+ if (lp_opendirectory()) {
+ tDirStatus dirStatus = eDSNullParameter;
- ret = True;
- } else {
+ become_root();
+ dirStatus =
+ opendirectory_set_workstation_nthash(p->dc->mach_acct, pwd);
+ unbecome_root();
- /* LM password should be NULL for machines */
- if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) {
- TALLOC_FREE(sampass);
- return NT_STATUS_NO_MEMORY;
- }
-
- if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) {
+ DEBUG(2, ("_net_srv_pwset "
+ "opendirectory_set_workstation_nthash [%d]\n",
+ dirStatus));
+ if (dirStatus != eDSNoErr) {
TALLOC_FREE(sampass);
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_UNSUCCESSFUL;
}
-
+ } else {
+ old_pw = pdb_get_nt_passwd(sampass);
+
+ if (old_pw && memcmp(pwd, old_pw, 16) == 0) {
+ /* Avoid backend modificiations and other fun if the
+ client changed the password to the *same thing* */
+
+ ret = True;
+ } else {
+
+ /* LM password should be NULL for machines */
+ if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) {
+ TALLOC_FREE(sampass);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) {
+ TALLOC_FREE(sampass);
+ return NT_STATUS_NO_MEMORY;
+ }
+
if (!pdb_set_pass_last_set_time(sampass, time(NULL), PDB_CHANGED)) {
- TALLOC_FREE(sampass);
- /* Not quite sure what this one qualifies as, but this will do */
- return NT_STATUS_UNSUCCESSFUL;
+ TALLOC_FREE(sampass);
+ /* Not quite sure what this one qualifies as, but this will do */
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ become_root();
+ r_u->status = pdb_update_sam_account(sampass);
+ unbecome_root();
}
-
- become_root();
- r_u->status = pdb_update_sam_account(sampass);
- unbecome_root();
}
/* set up the LSA Server Password Set response */
@@ -964,14 +1041,11 @@ static NTSTATUS _net_sam_logon_internal(
{
DOM_GID *gids = NULL;
const DOM_SID *user_sid = NULL;
- const DOM_SID *group_sid = NULL;
DOM_SID domain_sid;
uint32 user_rid, group_rid;
int num_gids = 0;
pstring my_name;
- fstring user_sid_string;
- fstring group_sid_string;
unsigned char user_session_key[16];
unsigned char lm_session_key[16];
unsigned char pipe_session_key[16];
@@ -983,28 +1057,14 @@ static NTSTATUS _net_sam_logon_internal(
usr_info->ptr_user_info = 0;
user_sid = pdb_get_user_sid(sampw);
- group_sid = pdb_get_group_sid(sampw);
- if ((user_sid == NULL) || (group_sid == NULL)) {
- DEBUG(1, ("_net_sam_logon: User without group or user SID\n"));
+ if ((user_sid == NULL)) {
+ DEBUG(1, ("_net_sam_logon: User without user SID\n"));
return NT_STATUS_UNSUCCESSFUL;
}
sid_copy(&domain_sid, user_sid);
sid_split_rid(&domain_sid, &user_rid);
-
- if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
- DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid "
- "%s\n but group sid %s.\n"
- "The conflicting domain portions are not "
- "supported for NETLOGON calls\n",
- pdb_get_domain(sampw),
- pdb_get_username(sampw),
- sid_to_string(user_sid_string, user_sid),
- sid_to_string(group_sid_string, group_sid)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
if(server_info->login_server) {
pstrcpy(my_name, server_info->login_server);
Index: samba/source/libsmb/credentials.c
===================================================================
--- samba/source/libsmb/credentials.c.orig
+++ samba/source/libsmb/credentials.c
@@ -70,9 +70,44 @@ static void creds_init_128(struct dcinfo
DEBUG(5,("\tclnt_chal_in: %s\n", credstr(clnt_chal_in->data)));
DEBUG(5,("\tsrv_chal_in : %s\n", credstr(srv_chal_in->data)));
dump_data_pw("\tsession_key ", (const unsigned char *)dc->sess_key, 16);
+ DEBUG(5,("\tsession_key : \n"));
+ dump_data(5, (const unsigned char *)dc->sess_key,16);
/* Generate the next client and server creds. */
-
+
+ des_crypt112(dc->clnt_chal.data, /* output */
+ clnt_chal_in->data, /* input */
+ dc->sess_key, /* input */
+ 1);
+
+ des_crypt112(dc->srv_chal.data, /* output */
+ srv_chal_in->data, /* input */
+ dc->sess_key, /* input */
+ 1);
+
+ /* Seed is the client chal. */
+ memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8);
+}
+
+/* In the OpenDirectory case, DirectoryService has already provided us
+ * the generated session key because we can't get at the trust account
+ * password hash.
+ */
+static void creds_init_od(struct dcinfo *dc,
+ const DOM_CHAL *clnt_chal_in,
+ const DOM_CHAL *srv_chal_in,
+ const unsigned char mach_pw[16])
+{
+ SMB_ASSERT(lp_opendirectory());
+
+ /* debug output */
+ DEBUG(5,("%s\n", __func__));
+ DEBUG(5,("\tclnt_chal_in: %s\n", credstr(clnt_chal_in->data)));
+ DEBUG(5,("\tsrv_chal_in : %s\n", credstr(srv_chal_in->data)));
+ DEBUG(5,("\tsess_key_out : %s\n", credstr(dc->sess_key)));
+
+ /* Generate the next client and server creds. */
+
des_crypt112(dc->clnt_chal.data, /* output */
clnt_chal_in->data, /* input */
dc->sess_key, /* input */
@@ -187,16 +222,19 @@ void creds_server_init(uint32 neg_flags,
dump_data_pw("creds_server_init: machine pass", mach_pw, 16);
/* Generate the session key and the next client and server creds. */
- if (neg_flags & NETLOGON_NEG_128BIT) {
- creds_init_128(dc,
- clnt_chal,
- srv_chal,
- mach_pw);
+ if (lp_opendirectory()) {
+ creds_init_od(dc, clnt_chal,
+ srv_chal, mach_pw);
} else {
- creds_init_64(dc,
- clnt_chal,
- srv_chal,
- mach_pw);
+ if (neg_flags & NETLOGON_NEG_128BIT) {
+ creds_init_128(dc,
+ clnt_chal,
+ srv_chal,
+ mach_pw);
+ } else {
+ creds_init_64(dc, clnt_chal,
+ srv_chal, mach_pw);
+ }
}
dump_data_pw("creds_server_init: session key", dc->sess_key, 16);
@@ -249,6 +287,10 @@ BOOL creds_server_step(struct dcinfo *dc
BOOL ret;
struct dcinfo tmp_dc = *dc;
+ if (!received_cred || !cred_out) {
+ return false;
+ }
+
/* Do all operations on a temporary copy of the dc,
which we throw away if the checks fail. */
Index: samba/source/rpc_server/srv_pipe.c
===================================================================
--- samba/source/rpc_server/srv_pipe.c.orig
+++ samba/source/rpc_server/srv_pipe.c
@@ -2062,7 +2062,7 @@ BOOL api_pipe_schannel_process(pipes_str
auth_len = p->hdr.auth_len;
- if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
+ if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
DEBUG(0,("Incorrect auth_len %u.\n", (unsigned int)auth_len ));
return False;
}