samba-tool tests: rename 'group create' to 'group add'
[Samba.git] / source3 / winbindd / winbindd_pam_chauthtok.c
blob3a61ba30f4c17cae62e001ec7d6324f94f2b60b4
1 /*
2 Unix SMB/CIFS implementation.
3 async implementation of WINBINDD_PAM_CHAUTHTOK
4 Copyright (C) Volker Lendecke 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "winbindd.h"
22 #include "lib/util/string_wrappers.h"
24 struct winbindd_pam_chauthtok_state {
25 struct winbindd_request *request;
26 struct winbindd_response *response;
29 static void winbindd_pam_chauthtok_done(struct tevent_req *subreq);
31 struct tevent_req *winbindd_pam_chauthtok_send(
32 TALLOC_CTX *mem_ctx,
33 struct tevent_context *ev,
34 struct winbindd_cli_state *cli,
35 struct winbindd_request *request)
37 struct tevent_req *req, *subreq;
38 struct winbindd_pam_chauthtok_state *state;
39 struct winbindd_domain *contact_domain;
40 fstring namespace, domain, user;
41 char *mapped_user;
42 NTSTATUS status;
43 bool ok;
45 req = tevent_req_create(mem_ctx, &state,
46 struct winbindd_pam_chauthtok_state);
47 if (req == NULL) {
48 return NULL;
50 state->request = request;
52 /* Ensure null termination */
53 request->data.chauthtok.user[
54 sizeof(request->data.chauthtok.user)-1]='\0';
56 DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)cli->pid,
57 request->data.chauthtok.user));
59 status = normalize_name_unmap(state, request->data.chauthtok.user,
60 &mapped_user);
62 if (NT_STATUS_IS_OK(status) ||
63 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
64 fstrcpy(request->data.chauthtok.user, mapped_user);
67 ok = canonicalize_username(request->data.chauthtok.user,
68 namespace,
69 domain,
70 user);
71 if (!ok) {
72 DEBUG(10, ("winbindd_pam_chauthtok: canonicalize_username %s "
73 "failed with\n", request->data.chauthtok.user));
74 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
75 return tevent_req_post(req, ev);
78 contact_domain = find_domain_from_name(namespace);
79 if (contact_domain == NULL) {
80 DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] "
81 "as %s is not a trusted domain\n",
82 request->data.chauthtok.user, domain, user, domain));
83 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
84 return tevent_req_post(req, ev);
87 subreq = wb_domain_request_send(state, global_event_context(),
88 contact_domain, request);
89 if (tevent_req_nomem(subreq, req)) {
90 return tevent_req_post(req, ev);
92 tevent_req_set_callback(subreq, winbindd_pam_chauthtok_done, req);
93 return req;
96 static void winbindd_pam_chauthtok_done(struct tevent_req *subreq)
98 struct tevent_req *req = tevent_req_callback_data(
99 subreq, struct tevent_req);
100 struct winbindd_pam_chauthtok_state *state = tevent_req_data(
101 req, struct winbindd_pam_chauthtok_state);
102 int res, err;
104 res = wb_domain_request_recv(subreq, state, &state->response, &err);
105 TALLOC_FREE(subreq);
106 if (res == -1) {
107 tevent_req_nterror(req, map_nt_error_from_unix(err));
108 return;
110 tevent_req_done(req);
113 NTSTATUS winbindd_pam_chauthtok_recv(struct tevent_req *req,
114 struct winbindd_response *response)
116 struct winbindd_pam_chauthtok_state *state = tevent_req_data(
117 req, struct winbindd_pam_chauthtok_state);
118 NTSTATUS status;
120 if (tevent_req_is_nterror(req, &status)) {
121 set_auth_errors(response, status);
122 return status;
124 *response = *state->response;
125 response->result = WINBINDD_PENDING;
126 state->response = talloc_move(response, &state->response);
128 status = NT_STATUS(response->data.auth.nt_status);
129 if (!NT_STATUS_IS_OK(status)) {
130 return status;
133 if (state->request->flags & WBFLAG_PAM_CACHED_LOGIN) {
135 /* Update the single sign-on memory creds. */
136 status = winbindd_replace_memory_creds(
137 state->request->data.chauthtok.user,
138 state->request->data.chauthtok.newpass);
140 DEBUG(10, ("winbindd_replace_memory_creds returned %s\n",
141 nt_errstr(status)));
144 * When we login from gdm or xdm and password expires,
145 * we change password, but there are no memory
146 * crendentials So, winbindd_replace_memory_creds()
147 * returns NT_STATUS_OBJECT_NAME_NOT_FOUND. This is
148 * not a failure. --- BoYang
150 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
151 status = NT_STATUS_OK;
154 return status;