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 _dbus_string_init (&nonce);
00141
00142 if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
00143 return -1;
00144 fd = _dbus_accept (listen_fd);
00145 if (_dbus_socket_is_invalid (fd))
00146 return fd;
00147 if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
00148 _dbus_verbose ("nonce check failed. Closing socket.\n");
00149 _dbus_close_socket(fd, NULL);
00150 return -1;
00151 }
00152
00153 return fd;
00154 }
00155
00156 static dbus_bool_t
00157 generate_and_write_nonce (const DBusString *filename, DBusError *error)
00158 {
00159 DBusString nonce;
00160 dbus_bool_t ret;
00161
00162 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00163
00164 _dbus_string_init (&nonce);
00165
00166 if (!_dbus_generate_random_bytes (&nonce, 16))
00167 {
00168 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00169 _dbus_string_free (&nonce);
00170 return FALSE;
00171 }
00172
00173 ret = _dbus_string_save_to_file (&nonce, filename, FALSE, error);
00174
00175 _dbus_string_free (&nonce);
00176
00177 return ret;
00178 }
00179
00189 dbus_bool_t
00190 _dbus_send_nonce (int fd, const DBusString *noncefile, DBusError *error)
00191 {
00192 dbus_bool_t read_result;
00193 int send_result;
00194 size_t sendLen;
00195 DBusString nonce;
00196
00197 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00198
00199 if (_dbus_string_get_length (noncefile) == 0)
00200 return FALSE;
00201
00202 if (!_dbus_string_init (&nonce))
00203 {
00204 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00205 return FALSE;
00206 }
00207
00208 read_result = _dbus_read_nonce (noncefile, &nonce, error);
00209 if (!read_result)
00210 {
00211 _DBUS_ASSERT_ERROR_IS_SET (error);
00212 _dbus_string_free (&nonce);
00213 return FALSE;
00214 }
00215 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00216
00217 send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce));
00218
00219 _dbus_string_free (&nonce);
00220
00221 if (send_result == -1)
00222 {
00223 dbus_set_error (error,
00224 _dbus_error_from_system_errno (),
00225 "Failed to send nonce (fd=%d): %s",
00226 fd, _dbus_strerror_from_errno ());
00227 return FALSE;
00228 }
00229
00230 return TRUE;
00231 }
00232
00233 static dbus_bool_t
00234 do_noncefile_create (DBusNonceFile *noncefile,
00235 DBusError *error,
00236 dbus_bool_t use_subdir)
00237 {
00238 dbus_bool_t ret;
00239 DBusString randomStr;
00240
00241 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00242
00243 _dbus_assert (noncefile);
00244
00245 if (!_dbus_string_init (&randomStr))
00246 {
00247 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00248 goto on_error;
00249 }
00250
00251 if (!_dbus_generate_random_ascii (&randomStr, 8))
00252 {
00253 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00254 goto on_error;
00255 }
00256
00257 if (!_dbus_string_init (&noncefile->dir)
00258 || !_dbus_string_append (&noncefile->dir, _dbus_get_tmpdir()))
00259 {
00260 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00261 goto on_error;
00262 }
00263 if (use_subdir)
00264 {
00265 if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-")
00266 || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) )
00267 {
00268 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00269 goto on_error;
00270 }
00271 if (!_dbus_string_init (&noncefile->path)
00272 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00273 || !_dbus_string_append (&noncefile->dir, "/nonce"))
00274 {
00275 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00276 goto on_error;
00277 }
00278 if (!_dbus_create_directory (&noncefile->dir, error))
00279 {
00280 _DBUS_ASSERT_ERROR_IS_SET (error);
00281 goto on_error;
00282 }
00283 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00284
00285 }
00286 else
00287 {
00288 if (!_dbus_string_init (&noncefile->path)
00289 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
00290 || !_dbus_string_append (&noncefile->path, "/dbus_nonce-")
00291 || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr)))
00292 {
00293 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00294 goto on_error;
00295 }
00296
00297 }
00298
00299 if (!generate_and_write_nonce (&noncefile->path, error))
00300 {
00301 _DBUS_ASSERT_ERROR_IS_SET (error);
00302 if (use_subdir)
00303 _dbus_delete_directory (&noncefile->dir, NULL);
00304 goto on_error;
00305 }
00306 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00307
00308 _dbus_string_free (&randomStr);
00309
00310 return TRUE;
00311 on_error:
00312 if (use_subdir)
00313 _dbus_delete_directory (&noncefile->dir, NULL);
00314 _dbus_string_free (&noncefile->dir);
00315 _dbus_string_free (&noncefile->path);
00316 _dbus_string_free (&randomStr);
00317 return FALSE;
00318 }
00319
00320 #ifdef DBUS_WIN
00321
00328 dbus_bool_t
00329 _dbus_noncefile_create (DBusNonceFile *noncefile,
00330 DBusError *error)
00331 {
00332 return do_noncefile_create (noncefile, error, FALSE);
00333 }
00334
00342 dbus_bool_t
00343 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00344 DBusError *error)
00345 {
00346 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00347
00348 _dbus_delete_file (&noncefile->path, error);
00349 _dbus_string_free (&noncefile->dir);
00350 _dbus_string_free (&noncefile->path);
00351 return TRUE;
00352 }
00353
00354 #else
00355
00363 dbus_bool_t
00364 _dbus_noncefile_create (DBusNonceFile *noncefile,
00365 DBusError *error)
00366 {
00367 return do_noncefile_create (noncefile, error, TRUE);
00368 }
00369
00377 dbus_bool_t
00378 _dbus_noncefile_delete (DBusNonceFile *noncefile,
00379 DBusError *error)
00380 {
00381 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00382
00383 _dbus_delete_directory (&noncefile->dir, error);
00384 _dbus_string_free (&noncefile->dir);
00385 _dbus_string_free (&noncefile->path);
00386 return TRUE;
00387 }
00388 #endif
00389
00390
00397 const DBusString*
00398 _dbus_noncefile_get_path (const DBusNonceFile *noncefile)
00399 {
00400 _dbus_assert (noncefile);
00401 return &noncefile->path;
00402 }
00403
00414 dbus_bool_t
00415 _dbus_noncefile_check_nonce (int fd,
00416 const DBusNonceFile *noncefile,
00417 DBusError* error)
00418 {
00419 return do_check_nonce (fd, _dbus_noncefile_get_path (noncefile), error);
00420 }
00421
00422