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 (int 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 n = _dbus_read_socket (fd, &p, nleft);
00057 if (n == -1 && _dbus_get_is_errno_eintr())
00058 ;
00059 else if (n == -1 && _dbus_get_is_errno_eagain_or_ewouldblock())
00060 _dbus_sleep_milliseconds (100);
00061 else if (n==-1)
00062 {
00063 dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
00064 _dbus_string_free (&p);
00065 _dbus_string_free (&buffer);
00066 return FALSE;
00067 }
00068 else if (!n)
00069 {
00070 _dbus_string_free (&p);
00071 _dbus_string_free (&buffer);
00072 dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
00073 return FALSE;
00074 }
00075 else
00076 {
00077 _dbus_string_append_len(&buffer, _dbus_string_get_const_data (&p), n);
00078 nleft -= n;
00079 }
00080 }
00081
00082 result = _dbus_string_equal_len (&buffer, nonce, 16);
00083 if (!result)
00084 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Nonces do not match, access denied (fd=%d)", fd );
00085
00086 _dbus_string_free (&p);
00087 _dbus_string_free (&buffer);
00088
00089 return result;
00090 }
00091
00100 dbus_bool_t
00101 _dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error)
00102 {
00103 FILE *fp;
00104 char buffer[17];
00105 size_t nread;
00106
00107 buffer[sizeof buffer - 1] = '\0';
00108
00109 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00110
00111 _dbus_verbose ("reading nonce from file: %s\n", _dbus_string_get_const_data (fname));
00112
00113
00114 fp = fopen (_dbus_string_get_const_data (fname), "rb");
00115 if (!fp)
00116 return FALSE;
00117 nread = fread (buffer, 1, sizeof buffer - 1, fp);
00118 fclose (fp);
00119 if (!nread)
00120 {
00121 dbus_set_error (error, DBUS_ERROR_FILE_NOT_FOUND, "Could not read nonce from file %s", _dbus_string_get_const_data (fname));
00122 return FALSE;
00123 }
00124
00125 if (!_dbus_string_append_len (nonce, buffer, sizeof buffer - 1 ))
00126 {
00127 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00128 return FALSE;
00129 }
00130 return TRUE;
00131 }
00132
00133 int
00134 _dbus_accept_with_noncefile (int listen_fd, const DBusNonceFile *noncefile)
00135 {
00136 int fd;
00137 DBusString nonce;
00138
00139 _dbus_assert (noncefile != NULL);
00140 if (!_dbus_string_init (&nonce))
00141 return -1;
00142
00143 if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
00144 return -1;
00145 fd = _dbus_accept (listen_fd);
00146 if (_dbus_socket_is_invalid (fd))
00147 return fd;
00148 if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
00149 _dbus_verbose ("nonce check failed. Closing socket.\n");
00150 _dbus_close_socket(fd, NULL);
00151 return -1;
00152 }
00153
00154 return fd;
00155 }
00156
00157 static dbus_bool_t
00158 generate_and_write_nonce (const DBusString *filename, DBusError *error)
00159 {
00160 DBusString nonce;
00161 dbus_bool_t ret;
00162
00163 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00164
00165 if (!_dbus_string_init (&nonce))
00166 {
00167 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00168 return FALSE;
00169 }
00170
00171 if (!_dbus_generate_random_bytes (&nonce, 16))
00172 {
00173 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00174 _dbus_string_free (&nonce);
00175 return FALSE;
00176 }
00177
00178 ret = _dbus_string_save_to_file (&nonce, filename, FALSE, error);
00179
00180 _dbus_string_free (&nonce);
00181
00182 return ret;
00183 }
00184
00194 dbus_bool_t
00195 _dbus_send_nonce (int fd, const DBusString *noncefile, DBusError *error)
00196 {
00197 dbus_bool_t read_result;
00198 int send_result;
00199 size_t sendLen;
00200 DBusString nonce;
00201
00202 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00203
00204 if (_dbus_string_get_length (noncefile) == 0)
00205 return FALSE;
00206
00207 if (!_dbus_string_init (&nonce))
00208 {
00209 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00210 return FALSE;
00211 }
00212
00213 read_result = _dbus_read_nonce (noncefile, &nonce, error);
00214 if (!read_result)
00215 {
00216 _DBUS_ASSERT_ERROR_IS_SET (error);
00217 _dbus_string_free (&nonce);
00218 return FALSE;
00219 }
00220 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00221
00222 send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce));
00223
00224 _dbus_string_free (&nonce);
00225
00226 if (send_result == -1)
00227 {
00228 dbus_set_error (error,
00229 _dbus_error_from_system_errno (),
00230 "Failed to send nonce (fd=%d): %s",
00231 fd, _dbus_strerror_from_errno ());
00232 return FALSE;
00233 }
00234
00235 return TRUE;
00236 }
00237
00238 static dbus_bool_t
00239 do_noncefile_create (DBusNonceFile *noncefile,
00240 DBusError *error,
00241 dbus_bool_t use_subdir)
00242 {
00243 dbus_bool_t ret;
00244 DBusString randomStr;
00245
00246 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00247
00248 _dbus_assert (noncefile);
00249
00250 if (!_dbus_string_init (&randomStr))
00251 {
00252 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00253 goto on_error;
00254 }
00255
00256 if (!_dbus_generate_random_ascii (&randomStr, 8))
00257 {
00258 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00259 goto on_error;
00260 }
00261
00262 if (!_dbus_string_init (&noncefile->dir)
00263 || !_dbus_string_append (&noncefile->dir, _dbus_get_tmpdir()))
00264 {
00265 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00266 goto on_error;
00267 }
00268 if (use_subdir)
00269 {
00270 if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-")
00271 || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) )
00272 {
00273 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00274 goto on_error;
00275 }
00276 if (!_dbus_string_init (&noncefile->path)
00277 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00278 || !_dbus_string_append (&noncefile->dir, "/nonce"))
00279 {
00280 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00281 goto on_error;
00282 }
00283 if (!_dbus_create_directory (&noncefile->dir, error))
00284 {
00285 _DBUS_ASSERT_ERROR_IS_SET (error);
00286 goto on_error;
00287 }
00288 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00289
00290 }
00291 else
00292 {
00293 if (!_dbus_string_init (&noncefile->path)
00294 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00295 || !_dbus_string_append (&noncefile->path, "/dbus_nonce-")
00296 || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr)))
00297 {
00298 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00299 goto on_error;
00300 }
00301
00302 }
00303
00304 if (!generate_and_write_nonce (&noncefile->path, error))
00305 {
00306 _DBUS_ASSERT_ERROR_IS_SET (error);
00307 if (use_subdir)
00308 _dbus_delete_directory (&noncefile->dir, NULL);
00309 goto on_error;
00310 }
00311 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00312
00313 _dbus_string_free (&randomStr);
00314
00315 return TRUE;
00316 on_error:
00317 if (use_subdir)
00318 _dbus_delete_directory (&noncefile->dir, NULL);
00319 _dbus_string_free (&noncefile->dir);
00320 _dbus_string_free (&noncefile->path);
00321 _dbus_string_free (&randomStr);
00322 return FALSE;
00323 }
00324
00325 #ifdef DBUS_WIN
00326
00333 dbus_bool_t
00334 _dbus_noncefile_create (DBusNonceFile *noncefile,
00335 DBusError *error)
00336 {
00337 return do_noncefile_create (noncefile, error, FALSE);
00338 }
00339
00347 dbus_bool_t
00348 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00349 DBusError *error)
00350 {
00351 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00352
00353 _dbus_delete_file (&noncefile->path, error);
00354 _dbus_string_free (&noncefile->dir);
00355 _dbus_string_free (&noncefile->path);
00356 return TRUE;
00357 }
00358
00359 #else
00360
00368 dbus_bool_t
00369 _dbus_noncefile_create (DBusNonceFile *noncefile,
00370 DBusError *error)
00371 {
00372 return do_noncefile_create (noncefile, error, TRUE);
00373 }
00374
00382 dbus_bool_t
00383 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00384 DBusError *error)
00385 {
00386 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00387
00388 _dbus_delete_directory (&noncefile->dir, error);
00389 _dbus_string_free (&noncefile->dir);
00390 _dbus_string_free (&noncefile->path);
00391 return TRUE;
00392 }
00393 #endif
00394
00395
00402 const DBusString*
00403 _dbus_noncefile_get_path (const DBusNonceFile *noncefile)
00404 {
00405 _dbus_assert (noncefile);
00406 return &noncefile->path;
00407 }
00408
00419 dbus_bool_t
00420 _dbus_noncefile_check_nonce (int fd,
00421 const DBusNonceFile *noncefile,
00422 DBusError* error)
00423 {
00424 return do_check_nonce (fd, _dbus_noncefile_get_path (noncefile), error);
00425 }
00426
00427