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 bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd)
25 {
26 dbus_bool_t db_ret;
27
28 if (pd->user == NULL) return false;
29 if (pd->service == NULL) pd->service = talloc_strdup(pd, "");
30 if (pd->tty == NULL) pd->tty = talloc_strdup(pd, "");
31 if (pd->ruser == NULL) pd->ruser = talloc_strdup(pd, "");
32 if (pd->rhost == NULL) pd->rhost = talloc_strdup(pd, "");
33
34
35 db_ret = dbus_message_append_args(msg,
36 DBUS_TYPE_INT32, &(pd->cmd),
37 DBUS_TYPE_STRING, &(pd->user),
38 DBUS_TYPE_STRING, &(pd->service),
39 DBUS_TYPE_STRING, &(pd->tty),
40 DBUS_TYPE_STRING, &(pd->ruser),
41 DBUS_TYPE_STRING, &(pd->rhost),
42 DBUS_TYPE_UINT32, &(pd->authtok_type),
43 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
44 &(pd->authtok),
45 (pd->authtok_size),
46 DBUS_TYPE_UINT32, &(pd->newauthtok_type),
47 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
48 &(pd->newauthtok),
49 pd->newauthtok_size,
50 DBUS_TYPE_INT32, &(pd->priv),
51 DBUS_TYPE_UINT32, &(pd->cli_pid),
52 DBUS_TYPE_INVALID);
53
54 return db_ret;
55 }
56
57 bool dp_unpack_pam_request(DBusMessage *msg, TALLOC_CTX *mem_ctx,
58 struct pam_data **new_pd, DBusError *dbus_error)
59 {
60 dbus_bool_t db_ret;
61 int ret;
62 struct pam_data pd;
63
64 memset(&pd, 0, sizeof(pd));
65
66 db_ret = dbus_message_get_args(msg, dbus_error,
67 DBUS_TYPE_INT32, &(pd.cmd),
68 DBUS_TYPE_STRING, &(pd.user),
69 DBUS_TYPE_STRING, &(pd.service),
70 DBUS_TYPE_STRING, &(pd.tty),
71 DBUS_TYPE_STRING, &(pd.ruser),
72 DBUS_TYPE_STRING, &(pd.rhost),
73 DBUS_TYPE_UINT32, &(pd.authtok_type),
74 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
75 &(pd.authtok),
76 &(pd.authtok_size),
77 DBUS_TYPE_UINT32, &(pd.newauthtok_type),
78 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
79 &(pd.newauthtok),
80 &(pd.newauthtok_size),
81 DBUS_TYPE_INT32, &(pd.priv),
82 DBUS_TYPE_UINT32, &(pd.cli_pid),
83 DBUS_TYPE_INVALID);
84
85 if (!db_ret) {
86 DEBUG(1, ("dbus_message_get_args failed.\n"));
87 return false;
88 }
89
90 ret = copy_pam_data(mem_ctx, &pd, new_pd);
91 if (ret != EOK) {
92 DEBUG(1, ("copy_pam_data failed.\n"));
93 return false;
94 }
95
96 if (pd.authtok_size != 0 && pd.authtok != NULL) {
97 memset(pd.authtok, 0, pd.authtok_size);
98 pd.authtok_size = 0;
99 }
100
101 if (pd.newauthtok_size != 0 && pd.newauthtok != NULL) {
102 memset(pd.newauthtok, 0, pd.newauthtok_size);
103 pd.newauthtok_size = 0;
104 }
105
106 return true;
107 }
108
109 bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd)
110 {
111 dbus_bool_t dbret;
112 struct response_data *resp;
113 DBusMessageIter iter;
114 DBusMessageIter array_iter;
115 DBusMessageIter struct_iter;
116 DBusMessageIter data_iter;
117
118 dbus_message_iter_init_append(msg, &iter);
119
120 /* Append the PAM status */
121 dbret = dbus_message_iter_append_basic(&iter,
122 DBUS_TYPE_UINT32, &(pd->pam_status));
At conditional (1): "!dbret": Taking false branch.
|
123 if (!dbret) {
124 return false;
125 }
126
127 /* Create an array of response structures */
128 dbret = dbus_message_iter_open_container(&iter,
129 DBUS_TYPE_ARRAY, "(uay)",
130 &array_iter);
At conditional (2): "!dbret": Taking false branch.
|
131 if (!dbret) {
132 return false;
133 }
134
Event deref_parm: Directly dereferencing parameter "pd".
|
135 resp = pd->resp_list;
136 while (resp != NULL) {
137 /* Create a DBUS struct */
138 dbret = dbus_message_iter_open_container(&array_iter,
139 DBUS_TYPE_STRUCT, NULL,
140 &struct_iter);
141 if (!dbret) {
142 return false;
143 }
144
145 /* Add the response type */
146 dbret = dbus_message_iter_append_basic(&struct_iter,
147 DBUS_TYPE_UINT32,
148 &(resp->type));
149 if (!dbret) {
150 return false;
151 }
152
153 /* Add the response message */
154 dbret = dbus_message_iter_open_container(&struct_iter,
155 DBUS_TYPE_ARRAY, "y",
156 &data_iter);
157 if (!dbret) {
158 return false;
159 }
160 dbret = dbus_message_iter_append_fixed_array(&data_iter,
161 DBUS_TYPE_BYTE, &(resp->data), resp->len);
162 if (!dbret) {
163 return false;
164 }
165 dbret = dbus_message_iter_close_container(&struct_iter, &data_iter);
166 if (!dbret) {
167 return false;
168 }
169
170 resp = resp->next;
171 dbret = dbus_message_iter_close_container(&array_iter, &struct_iter);
172 if (!dbret) {
173 return false;
174 }
175 }
176
177 /* Close the struct array */
178 dbret = dbus_message_iter_close_container(&iter, &array_iter);
179 if (!dbret) {
180 return false;
181 }
182
183 return true;
184 }
185
186 bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error)
187 {
188 DBusMessageIter iter;
189 DBusMessageIter array_iter;
190 DBusMessageIter struct_iter;
191 DBusMessageIter sub_iter;
192 int type;
193 int len;
194 const uint8_t *data;
195
196 if (!dbus_message_iter_init(msg, &iter)) {
197 DEBUG(1, ("pam response has no arguments.\n"));
198 return false;
199 }
200
201 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
202 DEBUG(1, ("pam response format error.\n"));
203 return false;
204 }
205 dbus_message_iter_get_basic(&iter, &(pd->pam_status));
206
207 if (!dbus_message_iter_next(&iter)) {
208 DEBUG(1, ("pam response has too few arguments.\n"));
209 return false;
210 }
211
212 /* After this point will be an array of pam data */
213 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
214 DEBUG(1, ("pam response format error.\n"));
215 DEBUG(1, ("Type was %c\n", (char)dbus_message_iter_get_arg_type(&iter)));
216 return false;
217 }
218
219 if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
220 DEBUG(1, ("pam response format error.\n"));
221 return false;
222 }
223
224 dbus_message_iter_recurse(&iter, &array_iter);
225 while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
226 /* Read in a pam data struct */
227 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
228 DEBUG(1, ("pam response format error.\n"));
229 return false;
230 }
231
232 dbus_message_iter_recurse(&array_iter, &struct_iter);
233
234 /* PAM data struct contains a type and a byte-array of data */
235
236 /* Get the pam data type */
237 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_UINT32) {
238 DEBUG(1, ("pam response format error.\n"));
239 return false;
240 }
241 dbus_message_iter_get_basic(&struct_iter, &type);
242
243 if (!dbus_message_iter_next(&struct_iter)) {
244 DEBUG(1, ("pam response format error.\n"));
245 return false;
246 }
247
248 /* Get the byte array */
249 if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_ARRAY ||
250 dbus_message_iter_get_element_type(&struct_iter) != DBUS_TYPE_BYTE) {
251 DEBUG(1, ("pam response format error.\n"));
252 return false;
253 }
254
255 dbus_message_iter_recurse(&struct_iter, &sub_iter);
256 dbus_message_iter_get_fixed_array(&sub_iter, &data, &len);
257
258 pam_add_response(pd, type, len, data);
259 dbus_message_iter_next(&array_iter);
260 }
261
262 return true;
263 }
264
265 void dp_id_callback(DBusPendingCall *pending, void *ptr)
266 {
267 DBusMessage *reply;
268 DBusError dbus_error;
269 dbus_bool_t ret;
270 dbus_uint16_t dp_ver;
271 int type;
272
273 dbus_error_init(&dbus_error);
274
275 reply = dbus_pending_call_steal_reply(pending);
276 if (!reply) {
277 /* reply should never be null. This function shouldn't be called
278 * until reply is valid or timeout has occurred. If reply is NULL
279 * here, something is seriously wrong and we should bail out.
280 */
281 DEBUG(0, ("Severe error. A reply callback was called but no"
282 " reply was received and no timeout occurred\n"));
283
284 /* FIXME: Destroy this connection ? */
285 goto done;
286 }
287
288 type = dbus_message_get_type(reply);
289 switch (type) {
290 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
291 ret = dbus_message_get_args(reply, &dbus_error,
292 DBUS_TYPE_UINT16, &dp_ver,
293 DBUS_TYPE_INVALID);
294 if (!ret) {
295 DEBUG(1, ("Failed to parse message\n"));
296 if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
297 /* FIXME: Destroy this connection ? */
298 goto done;
299 }
300
301 DEBUG(4, ("Got id ack and version (%d) from DP\n", dp_ver));
302
303 break;
304
305 case DBUS_MESSAGE_TYPE_ERROR:
306 DEBUG(0,("The Monitor returned an error [%s]\n",
307 dbus_message_get_error_name(reply)));
308 /* Falling through to default intentionally*/
309 default:
310 /*
311 * Timeout or other error occurred or something
312 * unexpected happened.
313 * It doesn't matter which, because either way we
314 * know that this connection isn't trustworthy.
315 * We'll destroy it now.
316 */
317
318 /* FIXME: Destroy this connection ? */
319 break;
320 }
321
322 done:
323 dbus_pending_call_unref(pending);
324 dbus_message_unref(reply);
325 }
326
327 int dp_common_send_id(struct sbus_connection *conn, uint16_t version,
328 const char *name)
329 {
330 DBusMessage *msg;
331 dbus_bool_t ret;
332 int retval;
333
334 /* create the message */
335 msg = dbus_message_new_method_call(NULL,
336 DP_PATH,
337 DP_INTERFACE,
338 DP_METHOD_REGISTER);
339 if (msg == NULL) {
340 DEBUG(0, ("Out of memory?!\n"));
341 return ENOMEM;
342 }
343
344 DEBUG(4, ("Sending ID to DP: (%d,%s)\n",
345 version, name));
346
347 ret = dbus_message_append_args(msg,
348 DBUS_TYPE_UINT16, &version,
349 DBUS_TYPE_STRING, &name,
350 DBUS_TYPE_INVALID);
351 if (!ret) {
352 DEBUG(1, ("Failed to build message\n"));
353 return EIO;
354 }
355
356 retval = sbus_conn_send(conn, msg, 30000, dp_id_callback, NULL, NULL);
357
358 dbus_message_unref(msg);
359 return retval;
360 }
361