00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025
00026 #include "dbus-nonce.h"
00027 #include "dbus-internals.h"
00028 #include "dbus-protocol.h"
00029 #include "dbus-sysdeps.h"
00030
00031 #include <stdio.h>
00032
00033 static dbus_bool_t
00034 do_check_nonce (DBusSocket fd, const DBusString *nonce, DBusError *error)
00035 {
00036 DBusString buffer;
00037 DBusString p;
00038 size_t nleft;
00039 dbus_bool_t result;
00040 int n;
00041
00042 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00043
00044 nleft = 16;
00045
00046 if ( !_dbus_string_init (&buffer)
00047 || !_dbus_string_init (&p) ) {
00048 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00049 _dbus_string_free (&p);
00050 _dbus_string_free (&buffer);
00051 return FALSE;
00052 }
00053
00054 while (nleft)
00055 {
00056 int saved_errno;
00057
00058 n = _dbus_read_socket (fd, &p, nleft);
00059 saved_errno = _dbus_save_socket_errno ();
00060
00061 if (n == -1 && _dbus_get_is_errno_eintr (saved_errno))
00062 ;
00063 else if (n == -1 && _dbus_get_is_errno_eagain_or_ewouldblock (saved_errno))
00064 _dbus_sleep_milliseconds (100);
00065 else if (n==-1)
00066 {
00067 dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
00068 _dbus_string_free (&p);
00069 _dbus_string_free (&buffer);
00070 return FALSE;
00071 }
00072 else if (!n)
00073 {
00074 _dbus_string_free (&p);
00075 _dbus_string_free (&buffer);
00076 dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
00077 return FALSE;
00078 }
00079 else
00080 {
00081 if (!_dbus_string_append_len (&buffer, _dbus_string_get_const_data (&p), n))
00082 {
00083 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00084 _dbus_string_free (&p);
00085 _dbus_string_free (&buffer);
00086 return FALSE;
00087 }
00088 nleft -= n;
00089 }
00090 }
00091
00092 result = _dbus_string_equal_len (&buffer, nonce, 16);
00093 if (!result)
00094 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Nonces do not match, access denied (fd=%d)", fd );
00095
00096 _dbus_string_free (&p);
00097 _dbus_string_free (&buffer);
00098
00099 return result;
00100 }
00101
00110 dbus_bool_t
00111 _dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error)
00112 {
00113 FILE *fp;
00114 char buffer[17];
00115 size_t nread;
00116
00117 buffer[sizeof buffer - 1] = '\0';
00118
00119 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00120
00121 _dbus_verbose ("reading nonce from file: %s\n", _dbus_string_get_const_data (fname));
00122
00123
00124 fp = fopen (_dbus_string_get_const_data (fname), "rb");
00125 if (!fp)
00126 {
00127 dbus_set_error (error,
00128 _dbus_error_from_system_errno (),
00129 "Failed to open %s for read: %s",
00130 _dbus_string_get_const_data (fname),
00131 _dbus_strerror_from_errno ());
00132 return FALSE;
00133 }
00134
00135 nread = fread (buffer, 1, sizeof buffer - 1, fp);
00136 fclose (fp);
00137 if (!nread)
00138 {
00139 dbus_set_error (error, DBUS_ERROR_FILE_NOT_FOUND, "Could not read nonce from file %s", _dbus_string_get_const_data (fname));
00140 return FALSE;
00141 }
00142
00143 if (!_dbus_string_append_len (nonce, buffer, sizeof buffer - 1 ))
00144 {
00145 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00146 return FALSE;
00147 }
00148 return TRUE;
00149 }
00150
00151 DBusSocket
00152 _dbus_accept_with_noncefile (DBusSocket listen_fd, const DBusNonceFile *noncefile)
00153 {
00154 DBusSocket fd;
00155 DBusString nonce;
00156
00157 _dbus_assert (noncefile != NULL);
00158 if (!_dbus_string_init (&nonce))
00159 return _dbus_socket_get_invalid ();
00160
00161 if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
00162 return _dbus_socket_get_invalid ();
00163 fd = _dbus_accept (listen_fd);
00164 if (!_dbus_socket_is_valid (fd))
00165 return fd;
00166 if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
00167 _dbus_verbose ("nonce check failed. Closing socket.\n");
00168 _dbus_close_socket(fd, NULL);
00169 return _dbus_socket_get_invalid ();
00170 }
00171
00172 return fd;
00173 }
00174
00175 static dbus_bool_t
00176 generate_and_write_nonce (const DBusString *filename, DBusError *error)
00177 {
00178 DBusString nonce;
00179 dbus_bool_t ret;
00180
00181 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00182
00183 if (!_dbus_string_init (&nonce))
00184 {
00185 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00186 return FALSE;
00187 }
00188
00189 if (!_dbus_generate_random_bytes (&nonce, 16, error))
00190 {
00191 _dbus_string_free (&nonce);
00192 return FALSE;
00193 }
00194
00195 ret = _dbus_string_save_to_file (&nonce, filename, FALSE, error);
00196
00197 _dbus_string_free (&nonce);
00198
00199 return ret;
00200 }
00201
00211 dbus_bool_t
00212 _dbus_send_nonce (DBusSocket fd,
00213 const DBusString *noncefile,
00214 DBusError *error)
00215 {
00216 dbus_bool_t read_result;
00217 int send_result;
00218 DBusString nonce;
00219
00220 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00221
00222 if (_dbus_string_get_length (noncefile) == 0)
00223 return FALSE;
00224
00225 if (!_dbus_string_init (&nonce))
00226 {
00227 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00228 return FALSE;
00229 }
00230
00231 read_result = _dbus_read_nonce (noncefile, &nonce, error);
00232 if (!read_result)
00233 {
00234 _DBUS_ASSERT_ERROR_IS_SET (error);
00235 _dbus_string_free (&nonce);
00236 return FALSE;
00237 }
00238 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00239
00240 send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce));
00241
00242 _dbus_string_free (&nonce);
00243
00244 if (send_result == -1)
00245 {
00246 dbus_set_error (error,
00247 _dbus_error_from_system_errno (),
00248 "Failed to send nonce (fd=%d): %s",
00249 fd, _dbus_strerror_from_errno ());
00250 return FALSE;
00251 }
00252
00253 return TRUE;
00254 }
00255
00256 static dbus_bool_t
00257 do_noncefile_create (DBusNonceFile *noncefile,
00258 DBusError *error,
00259 dbus_bool_t use_subdir)
00260 {
00261 DBusString randomStr;
00262 const char *tmp;
00263
00264 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00265
00266 _dbus_assert (noncefile);
00267
00268 if (!_dbus_string_init (&randomStr))
00269 {
00270 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00271 goto on_error;
00272 }
00273
00274 if (!_dbus_generate_random_ascii (&randomStr, 8, error))
00275 {
00276 goto on_error;
00277 }
00278
00279 tmp = _dbus_get_tmpdir ();
00280
00281 if (!_dbus_string_init (&noncefile->dir)
00282 || tmp == NULL
00283 || !_dbus_string_append (&noncefile->dir, tmp))
00284 {
00285 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00286 goto on_error;
00287 }
00288 if (use_subdir)
00289 {
00290 if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-")
00291 || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) )
00292 {
00293 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00294 goto on_error;
00295 }
00296 if (!_dbus_string_init (&noncefile->path)
00297 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00298 || !_dbus_string_append (&noncefile->path, "/nonce"))
00299 {
00300 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00301 goto on_error;
00302 }
00303 if (!_dbus_create_directory (&noncefile->dir, error))
00304 {
00305 _DBUS_ASSERT_ERROR_IS_SET (error);
00306 goto on_error;
00307 }
00308 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00309
00310 }
00311 else
00312 {
00313 if (!_dbus_string_init (&noncefile->path)
00314 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00315 || !_dbus_string_append (&noncefile->path, "/dbus_nonce-")
00316 || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr)))
00317 {
00318 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00319 goto on_error;
00320 }
00321
00322 }
00323
00324 if (!generate_and_write_nonce (&noncefile->path, error))
00325 {
00326 _DBUS_ASSERT_ERROR_IS_SET (error);
00327 if (use_subdir)
00328 _dbus_delete_directory (&noncefile->dir, NULL);
00329 goto on_error;
00330 }
00331 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00332
00333 _dbus_string_free (&randomStr);
00334
00335 return TRUE;
00336 on_error:
00337 if (use_subdir)
00338 _dbus_delete_directory (&noncefile->dir, NULL);
00339 _dbus_string_free (&noncefile->dir);
00340 _dbus_string_free (&noncefile->path);
00341 _dbus_string_free (&randomStr);
00342 return FALSE;
00343 }
00344
00345 #ifdef DBUS_WIN
00346
00353 dbus_bool_t
00354 _dbus_noncefile_create (DBusNonceFile *noncefile,
00355 DBusError *error)
00356 {
00357 return do_noncefile_create (noncefile, error, FALSE);
00358 }
00359
00367 dbus_bool_t
00368 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00369 DBusError *error)
00370 {
00371 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00372
00373 _dbus_delete_file (&noncefile->path, error);
00374 _dbus_string_free (&noncefile->dir);
00375 _dbus_string_free (&noncefile->path);
00376 return TRUE;
00377 }
00378
00379 #else
00380
00388 dbus_bool_t
00389 _dbus_noncefile_create (DBusNonceFile *noncefile,
00390 DBusError *error)
00391 {
00392 return do_noncefile_create (noncefile, error, TRUE);
00393 }
00394
00402 dbus_bool_t
00403 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00404 DBusError *error)
00405 {
00406 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00407
00408 _dbus_delete_directory (&noncefile->dir, error);
00409 _dbus_string_free (&noncefile->dir);
00410 _dbus_string_free (&noncefile->path);
00411 return TRUE;
00412 }
00413 #endif
00414
00415
00422 const DBusString*
00423 _dbus_noncefile_get_path (const DBusNonceFile *noncefile)
00424 {
00425 _dbus_assert (noncefile);
00426 return &noncefile->path;
00427 }
00428
00439 dbus_bool_t
00440 _dbus_noncefile_check_nonce (DBusSocket fd,
00441 const DBusNonceFile *noncefile,
00442 DBusError* error)
00443 {
00444 return do_check_nonce (fd, _dbus_noncefile_get_path (noncefile), error);
00445 }
00446
00447