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 DBusString nonce;
00200
00201 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00202
00203 if (_dbus_string_get_length (noncefile) == 0)
00204 return FALSE;
00205
00206 if (!_dbus_string_init (&nonce))
00207 {
00208 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00209 return FALSE;
00210 }
00211
00212 read_result = _dbus_read_nonce (noncefile, &nonce, error);
00213 if (!read_result)
00214 {
00215 _DBUS_ASSERT_ERROR_IS_SET (error);
00216 _dbus_string_free (&nonce);
00217 return FALSE;
00218 }
00219 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00220
00221 send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce));
00222
00223 _dbus_string_free (&nonce);
00224
00225 if (send_result == -1)
00226 {
00227 dbus_set_error (error,
00228 _dbus_error_from_system_errno (),
00229 "Failed to send nonce (fd=%d): %s",
00230 fd, _dbus_strerror_from_errno ());
00231 return FALSE;
00232 }
00233
00234 return TRUE;
00235 }
00236
00237 static dbus_bool_t
00238 do_noncefile_create (DBusNonceFile *noncefile,
00239 DBusError *error,
00240 dbus_bool_t use_subdir)
00241 {
00242 DBusString randomStr;
00243
00244 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00245
00246 _dbus_assert (noncefile);
00247
00248 if (!_dbus_string_init (&randomStr))
00249 {
00250 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00251 goto on_error;
00252 }
00253
00254 if (!_dbus_generate_random_ascii (&randomStr, 8))
00255 {
00256 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00257 goto on_error;
00258 }
00259
00260 if (!_dbus_string_init (&noncefile->dir)
00261 || !_dbus_string_append (&noncefile->dir, _dbus_get_tmpdir()))
00262 {
00263 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00264 goto on_error;
00265 }
00266 if (use_subdir)
00267 {
00268 if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-")
00269 || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) )
00270 {
00271 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00272 goto on_error;
00273 }
00274 if (!_dbus_string_init (&noncefile->path)
00275 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00276 || !_dbus_string_append (&noncefile->path, "/nonce"))
00277 {
00278 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00279 goto on_error;
00280 }
00281 if (!_dbus_create_directory (&noncefile->dir, error))
00282 {
00283 _DBUS_ASSERT_ERROR_IS_SET (error);
00284 goto on_error;
00285 }
00286 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00287
00288 }
00289 else
00290 {
00291 if (!_dbus_string_init (&noncefile->path)
00292 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00293 || !_dbus_string_append (&noncefile->path, "/dbus_nonce-")
00294 || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr)))
00295 {
00296 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00297 goto on_error;
00298 }
00299
00300 }
00301
00302 if (!generate_and_write_nonce (&noncefile->path, error))
00303 {
00304 _DBUS_ASSERT_ERROR_IS_SET (error);
00305 if (use_subdir)
00306 _dbus_delete_directory (&noncefile->dir, NULL);
00307 goto on_error;
00308 }
00309 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00310
00311 _dbus_string_free (&randomStr);
00312
00313 return TRUE;
00314 on_error:
00315 if (use_subdir)
00316 _dbus_delete_directory (&noncefile->dir, NULL);
00317 _dbus_string_free (&noncefile->dir);
00318 _dbus_string_free (&noncefile->path);
00319 _dbus_string_free (&randomStr);
00320 return FALSE;
00321 }
00322
00323 #ifdef DBUS_WIN
00324
00331 dbus_bool_t
00332 _dbus_noncefile_create (DBusNonceFile *noncefile,
00333 DBusError *error)
00334 {
00335 return do_noncefile_create (noncefile, error, FALSE);
00336 }
00337
00345 dbus_bool_t
00346 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00347 DBusError *error)
00348 {
00349 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00350
00351 _dbus_delete_file (&noncefile->path, error);
00352 _dbus_string_free (&noncefile->dir);
00353 _dbus_string_free (&noncefile->path);
00354 return TRUE;
00355 }
00356
00357 #else
00358
00366 dbus_bool_t
00367 _dbus_noncefile_create (DBusNonceFile *noncefile,
00368 DBusError *error)
00369 {
00370 return do_noncefile_create (noncefile, error, TRUE);
00371 }
00372
00380 dbus_bool_t
00381 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00382 DBusError *error)
00383 {
00384 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00385
00386 _dbus_delete_directory (&noncefile->dir, error);
00387 _dbus_string_free (&noncefile->dir);
00388 _dbus_string_free (&noncefile->path);
00389 return TRUE;
00390 }
00391 #endif
00392
00393
00400 const DBusString*
00401 _dbus_noncefile_get_path (const DBusNonceFile *noncefile)
00402 {
00403 _dbus_assert (noncefile);
00404 return &noncefile->path;
00405 }
00406
00417 dbus_bool_t
00418 _dbus_noncefile_check_nonce (int fd,
00419 const DBusNonceFile *noncefile,
00420 DBusError* error)
00421 {
00422 return do_check_nonce (fd, _dbus_noncefile_get_path (noncefile), error);
00423 }
00424
00425