D-Bus  1.10.12
dbus-marshal-header.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-marshal-header.c  Managing marshaling/demarshaling of message headers
00003  *
00004  * Copyright (C) 2005  Red Hat, Inc.
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus/dbus-shared.h"
00026 #include "dbus-marshal-header.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-byteswap.h"
00029 
00037 /* Not thread locked, but strictly const/read-only so should be OK
00038  */
00040 _DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
00042 _DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str,  DBUS_INTERFACE_LOCAL);
00044 _DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str,       DBUS_PATH_LOCAL);
00045 
00047 #define FIELDS_ARRAY_SIGNATURE_OFFSET 6
00048 
00049 #define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
00050 
00051 
00053 #define BYTE_ORDER_OFFSET    0
00054 
00055 #define TYPE_OFFSET          1
00056 
00057 #define FLAGS_OFFSET         2
00058 
00059 #define VERSION_OFFSET       3
00060 
00061 #define BODY_LENGTH_OFFSET 4
00062 
00063 #define SERIAL_OFFSET 8
00064 
00065 #define FIELDS_ARRAY_LENGTH_OFFSET 12
00066 
00067 #define FIRST_FIELD_OFFSET 16
00068 
00069 typedef struct
00070 {
00071   unsigned char code; 
00072   unsigned char type; 
00073 } HeaderFieldType;
00074 
00075 static const HeaderFieldType
00076 _dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
00077   { DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID },
00078   { DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH },
00079   { DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING },
00080   { DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING },
00081   { DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING },
00082   { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
00083   { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
00084   { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
00085   { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE },
00086   { DBUS_HEADER_FIELD_UNIX_FDS, DBUS_TYPE_UINT32 }
00087 };
00088 
00090 #define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
00091 
00093 #define MAX_POSSIBLE_HEADER_PADDING 7
00094 static dbus_bool_t
00095 reserve_header_padding (DBusHeader *header)
00096 {
00097   _dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING);
00098 
00099   if (!_dbus_string_lengthen (&header->data,
00100                               MAX_POSSIBLE_HEADER_PADDING - header->padding))
00101     return FALSE;
00102   header->padding = MAX_POSSIBLE_HEADER_PADDING;
00103   return TRUE;
00104 }
00105 
00106 static void
00107 correct_header_padding (DBusHeader *header)
00108 {
00109   int unpadded_len;
00110 
00111   _dbus_assert (header->padding == 7);
00112 
00113   _dbus_string_shorten (&header->data, header->padding);
00114   unpadded_len = _dbus_string_get_length (&header->data);
00115 
00116   if (!_dbus_string_align_length (&header->data, 8))
00117     _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
00118 
00119   header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
00120 }
00121 
00123 #define HEADER_END_BEFORE_PADDING(header) \
00124   (_dbus_string_get_length (&(header)->data) - (header)->padding)
00125 
00133 static void
00134 _dbus_header_cache_invalidate_all (DBusHeader *header)
00135 {
00136   int i;
00137 
00138   i = 0;
00139   while (i <= DBUS_HEADER_FIELD_LAST)
00140     {
00141       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
00142       ++i;
00143     }
00144 }
00145 
00153 static void
00154 _dbus_header_cache_one (DBusHeader     *header,
00155                         int             field_code,
00156                         DBusTypeReader *variant_reader)
00157 {
00158   header->fields[field_code].value_pos =
00159     _dbus_type_reader_get_value_pos (variant_reader);
00160 
00161 #if 0
00162   _dbus_verbose ("cached value_pos %d for field %d\n",
00163                  header->fields[field_code].value_pos, field_code)
00164 #endif
00165 }
00166 
00173 char
00174 _dbus_header_get_byte_order (const DBusHeader *header)
00175 {
00176   _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET);
00177 
00178   return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
00179 }
00180 
00186 static void
00187 _dbus_header_cache_revalidate (DBusHeader *header)
00188 {
00189   DBusTypeReader array;
00190   DBusTypeReader reader;
00191   int i;
00192 
00193   i = 0;
00194   while (i <= DBUS_HEADER_FIELD_LAST)
00195     {
00196       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
00197       ++i;
00198     }
00199 
00200   _dbus_type_reader_init (&reader,
00201                           _dbus_header_get_byte_order (header),
00202                           &_dbus_header_signature_str,
00203                           FIELDS_ARRAY_SIGNATURE_OFFSET,
00204                           &header->data,
00205                           FIELDS_ARRAY_LENGTH_OFFSET);
00206 
00207   _dbus_type_reader_recurse (&reader, &array);
00208 
00209   while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00210     {
00211       DBusTypeReader sub;
00212       DBusTypeReader variant;
00213       unsigned char field_code;
00214 
00215       _dbus_type_reader_recurse (&array, &sub);
00216 
00217       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
00218       _dbus_type_reader_read_basic (&sub, &field_code);
00219 
00220       /* Unknown fields should be ignored */
00221       if (field_code > DBUS_HEADER_FIELD_LAST)
00222         goto next_field;
00223 
00224       _dbus_type_reader_next (&sub);
00225 
00226       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
00227       _dbus_type_reader_recurse (&sub, &variant);
00228 
00229       _dbus_header_cache_one (header, field_code, &variant);
00230 
00231     next_field:
00232       _dbus_type_reader_next (&array);
00233     }
00234 }
00235 
00243 static dbus_bool_t
00244 _dbus_header_cache_check (DBusHeader    *header,
00245                           int            field)
00246 {
00247   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00248 
00249   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
00250     _dbus_header_cache_revalidate (header);
00251 
00252   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
00253     return FALSE;
00254 
00255   return TRUE;
00256 }
00257 
00266 static dbus_bool_t
00267 _dbus_header_cache_known_nonexistent (DBusHeader    *header,
00268                                       int            field)
00269 {
00270   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00271 
00272   return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
00273 }
00274 
00284 static dbus_bool_t
00285 write_basic_field (DBusTypeWriter *writer,
00286                    int             field,
00287                    int             type,
00288                    const void     *value)
00289 {
00290   DBusTypeWriter sub;
00291   DBusTypeWriter variant;
00292   int start;
00293   int padding;
00294   unsigned char field_byte;
00295   DBusString contained_type;
00296   char buf[2];
00297 
00298   start = writer->value_pos;
00299   padding = _dbus_string_get_length (writer->value_str) - start;
00300 
00301   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
00302                                   NULL, 0, &sub))
00303     goto append_failed;
00304 
00305   field_byte = field;
00306   if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
00307                                       &field_byte))
00308     goto append_failed;
00309 
00310   buf[0] = type;
00311   buf[1] = '\0';
00312   _dbus_string_init_const_len (&contained_type, buf, 1);
00313 
00314   if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
00315                                   &contained_type, 0, &variant))
00316     goto append_failed;
00317 
00318   if (!_dbus_type_writer_write_basic (&variant, type, value))
00319     goto append_failed;
00320 
00321   if (!_dbus_type_writer_unrecurse (&sub, &variant))
00322     goto append_failed;
00323 
00324   if (!_dbus_type_writer_unrecurse (writer, &sub))
00325     goto append_failed;
00326 
00327   return TRUE;
00328 
00329  append_failed:
00330   _dbus_string_delete (writer->value_str,
00331                        start,
00332                        _dbus_string_get_length (writer->value_str) - start - padding);
00333   return FALSE;
00334 }
00335 
00346 static dbus_bool_t
00347 set_basic_field (DBusTypeReader       *reader,
00348                  int                   field,
00349                  int                   type,
00350                  const void           *value,
00351                  const DBusTypeReader *realign_root)
00352 {
00353   DBusTypeReader sub;
00354   DBusTypeReader variant;
00355 
00356   _dbus_type_reader_recurse (reader, &sub);
00357 
00358   _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
00359 #ifndef DBUS_DISABLE_ASSERT
00360  {
00361    unsigned char v_BYTE;
00362    _dbus_type_reader_read_basic (&sub, &v_BYTE);
00363    _dbus_assert (((int) v_BYTE) == field);
00364  }
00365 #endif
00366 
00367   if (!_dbus_type_reader_next (&sub))
00368     _dbus_assert_not_reached ("no variant field?");
00369 
00370   _dbus_type_reader_recurse (&sub, &variant);
00371   _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
00372 
00373   if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
00374     return FALSE;
00375 
00376   return TRUE;
00377 }
00378 
00385 int
00386 _dbus_header_get_message_type (DBusHeader *header)
00387 {
00388   int type;
00389 
00390   type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
00391   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
00392 
00393   return type;
00394 }
00395 
00403 void
00404 _dbus_header_set_serial (DBusHeader    *header,
00405                          dbus_uint32_t  serial)
00406 {
00407   /* we use this function to set the serial on outgoing
00408    * messages, and to reset the serial in dbus_message_copy;
00409    * this assertion should catch a double-set on outgoing.
00410    */
00411   _dbus_assert (_dbus_header_get_serial (header) == 0 ||
00412                 serial == 0);
00413 
00414   _dbus_marshal_set_uint32 (&header->data,
00415                             SERIAL_OFFSET,
00416                             serial,
00417                             _dbus_header_get_byte_order (header));
00418 }
00419 
00426 dbus_uint32_t
00427 _dbus_header_get_serial (DBusHeader *header)
00428 {
00429   return _dbus_marshal_read_uint32 (&header->data,
00430                                     SERIAL_OFFSET,
00431                                     _dbus_header_get_byte_order (header),
00432                                     NULL);
00433 }
00434 
00442 void
00443 _dbus_header_reinit (DBusHeader *header)
00444 {
00445   _dbus_string_set_length (&header->data, 0);
00446 
00447   header->padding = 0;
00448 
00449   _dbus_header_cache_invalidate_all (header);
00450 }
00451 
00459 dbus_bool_t
00460 _dbus_header_init (DBusHeader *header)
00461 {
00462   if (!_dbus_string_init_preallocated (&header->data, 32))
00463     return FALSE;
00464 
00465   _dbus_header_reinit (header);
00466 
00467   return TRUE;
00468 }
00469 
00475 void
00476 _dbus_header_free (DBusHeader *header)
00477 {
00478   _dbus_string_free (&header->data);
00479 }
00480 
00489 dbus_bool_t
00490 _dbus_header_copy (const DBusHeader *header,
00491                    DBusHeader       *dest)
00492 {
00493   *dest = *header;
00494 
00495   if (!_dbus_string_init_preallocated (&dest->data,
00496                                        _dbus_string_get_length (&header->data)))
00497     return FALSE;
00498 
00499   if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
00500     {
00501       _dbus_string_free (&dest->data);
00502       return FALSE;
00503     }
00504 
00505   /* Reset the serial */
00506   _dbus_header_set_serial (dest, 0);
00507 
00508   return TRUE;
00509 }
00510 
00527 dbus_bool_t
00528 _dbus_header_create (DBusHeader  *header,
00529                      int          byte_order,
00530                      int          message_type,
00531                      const char  *destination,
00532                      const char  *path,
00533                      const char  *interface,
00534                      const char  *member,
00535                      const char  *error_name)
00536 {
00537   unsigned char v_BYTE;
00538   dbus_uint32_t v_UINT32;
00539   DBusTypeWriter writer;
00540   DBusTypeWriter array;
00541 
00542   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00543                 byte_order == DBUS_BIG_ENDIAN);
00544   _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
00545                 (error_name) ||
00546                 !(interface || member || error_name));
00547   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
00548 
00549   if (!reserve_header_padding (header))
00550     return FALSE;
00551 
00552   _dbus_type_writer_init_values_only (&writer, byte_order,
00553                                       &_dbus_header_signature_str, 0,
00554                                       &header->data,
00555                                       HEADER_END_BEFORE_PADDING (header));
00556 
00557   v_BYTE = byte_order;
00558   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00559                                       &v_BYTE))
00560     goto oom;
00561 
00562   v_BYTE = message_type;
00563   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00564                                       &v_BYTE))
00565     goto oom;
00566 
00567   v_BYTE = 0; /* flags */
00568   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00569                                       &v_BYTE))
00570     goto oom;
00571 
00572   v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
00573   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00574                                       &v_BYTE))
00575     goto oom;
00576 
00577   v_UINT32 = 0; /* body length */
00578   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
00579                                       &v_UINT32))
00580     goto oom;
00581 
00582   v_UINT32 = 0; /* serial */
00583   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
00584                                       &v_UINT32))
00585     goto oom;
00586 
00587   if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
00588                                   &_dbus_header_signature_str,
00589                                   FIELDS_ARRAY_SIGNATURE_OFFSET,
00590                                   &array))
00591     goto oom;
00592 
00593   /* Marshal all the fields (Marshall Fields?) */
00594 
00595   if (path != NULL)
00596     {
00597       if (!write_basic_field (&array,
00598                               DBUS_HEADER_FIELD_PATH,
00599                               DBUS_TYPE_OBJECT_PATH,
00600                               &path))
00601         goto oom;
00602     }
00603 
00604   if (destination != NULL)
00605     {
00606       if (!write_basic_field (&array,
00607                               DBUS_HEADER_FIELD_DESTINATION,
00608                               DBUS_TYPE_STRING,
00609                               &destination))
00610         goto oom;
00611     }
00612 
00613   if (interface != NULL)
00614     {
00615       if (!write_basic_field (&array,
00616                               DBUS_HEADER_FIELD_INTERFACE,
00617                               DBUS_TYPE_STRING,
00618                               &interface))
00619         goto oom;
00620     }
00621 
00622   if (member != NULL)
00623     {
00624       if (!write_basic_field (&array,
00625                               DBUS_HEADER_FIELD_MEMBER,
00626                               DBUS_TYPE_STRING,
00627                               &member))
00628         goto oom;
00629     }
00630 
00631   if (error_name != NULL)
00632     {
00633       if (!write_basic_field (&array,
00634                               DBUS_HEADER_FIELD_ERROR_NAME,
00635                               DBUS_TYPE_STRING,
00636                               &error_name))
00637         goto oom;
00638     }
00639 
00640   if (!_dbus_type_writer_unrecurse (&writer, &array))
00641     goto oom;
00642 
00643   correct_header_padding (header);
00644 
00645   return TRUE;
00646 
00647  oom:
00648   _dbus_string_delete (&header->data, 0,
00649                        _dbus_string_get_length (&header->data) - header->padding);
00650   correct_header_padding (header);
00651 
00652   return FALSE;
00653 }
00654 
00672 dbus_bool_t
00673 _dbus_header_have_message_untrusted (int                max_message_length,
00674                                      DBusValidity      *validity,
00675                                      int               *byte_order,
00676                                      int               *fields_array_len,
00677                                      int               *header_len,
00678                                      int               *body_len,
00679                                      const DBusString  *str,
00680                                      int                start,
00681                                      int                len)
00682 
00683 {
00684   dbus_uint32_t header_len_unsigned;
00685   dbus_uint32_t fields_array_len_unsigned;
00686   dbus_uint32_t body_len_unsigned;
00687 
00688   _dbus_assert (start >= 0);
00689   _dbus_assert (start < _DBUS_INT32_MAX / 2);
00690   _dbus_assert (len >= 0);
00691 
00692   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
00693 
00694   *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
00695 
00696   if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
00697     {
00698       *validity = DBUS_INVALID_BAD_BYTE_ORDER;
00699       return FALSE;
00700     }
00701 
00702   _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len);
00703   fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
00704                                                          *byte_order, NULL);
00705 
00706   if (fields_array_len_unsigned > (unsigned) max_message_length)
00707     {
00708       *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
00709       return FALSE;
00710     }
00711 
00712   _dbus_assert (BODY_LENGTH_OFFSET + 4 < len);
00713   body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
00714                                                  *byte_order, NULL);
00715 
00716   if (body_len_unsigned > (unsigned) max_message_length)
00717     {
00718       *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
00719       return FALSE;
00720     }
00721 
00722   header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
00723   header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
00724 
00725   /* overflow should be impossible since the lengths aren't allowed to
00726    * be huge.
00727    */
00728   _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
00729   if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
00730     {
00731       *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
00732       return FALSE;
00733     }
00734 
00735   _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
00736   _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
00737   _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
00738 
00739   *body_len = body_len_unsigned;
00740   *fields_array_len = fields_array_len_unsigned;
00741   *header_len = header_len_unsigned;
00742 
00743   *validity = DBUS_VALID;
00744 
00745   _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
00746                  len, body_len_unsigned, header_len_unsigned,
00747                  body_len_unsigned + header_len_unsigned);
00748 
00749   return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
00750 }
00751 
00752 static DBusValidity
00753 check_mandatory_fields (DBusHeader *header)
00754 {
00755 #define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
00756 
00757   switch (_dbus_header_get_message_type (header))
00758     {
00759     case DBUS_MESSAGE_TYPE_SIGNAL:
00760       REQUIRE_FIELD (INTERFACE);
00761       /* FALL THRU - signals also require the path and member */
00762     case DBUS_MESSAGE_TYPE_METHOD_CALL:
00763       REQUIRE_FIELD (PATH);
00764       REQUIRE_FIELD (MEMBER);
00765       break;
00766     case DBUS_MESSAGE_TYPE_ERROR:
00767       REQUIRE_FIELD (ERROR_NAME);
00768       REQUIRE_FIELD (REPLY_SERIAL);
00769       break;
00770     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00771       REQUIRE_FIELD (REPLY_SERIAL);
00772       break;
00773     default:
00774       /* other message types allowed but ignored */
00775       break;
00776     }
00777 
00778   return DBUS_VALID;
00779 }
00780 
00781 static DBusValidity
00782 load_and_validate_field (DBusHeader     *header,
00783                          int             field,
00784                          DBusTypeReader *variant_reader)
00785 {
00786   int type;
00787   int expected_type;
00788   const DBusString *value_str;
00789   int value_pos;
00790   int str_data_pos;
00791   dbus_uint32_t v_UINT32;
00792   int bad_string_code;
00793   dbus_bool_t (* string_validation_func) (const DBusString *str,
00794                                           int start, int len);
00795 
00796   /* Supposed to have been checked already */
00797   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00798   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
00799 
00800   /* Before we can cache a field, we need to know it has the right type */
00801   type = _dbus_type_reader_get_current_type (variant_reader);
00802 
00803   _dbus_assert (_dbus_header_field_types[field].code == field);
00804 
00805   expected_type = EXPECTED_TYPE_OF_FIELD (field);
00806   if (type != expected_type)
00807     {
00808       _dbus_verbose ("Field %d should have type %d but has %d\n",
00809                      field, expected_type, type);
00810       return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
00811     }
00812 
00813   /* If the field was provided twice, we aren't happy */
00814   if (header->fields[field].value_pos >= 0)
00815     {
00816       _dbus_verbose ("Header field %d seen a second time\n", field);
00817       return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
00818     }
00819 
00820   /* Now we can cache and look at the field content */
00821   _dbus_verbose ("initially caching field %d\n", field);
00822   _dbus_header_cache_one (header, field, variant_reader);
00823 
00824   string_validation_func = NULL;
00825 
00826   /* make compiler happy that all this is initialized */
00827   v_UINT32 = 0;
00828   value_str = NULL;
00829   value_pos = -1;
00830   str_data_pos = -1;
00831   bad_string_code = DBUS_VALID;
00832 
00833   if (expected_type == DBUS_TYPE_UINT32)
00834     {
00835       _dbus_header_get_field_basic (header, field, expected_type,
00836                                     &v_UINT32);
00837     }
00838   else if (expected_type == DBUS_TYPE_STRING ||
00839            expected_type == DBUS_TYPE_OBJECT_PATH ||
00840            expected_type == DBUS_TYPE_SIGNATURE)
00841     {
00842       _dbus_header_get_field_raw (header, field,
00843                                   &value_str, &value_pos);
00844       str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
00845     }
00846   else
00847     {
00848       _dbus_assert_not_reached ("none of the known fields should have this type");
00849     }
00850 
00851   switch (field)
00852     {
00853     case DBUS_HEADER_FIELD_DESTINATION:
00854       string_validation_func = _dbus_validate_bus_name;
00855       bad_string_code = DBUS_INVALID_BAD_DESTINATION;
00856       break;
00857     case DBUS_HEADER_FIELD_INTERFACE:
00858       string_validation_func = _dbus_validate_interface;
00859       bad_string_code = DBUS_INVALID_BAD_INTERFACE;
00860 
00861       if (_dbus_string_equal_substring (&_dbus_local_interface_str,
00862                                         0,
00863                                         _dbus_string_get_length (&_dbus_local_interface_str),
00864                                         value_str, str_data_pos))
00865         {
00866           _dbus_verbose ("Message is on the local interface\n");
00867           return DBUS_INVALID_USES_LOCAL_INTERFACE;
00868         }
00869       break;
00870 
00871     case DBUS_HEADER_FIELD_MEMBER:
00872       string_validation_func = _dbus_validate_member;
00873       bad_string_code = DBUS_INVALID_BAD_MEMBER;
00874       break;
00875 
00876     case DBUS_HEADER_FIELD_ERROR_NAME:
00877       string_validation_func = _dbus_validate_error_name;
00878       bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
00879       break;
00880 
00881     case DBUS_HEADER_FIELD_SENDER:
00882       string_validation_func = _dbus_validate_bus_name;
00883       bad_string_code = DBUS_INVALID_BAD_SENDER;
00884       break;
00885 
00886     case DBUS_HEADER_FIELD_PATH:
00887       /* OBJECT_PATH was validated generically due to its type */
00888       string_validation_func = NULL;
00889 
00890       if (_dbus_string_equal_substring (&_dbus_local_path_str,
00891                                         0,
00892                                         _dbus_string_get_length (&_dbus_local_path_str),
00893                                         value_str, str_data_pos))
00894         {
00895           _dbus_verbose ("Message is from the local path\n");
00896           return DBUS_INVALID_USES_LOCAL_PATH;
00897         }
00898       break;
00899 
00900     case DBUS_HEADER_FIELD_REPLY_SERIAL:
00901       /* Can't be 0 */
00902       if (v_UINT32 == 0)
00903         {
00904           return DBUS_INVALID_BAD_SERIAL;
00905         }
00906       break;
00907 
00908     case DBUS_HEADER_FIELD_UNIX_FDS:
00909       /* Every value makes sense */
00910       break;
00911 
00912     case DBUS_HEADER_FIELD_SIGNATURE:
00913       /* SIGNATURE validated generically due to its type */
00914       string_validation_func = NULL;
00915       break;
00916 
00917     default:
00918       _dbus_assert_not_reached ("unknown field shouldn't be seen here");
00919       break;
00920     }
00921 
00922   if (string_validation_func)
00923     {
00924       dbus_uint32_t len;
00925 
00926       _dbus_assert (bad_string_code != DBUS_VALID);
00927 
00928       len = _dbus_marshal_read_uint32 (value_str, value_pos,
00929                                        _dbus_header_get_byte_order (header),
00930                                        NULL);
00931 
00932 #if 0
00933       _dbus_verbose ("Validating string header field; code %d if fails\n",
00934                      bad_string_code);
00935 #endif
00936       if (!(*string_validation_func) (value_str, str_data_pos, len))
00937         return bad_string_code;
00938     }
00939 
00940   return DBUS_VALID;
00941 }
00942 
00969 dbus_bool_t
00970 _dbus_header_load (DBusHeader        *header,
00971                    DBusValidationMode mode,
00972                    DBusValidity      *validity,
00973                    int                byte_order,
00974                    int                fields_array_len,
00975                    int                header_len,
00976                    int                body_len,
00977                    const DBusString  *str,
00978                    int                start,
00979                    int                len)
00980 {
00981   int leftover;
00982   DBusValidity v;
00983   DBusTypeReader reader;
00984   DBusTypeReader array_reader;
00985   unsigned char v_byte;
00986   dbus_uint32_t v_uint32;
00987   dbus_uint32_t serial;
00988   int padding_start;
00989   int padding_len;
00990   int i;
00991 
00992   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
00993   _dbus_assert (header_len <= len);
00994   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
00995 
00996   if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
00997     {
00998       _dbus_verbose ("Failed to copy buffer into new header\n");
00999       *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
01000       return FALSE;
01001     }
01002 
01003   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
01004     {
01005       leftover = len - header_len - body_len - start;
01006     }
01007   else
01008     {
01009       v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
01010                                            byte_order,
01011                                            &leftover,
01012                                            str, start, len);
01013       
01014       if (v != DBUS_VALID)
01015         {
01016           *validity = v;
01017           goto invalid;
01018         }
01019     }
01020 
01021   _dbus_assert (leftover < len);
01022 
01023   padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
01024   padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
01025   _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
01026   _dbus_assert (start + header_len == padding_start + padding_len);
01027 
01028   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
01029     {
01030       if (!_dbus_string_validate_nul (str, padding_start, padding_len))
01031         {
01032           *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
01033           goto invalid;
01034         }
01035     }
01036 
01037   header->padding = padding_len;
01038 
01039   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
01040     {
01041       *validity = DBUS_VALID;
01042       return TRUE;
01043     }
01044 
01045   /* We now know the data is well-formed, but we have to check that
01046    * it's valid.
01047    */
01048 
01049   _dbus_type_reader_init (&reader,
01050                           byte_order,
01051                           &_dbus_header_signature_str, 0,
01052                           str, start);
01053 
01054   /* BYTE ORDER */
01055   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01056   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
01057   _dbus_type_reader_read_basic (&reader, &v_byte);
01058   _dbus_type_reader_next (&reader);
01059 
01060   _dbus_assert (v_byte == byte_order);
01061 
01062   /* MESSAGE TYPE */
01063   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01064   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
01065   _dbus_type_reader_read_basic (&reader, &v_byte);
01066   _dbus_type_reader_next (&reader);
01067 
01068   /* unknown message types are supposed to be ignored, so only validation here is
01069    * that it isn't invalid
01070    */
01071   if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
01072     {
01073       *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
01074       goto invalid;
01075     }
01076 
01077   /* FLAGS */
01078   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01079   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
01080   _dbus_type_reader_read_basic (&reader, &v_byte);
01081   _dbus_type_reader_next (&reader);
01082 
01083   /* unknown flags should be ignored */
01084 
01085   /* PROTOCOL VERSION */
01086   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01087   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
01088   _dbus_type_reader_read_basic (&reader, &v_byte);
01089   _dbus_type_reader_next (&reader);
01090 
01091   if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
01092     {
01093       *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
01094       goto invalid;
01095     }
01096 
01097   /* BODY LENGTH */
01098   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
01099   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
01100   _dbus_type_reader_read_basic (&reader, &v_uint32);
01101   _dbus_type_reader_next (&reader);
01102 
01103   _dbus_assert (body_len == (signed) v_uint32);
01104 
01105   /* SERIAL */
01106   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
01107   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
01108   _dbus_type_reader_read_basic (&reader, &serial);
01109   _dbus_type_reader_next (&reader);
01110 
01111   if (serial == 0)
01112     {
01113       *validity = DBUS_INVALID_BAD_SERIAL;
01114       goto invalid;
01115     }
01116 
01117   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
01118   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);
01119 
01120   _dbus_type_reader_recurse (&reader, &array_reader);
01121   while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
01122     {
01123       DBusTypeReader struct_reader;
01124       DBusTypeReader variant_reader;
01125       unsigned char field_code;
01126 
01127       _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);
01128 
01129       _dbus_type_reader_recurse (&array_reader, &struct_reader);
01130 
01131       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
01132       _dbus_type_reader_read_basic (&struct_reader, &field_code);
01133       _dbus_type_reader_next (&struct_reader);
01134 
01135       if (field_code == DBUS_HEADER_FIELD_INVALID)
01136         {
01137           _dbus_verbose ("invalid header field code\n");
01138           *validity = DBUS_INVALID_HEADER_FIELD_CODE;
01139           goto invalid;
01140         }
01141 
01142       if (field_code > DBUS_HEADER_FIELD_LAST)
01143         {
01144           _dbus_verbose ("unknown header field code %d, skipping\n",
01145                          field_code);
01146           goto next_field;
01147         }
01148 
01149       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
01150       _dbus_type_reader_recurse (&struct_reader, &variant_reader);
01151 
01152       v = load_and_validate_field (header, field_code, &variant_reader);
01153       if (v != DBUS_VALID)
01154         {
01155           _dbus_verbose ("Field %d was invalid\n", field_code);
01156           *validity = v;
01157           goto invalid;
01158         }
01159 
01160     next_field:
01161       _dbus_type_reader_next (&array_reader);
01162     }
01163 
01164   /* Anything we didn't fill in is now known not to exist */
01165   i = 0;
01166   while (i <= DBUS_HEADER_FIELD_LAST)
01167     {
01168       if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
01169         header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
01170       ++i;
01171     }
01172 
01173   v = check_mandatory_fields (header);
01174   if (v != DBUS_VALID)
01175     {
01176       _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
01177       *validity = v;
01178       goto invalid;
01179     }
01180 
01181   *validity = DBUS_VALID;
01182   return TRUE;
01183 
01184  invalid:
01185   _dbus_string_set_length (&header->data, 0);
01186   return FALSE;
01187 }
01188 
01195 void
01196 _dbus_header_update_lengths (DBusHeader *header,
01197                              int         body_len)
01198 {
01199   _dbus_marshal_set_uint32 (&header->data,
01200                             BODY_LENGTH_OFFSET,
01201                             body_len,
01202                             _dbus_header_get_byte_order (header));
01203 }
01204 
01218 static dbus_bool_t
01219 find_field_for_modification (DBusHeader     *header,
01220                              int             field,
01221                              DBusTypeReader *reader,
01222                              DBusTypeReader *realign_root)
01223 {
01224   dbus_bool_t retval;
01225 
01226   retval = FALSE;
01227 
01228   _dbus_type_reader_init (realign_root,
01229                           _dbus_header_get_byte_order (header),
01230                           &_dbus_header_signature_str,
01231                           FIELDS_ARRAY_SIGNATURE_OFFSET,
01232                           &header->data,
01233                           FIELDS_ARRAY_LENGTH_OFFSET);
01234 
01235   _dbus_type_reader_recurse (realign_root, reader);
01236 
01237   while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID)
01238     {
01239       DBusTypeReader sub;
01240       unsigned char field_code;
01241 
01242       _dbus_type_reader_recurse (reader, &sub);
01243 
01244       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
01245       _dbus_type_reader_read_basic (&sub, &field_code);
01246 
01247       if (field_code == (unsigned) field)
01248         {
01249           _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT);
01250           retval = TRUE;
01251           goto done;
01252         }
01253 
01254       _dbus_type_reader_next (reader);
01255     }
01256 
01257  done:
01258   return retval;
01259 }
01260 
01272 dbus_bool_t
01273 _dbus_header_set_field_basic (DBusHeader       *header,
01274                               int               field,
01275                               int               type,
01276                               const void       *value)
01277 {
01278   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
01279 
01280   if (!reserve_header_padding (header))
01281     return FALSE;
01282 
01283   /* If the field exists we set, otherwise we append */
01284   if (_dbus_header_cache_check (header, field))
01285     {
01286       DBusTypeReader reader;
01287       DBusTypeReader realign_root;
01288 
01289       if (!find_field_for_modification (header, field,
01290                                         &reader, &realign_root))
01291         _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
01292 
01293       if (!set_basic_field (&reader, field, type, value, &realign_root))
01294         return FALSE;
01295     }
01296   else
01297     {
01298       DBusTypeWriter writer;
01299       DBusTypeWriter array;
01300 
01301       _dbus_type_writer_init_values_only (&writer,
01302                                           _dbus_header_get_byte_order (header),
01303                                           &_dbus_header_signature_str,
01304                                           FIELDS_ARRAY_SIGNATURE_OFFSET,
01305                                           &header->data,
01306                                           FIELDS_ARRAY_LENGTH_OFFSET);
01307 
01308       /* recurse into array without creating a new length, and jump to
01309        * end of array.
01310        */
01311       if (!_dbus_type_writer_append_array (&writer,
01312                                            &_dbus_header_signature_str,
01313                                            FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET,
01314                                            &array))
01315         _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
01316 
01317       _dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET);
01318       _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
01319       _dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header));
01320 
01321       if (!write_basic_field (&array,
01322                               field, type, value))
01323         return FALSE;
01324 
01325       if (!_dbus_type_writer_unrecurse (&writer, &array))
01326         _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
01327     }
01328 
01329   correct_header_padding (header);
01330 
01331   /* We could be smarter about this (only invalidate fields after the
01332    * one we modified, or even only if the one we modified changed
01333    * length). But this hack is a start.
01334    */
01335   _dbus_header_cache_invalidate_all (header);
01336 
01337   return TRUE;
01338 }
01339 
01350 dbus_bool_t
01351 _dbus_header_get_field_basic (DBusHeader    *header,
01352                               int            field,
01353                               int            type,
01354                               void          *value)
01355 {
01356   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
01357   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
01358   _dbus_assert (_dbus_header_field_types[field].code == field);
01359   /* in light of this you might ask why the type is passed in;
01360    * the only rationale I can think of is so the caller has
01361    * to specify its expectation and breaks if we change it
01362    */
01363   _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
01364 
01365   if (!_dbus_header_cache_check (header, field))
01366     return FALSE;
01367 
01368   _dbus_assert (header->fields[field].value_pos >= 0);
01369 
01370   _dbus_marshal_read_basic (&header->data,
01371                             header->fields[field].value_pos,
01372                             type, value, _dbus_header_get_byte_order (header),
01373                             NULL);
01374 
01375   return TRUE;
01376 }
01377 
01391 dbus_bool_t
01392 _dbus_header_get_field_raw (DBusHeader        *header,
01393                             int                field,
01394                             const DBusString **str,
01395                             int               *pos)
01396 {
01397   if (!_dbus_header_cache_check (header, field))
01398     return FALSE;
01399 
01400   if (str)
01401     *str = &header->data;
01402   if (pos)
01403     *pos = header->fields[field].value_pos;
01404 
01405   return TRUE;
01406 }
01407 
01415 dbus_bool_t
01416 _dbus_header_delete_field (DBusHeader *header,
01417                            int         field)
01418 {
01419   DBusTypeReader reader;
01420   DBusTypeReader realign_root;
01421 
01422   if (_dbus_header_cache_known_nonexistent (header, field))
01423     return TRUE; /* nothing to do */
01424 
01425   /* Scan to the field we want, delete and realign, reappend
01426    * padding. Field may turn out not to exist.
01427    */
01428   if (!find_field_for_modification (header, field,
01429                                     &reader, &realign_root))
01430     return TRUE; /* nothing to do */
01431 
01432   if (!reserve_header_padding (header))
01433     return FALSE;
01434 
01435   if (!_dbus_type_reader_delete (&reader,
01436                                  &realign_root))
01437     return FALSE;
01438 
01439   correct_header_padding (header);
01440 
01441   _dbus_header_cache_invalidate_all (header);
01442 
01443   _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
01444 
01445   return TRUE;
01446 }
01447 
01456 void
01457 _dbus_header_toggle_flag (DBusHeader   *header,
01458                           dbus_uint32_t flag,
01459                           dbus_bool_t   value)
01460 {
01461   unsigned char *flags_p;
01462 
01463   flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1);
01464 
01465   if (value)
01466     *flags_p |= flag;
01467   else
01468     *flags_p &= ~flag;
01469 }
01470 
01478 dbus_bool_t
01479 _dbus_header_get_flag (DBusHeader   *header,
01480                        dbus_uint32_t flag)
01481 {
01482   const unsigned char *flags_p;
01483 
01484   flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1);
01485 
01486   return (*flags_p & flag) != 0;
01487 }
01488 
01495 void
01496 _dbus_header_byteswap (DBusHeader *header,
01497                        int         new_order)
01498 {
01499   char byte_order;
01500 
01501   byte_order = _dbus_header_get_byte_order (header);
01502 
01503   if (byte_order == new_order)
01504     return;
01505 
01506   _dbus_marshal_byteswap (&_dbus_header_signature_str,
01507                           0, byte_order,
01508                           new_order,
01509                           &header->data, 0);
01510 
01511   _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
01512 }
01513