1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-nonce.c Nonce handling functions used by nonce-tcp (internal to D-Bus implementation)
4 * Copyright (C) 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
6 * Licensed under the Academic Free License version 2.1
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 2 of the License, or
11 * (at your option) any later version.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 // major sections of this file are modified code from libassuan, (C) FSF
25 #include "dbus-nonce.h"
26 #include "dbus-internals.h"
27 #include "dbus-protocol.h"
28 #include "dbus-sysdeps.h"
37 do_check_nonce (int fd, const DBusString *nonce, DBusError *error)
45 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
49 if ( !_dbus_string_init (&buffer)
50 || !_dbus_string_init (&p) ) {
51 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
52 _dbus_string_free (&p);
53 _dbus_string_free (&buffer);
59 n = _dbus_read_socket (fd, &p, nleft);
60 if (n == -1 && _dbus_get_is_errno_eintr())
62 else if (n == -1 && _dbus_get_is_errno_eagain_or_ewouldblock())
63 _dbus_sleep_milliseconds (100);
66 dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
67 _dbus_string_free (&p);
68 _dbus_string_free (&buffer);
73 _dbus_string_free (&p);
74 _dbus_string_free (&buffer);
75 dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
80 _dbus_string_append_len(&buffer, _dbus_string_get_const_data (&p), n);
85 result = _dbus_string_equal_len (&buffer, nonce, 16);
87 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Nonces do not match, access denied (fd=%d)", fd );
89 _dbus_string_free (&p);
90 _dbus_string_free (&buffer);
96 * reads the nonce from the nonce file and stores it in a string
98 * @param fname the file to read the nonce from
99 * @param nonce returns the nonce. Must be an initialized string, the nonce will be appended.
100 * @param error error object to report possible errors
101 * @return FALSE iff reading the nonce fails (error is set then)
104 _dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error)
110 buffer[sizeof buffer - 1] = '\0';
112 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
114 _dbus_verbose ("reading nonce from file: %s\n", _dbus_string_get_const_data (fname));
117 fp = fopen (_dbus_string_get_const_data (fname), "rb");
120 nread = fread (buffer, 1, sizeof buffer - 1, fp);
124 dbus_set_error (error, DBUS_ERROR_FILE_NOT_FOUND, "Could not read nonce from file %s", _dbus_string_get_const_data (fname));
128 if (!_dbus_string_append_len (nonce, buffer, sizeof buffer - 1 ))
130 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
137 accept_with_nonce (int listen_fd, const DBusString *nonce)
143 _dbus_accept_with_noncefile (int listen_fd, const DBusNonceFile *noncefile)
148 _dbus_assert (noncefile != NULL);
149 _dbus_string_init (&nonce);
150 //PENDING(kdab): set better errors
151 if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
153 fd = _dbus_accept (listen_fd);
154 if (_dbus_socket_is_invalid (fd))
156 if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
157 _dbus_verbose ("nonce check failed. Closing socket.\n");
158 _dbus_close_socket(fd, NULL);
166 generate_and_write_nonce (const DBusString *filename, DBusError *error)
171 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
173 _dbus_string_init (&nonce);
175 if (!_dbus_generate_random_bytes (&nonce, 16))
177 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
178 _dbus_string_free (&nonce);
182 ret = _dbus_string_save_to_file (&nonce, filename, error);
184 _dbus_string_free (&nonce);
190 * sends the nonce over a given socket. Blocks while doing so.
192 * @param fd the file descriptor to write the nonce data to (usually a socket)
193 * @param noncefile the noncefile location to read the nonce from
194 * @param error contains error details if FALSE is returned
195 * @return TRUE iff the nonce was successfully sent. Note that this does not
196 * indicate whether the server accepted the nonce.
199 _dbus_send_nonce(int fd, const DBusString *noncefile, DBusError *error)
201 dbus_bool_t read_result;
206 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
208 if (_dbus_string_get_length (noncefile) == 0)
211 if ( !_dbus_string_init (&nonce) )
213 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
217 read_result = _dbus_read_nonce (noncefile, &nonce, NULL);
221 dbus_set_error (error,
222 _dbus_error_from_errno (errno),
223 "Could not read nonce from file %s (%s)",
224 _dbus_string_get_const_data (noncefile), _dbus_strerror(errno));
225 _dbus_string_free (&nonce);
229 send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce));
231 _dbus_string_free (&nonce);
233 if (send_result == -1)
235 dbus_set_error (error,
236 _dbus_error_from_errno (errno),
237 "Failed to send nonce (fd=%d): %s",
238 fd, _dbus_strerror(errno));
246 do_noncefile_create (DBusNonceFile *noncefile,
248 dbus_bool_t use_subdir)
251 DBusString randomStr;
253 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
255 _dbus_assert (noncefile);
257 if (!_dbus_string_init (&randomStr))
259 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
263 if (!_dbus_generate_random_ascii (&randomStr, 8))
265 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
269 if (!_dbus_string_init (&noncefile->dir)
270 || !_dbus_string_append (&noncefile->dir, _dbus_get_tmpdir()))
272 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
277 if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-")
278 || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) )
280 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
283 if (!_dbus_string_init (&noncefile->path)
284 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
285 || !_dbus_string_append (&noncefile->dir, "/nonce"))
287 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
290 if (!_dbus_create_directory (&noncefile->dir, error))
298 if (!_dbus_string_init (&noncefile->path)
299 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
300 || !_dbus_string_append (&noncefile->path, "/dbus_nonce-")
301 || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr)))
303 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
309 if (!generate_and_write_nonce (&noncefile->path, error))
312 _dbus_delete_directory (&noncefile->dir, NULL); //we ignore possible errors deleting the dir and return the write error instead
316 _dbus_string_free (&randomStr);
321 _dbus_delete_directory (&noncefile->dir, NULL);
322 _dbus_string_free (&noncefile->dir);
323 _dbus_string_free (&noncefile->path);
324 _dbus_string_free (&randomStr);
330 * creates a nonce file in a user-readable location and writes a generated nonce to it
332 * @param noncefile returns the nonce file location
333 * @param error error details if creating the nonce file fails
334 * @return TRUE iff the nonce file was successfully created
337 _dbus_noncefile_create (DBusNonceFile *noncefile,
340 return do_noncefile_create (noncefile, error, /*use_subdir=*/FALSE);
344 * deletes the noncefile and frees the DBusNonceFile object.
346 * @param noncefile the nonce file to delete. Contents will be freed.
347 * @param error error details if the nonce file could not be deleted
351 _dbus_noncefile_delete (DBusNonceFile *noncefile,
354 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
356 _dbus_delete_file (&noncefile->path, error);
357 _dbus_string_free (&noncefile->dir);
358 _dbus_string_free (&noncefile->path);
364 * creates a nonce file in a user-readable location and writes a generated nonce to it.
365 * Initializes the noncefile object.
367 * @param noncefile returns the nonce file location
368 * @param error error details if creating the nonce file fails
369 * @return TRUE iff the nonce file was successfully created
372 _dbus_noncefile_create (DBusNonceFile *noncefile,
375 return do_noncefile_create (noncefile, error, /*use_subdir=*/TRUE);
379 * deletes the noncefile and frees the DBusNonceFile object.
381 * @param noncefile the nonce file to delete. Contents will be freed.
382 * @param error error details if the nonce file could not be deleted
386 _dbus_noncefile_delete (DBusNonceFile *noncefile,
389 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
391 _dbus_delete_directory (&noncefile->dir, error);
392 _dbus_string_free (&noncefile->dir);
393 _dbus_string_free (&noncefile->path);
400 * returns the absolute file path of the nonce file
402 * @param noncefile an initialized noncefile object
403 * @return the absolute path of the nonce file
406 _dbus_noncefile_get_path (const DBusNonceFile *noncefile)
408 _dbus_assert (noncefile);
409 return &noncefile->path;
413 * reads data from a file descriptor and checks if the received data matches
414 * the data in the given noncefile.
416 * @param fd the file descriptor to read the nonce from
417 * @param noncefile the nonce file to check the received data against
418 * @param error error details on fail
419 * @return TRUE iff a nonce could be successfully read from the file descriptor
420 * and matches the nonce from the given nonce file
423 _dbus_noncefile_check_nonce (int fd,
424 const DBusNonceFile *noncefile,
427 return do_check_nonce (fd, _dbus_noncefile_get_path (noncefile), error);
431 /** @} end of nonce */