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

Generated on Fri Sep 21 18:12:12 2007 for D-Bus by  doxygen 1.5.1