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 : /* Create an array of response structures */
164 0 : dbret = dbus_message_iter_open_container(&iter,
165 : DBUS_TYPE_ARRAY, "(uay)",
166 : &array_iter);
167 0 : if (!dbret) {
168 0 : return false;
169 : }
170 :
171 0 : resp = pd->resp_list;
172 0 : while (resp != NULL) {
173 : /* Create a DBUS struct */
174 0 : dbret = dbus_message_iter_open_container(&array_iter,
175 : DBUS_TYPE_STRUCT, NULL,
176 : &struct_iter);
177 0 : if (!dbret) {
178 0 : return false;
179 : }
180 :
181 : /* Add the response type */
182 0 : resp_type = resp->type;
183 0 : dbret = dbus_message_iter_append_basic(&struct_iter,
184 : DBUS_TYPE_UINT32,
185 : &resp_type);
186 0 : if (!dbret) {
187 0 : return false;
188 : }
189 :
190 : /* Add the response message */
191 0 : dbret = dbus_message_iter_open_container(&struct_iter,
192 : DBUS_TYPE_ARRAY, "y",
193 : &data_iter);
194 0 : if (!dbret) {
195 0 : return false;
196 : }
197 0 : dbret = dbus_message_iter_append_fixed_array(&data_iter,
198 0 : DBUS_TYPE_BYTE, &(resp->data), resp->len);
199 0 : if (!dbret) {
200 0 : return false;
201 : }
202 0 : dbret = dbus_message_iter_close_container(&struct_iter, &data_iter);
203 0 : if (!dbret) {
204 0 : return false;
205 : }
206 :
207 0 : resp = resp->next;
208 0 : dbret = dbus_message_iter_close_container(&array_iter, &struct_iter);
209 0 : if (!dbret) {
210 0 : return false;
211 : }
212 : }
213 :
214 : /* Close the struct array */
215 0 : dbret = dbus_message_iter_close_container(&iter, &array_iter);
216 0 : if (!dbret) {
217 0 : return false;
218 : }
219 :
220 0 : return true;
221 : }
222 :
223 0 : bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error)
224 : {
225 : DBusMessageIter iter;
226 : DBusMessageIter array_iter;
227 : DBusMessageIter struct_iter;
228 : DBusMessageIter sub_iter;
229 : int type;
230 : int len;
231 : const uint8_t *data;
232 :
233 0 : if (!dbus_message_iter_init(msg, &iter)) {
234 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response has no arguments.\n");
235 0 : return false;
236 : }
237 :
238 0 : if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
239 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
240 0 : return false;
241 : }
242 0 : dbus_message_iter_get_basic(&iter, &(pd->pam_status));
243 :
244 0 : if (!dbus_message_iter_next(&iter)) {
245 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response has too few arguments.\n");
246 0 : return false;
247 : }
248 :
249 : /* After this point will be an array of pam data */
250 0 : if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
251 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
252 0 : DEBUG(SSSDBG_CRIT_FAILURE,
253 : "Type was %c\n", (char)dbus_message_iter_get_arg_type(&iter));
254 0 : return false;
255 : }
256 :
257 0 : if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
258 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
259 0 : return false;
260 : }
261 :
262 0 : dbus_message_iter_recurse(&iter, &array_iter);
263 0 : while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
264 : /* Read in a pam data struct */
265 0 : if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
266 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
267 0 : return false;
268 : }
269 :
270 0 : dbus_message_iter_recurse(&array_iter, &struct_iter);
271 :
272 : /* PAM data struct contains a type and a byte-array of data */
273 :
274 : /* Get the pam data type */
275 0 : if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_UINT32) {
276 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
277 0 : return false;
278 : }
279 0 : dbus_message_iter_get_basic(&struct_iter, &type);
280 :
281 0 : if (!dbus_message_iter_next(&struct_iter)) {
282 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
283 0 : return false;
284 : }
285 :
286 : /* Get the byte array */
287 0 : if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_ARRAY ||
288 0 : dbus_message_iter_get_element_type(&struct_iter) != DBUS_TYPE_BYTE) {
289 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
290 0 : return false;
291 : }
292 :
293 0 : dbus_message_iter_recurse(&struct_iter, &sub_iter);
294 0 : dbus_message_iter_get_fixed_array(&sub_iter, &data, &len);
295 :
296 0 : if (pam_add_response(pd, type, len, data) != EOK) {
297 0 : DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
298 0 : return false;
299 : }
300 0 : dbus_message_iter_next(&array_iter);
301 : }
302 :
303 0 : return true;
304 : }
305 :
306 0 : void dp_id_callback(DBusPendingCall *pending, void *ptr)
307 : {
308 : DBusMessage *reply;
309 : DBusError dbus_error;
310 : dbus_bool_t ret;
311 : dbus_uint16_t dp_ver;
312 : int type;
313 :
314 0 : dbus_error_init(&dbus_error);
315 :
316 0 : reply = dbus_pending_call_steal_reply(pending);
317 0 : if (!reply) {
318 : /* reply should never be null. This function shouldn't be called
319 : * until reply is valid or timeout has occurred. If reply is NULL
320 : * here, something is seriously wrong and we should bail out.
321 : */
322 0 : DEBUG(SSSDBG_FATAL_FAILURE,
323 : "Severe error. A reply callback was called but no"
324 : " reply was received and no timeout occurred\n");
325 :
326 : /* FIXME: Destroy this connection ? */
327 0 : goto done;
328 : }
329 :
330 0 : type = dbus_message_get_type(reply);
331 0 : switch (type) {
332 : case DBUS_MESSAGE_TYPE_METHOD_RETURN:
333 0 : ret = dbus_message_get_args(reply, &dbus_error,
334 : DBUS_TYPE_UINT16, &dp_ver,
335 : DBUS_TYPE_INVALID);
336 0 : if (!ret) {
337 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse message\n");
338 0 : if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
339 : /* FIXME: Destroy this connection ? */
340 0 : goto done;
341 : }
342 :
343 0 : DEBUG(SSSDBG_CONF_SETTINGS,
344 : "Got id ack and version (%d) from DP\n", dp_ver);
345 :
346 0 : break;
347 :
348 : case DBUS_MESSAGE_TYPE_ERROR:
349 0 : DEBUG(SSSDBG_FATAL_FAILURE,"The Monitor returned an error [%s]\n",
350 : dbus_message_get_error_name(reply));
351 : /* Falling through to default intentionally*/
352 : default:
353 : /*
354 : * Timeout or other error occurred or something
355 : * unexpected happened.
356 : * It doesn't matter which, because either way we
357 : * know that this connection isn't trustworthy.
358 : * We'll destroy it now.
359 : */
360 :
361 : /* FIXME: Destroy this connection ? */
362 0 : break;
363 : }
364 :
365 : done:
366 0 : dbus_pending_call_unref(pending);
367 0 : dbus_message_unref(reply);
368 0 : }
369 :
370 0 : int dp_common_send_id(struct sbus_connection *conn, uint16_t version,
371 : const char *name)
372 : {
373 : DBusMessage *msg;
374 : dbus_bool_t ret;
375 : int retval;
376 :
377 : /* create the message */
378 0 : msg = dbus_message_new_method_call(NULL,
379 : DP_PATH,
380 : DATA_PROVIDER_IFACE,
381 : DATA_PROVIDER_IFACE_REGISTERSERVICE);
382 0 : if (msg == NULL) {
383 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?!\n");
384 0 : return ENOMEM;
385 : }
386 :
387 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Sending ID to DP: (%d,%s)\n",
388 : version, name);
389 :
390 0 : ret = dbus_message_append_args(msg,
391 : DBUS_TYPE_UINT16, &version,
392 : DBUS_TYPE_STRING, &name,
393 : DBUS_TYPE_INVALID);
394 0 : if (!ret) {
395 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n");
396 0 : return EIO;
397 : }
398 :
399 0 : retval = sbus_conn_send(conn, msg, 30000, dp_id_callback, NULL, NULL);
400 :
401 0 : dbus_message_unref(msg);
402 0 : return retval;
403 : }
404 :
|