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

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 
00172 static void
00173 _dbus_header_cache_revalidate (DBusHeader *header)
00174 {
00175   DBusTypeReader array;
00176   DBusTypeReader reader;
00177   int i;
00178 
00179   i = 0;
00180   while (i <= DBUS_HEADER_FIELD_LAST)
00181     {
00182       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
00183       ++i;
00184     }
00185 
00186   _dbus_type_reader_init (&reader,
00187                           header->byte_order,
00188                           &_dbus_header_signature_str,
00189                           FIELDS_ARRAY_SIGNATURE_OFFSET,
00190                           &header->data,
00191                           FIELDS_ARRAY_LENGTH_OFFSET);
00192 
00193   _dbus_type_reader_recurse (&reader, &array);
00194 
00195   while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00196     {
00197       DBusTypeReader sub;
00198       DBusTypeReader variant;
00199       unsigned char field_code;
00200 
00201       _dbus_type_reader_recurse (&array, &sub);
00202 
00203       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
00204       _dbus_type_reader_read_basic (&sub, &field_code);
00205 
00206       /* Unknown fields should be ignored */
00207       if (field_code > DBUS_HEADER_FIELD_LAST)
00208         goto next_field;
00209 
00210       _dbus_type_reader_next (&sub);
00211 
00212       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
00213       _dbus_type_reader_recurse (&sub, &variant);
00214 
00215       _dbus_header_cache_one (header, field_code, &variant);
00216 
00217     next_field:
00218       _dbus_type_reader_next (&array);
00219     }
00220 }
00221 
00229 static dbus_bool_t
00230 _dbus_header_cache_check (DBusHeader    *header,
00231                           int            field)
00232 {
00233   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00234 
00235   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
00236     _dbus_header_cache_revalidate (header);
00237 
00238   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
00239     return FALSE;
00240 
00241   return TRUE;
00242 }
00243 
00252 static dbus_bool_t
00253 _dbus_header_cache_known_nonexistent (DBusHeader    *header,
00254                                       int            field)
00255 {
00256   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00257 
00258   return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
00259 }
00260 
00269 static dbus_bool_t
00270 write_basic_field (DBusTypeWriter *writer,
00271                    int             field,
00272                    int             type,
00273                    const void     *value)
00274 {
00275   DBusTypeWriter sub;
00276   DBusTypeWriter variant;
00277   int start;
00278   int padding;
00279   unsigned char field_byte;
00280   DBusString contained_type;
00281   char buf[2];
00282 
00283   start = writer->value_pos;
00284   padding = _dbus_string_get_length (writer->value_str) - start;
00285 
00286   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
00287                                   NULL, 0, &sub))
00288     goto append_failed;
00289 
00290   field_byte = field;
00291   if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
00292                                       &field_byte))
00293     goto append_failed;
00294 
00295   buf[0] = type;
00296   buf[1] = '\0';
00297   _dbus_string_init_const_len (&contained_type, buf, 1);
00298 
00299   if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
00300                                   &contained_type, 0, &variant))
00301     goto append_failed;
00302 
00303   if (!_dbus_type_writer_write_basic (&variant, type, value))
00304     goto append_failed;
00305 
00306   if (!_dbus_type_writer_unrecurse (&sub, &variant))
00307     goto append_failed;
00308 
00309   if (!_dbus_type_writer_unrecurse (writer, &sub))
00310     goto append_failed;
00311 
00312   return TRUE;
00313 
00314  append_failed:
00315   _dbus_string_delete (writer->value_str,
00316                        start,
00317                        _dbus_string_get_length (writer->value_str) - start - padding);
00318   return FALSE;
00319 }
00320 
00330 static dbus_bool_t
00331 set_basic_field (DBusTypeReader       *reader,
00332                  int                   field,
00333                  int                   type,
00334                  const void           *value,
00335                  const DBusTypeReader *realign_root)
00336 {
00337   DBusTypeReader sub;
00338   DBusTypeReader variant;
00339 
00340   _dbus_type_reader_recurse (reader, &sub);
00341 
00342   _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
00343 #ifndef DBUS_DISABLE_ASSERT
00344  {
00345    unsigned char v_BYTE;
00346    _dbus_type_reader_read_basic (&sub, &v_BYTE);
00347    _dbus_assert (((int) v_BYTE) == field);
00348  }
00349 #endif
00350 
00351   if (!_dbus_type_reader_next (&sub))
00352     _dbus_assert_not_reached ("no variant field?");
00353 
00354   _dbus_type_reader_recurse (&sub, &variant);
00355   _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
00356 
00357   if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
00358     return FALSE;
00359 
00360   return TRUE;
00361 }
00362 
00369 int
00370 _dbus_header_get_message_type (DBusHeader *header)
00371 {
00372   int type;
00373 
00374   type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
00375   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
00376 
00377   return type;
00378 }
00379 
00387 void
00388 _dbus_header_set_serial (DBusHeader    *header,
00389                          dbus_uint32_t  serial)
00390 {
00391   /* we use this function to set the serial on outgoing
00392    * messages, and to reset the serial in dbus_message_copy;
00393    * this assertion should catch a double-set on outgoing.
00394    */
00395   _dbus_assert (_dbus_header_get_serial (header) == 0 ||
00396                 serial == 0);
00397 
00398   _dbus_marshal_set_uint32 (&header->data,
00399                             SERIAL_OFFSET,
00400                             serial,
00401                             header->byte_order);
00402 }
00403 
00410 dbus_uint32_t
00411 _dbus_header_get_serial (DBusHeader *header)
00412 {
00413   return _dbus_marshal_read_uint32 (&header->data,
00414                                     SERIAL_OFFSET,
00415                                     header->byte_order,
00416                                     NULL);
00417 }
00418 
00427 void
00428 _dbus_header_reinit (DBusHeader *header,
00429                      int         byte_order)
00430 {
00431   _dbus_string_set_length (&header->data, 0);
00432 
00433   header->byte_order = byte_order;
00434   header->padding = 0;
00435 
00436   _dbus_header_cache_invalidate_all (header);
00437 }
00438 
00447 dbus_bool_t
00448 _dbus_header_init (DBusHeader *header,
00449                    int         byte_order)
00450 {
00451   if (!_dbus_string_init_preallocated (&header->data, 32))
00452     return FALSE;
00453 
00454   _dbus_header_reinit (header, byte_order);
00455 
00456   return TRUE;
00457 }
00458 
00464 void
00465 _dbus_header_free (DBusHeader *header)
00466 {
00467   _dbus_string_free (&header->data);
00468 }
00469 
00478 dbus_bool_t
00479 _dbus_header_copy (const DBusHeader *header,
00480                    DBusHeader       *dest)
00481 {
00482   *dest = *header;
00483 
00484   if (!_dbus_string_init_preallocated (&dest->data,
00485                                        _dbus_string_get_length (&header->data)))
00486     return FALSE;
00487 
00488   if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
00489     {
00490       _dbus_string_free (&dest->data);
00491       return FALSE;
00492     }
00493 
00494   /* Reset the serial */
00495   _dbus_header_set_serial (dest, 0);
00496 
00497   return TRUE;
00498 }
00499 
00515 dbus_bool_t
00516 _dbus_header_create (DBusHeader  *header,
00517                      int          message_type,
00518                      const char  *destination,
00519                      const char  *path,
00520                      const char  *interface,
00521                      const char  *member,
00522                      const char  *error_name)
00523 {
00524   unsigned char v_BYTE;
00525   dbus_uint32_t v_UINT32;
00526   DBusTypeWriter writer;
00527   DBusTypeWriter array;
00528 
00529   _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
00530                 (error_name) ||
00531                 !(interface || member || error_name));
00532   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
00533 
00534   if (!reserve_header_padding (header))
00535     return FALSE;
00536 
00537   _dbus_type_writer_init_values_only (&writer, header->byte_order,
00538                                       &_dbus_header_signature_str, 0,
00539                                       &header->data,
00540                                       HEADER_END_BEFORE_PADDING (header));
00541 
00542   v_BYTE = header->byte_order;
00543   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00544                                       &v_BYTE))
00545     goto oom;
00546 
00547   v_BYTE = message_type;
00548   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00549                                       &v_BYTE))
00550     goto oom;
00551 
00552   v_BYTE = 0; /* flags */
00553   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00554                                       &v_BYTE))
00555     goto oom;
00556 
00557   v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
00558   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
00559                                       &v_BYTE))
00560     goto oom;
00561 
00562   v_UINT32 = 0; /* body length */
00563   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
00564                                       &v_UINT32))
00565     goto oom;
00566 
00567   v_UINT32 = 0; /* serial */
00568   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
00569                                       &v_UINT32))
00570     goto oom;
00571 
00572   if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
00573                                   &_dbus_header_signature_str,
00574                                   FIELDS_ARRAY_SIGNATURE_OFFSET,
00575                                   &array))
00576     goto oom;
00577 
00578   /* Marshal all the fields (Marshall Fields?) */
00579 
00580   if (path != NULL)
00581     {
00582       if (!write_basic_field (&array,
00583                               DBUS_HEADER_FIELD_PATH,
00584                               DBUS_TYPE_OBJECT_PATH,
00585                               &path))
00586         goto oom;
00587     }
00588 
00589   if (destination != NULL)
00590     {
00591       if (!write_basic_field (&array,
00592                               DBUS_HEADER_FIELD_DESTINATION,
00593                               DBUS_TYPE_STRING,
00594                               &destination))
00595         goto oom;
00596     }
00597 
00598   if (interface != NULL)
00599     {
00600       if (!write_basic_field (&array,
00601                               DBUS_HEADER_FIELD_INTERFACE,
00602                               DBUS_TYPE_STRING,
00603                               &interface))
00604         goto oom;
00605     }
00606 
00607   if (member != NULL)
00608     {
00609       if (!write_basic_field (&array,
00610                               DBUS_HEADER_FIELD_MEMBER,
00611                               DBUS_TYPE_STRING,
00612                               &member))
00613         goto oom;
00614     }
00615 
00616   if (error_name != NULL)
00617     {
00618       if (!write_basic_field (&array,
00619                               DBUS_HEADER_FIELD_ERROR_NAME,
00620                               DBUS_TYPE_STRING,
00621                               &error_name))
00622         goto oom;
00623     }
00624 
00625   if (!_dbus_type_writer_unrecurse (&writer, &array))
00626     goto oom;
00627 
00628   correct_header_padding (header);
00629 
00630   return TRUE;
00631 
00632  oom:
00633   _dbus_string_delete (&header->data, 0,
00634                        _dbus_string_get_length (&header->data) - header->padding);
00635   correct_header_padding (header);
00636 
00637   return FALSE;
00638 }
00639 
00657 dbus_bool_t
00658 _dbus_header_have_message_untrusted (int                max_message_length,
00659                                      DBusValidity      *validity,
00660                                      int               *byte_order,
00661                                      int               *fields_array_len,
00662                                      int               *header_len,
00663                                      int               *body_len,
00664                                      const DBusString  *str,
00665                                      int                start,
00666                                      int                len)
00667 
00668 {
00669   dbus_uint32_t header_len_unsigned;
00670   dbus_uint32_t fields_array_len_unsigned;
00671   dbus_uint32_t body_len_unsigned;
00672 
00673   _dbus_assert (start >= 0);
00674   _dbus_assert (start < _DBUS_INT32_MAX / 2);
00675   _dbus_assert (len >= 0);
00676 
00677   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
00678 
00679   *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
00680 
00681   if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
00682     {
00683       *validity = DBUS_INVALID_BAD_BYTE_ORDER;
00684       return FALSE;
00685     }
00686 
00687   _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len);
00688   fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
00689                                                          *byte_order, NULL);
00690 
00691   if (fields_array_len_unsigned > (unsigned) max_message_length)
00692     {
00693       *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
00694       return FALSE;
00695     }
00696 
00697   _dbus_assert (BODY_LENGTH_OFFSET + 4 < len);
00698   body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
00699                                                  *byte_order, NULL);
00700 
00701   if (body_len_unsigned > (unsigned) max_message_length)
00702     {
00703       *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
00704       return FALSE;
00705     }
00706 
00707   header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
00708   header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
00709 
00710   /* overflow should be impossible since the lengths aren't allowed to
00711    * be huge.
00712    */
00713   _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
00714   if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
00715     {
00716       *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
00717       return FALSE;
00718     }
00719 
00720   _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
00721   _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
00722   _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
00723 
00724   *body_len = body_len_unsigned;
00725   *fields_array_len = fields_array_len_unsigned;
00726   *header_len = header_len_unsigned;
00727 
00728   *validity = DBUS_VALID;
00729 
00730   _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
00731                  len, body_len_unsigned, header_len_unsigned,
00732                  body_len_unsigned + header_len_unsigned);
00733 
00734   return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
00735 }
00736 
00737 static DBusValidity
00738 check_mandatory_fields (DBusHeader *header)
00739 {
00740 #define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
00741 
00742   switch (_dbus_header_get_message_type (header))
00743     {
00744     case DBUS_MESSAGE_TYPE_SIGNAL:
00745       REQUIRE_FIELD (INTERFACE);
00746       /* FALL THRU - signals also require the path and member */
00747     case DBUS_MESSAGE_TYPE_METHOD_CALL:
00748       REQUIRE_FIELD (PATH);
00749       REQUIRE_FIELD (MEMBER);
00750       break;
00751     case DBUS_MESSAGE_TYPE_ERROR:
00752       REQUIRE_FIELD (ERROR_NAME);
00753       REQUIRE_FIELD (REPLY_SERIAL);
00754       break;
00755     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00756       REQUIRE_FIELD (REPLY_SERIAL);
00757       break;
00758     default:
00759       /* other message types allowed but ignored */
00760       break;
00761     }
00762 
00763   return DBUS_VALID;
00764 }
00765 
00766 static DBusValidity
00767 load_and_validate_field (DBusHeader     *header,
00768                          int             field,
00769                          DBusTypeReader *variant_reader)
00770 {
00771   int type;
00772   int expected_type;
00773   const DBusString *value_str;
00774   int value_pos;
00775   int str_data_pos;
00776   dbus_uint32_t v_UINT32;
00777   int bad_string_code;
00778   dbus_bool_t (* string_validation_func) (const DBusString *str,
00779                                           int start, int len);
00780 
00781   /* Supposed to have been checked already */
00782   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00783   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
00784 
00785   /* Before we can cache a field, we need to know it has the right type */
00786   type = _dbus_type_reader_get_current_type (variant_reader);
00787 
00788   _dbus_assert (_dbus_header_field_types[field].code == field);
00789 
00790   expected_type = EXPECTED_TYPE_OF_FIELD (field);
00791   if (type != expected_type)
00792     {
00793       _dbus_verbose ("Field %d should have type %d but has %d\n",
00794                      field, expected_type, type);
00795       return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
00796     }
00797 
00798   /* If the field was provided twice, we aren't happy */
00799   if (header->fields[field].value_pos >= 0)
00800     {
00801       _dbus_verbose ("Header field %d seen a second time\n", field);
00802       return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
00803     }
00804 
00805   /* Now we can cache and look at the field content */
00806   _dbus_verbose ("initially caching field %d\n", field);
00807   _dbus_header_cache_one (header, field, variant_reader);
00808 
00809   string_validation_func = NULL;
00810 
00811   /* make compiler happy that all this is initialized */
00812   v_UINT32 = 0;
00813   value_str = NULL;
00814   value_pos = -1;
00815   str_data_pos = -1;
00816   bad_string_code = DBUS_VALID;
00817 
00818   if (expected_type == DBUS_TYPE_UINT32)
00819     {
00820       _dbus_header_get_field_basic (header, field, expected_type,
00821                                     &v_UINT32);
00822     }
00823   else if (expected_type == DBUS_TYPE_STRING ||
00824            expected_type == DBUS_TYPE_OBJECT_PATH ||
00825            expected_type == DBUS_TYPE_SIGNATURE)
00826     {
00827       _dbus_header_get_field_raw (header, field,
00828                                   &value_str, &value_pos);
00829       str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
00830     }
00831   else
00832     {
00833       _dbus_assert_not_reached ("none of the known fields should have this type");
00834     }
00835 
00836   switch (field)
00837     {
00838     case DBUS_HEADER_FIELD_DESTINATION:
00839       string_validation_func = _dbus_validate_bus_name;
00840       bad_string_code = DBUS_INVALID_BAD_DESTINATION;
00841       break;
00842     case DBUS_HEADER_FIELD_INTERFACE:
00843       string_validation_func = _dbus_validate_interface;
00844       bad_string_code = DBUS_INVALID_BAD_INTERFACE;
00845 
00846       if (_dbus_string_equal_substring (&_dbus_local_interface_str,
00847                                         0,
00848                                         _dbus_string_get_length (&_dbus_local_interface_str),
00849                                         value_str, str_data_pos))
00850         {
00851           _dbus_verbose ("Message is on the local interface\n");
00852           return DBUS_INVALID_USES_LOCAL_INTERFACE;
00853         }
00854       break;
00855 
00856     case DBUS_HEADER_FIELD_MEMBER:
00857       string_validation_func = _dbus_validate_member;
00858       bad_string_code = DBUS_INVALID_BAD_MEMBER;
00859       break;
00860 
00861     case DBUS_HEADER_FIELD_ERROR_NAME:
00862       string_validation_func = _dbus_validate_error_name;
00863       bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
00864       break;
00865 
00866     case DBUS_HEADER_FIELD_SENDER:
00867       string_validation_func = _dbus_validate_bus_name;
00868       bad_string_code = DBUS_INVALID_BAD_SENDER;
00869       break;
00870 
00871     case DBUS_HEADER_FIELD_PATH:
00872       /* OBJECT_PATH was validated generically due to its type */
00873       string_validation_func = NULL;
00874 
00875       if (_dbus_string_equal_substring (&_dbus_local_path_str,
00876                                         0,
00877                                         _dbus_string_get_length (&_dbus_local_path_str),
00878                                         value_str, str_data_pos))
00879         {
00880           _dbus_verbose ("Message is from the local path\n");
00881           return DBUS_INVALID_USES_LOCAL_PATH;
00882         }
00883       break;
00884 
00885     case DBUS_HEADER_FIELD_REPLY_SERIAL:
00886       /* Can't be 0 */
00887       if (v_UINT32 == 0)
00888         {
00889           return DBUS_INVALID_BAD_SERIAL;
00890         }
00891       break;
00892 
00893     case DBUS_HEADER_FIELD_UNIX_FDS:
00894       /* Every value makes sense */
00895       break;
00896 
00897     case DBUS_HEADER_FIELD_SIGNATURE:
00898       /* SIGNATURE validated generically due to its type */
00899       string_validation_func = NULL;
00900       break;
00901 
00902     default:
00903       _dbus_assert_not_reached ("unknown field shouldn't be seen here");
00904       break;
00905     }
00906 
00907   if (string_validation_func)
00908     {
00909       dbus_uint32_t len;
00910 
00911       _dbus_assert (bad_string_code != DBUS_VALID);
00912 
00913       len = _dbus_marshal_read_uint32 (value_str, value_pos,
00914                                        header->byte_order, NULL);
00915 
00916 #if 0
00917       _dbus_verbose ("Validating string header field; code %d if fails\n",
00918                      bad_string_code);
00919 #endif
00920       if (!(*string_validation_func) (value_str, str_data_pos, len))
00921         return bad_string_code;
00922     }
00923 
00924   return DBUS_VALID;
00925 }
00926 
00953 dbus_bool_t
00954 _dbus_header_load (DBusHeader        *header,
00955                    DBusValidationMode mode,
00956                    DBusValidity      *validity,
00957                    int                byte_order,
00958                    int                fields_array_len,
00959                    int                header_len,
00960                    int                body_len,
00961                    const DBusString  *str,
00962                    int                start,
00963                    int                len)
00964 {
00965   int leftover;
00966   DBusValidity v;
00967   DBusTypeReader reader;
00968   DBusTypeReader array_reader;
00969   unsigned char v_byte;
00970   dbus_uint32_t v_uint32;
00971   dbus_uint32_t serial;
00972   int padding_start;
00973   int padding_len;
00974   int i;
00975 
00976   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
00977   _dbus_assert (header_len <= len);
00978   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
00979 
00980   if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
00981     {
00982       _dbus_verbose ("Failed to copy buffer into new header\n");
00983       *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
00984       return FALSE;
00985     }
00986 
00987   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
00988     {
00989       leftover = len - header_len - body_len - start;
00990     }
00991   else
00992     {
00993       v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
00994                                            byte_order,
00995                                            &leftover,
00996                                            str, start, len);
00997       
00998       if (v != DBUS_VALID)
00999         {
01000           *validity = v;
01001           goto invalid;
01002         }
01003     }
01004 
01005   _dbus_assert (leftover < len);
01006 
01007   padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
01008   padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
01009   _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
01010   _dbus_assert (start + header_len == padding_start + padding_len);
01011 
01012   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
01013     {
01014       if (!_dbus_string_validate_nul (str, padding_start, padding_len))
01015         {
01016           *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
01017           goto invalid;
01018         }
01019     }
01020 
01021   header->padding = padding_len;
01022 
01023   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
01024     {
01025       *validity = DBUS_VALID;
01026       return TRUE;
01027     }
01028 
01029   /* We now know the data is well-formed, but we have to check that
01030    * it's valid.
01031    */
01032 
01033   _dbus_type_reader_init (&reader,
01034                           byte_order,
01035                           &_dbus_header_signature_str, 0,
01036                           str, start);
01037 
01038   /* BYTE ORDER */
01039   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01040   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
01041   _dbus_type_reader_read_basic (&reader, &v_byte);
01042   _dbus_type_reader_next (&reader);
01043 
01044   _dbus_assert (v_byte == byte_order);
01045   header->byte_order = byte_order;
01046 
01047   /* MESSAGE TYPE */
01048   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01049   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
01050   _dbus_type_reader_read_basic (&reader, &v_byte);
01051   _dbus_type_reader_next (&reader);
01052 
01053   /* unknown message types are supposed to be ignored, so only validation here is
01054    * that it isn't invalid
01055    */
01056   if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
01057     {
01058       *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
01059       goto invalid;
01060     }
01061 
01062   /* FLAGS */
01063   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01064   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
01065   _dbus_type_reader_read_basic (&reader, &v_byte);
01066   _dbus_type_reader_next (&reader);
01067 
01068   /* unknown flags should be ignored */
01069 
01070   /* PROTOCOL VERSION */
01071   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
01072   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
01073   _dbus_type_reader_read_basic (&reader, &v_byte);
01074   _dbus_type_reader_next (&reader);
01075 
01076   if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
01077     {
01078       *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
01079       goto invalid;
01080     }
01081 
01082   /* BODY LENGTH */
01083   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
01084   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
01085   _dbus_type_reader_read_basic (&reader, &v_uint32);
01086   _dbus_type_reader_next (&reader);
01087 
01088   _dbus_assert (body_len == (signed) v_uint32);
01089 
01090   /* SERIAL */
01091   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
01092   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
01093   _dbus_type_reader_read_basic (&reader, &serial);
01094   _dbus_type_reader_next (&reader);
01095 
01096   if (serial == 0)
01097     {
01098       *validity = DBUS_INVALID_BAD_SERIAL;
01099       goto invalid;
01100     }
01101 
01102   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
01103   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);
01104 
01105   _dbus_type_reader_recurse (&reader, &array_reader);
01106   while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
01107     {
01108       DBusTypeReader struct_reader;
01109       DBusTypeReader variant_reader;
01110       unsigned char field_code;
01111 
01112       _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);
01113 
01114       _dbus_type_reader_recurse (&array_reader, &struct_reader);
01115 
01116       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
01117       _dbus_type_reader_read_basic (&struct_reader, &field_code);
01118       _dbus_type_reader_next (&struct_reader);
01119 
01120       if (field_code == DBUS_HEADER_FIELD_INVALID)
01121         {
01122           _dbus_verbose ("invalid header field code\n");
01123           *validity = DBUS_INVALID_HEADER_FIELD_CODE;
01124           goto invalid;
01125         }
01126 
01127       if (field_code > DBUS_HEADER_FIELD_LAST)
01128         {
01129           _dbus_verbose ("unknown header field code %d, skipping\n",
01130                          field_code);
01131           goto next_field;
01132         }
01133 
01134       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
01135       _dbus_type_reader_recurse (&struct_reader, &variant_reader);
01136 
01137       v = load_and_validate_field (header, field_code, &variant_reader);
01138       if (v != DBUS_VALID)
01139         {
01140           _dbus_verbose ("Field %d was invalid\n", field_code);
01141           *validity = v;
01142           goto invalid;
01143         }
01144 
01145     next_field:
01146       _dbus_type_reader_next (&array_reader);
01147     }
01148 
01149   /* Anything we didn't fill in is now known not to exist */
01150   i = 0;
01151   while (i <= DBUS_HEADER_FIELD_LAST)
01152     {
01153       if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
01154         header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
01155       ++i;
01156     }
01157 
01158   v = check_mandatory_fields (header);
01159   if (v != DBUS_VALID)
01160     {
01161       _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
01162       *validity = v;
01163       goto invalid;
01164     }
01165 
01166   *validity = DBUS_VALID;
01167   return TRUE;
01168 
01169  invalid:
01170   _dbus_string_set_length (&header->data, 0);
01171   return FALSE;
01172 }
01173 
01180 void
01181 _dbus_header_update_lengths (DBusHeader *header,
01182                              int         body_len)
01183 {
01184   _dbus_marshal_set_uint32 (&header->data,
01185                             BODY_LENGTH_OFFSET,
01186                             body_len,
01187                             header->byte_order);
01188 }
01189 
01190 static dbus_bool_t
01191 find_field_for_modification (DBusHeader     *header,
01192                              int             field,
01193                              DBusTypeReader *reader,
01194                              DBusTypeReader *realign_root)
01195 {
01196   dbus_bool_t retval;
01197 
01198   retval = FALSE;
01199 
01200   _dbus_type_reader_init (realign_root,
01201                           header->byte_order,
01202                           &_dbus_header_signature_str,
01203                           FIELDS_ARRAY_SIGNATURE_OFFSET,
01204                           &header->data,
01205                           FIELDS_ARRAY_LENGTH_OFFSET);
01206 
01207   _dbus_type_reader_recurse (realign_root, reader);
01208 
01209   while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID)
01210     {
01211       DBusTypeReader sub;
01212       unsigned char field_code;
01213 
01214       _dbus_type_reader_recurse (reader, &sub);
01215 
01216       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
01217       _dbus_type_reader_read_basic (&sub, &field_code);
01218 
01219       if (field_code == (unsigned) field)
01220         {
01221           _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT);
01222           retval = TRUE;
01223           goto done;
01224         }
01225 
01226       _dbus_type_reader_next (reader);
01227     }
01228 
01229  done:
01230   return retval;
01231 }
01232 
01244 dbus_bool_t
01245 _dbus_header_set_field_basic (DBusHeader       *header,
01246                               int               field,
01247                               int               type,
01248                               const void       *value)
01249 {
01250   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
01251 
01252   if (!reserve_header_padding (header))
01253     return FALSE;
01254 
01255   /* If the field exists we set, otherwise we append */
01256   if (_dbus_header_cache_check (header, field))
01257     {
01258       DBusTypeReader reader;
01259       DBusTypeReader realign_root;
01260 
01261       if (!find_field_for_modification (header, field,
01262                                         &reader, &realign_root))
01263         _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
01264 
01265       if (!set_basic_field (&reader, field, type, value, &realign_root))
01266         return FALSE;
01267     }
01268   else
01269     {
01270       DBusTypeWriter writer;
01271       DBusTypeWriter array;
01272 
01273       _dbus_type_writer_init_values_only (&writer,
01274                                           header->byte_order,
01275                                           &_dbus_header_signature_str,
01276                                           FIELDS_ARRAY_SIGNATURE_OFFSET,
01277                                           &header->data,
01278                                           FIELDS_ARRAY_LENGTH_OFFSET);
01279 
01280       /* recurse into array without creating a new length, and jump to
01281        * end of array.
01282        */
01283       if (!_dbus_type_writer_append_array (&writer,
01284                                            &_dbus_header_signature_str,
01285                                            FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET,
01286                                            &array))
01287         _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
01288 
01289       _dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET);
01290       _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
01291       _dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header));
01292 
01293       if (!write_basic_field (&array,
01294                               field, type, value))
01295         return FALSE;
01296 
01297       if (!_dbus_type_writer_unrecurse (&writer, &array))
01298         _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
01299     }
01300 
01301   correct_header_padding (header);
01302 
01303   /* We could be smarter about this (only invalidate fields after the
01304    * one we modified, or even only if the one we modified changed
01305    * length). But this hack is a start.
01306    */
01307   _dbus_header_cache_invalidate_all (header);
01308 
01309   return TRUE;
01310 }
01311 
01322 dbus_bool_t
01323 _dbus_header_get_field_basic (DBusHeader    *header,
01324                               int            field,
01325                               int            type,
01326                               void          *value)
01327 {
01328   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
01329   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
01330   _dbus_assert (_dbus_header_field_types[field].code == field);
01331   /* in light of this you might ask why the type is passed in;
01332    * the only rationale I can think of is so the caller has
01333    * to specify its expectation and breaks if we change it
01334    */
01335   _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
01336 
01337   if (!_dbus_header_cache_check (header, field))
01338     return FALSE;
01339 
01340   _dbus_assert (header->fields[field].value_pos >= 0);
01341 
01342   _dbus_marshal_read_basic (&header->data,
01343                             header->fields[field].value_pos,
01344                             type, value, header->byte_order,
01345                             NULL);
01346 
01347   return TRUE;
01348 }
01349 
01363 dbus_bool_t
01364 _dbus_header_get_field_raw (DBusHeader        *header,
01365                             int                field,
01366                             const DBusString **str,
01367                             int               *pos)
01368 {
01369   if (!_dbus_header_cache_check (header, field))
01370     return FALSE;
01371 
01372   if (str)
01373     *str = &header->data;
01374   if (pos)
01375     *pos = header->fields[field].value_pos;
01376 
01377   return TRUE;
01378 }
01379 
01387 dbus_bool_t
01388 _dbus_header_delete_field (DBusHeader *header,
01389                            int         field)
01390 {
01391   DBusTypeReader reader;
01392   DBusTypeReader realign_root;
01393 
01394   if (_dbus_header_cache_known_nonexistent (header, field))
01395     return TRUE; /* nothing to do */
01396 
01397   /* Scan to the field we want, delete and realign, reappend
01398    * padding. Field may turn out not to exist.
01399    */
01400   if (!find_field_for_modification (header, field,
01401                                     &reader, &realign_root))
01402     return TRUE; /* nothing to do */
01403 
01404   if (!reserve_header_padding (header))
01405     return FALSE;
01406 
01407   if (!_dbus_type_reader_delete (&reader,
01408                                  &realign_root))
01409     return FALSE;
01410 
01411   correct_header_padding (header);
01412 
01413   _dbus_header_cache_invalidate_all (header);
01414 
01415   _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
01416 
01417   return TRUE;
01418 }
01419 
01428 void
01429 _dbus_header_toggle_flag (DBusHeader   *header,
01430                           dbus_uint32_t flag,
01431                           dbus_bool_t   value)
01432 {
01433   unsigned char *flags_p;
01434 
01435   flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1);
01436 
01437   if (value)
01438     *flags_p |= flag;
01439   else
01440     *flags_p &= ~flag;
01441 }
01442 
01450 dbus_bool_t
01451 _dbus_header_get_flag (DBusHeader   *header,
01452                        dbus_uint32_t flag)
01453 {
01454   const unsigned char *flags_p;
01455 
01456   flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1);
01457 
01458   return (*flags_p & flag) != 0;
01459 }
01460 
01467 void
01468 _dbus_header_byteswap (DBusHeader *header,
01469                        int         new_order)
01470 {
01471   if (header->byte_order == new_order)
01472     return;
01473 
01474   _dbus_marshal_byteswap (&_dbus_header_signature_str,
01475                           0, header->byte_order,
01476                           new_order,
01477                           &header->data, 0);
01478 
01479   header->byte_order = new_order;
01480 }
01481 
01484 #ifdef DBUS_BUILD_TESTS
01485 #include "dbus-test.h"
01486 #include <stdio.h>
01487 
01488 dbus_bool_t
01489 _dbus_marshal_header_test (void)
01490 {
01491 
01492   return TRUE;
01493 }
01494 
01495 #endif /* DBUS_BUILD_TESTS */

Generated on Mon Sep 27 2010 22:54:23 for D-Bus by  doxygen 1.7.1