Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

dbus-marshal-header.c

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

Generated on Wed Jan 3 04:49:04 2007 for D-BUS by  doxygen 1.4.4