D-Bus 1.4.0
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-nonce.c Nonce handling functions used by nonce-tcp (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 // major sections of this file are modified code from libassuan, (C) FSF 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 //PENDING(kdab): set better errors 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); //we ignore possible errors deleting the dir and return the write error instead 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, /*use_subdir=*/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, /*use_subdir=*/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