s3/winbind_ccache: Fix typo in debug message.
[ira/wip.git] / source3 / winbindd / winbindd_ccache_access.c
index ffb20ac6c464fa0e95347e76f711fd209bdc3557..f8f57f6add9779aad2d4134433911a1e1756d7f0 100644 (file)
@@ -6,23 +6,24 @@
    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
@@ -46,10 +47,11 @@ static NTSTATUS do_ntlm_auth_with_hashes(const char *username,
                                        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);
@@ -77,13 +79,15 @@ static NTSTATUS do_ntlm_auth_with_hashes(const char *username,
        }
 
        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.
@@ -115,7 +119,16 @@ static NTSTATUS do_ntlm_auth_with_hashes(const char *username,
                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:
@@ -169,7 +182,7 @@ void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state)
                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",
@@ -250,20 +263,16 @@ enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *doma
                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;
@@ -283,3 +292,75 @@ enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *doma
   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;
+}