|
D-Bus
1.8.20
|
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 if (!_dbus_string_append_len (&buffer, _dbus_string_get_const_data (&p), n)) 00078 { 00079 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00080 _dbus_string_free (&p); 00081 _dbus_string_free (&buffer); 00082 return FALSE; 00083 } 00084 nleft -= n; 00085 } 00086 } 00087 00088 result = _dbus_string_equal_len (&buffer, nonce, 16); 00089 if (!result) 00090 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Nonces do not match, access denied (fd=%d)", fd ); 00091 00092 _dbus_string_free (&p); 00093 _dbus_string_free (&buffer); 00094 00095 return result; 00096 } 00097 00106 dbus_bool_t 00107 _dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error) 00108 { 00109 FILE *fp; 00110 char buffer[17]; 00111 size_t nread; 00112 00113 buffer[sizeof buffer - 1] = '\0'; 00114 00115 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00116 00117 _dbus_verbose ("reading nonce from file: %s\n", _dbus_string_get_const_data (fname)); 00118 00119 00120 fp = fopen (_dbus_string_get_const_data (fname), "rb"); 00121 if (!fp) 00122 { 00123 dbus_set_error (error, 00124 _dbus_error_from_system_errno (), 00125 "Failed to open %s for read: %s", 00126 _dbus_string_get_const_data (fname), 00127 _dbus_strerror_from_errno ()); 00128 return FALSE; 00129 } 00130 00131 nread = fread (buffer, 1, sizeof buffer - 1, fp); 00132 fclose (fp); 00133 if (!nread) 00134 { 00135 dbus_set_error (error, DBUS_ERROR_FILE_NOT_FOUND, "Could not read nonce from file %s", _dbus_string_get_const_data (fname)); 00136 return FALSE; 00137 } 00138 00139 if (!_dbus_string_append_len (nonce, buffer, sizeof buffer - 1 )) 00140 { 00141 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00142 return FALSE; 00143 } 00144 return TRUE; 00145 } 00146 00147 int 00148 _dbus_accept_with_noncefile (int listen_fd, const DBusNonceFile *noncefile) 00149 { 00150 int fd; 00151 DBusString nonce; 00152 00153 _dbus_assert (noncefile != NULL); 00154 if (!_dbus_string_init (&nonce)) 00155 return -1; 00156 //PENDING(kdab): set better errors 00157 if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE) 00158 return -1; 00159 fd = _dbus_accept (listen_fd); 00160 if (_dbus_socket_is_invalid (fd)) 00161 return fd; 00162 if (do_check_nonce(fd, &nonce, NULL) != TRUE) { 00163 _dbus_verbose ("nonce check failed. Closing socket.\n"); 00164 _dbus_close_socket(fd, NULL); 00165 return -1; 00166 } 00167 00168 return fd; 00169 } 00170 00171 static dbus_bool_t 00172 generate_and_write_nonce (const DBusString *filename, DBusError *error) 00173 { 00174 DBusString nonce; 00175 dbus_bool_t ret; 00176 00177 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00178 00179 if (!_dbus_string_init (&nonce)) 00180 { 00181 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00182 return FALSE; 00183 } 00184 00185 if (!_dbus_generate_random_bytes (&nonce, 16)) 00186 { 00187 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00188 _dbus_string_free (&nonce); 00189 return FALSE; 00190 } 00191 00192 ret = _dbus_string_save_to_file (&nonce, filename, FALSE, error); 00193 00194 _dbus_string_free (&nonce); 00195 00196 return ret; 00197 } 00198 00208 dbus_bool_t 00209 _dbus_send_nonce (int fd, const DBusString *noncefile, DBusError *error) 00210 { 00211 dbus_bool_t read_result; 00212 int send_result; 00213 DBusString nonce; 00214 00215 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00216 00217 if (_dbus_string_get_length (noncefile) == 0) 00218 return FALSE; 00219 00220 if (!_dbus_string_init (&nonce)) 00221 { 00222 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00223 return FALSE; 00224 } 00225 00226 read_result = _dbus_read_nonce (noncefile, &nonce, error); 00227 if (!read_result) 00228 { 00229 _DBUS_ASSERT_ERROR_IS_SET (error); 00230 _dbus_string_free (&nonce); 00231 return FALSE; 00232 } 00233 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00234 00235 send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce)); 00236 00237 _dbus_string_free (&nonce); 00238 00239 if (send_result == -1) 00240 { 00241 dbus_set_error (error, 00242 _dbus_error_from_system_errno (), 00243 "Failed to send nonce (fd=%d): %s", 00244 fd, _dbus_strerror_from_errno ()); 00245 return FALSE; 00246 } 00247 00248 return TRUE; 00249 } 00250 00251 static dbus_bool_t 00252 do_noncefile_create (DBusNonceFile *noncefile, 00253 DBusError *error, 00254 dbus_bool_t use_subdir) 00255 { 00256 DBusString randomStr; 00257 const char *tmp; 00258 00259 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00260 00261 _dbus_assert (noncefile); 00262 00263 if (!_dbus_string_init (&randomStr)) 00264 { 00265 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00266 goto on_error; 00267 } 00268 00269 if (!_dbus_generate_random_ascii (&randomStr, 8)) 00270 { 00271 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00272 goto on_error; 00273 } 00274 00275 tmp = _dbus_get_tmpdir (); 00276 00277 if (!_dbus_string_init (&noncefile->dir) 00278 || tmp == NULL 00279 || !_dbus_string_append (&noncefile->dir, tmp)) 00280 { 00281 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00282 goto on_error; 00283 } 00284 if (use_subdir) 00285 { 00286 if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-") 00287 || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) ) 00288 { 00289 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00290 goto on_error; 00291 } 00292 if (!_dbus_string_init (&noncefile->path) 00293 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0) 00294 || !_dbus_string_append (&noncefile->path, "/nonce")) 00295 { 00296 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00297 goto on_error; 00298 } 00299 if (!_dbus_create_directory (&noncefile->dir, error)) 00300 { 00301 _DBUS_ASSERT_ERROR_IS_SET (error); 00302 goto on_error; 00303 } 00304 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00305 00306 } 00307 else 00308 { 00309 if (!_dbus_string_init (&noncefile->path) 00310 || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0) 00311 || !_dbus_string_append (&noncefile->path, "/dbus_nonce-") 00312 || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr))) 00313 { 00314 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00315 goto on_error; 00316 } 00317 00318 } 00319 00320 if (!generate_and_write_nonce (&noncefile->path, error)) 00321 { 00322 _DBUS_ASSERT_ERROR_IS_SET (error); 00323 if (use_subdir) 00324 _dbus_delete_directory (&noncefile->dir, NULL); //we ignore possible errors deleting the dir and return the write error instead 00325 goto on_error; 00326 } 00327 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00328 00329 _dbus_string_free (&randomStr); 00330 00331 return TRUE; 00332 on_error: 00333 if (use_subdir) 00334 _dbus_delete_directory (&noncefile->dir, NULL); 00335 _dbus_string_free (&noncefile->dir); 00336 _dbus_string_free (&noncefile->path); 00337 _dbus_string_free (&randomStr); 00338 return FALSE; 00339 } 00340 00341 #ifdef DBUS_WIN 00342 00349 dbus_bool_t 00350 _dbus_noncefile_create (DBusNonceFile *noncefile, 00351 DBusError *error) 00352 { 00353 return do_noncefile_create (noncefile, error, /*use_subdir=*/FALSE); 00354 } 00355 00363 dbus_bool_t 00364 _dbus_noncefile_delete (DBusNonceFile *noncefile, 00365 DBusError *error) 00366 { 00367 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00368 00369 _dbus_delete_file (&noncefile->path, error); 00370 _dbus_string_free (&noncefile->dir); 00371 _dbus_string_free (&noncefile->path); 00372 return TRUE; 00373 } 00374 00375 #else 00376 00384 dbus_bool_t 00385 _dbus_noncefile_create (DBusNonceFile *noncefile, 00386 DBusError *error) 00387 { 00388 return do_noncefile_create (noncefile, error, /*use_subdir=*/TRUE); 00389 } 00390 00398 dbus_bool_t 00399 _dbus_noncefile_delete (DBusNonceFile *noncefile, 00400 DBusError *error) 00401 { 00402 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00403 00404 _dbus_delete_directory (&noncefile->dir, error); 00405 _dbus_string_free (&noncefile->dir); 00406 _dbus_string_free (&noncefile->path); 00407 return TRUE; 00408 } 00409 #endif 00410 00411 00418 const DBusString* 00419 _dbus_noncefile_get_path (const DBusNonceFile *noncefile) 00420 { 00421 _dbus_assert (noncefile); 00422 return &noncefile->path; 00423 } 00424 00435 dbus_bool_t 00436 _dbus_noncefile_check_nonce (int fd, 00437 const DBusNonceFile *noncefile, 00438 DBusError* error) 00439 { 00440 return do_check_nonce (fd, _dbus_noncefile_get_path (noncefile), error); 00441 } 00442 00443
1.7.6.1