Copyright (C) Robert O'Callahan 2006
Copyright (C) Jeremy Allison 2006 (minor fixes to fit into Samba and
protect against integer wrap).
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "winbindd.h"
+#include "ntlmssp.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
const unsigned char nt_hash[NT_HASH_LEN],
const DATA_BLOB initial_msg,
const DATA_BLOB challenge_msg,
- DATA_BLOB *auth_msg)
+ DATA_BLOB *auth_msg,
+ uint8_t session_key[16])
{
NTSTATUS status;
- NTLMSSP_STATE *ntlmssp_state = NULL;
+ struct ntlmssp_state *ntlmssp_state = NULL;
DATA_BLOB dummy_msg, reply;
status = ntlmssp_client_start(&ntlmssp_state);
}
status = ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash);
-
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Could not set hashes: %s\n",
nt_errstr(status)));
goto done;
}
+ ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
+
/* 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.
data_blob_free(&reply);
goto done;
}
- *auth_msg = reply;
+
+ if (ntlmssp_state->session_key.length != 16) {
+ DEBUG(1, ("invalid session key length %d\n",
+ (int)ntlmssp_state->session_key.length));
+ data_blob_free(&reply);
+ goto done;
+ }
+
+ *auth_msg = data_blob(reply.data, reply.length);
+ memcpy(session_key, ntlmssp_state->session_key.data, 16);
status = NT_STATUS_OK;
done:
return;
}
- domain = find_auth_domain(state, name_domain);
+ domain = find_auth_domain(state->request->flags, name_domain);
if (domain == NULL) {
DEBUG(5,("winbindd_ccache_ntlm_auth: can't get domain [%s]\n",
goto process_result;
}
- initial = data_blob(state->request->extra_data.data, initial_blob_len);
- challenge = data_blob(state->request->extra_data.data + initial_blob_len,
- state->request->data.ccache_ntlm_auth.challenge_blob_len);
-
- if (!initial.data || !challenge.data) {
- result = NT_STATUS_NO_MEMORY;
- } else {
- result = do_ntlm_auth_with_hashes(name_user, name_domain,
- entry->lm_hash, entry->nt_hash,
- initial, challenge, &auth);
- }
+ initial = data_blob_const(state->request->extra_data.data,
+ initial_blob_len);
+ challenge = data_blob_const(
+ state->request->extra_data.data + initial_blob_len,
+ state->request->data.ccache_ntlm_auth.challenge_blob_len);
- data_blob_free(&initial);
- data_blob_free(&challenge);
+ result = do_ntlm_auth_with_hashes(
+ name_user, name_domain, entry->lm_hash, entry->nt_hash,
+ initial, challenge, &auth,
+ state->response->data.ccache_ntlm_auth.session_key);
if (!NT_STATUS_IS_OK(result)) {
goto process_result;
process_result:
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
+
+void winbindd_ccache_save(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain;
+ fstring name_domain, name_user;
+
+ /* Ensure null termination */
+ state->request->data.ccache_save.user[
+ sizeof(state->request->data.ccache_save.user)-1]='\0';
+ state->request->data.ccache_save.pass[
+ sizeof(state->request->data.ccache_save.pass)-1]='\0';
+
+ DEBUG(3, ("[%5lu]: save password of user %s\n",
+ (unsigned long)state->pid,
+ state->request->data.ccache_save.user));
+
+ /* Parse domain and username */
+
+ if (!canonicalize_username(state->request->data.ccache_ntlm_auth.user,
+ name_domain, name_user)) {
+ DEBUG(5,("winbindd_ccache_save: cannot parse domain and user "
+ "from name [%s]\n",
+ state->request->data.ccache_save.user));
+ request_error(state);
+ return;
+ }
+
+ domain = find_auth_domain(state->request->flags, name_domain);
+
+ if (domain == NULL) {
+ DEBUG(5, ("winbindd_ccache_save: can't get domain [%s]\n",
+ name_domain));
+ request_error(state);
+ return;
+ }
+
+ if (!check_client_uid(state, state->request->data.ccache_save.uid)) {
+ request_error(state);
+ return;
+ }
+
+ sendto_domain(state, domain);
+}
+
+enum winbindd_result winbindd_dual_ccache_save(
+ struct winbindd_domain *domain, struct winbindd_cli_state *state)
+{
+ NTSTATUS status = NT_STATUS_NOT_SUPPORTED;
+
+ /* Ensure null termination */
+ state->request->data.ccache_save.user[
+ sizeof(state->request->data.ccache_save.user)-1]='\0';
+ state->request->data.ccache_save.pass[
+ sizeof(state->request->data.ccache_save.pass)-1]='\0';
+
+ DEBUG(3, ("winbindd_dual_ccache_save: [%5lu]: save password of user "
+ "%s\n", (unsigned long)state->pid,
+ state->request->data.ccache_save.user));
+
+ status = winbindd_add_memory_creds(
+ state->request->data.ccache_save.user,
+ state->request->data.ccache_save.uid,
+ state->request->data.ccache_save.pass);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("winbindd_add_memory_creds failed %s\n",
+ nt_errstr(status)));
+ return WINBINDD_ERROR;
+ }
+
+ return WINBINDD_OK;
+}