• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

dbus-nonce.c

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 

Generated on Sun Aug 28 2011 for D-Bus by  doxygen 1.7.1