wafsamba: simplify SAMBA_PIDL_TABLES() rule
[Samba.git] / source3 / winbindd / winbindd_pam_logoff.c
blob30f69e1004507ba7d0262e27b2e5e54fd0eef235
1 /*
2 Unix SMB/CIFS implementation.
3 async implementation of WINBINDD_PAM_LOGOFF
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"
23 struct winbindd_pam_logoff_state {
24 struct winbindd_request *request;
25 struct winbindd_response *response;
28 static void winbindd_pam_logoff_done(struct tevent_req *subreq);
30 struct tevent_req *winbindd_pam_logoff_send(TALLOC_CTX *mem_ctx,
31 struct tevent_context *ev,
32 struct winbindd_cli_state *cli,
33 struct winbindd_request *request)
35 struct tevent_req *req, *subreq;
36 struct winbindd_pam_logoff_state *state;
37 struct winbindd_domain *domain;
38 fstring name_namespace, name_domain, user;
39 uid_t caller_uid;
40 gid_t caller_gid;
41 int res;
42 bool ok;
44 req = tevent_req_create(mem_ctx, &state,
45 struct winbindd_pam_logoff_state);
46 if (req == NULL) {
47 return NULL;
49 state->request = request;
51 /* Ensure null termination */
52 /* Ensure null termination */
53 request->data.logoff.user[sizeof(request->data.logoff.user)-1]='\0';
54 request->data.logoff.krb5ccname[
55 sizeof(request->data.logoff.krb5ccname)-1]='\0';
57 DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)cli->pid,
58 request->data.auth.user));
60 if (request->data.logoff.uid == (uid_t)-1) {
61 goto failed;
64 ok = canonicalize_username(request->data.logoff.user,
65 name_namespace,
66 name_domain,
67 user);
68 if (!ok) {
69 goto failed;
72 domain = find_auth_domain(request->flags, name_namespace);
73 if (domain == NULL) {
74 goto failed;
77 caller_uid = (uid_t)-1;
79 res = getpeereid(cli->sock, &caller_uid, &caller_gid);
80 if (res != 0) {
81 DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n",
82 strerror(errno)));
83 goto failed;
86 switch (caller_uid) {
87 case -1:
88 goto failed;
89 case 0:
90 /* root must be able to logoff any user - gd */
91 break;
92 default:
93 if (caller_uid != request->data.logoff.uid) {
94 DEBUG(1,("winbindd_pam_logoff: caller requested "
95 "invalid uid\n"));
96 goto failed;
98 break;
101 subreq = wb_domain_request_send(state, global_event_context(), domain,
102 request);
103 if (tevent_req_nomem(subreq, req)) {
104 return tevent_req_post(req, ev);
106 tevent_req_set_callback(subreq, winbindd_pam_logoff_done, req);
107 return req;
109 failed:
110 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
111 return tevent_req_post(req, ev);
114 static void winbindd_pam_logoff_done(struct tevent_req *subreq)
116 struct tevent_req *req = tevent_req_callback_data(
117 subreq, struct tevent_req);
118 struct winbindd_pam_logoff_state *state = tevent_req_data(
119 req, struct winbindd_pam_logoff_state);
120 int res, err;
122 res = wb_domain_request_recv(subreq, state, &state->response, &err);
123 TALLOC_FREE(subreq);
124 if (res == -1) {
125 tevent_req_nterror(req, map_nt_error_from_unix(err));
126 return;
128 tevent_req_done(req);
131 NTSTATUS winbindd_pam_logoff_recv(struct tevent_req *req,
132 struct winbindd_response *response)
134 struct winbindd_pam_logoff_state *state = tevent_req_data(
135 req, struct winbindd_pam_logoff_state);
136 NTSTATUS status;
138 if (tevent_req_is_nterror(req, &status)) {
139 set_auth_errors(response, status);
140 return status;
142 *response = *state->response;
143 response->result = WINBINDD_PENDING;
144 state->response = talloc_move(response, &state->response);
146 status = NT_STATUS(response->data.auth.nt_status);
147 if (!NT_STATUS_IS_OK(status)) {
148 return status;
150 winbindd_delete_memory_creds(state->request->data.logoff.user);
151 return status;