LCOV - code coverage report
Current view: top level - pkcs11/rpc-layer - gkm-rpc-message.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 54.9 % 206 113
Test Date: 2024-04-08 13:24:42 Functions: 59.1 % 22 13

            Line data    Source code
       1              : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
       2              : /* p11-rpc-message.c - our marshalled PKCS#11 protocol.
       3              : 
       4              :    Copyright (C) 2008, Stef Walter
       5              : 
       6              :    The Gnome Keyring Library is free software; you can redistribute it and/or
       7              :    modify it under the terms of the GNU Library General Public License as
       8              :    published by the Free Software Foundation; either version 2 of the
       9              :    License, or (at your option) any later version.
      10              : 
      11              :    The Gnome Keyring Library is distributed in the hope that it will be useful,
      12              :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :    Library General Public License for more details.
      15              : 
      16              :    You should have received a copy of the GNU Library General Public
      17              :    License along with the Gnome Library; see the file COPYING.LIB.  If not,
      18              :    <http://www.gnu.org/licenses/>.
      19              : 
      20              :    Author: Stef Walter <stef@memberwebs.com>
      21              : */
      22              : 
      23              : #include "config.h"
      24              : 
      25              : #include "gkm-rpc-layer.h"
      26              : #include "gkm-rpc-private.h"
      27              : 
      28              : #include <string.h>
      29              : 
      30              : #ifdef G_DISABLE_ASSERT
      31              : #define assert(x)
      32              : #else
      33              : #include <assert.h>
      34              : #endif
      35              : 
      36              : GkmRpcMessage*
      37            8 : gkm_rpc_message_new (EggBufferAllocator allocator)
      38              : {
      39              :         GkmRpcMessage *msg;
      40              : 
      41            8 :         assert (allocator);
      42              : 
      43            8 :         msg = (GkmRpcMessage*) (allocator)(NULL, sizeof (GkmRpcMessage));
      44            8 :         if (!msg)
      45            0 :                 return NULL;
      46            8 :         memset (msg, 0, sizeof (*msg));
      47              : 
      48            8 :         if (!egg_buffer_init_full (&msg->buffer, 64, allocator)) {
      49            0 :                 (allocator) (msg, 0); /* Frees allocation */
      50            0 :                 return NULL;
      51              :         }
      52              : 
      53            8 :         gkm_rpc_message_reset (msg);
      54              : 
      55            8 :         return msg;
      56              : }
      57              : 
      58              : void
      59            8 : gkm_rpc_message_free (GkmRpcMessage *msg)
      60              : {
      61              :         EggBufferAllocator allocator;
      62              : 
      63            8 :         if (msg) {
      64            8 :                 assert (msg->buffer.allocator);
      65            8 :                 allocator = msg->buffer.allocator;
      66            8 :                 egg_buffer_uninit (&msg->buffer);
      67              : 
      68              :                 /* frees data buffer */
      69            8 :                 (allocator) (msg, 0);
      70              :         }
      71            8 : }
      72              : 
      73              : void
      74           52 : gkm_rpc_message_reset (GkmRpcMessage *msg)
      75              : {
      76           52 :         assert (msg);
      77              : 
      78           52 :         msg->call_id = 0;
      79           52 :         msg->call_type = 0;
      80           52 :         msg->signature = NULL;
      81           52 :         msg->sigverify = NULL;
      82           52 :         msg->parsed = 0;
      83              : 
      84           52 :         egg_buffer_reset (&msg->buffer);
      85           52 : }
      86              : 
      87              : int
      88           12 : gkm_rpc_message_prep (GkmRpcMessage *msg, int call_id, GkmRpcMessageType type)
      89              : {
      90              :         int len;
      91              : 
      92           12 :         assert (type);
      93           12 :         assert (call_id >= GKM_RPC_CALL_ERROR);
      94           12 :         assert (call_id < GKM_RPC_CALL_MAX);
      95              : 
      96           12 :         gkm_rpc_message_reset (msg);
      97              : 
      98           12 :         if (call_id != GKM_RPC_CALL_ERROR) {
      99              : 
     100              :                 /* The call id and signature */
     101           12 :                 if (type == GKM_RPC_REQUEST)
     102            6 :                         msg->signature = gkm_rpc_calls[call_id].request;
     103            6 :                 else if (type == GKM_RPC_RESPONSE)
     104            6 :                         msg->signature = gkm_rpc_calls[call_id].response;
     105              :                 else
     106            0 :                         assert (0 && "invalid message type");
     107           12 :                 assert (msg->signature);
     108           12 :                 msg->sigverify = msg->signature;
     109              :         }
     110              : 
     111           12 :         msg->call_id = call_id;
     112           12 :         msg->call_type = type;
     113              : 
     114              :         /* Encode the two of them */
     115           12 :         egg_buffer_add_uint32 (&msg->buffer, call_id);
     116           12 :         if (msg->signature) {
     117           12 :                 len = strlen (msg->signature);
     118           12 :                 egg_buffer_add_byte_array (&msg->buffer, (unsigned char*)msg->signature, len);
     119              :         }
     120              : 
     121           12 :         msg->parsed = 0;
     122           12 :         return !egg_buffer_has_error (&msg->buffer);
     123              : }
     124              : 
     125              : int
     126           12 : gkm_rpc_message_parse (GkmRpcMessage *msg, GkmRpcMessageType type)
     127              : {
     128              :         const unsigned char *val;
     129              :         size_t len;
     130              :         uint32_t call_id;
     131              : 
     132           12 :         msg->parsed = 0;
     133              : 
     134              :         /* Pull out the call identifier */
     135           12 :         if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &(msg->parsed), &call_id)) {
     136            0 :                 gkm_rpc_warn ("invalid message: couldn't read call identifier");
     137            0 :                 return 0;
     138              :         }
     139              : 
     140           12 :         msg->signature = msg->sigverify = NULL;
     141              : 
     142              :         /* If it's an error code then no more processing */
     143           12 :         if (call_id == GKM_RPC_CALL_ERROR) {
     144            0 :                 if (type == GKM_RPC_REQUEST) {
     145            0 :                         gkm_rpc_warn ("invalid message: error code in request");
     146            0 :                         return 0;
     147              :                 }
     148              : 
     149            0 :                 return 1;
     150              :         }
     151              : 
     152              :         /* The call id and signature */
     153           12 :         if (call_id <= 0 || call_id >= GKM_RPC_CALL_MAX) {
     154            0 :                 gkm_rpc_warn ("invalid message: bad call id: %d", call_id);
     155            0 :                 return 0;
     156              :         }
     157           12 :         if (type == GKM_RPC_REQUEST)
     158            6 :                 msg->signature = gkm_rpc_calls[call_id].request;
     159            6 :         else if (type == GKM_RPC_RESPONSE)
     160            6 :                 msg->signature = gkm_rpc_calls[call_id].response;
     161              :         else
     162            0 :                 assert (0 && "invalid message type");
     163           12 :         msg->call_id = call_id;
     164           12 :         msg->call_type = type;
     165           12 :         msg->sigverify = msg->signature;
     166              : 
     167              :         /* Verify the incoming signature */
     168           12 :         if (!egg_buffer_get_byte_array (&msg->buffer, msg->parsed, &(msg->parsed), &val, &len)) {
     169            0 :                 gkm_rpc_warn ("invalid message: couldn't read signature");
     170            0 :                 return 0;
     171              :         }
     172              : 
     173           12 :         if ((strlen (msg->signature) != len) || (memcmp (val, msg->signature, len) != 0)) {
     174            0 :                 gkm_rpc_warn ("invalid message: signature doesn't match");
     175            0 :                 return 0;
     176              :         }
     177              : 
     178           12 :         return 1;
     179              : }
     180              : 
     181              : int
     182            0 : gkm_rpc_message_equals (GkmRpcMessage *m1, GkmRpcMessage *m2)
     183              : {
     184            0 :         assert (m1 && m2);
     185              : 
     186              :         /* Any errors and messages are never equal */
     187            0 :         if (egg_buffer_has_error (&m1->buffer) ||
     188            0 :             egg_buffer_has_error (&m2->buffer))
     189            0 :                 return 0;
     190              : 
     191              :         /* Calls and signatures must be identical */
     192            0 :         if (m1->call_id != m2->call_id)
     193            0 :                 return 0;
     194            0 :         if (m1->call_type != m2->call_type)
     195            0 :                 return 0;
     196            0 :         if (m1->signature && m2->signature) {
     197            0 :                 if (strcmp (m1->signature, m2->signature) != 0)
     198            0 :                         return 0;
     199            0 :         } else if (m1->signature != m2->signature) {
     200            0 :                 return 0;
     201              :         }
     202              : 
     203              :         /* Data in buffer must be identical */
     204            0 :         return egg_buffer_equal (&m1->buffer, &m2->buffer);
     205              : }
     206              : 
     207              : int
     208           24 : gkm_rpc_message_verify_part (GkmRpcMessage *msg, const char* part)
     209              : {
     210              :         int len, ok;
     211              : 
     212           24 :         if (!msg->sigverify)
     213            0 :                 return 1;
     214              : 
     215           24 :         len = strlen (part);
     216           24 :         ok = (strncmp (msg->sigverify, part, len) == 0);
     217           24 :         if (ok)
     218           24 :                 msg->sigverify += len;
     219           24 :         return ok;
     220              : }
     221              : 
     222              : int
     223            0 : gkm_rpc_message_write_attribute_buffer (GkmRpcMessage *msg, CK_ATTRIBUTE_PTR arr,
     224              :                                         CK_ULONG num)
     225              : {
     226              :         CK_ATTRIBUTE_PTR attr;
     227              :         CK_ULONG i;
     228              : 
     229            0 :         assert (!num || arr);
     230            0 :         assert (msg);
     231              : 
     232              :         /* Make sure this is in the rigth order */
     233            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "fA"));
     234              : 
     235              :         /* Write the number of items */
     236            0 :         egg_buffer_add_uint32 (&msg->buffer, num);
     237              : 
     238            0 :         for (i = 0; i < num; ++i) {
     239            0 :                 attr = &(arr[i]);
     240              : 
     241              :                 /* The attribute type */
     242            0 :                 egg_buffer_add_uint32 (&msg->buffer, attr->type);
     243              : 
     244              :                 /* And the attribute buffer length */
     245            0 :                 egg_buffer_add_uint32 (&msg->buffer, attr->pValue ? attr->ulValueLen : 0);
     246              :         }
     247              : 
     248            0 :         return !egg_buffer_has_error (&msg->buffer);
     249              : }
     250              : 
     251              : int
     252            0 : gkm_rpc_message_write_attribute_array (GkmRpcMessage *msg,
     253              :                                        CK_ATTRIBUTE_PTR arr, CK_ULONG num)
     254              : {
     255              :         CK_ULONG i;
     256              :         CK_ATTRIBUTE_PTR attr;
     257              :         unsigned char validity;
     258              : 
     259            0 :         assert (!num || arr);
     260            0 :         assert (msg);
     261              : 
     262              :         /* Make sure this is in the rigth order */
     263            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "aA"));
     264              : 
     265              :         /* Write the number of items */
     266            0 :         egg_buffer_add_uint32 (&msg->buffer, num);
     267              : 
     268            0 :         for (i = 0; i < num; ++i) {
     269            0 :                 attr = &(arr[i]);
     270              : 
     271              :                 /* The attribute type */
     272            0 :                 egg_buffer_add_uint32 (&msg->buffer, attr->type);
     273              : 
     274              :                 /* Write out the attribute validity */
     275            0 :                 validity = (((CK_LONG)attr->ulValueLen) == -1) ? 0 : 1;
     276            0 :                 egg_buffer_add_byte (&msg->buffer, validity);
     277              : 
     278              :                 /* The attribute length and value */
     279            0 :                 if (validity) {
     280            0 :                         egg_buffer_add_uint32 (&msg->buffer, attr->ulValueLen);
     281            0 :                         egg_buffer_add_byte_array (&msg->buffer, attr->pValue, attr->ulValueLen);
     282              :                 }
     283              :         }
     284              : 
     285            0 :         return !egg_buffer_has_error (&msg->buffer);
     286              : }
     287              : 
     288              : int
     289            0 : gkm_rpc_message_read_byte (GkmRpcMessage *msg, CK_BYTE *val)
     290              : {
     291            0 :         assert (msg);
     292              : 
     293              :         /* Make sure this is in the right order */
     294            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "y"));
     295            0 :         return egg_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, val);
     296              : }
     297              : 
     298              : int
     299            0 : gkm_rpc_message_write_byte (GkmRpcMessage *msg, CK_BYTE val)
     300              : {
     301            0 :         assert (msg);
     302              : 
     303              :         /* Make sure this is in the right order */
     304            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "y"));
     305            0 :         return egg_buffer_add_byte (&msg->buffer, val);
     306              : }
     307              : 
     308              : int
     309            2 : gkm_rpc_message_read_ulong (GkmRpcMessage *msg, CK_ULONG *val)
     310              : {
     311              :         uint64_t v;
     312            2 :         assert (msg);
     313              : 
     314              :         /* Make sure this is in the right order */
     315            2 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "u"));
     316              : 
     317            2 :         if (!egg_buffer_get_uint64 (&msg->buffer, msg->parsed, &msg->parsed, &v))
     318            0 :                 return 0;
     319            2 :         if (val)
     320            2 :                 *val = (CK_ULONG)v;
     321            2 :         return 1;
     322              : }
     323              : 
     324              : int
     325            2 : gkm_rpc_message_write_ulong (GkmRpcMessage *msg, CK_ULONG val)
     326              : {
     327            2 :         assert (msg);
     328              : 
     329              :         /* Make sure this is in the rigth order */
     330            2 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "u"));
     331            2 :         return egg_buffer_add_uint64 (&msg->buffer, val);
     332              : }
     333              : 
     334              : int
     335            0 : gkm_rpc_message_write_byte_buffer (GkmRpcMessage *msg, CK_ULONG count)
     336              : {
     337            0 :         assert (msg);
     338              : 
     339              :         /* Make sure this is in the right order */
     340            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "fy"));
     341            0 :         return egg_buffer_add_uint32 (&msg->buffer, count);
     342              : }
     343              : 
     344              : int
     345            2 : gkm_rpc_message_write_byte_array (GkmRpcMessage *msg, CK_BYTE_PTR arr, CK_ULONG num)
     346              : {
     347            2 :         assert (msg);
     348              : 
     349              :         /* Make sure this is in the right order */
     350            2 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "ay"));
     351              : 
     352              :         /* No array, no data, just length */
     353            2 :         if (!arr) {
     354            0 :                 egg_buffer_add_byte (&msg->buffer, 0);
     355            0 :                 egg_buffer_add_uint32 (&msg->buffer, num);
     356              :         } else {
     357            2 :                 egg_buffer_add_byte (&msg->buffer, 1);
     358            2 :                 egg_buffer_add_byte_array (&msg->buffer, arr, num);
     359              :         }
     360              : 
     361            2 :         return !egg_buffer_has_error (&msg->buffer);
     362              : }
     363              : 
     364              : int
     365            0 : gkm_rpc_message_write_ulong_buffer (GkmRpcMessage *msg, CK_ULONG count)
     366              : {
     367            0 :         assert (msg);
     368              : 
     369              :         /* Make sure this is in the right order */
     370            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "fu"));
     371            0 :         return egg_buffer_add_uint32 (&msg->buffer, count);
     372              : }
     373              : 
     374              : int
     375            0 : gkm_rpc_message_write_ulong_array (GkmRpcMessage *msg, CK_ULONG_PTR array, CK_ULONG n_array)
     376              : {
     377              :         CK_ULONG i;
     378              : 
     379            0 :         assert (msg);
     380              : 
     381              :         /* Check that we're supposed to have this at this point */
     382            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "au"));
     383              : 
     384              :         /* We send a byte which determines whether there's actual data present or not */
     385            0 :         egg_buffer_add_byte (&msg->buffer, array ? 1 : 0);
     386            0 :         egg_buffer_add_uint32 (&msg->buffer, n_array);
     387              : 
     388              :         /* Now send the data if valid */
     389            0 :         if (array) {
     390            0 :                 for (i = 0; i < n_array; ++i)
     391            0 :                         egg_buffer_add_uint64 (&msg->buffer, array[i]);
     392              :         }
     393              : 
     394            0 :         return !egg_buffer_has_error (&msg->buffer);
     395              : }
     396              : 
     397              : int
     398            4 : gkm_rpc_message_read_version (GkmRpcMessage *msg, CK_VERSION* version)
     399              : {
     400            4 :         assert (msg);
     401            4 :         assert (version);
     402              : 
     403              :         /* Check that we're supposed to have this at this point */
     404            4 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "v"));
     405              : 
     406            8 :         return egg_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &version->major) &&
     407            4 :                egg_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &version->minor);
     408              : }
     409              : 
     410              : int
     411            4 : gkm_rpc_message_write_version (GkmRpcMessage *msg, CK_VERSION* version)
     412              : {
     413            4 :         assert (msg);
     414            4 :         assert (version);
     415              : 
     416              :         /* Check that we're supposed to have this at this point */
     417            4 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "v"));
     418              : 
     419            4 :         egg_buffer_add_byte (&msg->buffer, version->major);
     420            4 :         egg_buffer_add_byte (&msg->buffer, version->minor);
     421              : 
     422            4 :         return !egg_buffer_has_error (&msg->buffer);
     423              : }
     424              : 
     425              : int
     426            4 : gkm_rpc_message_read_space_string (GkmRpcMessage *msg, CK_UTF8CHAR* buffer, CK_ULONG length)
     427              : {
     428              :         const unsigned char *data;
     429              :         size_t n_data;
     430              : 
     431            4 :         assert (msg);
     432            4 :         assert (buffer);
     433            4 :         assert (length);
     434              : 
     435            4 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "s"));
     436              : 
     437            4 :         if (!egg_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data))
     438            0 :                 return 0;
     439              : 
     440            4 :         if (n_data != length) {
     441            0 :                 gkm_rpc_warn ("invalid length space padded string received: %d != %d", length, n_data);
     442            0 :                 return 0;
     443              :         }
     444              : 
     445            4 :         memcpy (buffer, data, length);
     446            4 :         return 1;
     447              : }
     448              : 
     449              : int
     450            4 : gkm_rpc_message_write_space_string (GkmRpcMessage *msg, CK_UTF8CHAR* buffer, CK_ULONG length)
     451              : {
     452            4 :         assert (msg);
     453            4 :         assert (buffer);
     454            4 :         assert (length);
     455              : 
     456            4 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "s"));
     457              : 
     458            4 :         return egg_buffer_add_byte_array (&msg->buffer, buffer, length);
     459              : }
     460              : 
     461              : int
     462            0 : gkm_rpc_message_write_zero_string (GkmRpcMessage *msg, CK_UTF8CHAR* string)
     463              : {
     464            0 :         assert (msg);
     465            0 :         assert (string);
     466              : 
     467            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "z"));
     468              : 
     469            0 :         return egg_buffer_add_string (&msg->buffer, (const char*)string);
     470              : }
        

Generated by: LCOV version 2.0-1