void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state) { struct winbindd_domain *domain; fstring name_domain, name_user; 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; /* Ensure null termination */ state->request->data.ccache_ntlm_auth.user[ sizeof(state->request->data.ccache_ntlm_auth.user)-1]='\0'; DEBUG(3, ("[%5lu]: perform NTLM auth on behalf of user %s\n", (unsigned long)state->pid, state->request->data.ccache_ntlm_auth.user)); /* Parse domain and username */ if (!canonicalize_username(state->request->data.ccache_ntlm_auth.user, name_domain, name_user)) { DEBUG(5,("winbindd_ccache_ntlm_auth: cannot parse domain and user from name [%s]\n", state->request->data.ccache_ntlm_auth.user)); request_error(state); return; } domain = find_auth_domain(state->request->flags, name_domain); if (domain == NULL) { DEBUG(5,("winbindd_ccache_ntlm_auth: can't get domain [%s]\n", name_domain)); request_error(state); return; } if (!check_client_uid(state, state->request->data.ccache_ntlm_auth.uid)) { request_error(state); return; } /* validate blob lengths */ initial_blob_len = state->request->data.ccache_ntlm_auth.initial_blob_len; challenge_blob_len = state->request->data.ccache_ntlm_auth.challenge_blob_len; extra_len = state->request->extra_len; if (initial_blob_len > extra_len || challenge_blob_len > extra_len || initial_blob_len + challenge_blob_len > extra_len || initial_blob_len + challenge_blob_len < initial_blob_len || initial_blob_len + challenge_blob_len < challenge_blob_len) { DEBUG(10,("winbindd_dual_ccache_ntlm_auth: blob lengths overrun " "or wrap. Buffer [%d+%d > %d]\n", initial_blob_len, challenge_blob_len, extra_len)); goto process_result; } /* Parse domain and username */ if (!parse_domain_user(state->request->data.ccache_ntlm_auth.user, name_domain, name_user)) { DEBUG(10,("winbindd_dual_ccache_ntlm_auth: cannot parse " "domain and user from name [%s]\n", state->request->data.ccache_ntlm_auth.user)); goto process_result; } entry = find_memory_creds_by_name(state->request->data.ccache_ntlm_auth.user); if (entry == NULL || entry->nt_hash == NULL || entry->lm_hash == NULL) { DEBUG(10,("winbindd_dual_ccache_ntlm_auth: could not find " "credentials for user %s\n", state->request->data.ccache_ntlm_auth.user)); goto process_result; } DEBUG(10,("winbindd_dual_ccache_ntlm_auth: found ccache [%s]\n", entry->username)); if (!client_can_access_ccache_entry(state->request->data.ccache_ntlm_auth.uid, entry)) { goto process_result; } if (initial_blob_len == 0 && challenge_blob_len == 0) { /* this is just a probe to see if credentials are available. */ result = NT_STATUS_OK; state->response->data.ccache_ntlm_auth.auth_blob_len = 0; goto process_result; } 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); 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; } state->response->extra_data.data = talloc_memdup( state->mem_ctx, auth.data, auth.length); if (!state->response->extra_data.data) { result = NT_STATUS_NO_MEMORY; goto process_result; } state->response->length += auth.length; state->response->data.ccache_ntlm_auth.auth_blob_len = auth.length; data_blob_free(&auth); process_result: if (!NT_STATUS_IS_OK(result)) { request_error(state); return; } request_ok(state); }
enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *domain, struct winbindd_cli_state *state) { NTSTATUS result = NT_STATUS_NOT_SUPPORTED; struct WINBINDD_MEMORY_CREDS *entry; DATA_BLOB initial, challenge, auth; fstring name_domain, name_user; uint32 initial_blob_len, challenge_blob_len, extra_len; /* Ensure null termination */ state->request.data.ccache_ntlm_auth.user[ sizeof(state->request.data.ccache_ntlm_auth.user)-1]='\0'; DEBUG(3, ("winbindd_dual_ccache_ntlm_auth: [%5lu]: perform NTLM auth on " "behalf of user %s (dual)\n", (unsigned long)state->pid, state->request.data.ccache_ntlm_auth.user)); /* validate blob lengths */ initial_blob_len = state->request.data.ccache_ntlm_auth.initial_blob_len; challenge_blob_len = state->request.data.ccache_ntlm_auth.challenge_blob_len; extra_len = state->request.extra_len; if (initial_blob_len > extra_len || challenge_blob_len > extra_len || initial_blob_len + challenge_blob_len > extra_len || initial_blob_len + challenge_blob_len < initial_blob_len || initial_blob_len + challenge_blob_len < challenge_blob_len) { DEBUG(10,("winbindd_dual_ccache_ntlm_auth: blob lengths overrun " "or wrap. Buffer [%d+%d > %d]\n", initial_blob_len, challenge_blob_len, extra_len)); goto process_result; } /* Parse domain and username */ if (!parse_domain_user(state->request.data.ccache_ntlm_auth.user, name_domain, name_user)) { DEBUG(10,("winbindd_dual_ccache_ntlm_auth: cannot parse " "domain and user from name [%s]\n", state->request.data.ccache_ntlm_auth.user)); goto process_result; } entry = find_memory_creds_by_name(state->request.data.ccache_ntlm_auth.user); if (entry == NULL || entry->nt_hash == NULL || entry->lm_hash == NULL) { DEBUG(10,("winbindd_dual_ccache_ntlm_auth: could not find " "credentials for user %s\n", state->request.data.ccache_ntlm_auth.user)); goto process_result; } DEBUG(10,("winbindd_dual_ccache_ntlm_auth: found ccache [%s]\n", entry->username)); if (!client_can_access_ccache_entry(state->request.data.ccache_ntlm_auth.uid, entry)) { goto process_result; } if (initial_blob_len == 0 && challenge_blob_len == 0) { /* this is just a probe to see if credentials are available. */ result = NT_STATUS_OK; state->response.data.ccache_ntlm_auth.auth_blob_len = 0; 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); } data_blob_free(&initial); data_blob_free(&challenge); if (!NT_STATUS_IS_OK(result)) { goto process_result; } state->response.extra_data.data = smb_xmemdup(auth.data, auth.length); if (!state->response.extra_data.data) { result = NT_STATUS_NO_MEMORY; goto process_result; } state->response.length += auth.length; state->response.data.ccache_ntlm_auth.auth_blob_len = auth.length; data_blob_free(&auth); process_result: return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; }