Line data Source code
1 : /*
2 : SSSD
3 :
4 : Data Provider, auth utils
5 :
6 : Copyright (C) Sumit Bose <sbose@redhat.com> 2009
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "data_provider.h"
23 :
24 0 : bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd)
25 : {
26 : dbus_bool_t db_ret;
27 : const char *service;
28 : const char *tty;
29 : const char *ruser;
30 : const char *rhost;
31 : uint32_t authtok_type;
32 : int authtok_length;
33 : uint8_t *authtok_data;
34 : uint32_t new_authtok_type;
35 : int new_authtok_length;
36 : uint8_t *new_authtok_data;
37 : int32_t pd_priv;
38 : int32_t pd_cmd;
39 :
40 0 : if (pd->user == NULL) return false;
41 0 : service = pd->service ? pd->service : "";
42 0 : tty = pd->tty ? pd->tty : "";
43 0 : ruser = pd->ruser ? pd->ruser : "";
44 0 : rhost = pd->rhost ? pd->rhost : "";
45 0 : authtok_type = (uint32_t)sss_authtok_get_type(pd->authtok);
46 0 : authtok_data = sss_authtok_get_data(pd->authtok);
47 0 : authtok_length = sss_authtok_get_size(pd->authtok);
48 0 : new_authtok_type = (uint32_t)sss_authtok_get_type(pd->newauthtok);
49 0 : new_authtok_data = sss_authtok_get_data(pd->newauthtok);
50 0 : new_authtok_length = sss_authtok_get_size(pd->newauthtok);
51 0 : pd_priv = pd->priv;
52 0 : pd_cmd = pd->cmd;
53 :
54 0 : db_ret = dbus_message_append_args(msg,
55 : DBUS_TYPE_INT32, &pd_cmd,
56 : DBUS_TYPE_STRING, &(pd->user),
57 : DBUS_TYPE_STRING, &(pd->domain),
58 : DBUS_TYPE_STRING, &service,
59 : DBUS_TYPE_STRING, &tty,
60 : DBUS_TYPE_STRING, &ruser,
61 : DBUS_TYPE_STRING, &rhost,
62 : DBUS_TYPE_UINT32, &authtok_type,
63 : DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
64 : &authtok_data, authtok_length,
65 : DBUS_TYPE_UINT32, &new_authtok_type,
66 : DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
67 : &new_authtok_data, new_authtok_length,
68 : DBUS_TYPE_INT32, &pd_priv,
69 : DBUS_TYPE_UINT32, &(pd->cli_pid),
70 : DBUS_TYPE_INVALID);
71 :
72 0 : return db_ret;
73 : }
74 :
75 0 : bool dp_unpack_pam_request(DBusMessage *msg, TALLOC_CTX *mem_ctx,
76 : struct pam_data **new_pd, DBusError *dbus_error)
77 : {
78 : dbus_bool_t db_ret;
79 : int ret;
80 : struct pam_data pd;
81 : uint32_t authtok_type;
82 : int authtok_length;
83 : uint8_t *authtok_data;
84 : uint32_t new_authtok_type;
85 : int new_authtok_length;
86 : uint8_t *new_authtok_data;
87 : int32_t pd_cmd;
88 : int32_t pd_priv;
89 :
90 0 : memset(&pd, 0, sizeof(pd));
91 :
92 0 : db_ret = dbus_message_get_args(msg, dbus_error,
93 : DBUS_TYPE_INT32, &pd_cmd,
94 : DBUS_TYPE_STRING, &(pd.user),
95 : DBUS_TYPE_STRING, &(pd.domain),
96 : DBUS_TYPE_STRING, &(pd.service),
97 : DBUS_TYPE_STRING, &(pd.tty),
98 : DBUS_TYPE_STRING, &(pd.ruser),
99 : DBUS_TYPE_STRING, &(pd.rhost),
100 : DBUS_TYPE_UINT32, &authtok_type,
101 : DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
102 : &authtok_data, &authtok_length,
103 : DBUS_TYPE_UINT32, &new_authtok_type,
104 : DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
105 : &new_authtok_data, &new_authtok_length,
106 : DBUS_TYPE_INT32, &pd_priv,
107 : DBUS_TYPE_UINT32, &(pd.cli_pid),
108 : DBUS_TYPE_INVALID);
109 :
110 0 : if (!db_ret) {
111 0 : DEBUG(SSSDBG_CRIT_FAILURE, "dbus_message_get_args failed.\n");
112 0 : return false;
113 : }
114 :
115 0 : pd.cmd = pd_cmd;
116 0 : pd.priv = pd_priv;
117 :
118 0 : ret = copy_pam_data(mem_ctx, &pd, new_pd);
119 0 : if (ret != EOK) {
120 0 : DEBUG(SSSDBG_CRIT_FAILURE, "copy_pam_data failed.\n");
121 0 : return false;
122 : }
123 :
124 0 : ret = sss_authtok_set((*new_pd)->authtok, authtok_type,
125 : authtok_data, authtok_length);
126 0 : if (ret) {
127 0 : DEBUG(SSSDBG_CRIT_FAILURE,
128 : "Failed to set auth token: %d [%s]\n", ret, strerror(ret));
129 0 : return false;
130 : }
131 0 : ret = sss_authtok_set((*new_pd)->newauthtok, new_authtok_type,
132 : new_authtok_data, new_authtok_length);
133 0 : if (ret) {
134 0 : DEBUG(SSSDBG_CRIT_FAILURE,
135 : "Failed to set auth token: %d [%s]\n", ret, strerror(ret));
136 0 : return false;
137 : }
138 :
139 0 : return true;
140 : }
141 :
142 0 : bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd)
143 : {
144 : dbus_bool_t dbret;
145 : struct response_data *resp;
146 : DBusMessageIter iter;
147 : DBusMessageIter array_iter;
148 : DBusMessageIter struct_iter;
149 : DBusMessageIter data_iter;
150 : uint32_t pam_status;
151 : uint32_t resp_type;
152 :
153 0 : dbus_message_iter_init_append(msg, &iter);
154 :
155 : /* Append the PAM status */
156 0 : pam_status = pd->pam_status;
157 0 : dbret = dbus_message_iter_append_basic(&iter,
158 : DBUS_TYPE_UINT32, &pam_status);
159 0 : if (!dbret) {
160 0 : return false;
161 : }
162 :
163 : /* Append the lockout of account */
164 0 : dbret = dbus_message_iter_append_basic(&iter,
165 : DBUS_TYPE_UINT32,
166 0 : &pd->account_locked);
167 0 : if (!dbret) {
168 0 : return false;
169 : }
170 :
171 : /* Create an array of response structures */
172 0 : dbret = dbus_message_iter_open_container(&iter,
173 : DBUS_TYPE_ARRAY, "(uay)",
174 : &array_iter);
175 0 : if (!dbret) {
176 0 : return false;
177 : }
178 :
179 0 : resp = pd->resp_list;
180 0 : while (resp != NULL) {
181 : /* Create a DBUS struct */
182 0 : dbret = dbus_message_iter_open_container(&array_iter,
183 : DBUS_TYPE_STRUCT, NULL,
184 : &struct_iter);
185 0 : if (!dbret) {
186 0 : return false;
187 : }
188 :
189 : /* Add the response type */
190 0 : resp_type = resp->type;
191 0 : dbret = dbus_message_iter_append_basic(&struct_iter,
192 : DBUS_TYPE_UINT32,
193 : &resp_type);
194 0 : if (!dbret) {
195 0 : return false;
196 : }
197 :
198 : /* Add the response message */
199 0 : dbret = dbus_message_iter_open_container(&struct_iter,
200 : DBUS_TYPE_ARRAY, "y",
201 : &data_iter);
202 0 : if (!dbret) {
203 0 : return false;
204 : }
205 0 : dbret = dbus_message_iter_append_fixed_array(&data_iter,
206 0 : DBUS_TYPE_BYTE, &(resp->data), resp->len);
207 0 : if (!dbret) {
208 0 : return false;
209 : }
210 0 : dbret = dbus_message_iter_close_container(&struct_iter, &data_iter);
211 0 : if (!dbret) {
212 0 : return false;
213 : }
214 :
215 0 : resp = resp->next;
216 0 : dbret = dbus_message_iter_close_container(&array_iter, &struct_iter);
217 0 : if (!dbret) {
218 0 : return false;
219 : }
220 : }
221 :
222 : /* Close the struct array */
223 0 : dbret = dbus_message_iter_close_container(&iter, &array_iter);
224 0 : if (!dbret) {
225 0 : return false;
226 : }
227 :
228 0 : return true;
229 : }
230 :
231 0 : bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error)
232 : {
233 : DBusMessageIter iter;
234 : DBusMessageIter array_iter;
235 : DBusMessageIter struct_iter;
236 : DBusMessageIter sub_iter;
237 : int type;
238 : int len;
239 : const uint8_t *data;
240 :
241 0 : if (!dbus_message_iter_init(msg, &iter)) {
242 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response has no arguments.\n");
243 0 : return false;
244 : }
245 :
246 0 : if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
247 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
248 0 : return false;
249 : }
250 0 : dbus_message_iter_get_basic(&iter, &(pd->pam_status));
251 :
252 0 : if (!dbus_message_iter_next(&iter)) {
253 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response has too few arguments.\n");
254 0 : return false;
255 : }
256 :
257 0 : if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
258 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
259 0 : return false;
260 : }
261 0 : dbus_message_iter_get_basic(&iter, &(pd->account_locked));
262 :
263 0 : if (!dbus_message_iter_next(&iter)) {
264 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response has too few arguments.\n");
265 0 : return false;
266 : }
267 :
268 : /* After this point will be an array of pam data */
269 0 : if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
270 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
271 0 : DEBUG(SSSDBG_CRIT_FAILURE,
272 : "Type was %c\n", (char)dbus_message_iter_get_arg_type(&iter));
273 0 : return false;
274 : }
275 :
276 0 : if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
277 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
278 0 : return false;
279 : }
280 :
281 0 : dbus_message_iter_recurse(&iter, &array_iter);
282 0 : while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
283 : /* Read in a pam data struct */
284 0 : if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
285 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
286 0 : return false;
287 : }
288 :
289 0 : dbus_message_iter_recurse(&array_iter, &struct_iter);
290 :
291 : /* PAM data struct contains a type and a byte-array of data */
292 :
293 : /* Get the pam data type */
294 0 : if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_UINT32) {
295 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
296 0 : return false;
297 : }
298 0 : dbus_message_iter_get_basic(&struct_iter, &type);
299 :
300 0 : if (!dbus_message_iter_next(&struct_iter)) {
301 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
302 0 : return false;
303 : }
304 :
305 : /* Get the byte array */
306 0 : if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_ARRAY ||
307 0 : dbus_message_iter_get_element_type(&struct_iter) != DBUS_TYPE_BYTE) {
308 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
309 0 : return false;
310 : }
311 :
312 0 : dbus_message_iter_recurse(&struct_iter, &sub_iter);
313 0 : dbus_message_iter_get_fixed_array(&sub_iter, &data, &len);
314 :
315 0 : if (pam_add_response(pd, type, len, data) != EOK) {
316 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
317 0 : return false;
318 : }
319 0 : dbus_message_iter_next(&array_iter);
320 : }
321 :
322 0 : return true;
323 : }
324 :
325 0 : void dp_id_callback(DBusPendingCall *pending, void *ptr)
326 : {
327 : DBusMessage *reply;
328 : DBusError dbus_error;
329 : dbus_bool_t ret;
330 : dbus_uint16_t dp_ver;
331 : int type;
332 :
333 0 : dbus_error_init(&dbus_error);
334 :
335 0 : reply = dbus_pending_call_steal_reply(pending);
336 0 : if (!reply) {
337 : /* reply should never be null. This function shouldn't be called
338 : * until reply is valid or timeout has occurred. If reply is NULL
339 : * here, something is seriously wrong and we should bail out.
340 : */
341 0 : DEBUG(SSSDBG_FATAL_FAILURE,
342 : "Severe error. A reply callback was called but no"
343 : " reply was received and no timeout occurred\n");
344 :
345 : /* FIXME: Destroy this connection ? */
346 0 : goto done;
347 : }
348 :
349 0 : type = dbus_message_get_type(reply);
350 0 : switch (type) {
351 : case DBUS_MESSAGE_TYPE_METHOD_RETURN:
352 0 : ret = dbus_message_get_args(reply, &dbus_error,
353 : DBUS_TYPE_UINT16, &dp_ver,
354 : DBUS_TYPE_INVALID);
355 0 : if (!ret) {
356 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse message\n");
357 0 : if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
358 : /* FIXME: Destroy this connection ? */
359 0 : goto done;
360 : }
361 :
362 0 : DEBUG(SSSDBG_CONF_SETTINGS,
363 : "Got id ack and version (%d) from DP\n", dp_ver);
364 :
365 0 : break;
366 :
367 : case DBUS_MESSAGE_TYPE_ERROR:
368 0 : DEBUG(SSSDBG_FATAL_FAILURE,"The Monitor returned an error [%s]\n",
369 : dbus_message_get_error_name(reply));
370 : /* Falling through to default intentionally*/
371 : default:
372 : /*
373 : * Timeout or other error occurred or something
374 : * unexpected happened.
375 : * It doesn't matter which, because either way we
376 : * know that this connection isn't trustworthy.
377 : * We'll destroy it now.
378 : */
379 :
380 : /* FIXME: Destroy this connection ? */
381 0 : break;
382 : }
383 :
384 : done:
385 0 : dbus_pending_call_unref(pending);
386 0 : dbus_message_unref(reply);
387 0 : }
|