D-Bus 1.4.10
|
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 if (!_dbus_string_init (&nonce)) 00141 return -1; 00142 //PENDING(kdab): set better errors 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->path, "/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); //we ignore possible errors deleting the dir and return the write error instead 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, /*use_subdir=*/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, /*use_subdir=*/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