const char *password,
const DATA_BLOB initial_msg,
const DATA_BLOB challenge_msg,
+ TALLOC_CTX *mem_ctx,
DATA_BLOB *auth_msg,
- uint8_t session_key[16])
+ uint8_t session_key[16],
+ uint8_t *new_spnego)
{
NTSTATUS status;
struct auth_generic_state *auth_generic_state = NULL;
- DATA_BLOB dummy_msg, reply, session_key_blob;
+ DATA_BLOB reply, session_key_blob;
- status = auth_generic_client_prepare(NULL, &auth_generic_state);
+ status = auth_generic_client_prepare(mem_ctx, &auth_generic_state);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Could not start NTLMSSP client: %s\n",
goto done;
}
- gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SESSION_KEY);
+ if (initial_msg.length == 0) {
+ gensec_want_feature(auth_generic_state->gensec_security,
+ GENSEC_FEATURE_SESSION_KEY);
+ }
- status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
+ status = auth_generic_client_start_by_name(auth_generic_state,
+ "ntlmssp_resume_ccache");
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Could not start NTLMSSP mech: %s\n",
+ DEBUG(1, ("Could not start NTLMSSP resume mech: %s\n",
nt_errstr(status)));
goto done;
}
- /* We need to get our protocol handler into the right state. So first
- we ask it to generate the initial message. Actually the client has already
- sent its own initial message, so we're going to drop this one on the floor.
- The client might have sent a different message, for example with different
- negotiation options, but as far as I can tell this won't hurt us. (Unless
- the client sent a different username or domain, in which case that's their
- problem for telling us the wrong username or domain.)
- Since we have a copy of the initial message that the client sent, we could
- resolve any discrepancies if we had to.
- */
- dummy_msg = data_blob_null;
+ /*
+ * We inject the inital NEGOTIATE message our caller used
+ * in order to get the state machine into the correct possition.
+ */
reply = data_blob_null;
status = gensec_update(auth_generic_state->gensec_security,
- talloc_tos(), NULL, dummy_msg, &reply);
+ talloc_tos(), initial_msg, &reply);
data_blob_free(&reply);
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
/* Now we are ready to handle the server's actual response. */
status = gensec_update(auth_generic_state->gensec_security,
- NULL, NULL, challenge_msg, &reply);
+ mem_ctx, challenge_msg, &reply);
if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
DEBUG(1, ("We didn't get a response to the challenge! [%s]\n",
nt_errstr(status)));
memcpy(session_key, session_key_blob.data, 16);
data_blob_free(&session_key_blob);
*auth_msg = reply;
+ *new_spnego = gensec_have_feature(auth_generic_state->gensec_security,
+ GENSEC_FEATURE_NEW_SPNEGO);
status = NT_STATUS_OK;
done:
return False;
}
- if (uid != ret_uid) {
+ if (uid != ret_uid && ret_uid != sec_initial_uid()) {
DEBUG(1, ("check_client_uid: Client lied about its uid: said %u, "
"actually was %u; denying access\n",
(unsigned int)uid, (unsigned int)ret_uid));
NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
struct WINBINDD_MEMORY_CREDS *entry;
DATA_BLOB initial, challenge, auth;
- uint32 initial_blob_len, challenge_blob_len, extra_len;
+ uint32_t initial_blob_len, challenge_blob_len, extra_len;
/* Ensure null termination */
state->request->data.ccache_ntlm_auth.user[
result = do_ntlm_auth_with_stored_pw(
name_user, name_domain, entry->pass,
- initial, challenge, &auth,
- state->response->data.ccache_ntlm_auth.session_key);
+ initial, challenge, talloc_tos(), &auth,
+ state->response->data.ccache_ntlm_auth.session_key,
+ &state->response->data.ccache_ntlm_auth.new_spnego);
if (!NT_STATUS_IS_OK(result)) {
goto process_result;