s3:utils: let smbstatus report anonymous signing/encryption explicitly
[samba.git] / source3 / winbindd / winbindd_pam_chng_pswd_auth_crap.c
1 /*
2    Unix SMB/CIFS implementation.
3    async implementation of WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
4    Copyright (C) Volker Lendecke 2010
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "winbindd.h"
22 #include "lib/global_contexts.h"
23 #include "librpc/gen_ndr/ndr_winbind_c.h"
24
25 struct winbindd_pam_chng_pswd_auth_crap_state {
26         struct wbint_PamAuthCrapChangePassword r;
27 };
28
29 static void winbindd_pam_chng_pswd_auth_crap_done(struct tevent_req *subreq);
30
31 struct tevent_req *winbindd_pam_chng_pswd_auth_crap_send(
32         TALLOC_CTX *mem_ctx,
33         struct tevent_context *ev,
34         struct winbindd_cli_state *cli,
35         struct winbindd_request *request)
36 {
37         struct tevent_req *req, *subreq;
38         struct winbindd_pam_chng_pswd_auth_crap_state *state;
39         struct winbindd_domain *domain;
40         const char *domain_name;
41
42         req = tevent_req_create(mem_ctx, &state,
43                                 struct winbindd_pam_chng_pswd_auth_crap_state);
44         if (req == NULL) {
45                 return NULL;
46         }
47
48         /* Ensure null termination */
49         request->data.chng_pswd_auth_crap.user[
50                 sizeof(request->data.chng_pswd_auth_crap.user)-1]='\0';
51         request->data.chng_pswd_auth_crap.domain[
52                 sizeof(request->data.chng_pswd_auth_crap.domain)-1]=0;
53
54         DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
55                   (unsigned long)cli->pid,
56                   request->data.chng_pswd_auth_crap.domain,
57                   request->data.chng_pswd_auth_crap.user));
58
59         domain_name = NULL;
60         if (*request->data.chng_pswd_auth_crap.domain != '\0') {
61                 domain_name = request->data.chng_pswd_auth_crap.domain;
62         } else if (lp_winbind_use_default_domain()) {
63                 domain_name = lp_workgroup();
64         }
65
66         domain = NULL;
67         if (domain_name != NULL) {
68                 domain = find_domain_from_name(domain_name);
69         }
70
71         if (domain == NULL) {
72                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
73                 return tevent_req_post(req, ev);
74         }
75
76         state->r.in.client_pid = request->pid;
77         state->r.in.client_name = talloc_strdup(state, request->client_name);
78         if (tevent_req_nomem(state->r.in.client_name, req)) {
79                 return tevent_req_post(req, ev);
80         }
81
82         state->r.in.domain = talloc_strdup(state, domain_name);
83         if (tevent_req_nomem(state->r.in.domain, req)) {
84                 return tevent_req_post(req, ev);
85         }
86         state->r.in.user = talloc_strdup(state,
87                 request->data.chng_pswd_auth_crap.user);
88         if (tevent_req_nomem(state->r.in.user, req)) {
89                 return tevent_req_post(req, ev);
90         }
91
92         state->r.in.new_nt_pswd = data_blob_talloc(state,
93                 request->data.chng_pswd_auth_crap.new_nt_pswd,
94                 request->data.chng_pswd_auth_crap.new_nt_pswd_len);
95         if (tevent_req_nomem(state->r.in.new_nt_pswd.data, req)) {
96                 return tevent_req_post(req, ev);
97         }
98
99         state->r.in.old_nt_hash_enc = data_blob_talloc(state,
100                 request->data.chng_pswd_auth_crap.old_nt_hash_enc,
101                 request->data.chng_pswd_auth_crap.old_nt_hash_enc_len);
102         if (tevent_req_nomem(state->r.in.old_nt_hash_enc.data, req)) {
103                 return tevent_req_post(req, ev);
104         }
105
106         if (request->data.chng_pswd_auth_crap.new_lm_pswd_len > 0) {
107                 state->r.in.new_lm_pswd = data_blob_talloc(state,
108                         request->data.chng_pswd_auth_crap.new_lm_pswd,
109                         request->data.chng_pswd_auth_crap.new_lm_pswd_len);
110                 if (tevent_req_nomem(state->r.in.new_lm_pswd.data, req)) {
111                         return tevent_req_post(req, ev);
112                 }
113
114                 state->r.in.old_lm_hash_enc = data_blob_talloc(state,
115                         request->data.chng_pswd_auth_crap.old_lm_hash_enc,
116                         request->data.chng_pswd_auth_crap.old_lm_hash_enc_len);
117                 if (tevent_req_nomem(state->r.in.old_lm_hash_enc.data, req)) {
118                         return tevent_req_post(req, ev);
119                 }
120         } else {
121                 state->r.in.new_lm_pswd = data_blob_null;
122                 state->r.in.old_lm_hash_enc = data_blob_null;
123         }
124
125         subreq = dcerpc_wbint_PamAuthCrapChangePassword_r_send(state,
126                                                 global_event_context(),
127                                                 dom_child_handle(domain),
128                                                 &state->r);
129         if (tevent_req_nomem(subreq, req)) {
130                 return tevent_req_post(req, ev);
131         }
132         tevent_req_set_callback(subreq, winbindd_pam_chng_pswd_auth_crap_done,
133                                 req);
134         return req;
135 }
136
137 static void winbindd_pam_chng_pswd_auth_crap_done(struct tevent_req *subreq)
138 {
139         struct tevent_req *req = tevent_req_callback_data(
140                 subreq, struct tevent_req);
141         struct winbindd_pam_chng_pswd_auth_crap_state *state = tevent_req_data(
142                 req, struct winbindd_pam_chng_pswd_auth_crap_state);
143         NTSTATUS status;
144
145         status = dcerpc_wbint_PamAuthCrapChangePassword_r_recv(subreq, state);
146         TALLOC_FREE(subreq);
147         if (tevent_req_nterror(req, status)) {
148                 return;
149         }
150
151         tevent_req_done(req);
152 }
153
154 NTSTATUS winbindd_pam_chng_pswd_auth_crap_recv(
155         struct tevent_req *req,
156         struct winbindd_response *response)
157 {
158         struct winbindd_pam_chng_pswd_auth_crap_state *state = tevent_req_data(
159                 req, struct winbindd_pam_chng_pswd_auth_crap_state);
160         NTSTATUS status = NT_STATUS_OK;
161
162         if (tevent_req_is_nterror(req, &status)) {
163                 set_auth_errors(response, status);
164                 return status;
165         }
166
167         response->result = WINBINDD_PENDING;
168         set_auth_errors(response, state->r.out.result);
169
170         return NT_STATUS(response->data.auth.nt_status);
171 }