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