LCOV - code coverage report
Current view: top level - pkcs11/rpc-layer - gkm-rpc-dispatch.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 21.2 % 1056 224
Test Date: 2024-05-07 18:02:03 Functions: 18.6 % 97 18

            Line data    Source code
       1              : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
       2              : /* gkm-rpc-dispatch.h - receiver of our 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 "pkcs11/pkcs11.h"
      29              : #include "pkcs11/pkcs11i.h"
      30              : 
      31              : #include "egg/egg-error.h"
      32              : #include "egg/egg-unix-credentials.h"
      33              : 
      34              : #include <glib.h>
      35              : 
      36              : #include <sys/types.h>
      37              : #include <sys/param.h>
      38              : #include <sys/socket.h>
      39              : #include <sys/un.h>
      40              : #include <pthread.h>
      41              : 
      42              : #include <stdlib.h>
      43              : #include <string.h>
      44              : #include <unistd.h>
      45              : #include <errno.h>
      46              : #include <stdio.h>
      47              : 
      48              : #include <glib.h>
      49              : 
      50              : /* Where we dispatch the calls to */
      51              : static CK_FUNCTION_LIST_PTR pkcs11_module = NULL;
      52              : 
      53              : /* The error returned on protocol failures */
      54              : #define PARSE_ERROR CKR_DEVICE_ERROR
      55              : #define PREP_ERROR  CKR_DEVICE_MEMORY
      56              : 
      57              : /* -----------------------------------------------------------------------------
      58              :  * LOGGING and DEBUGGING
      59              :  */
      60              : 
      61              : #if DEBUG_OUTPUT
      62              : #define debug(x) gkm_rpc_debug x
      63              : #else
      64              : #define debug(x)
      65              : #endif
      66              : 
      67              : #define warning(x) gkm_rpc_warn x
      68              : 
      69              : #define return_val_if_fail(x, v) \
      70              :         if (!(x)) { rpc_warn ("'%s' not true at %s", #x, __func__); return v; }
      71              : 
      72              : void
      73            0 : gkm_rpc_log (const char *line)
      74              : {
      75            0 :         g_message ("%s", line);
      76            0 : }
      77              : 
      78              : /* -------------------------------------------------------------------------------
      79              :  * CALL STRUCTURES
      80              :  */
      81              : 
      82              : typedef struct _ClientInstance {
      83              :         struct _ClientInstance *next;
      84              :         CK_G_APPLICATION application;
      85              :         pid_t pid;
      86              :         uid_t uid;
      87              :         int refcount;
      88              : } ClientInstance;
      89              : 
      90              : typedef struct _CallState {
      91              :         GkmRpcMessage *req;
      92              :         GkmRpcMessage *resp;
      93              :         void *allocated;
      94              :         ClientInstance *client;
      95              : } CallState;
      96              : 
      97              : static ClientInstance *clients = NULL;
      98              : static pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
      99              : 
     100              : static int
     101            2 : call_init (CallState *cs, uid_t uid, pid_t pid)
     102              : {
     103              :         ClientInstance *cl;
     104              : 
     105            2 :         assert (cs);
     106              : 
     107            2 :         cs->req = gkm_rpc_message_new ((EggBufferAllocator)realloc);
     108            2 :         cs->resp = gkm_rpc_message_new ((EggBufferAllocator)realloc);
     109            2 :         if (!cs->req || !cs->resp) {
     110            0 :                 gkm_rpc_message_free (cs->req);
     111            0 :                 gkm_rpc_message_free (cs->resp);
     112            0 :                 return 0;
     113              :         }
     114              : 
     115            2 :         pthread_mutex_lock (&clients_mutex);
     116              : 
     117            2 :         for (cl = clients; cl; cl = cl->next) {
     118            0 :                 if (cl->uid == uid && cl->pid == pid) {
     119            0 :                         cl->refcount++;
     120            0 :                         break;
     121              :                 }
     122              :         }
     123            2 :         if (!cl) {
     124            2 :                 cl = malloc (sizeof (*cl));
     125            2 :                 if (!cl) {
     126            0 :                         pthread_mutex_unlock (&clients_mutex);
     127            0 :                         return 0;
     128              :                 }
     129            2 :                 cl->next = clients;
     130            2 :                 clients = cl;
     131              : 
     132            2 :                 cl->uid = uid;
     133            2 :                 cl->pid = pid;
     134            2 :                 cl->refcount = 1;
     135              : 
     136            2 :                 memset (&cl->application, 0, sizeof (cl->application));
     137            2 :                 cl->application.applicationData = cl;
     138              :         }
     139              : 
     140            2 :         pthread_mutex_unlock (&clients_mutex);
     141              : 
     142            2 :         cs->client = cl;
     143            2 :         cs->allocated = NULL;
     144            2 :         return 1;
     145              : }
     146              : 
     147              : static void*
     148            0 : call_alloc (CallState *cs, size_t length)
     149              : {
     150              :         void **data;
     151              : 
     152            0 :         assert (cs);
     153              : 
     154            0 :         if (length > 0x7fffffff)
     155            0 :                 return NULL;
     156              : 
     157            0 :         data = malloc (sizeof (void*) + length);
     158            0 :         if (!data)
     159            0 :                 return NULL;
     160              : 
     161              :         /* Munch up the memory to help catch bugs */
     162            0 :         memset (data, 0xff, sizeof (void*) + length);
     163              : 
     164              :         /* Store pointer to next allocated block at beginning */
     165            0 :         *data = cs->allocated;
     166            0 :         cs->allocated = data;
     167              : 
     168              :         /* Data starts after first pointer */
     169            0 :         return (void*)(data + 1);
     170              : }
     171              : 
     172              : static void
     173           10 : call_reset (CallState *cs)
     174              : {
     175              :         void *allocated;
     176              :         void **data;
     177              : 
     178           10 :         assert (cs);
     179              : 
     180           10 :         allocated = cs->allocated;
     181           10 :         while (allocated) {
     182            0 :                 data = (void**)allocated;
     183              : 
     184              :                 /* Pointer to the next allocation */
     185            0 :                 allocated = *data;
     186            0 :                 free (data);
     187              :         }
     188              : 
     189           10 :         cs->allocated = NULL;
     190           10 :         gkm_rpc_message_reset (cs->req);
     191           10 :         gkm_rpc_message_reset (cs->resp);
     192           10 : }
     193              : 
     194              : static void
     195            2 : call_uninit (CallState *cs)
     196              : {
     197            2 :         assert (cs);
     198              : 
     199            2 :         call_reset (cs);
     200              : 
     201            2 :         gkm_rpc_message_free (cs->req);
     202            2 :         gkm_rpc_message_free (cs->resp);
     203            2 : }
     204              : 
     205              : /* -------------------------------------------------------------------
     206              :  * PROTOCOL CODE
     207              :  */
     208              : 
     209              : static CK_RV
     210            0 : proto_read_byte_buffer (CallState *cs, CK_BYTE_PTR* buffer, CK_ULONG* n_buffer)
     211              : {
     212              :         GkmRpcMessage *msg;
     213              :         uint32_t length;
     214              : 
     215            0 :         assert (cs);
     216            0 :         assert (buffer);
     217            0 :         assert (n_buffer);
     218              : 
     219            0 :         msg = cs->req;
     220              : 
     221              :         /* Check that we're supposed to be reading this at this point */
     222            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "fy"));
     223              : 
     224              :         /* The number of ulongs there's room for on the other end */
     225            0 :         if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &length))
     226            0 :                 return PARSE_ERROR;
     227              : 
     228            0 :         *n_buffer = length;
     229            0 :         *buffer = NULL;
     230              : 
     231              :         /* If set to zero, then they just want the length */
     232            0 :         if (!length)
     233            0 :                 return CKR_OK;
     234              : 
     235            0 :         *buffer = call_alloc (cs, length * sizeof (CK_BYTE));
     236            0 :         if (!*buffer)
     237            0 :                 return CKR_DEVICE_MEMORY;
     238              : 
     239            0 :         return CKR_OK;
     240              : }
     241              : 
     242              : static CK_RV
     243            2 : proto_read_byte_array (CallState *cs, CK_BYTE_PTR* array, CK_ULONG* n_array)
     244              : {
     245              :         GkmRpcMessage *msg;
     246              :         const unsigned char *data;
     247              :         unsigned char valid;
     248              :         size_t n_data;
     249              : 
     250            2 :         assert (cs);
     251              : 
     252            2 :         msg = cs->req;
     253              : 
     254              :         /* Check that we're supposed to have this at this point */
     255            2 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "ay"));
     256              : 
     257              :         /* Read out the byte which says whether data is present or not */
     258            2 :         if (!egg_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &valid))
     259            0 :                 return PARSE_ERROR;
     260              : 
     261            2 :         if (!valid) {
     262            0 :                 *array = NULL;
     263            0 :                 *n_array = 0;
     264            0 :                 return CKR_OK;
     265              :         }
     266              : 
     267              :         /* Point our arguments into the buffer */
     268            2 :         if (!egg_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed,
     269              :                                         &data, &n_data))
     270            0 :                 return PARSE_ERROR;
     271              : 
     272            2 :         *array = (CK_BYTE_PTR)data;
     273            2 :         *n_array = n_data;
     274            2 :         return CKR_OK;
     275              : }
     276              : 
     277              : static CK_RV
     278            0 : proto_write_byte_array (CallState *cs, CK_BYTE_PTR array, CK_ULONG len, CK_RV ret)
     279              : {
     280            0 :         assert (cs);
     281              : 
     282              :         /*
     283              :          * When returning an byte array, in many cases we need to pass
     284              :          * an invalid array along with a length, which signifies CKR_BUFFER_TOO_SMALL.
     285              :          */
     286              : 
     287            0 :         switch (ret) {
     288            0 :         case CKR_BUFFER_TOO_SMALL:
     289            0 :                 array = NULL;
     290              :                 /* fall through */
     291            0 :         case CKR_OK:
     292            0 :                 break;
     293              : 
     294              :         /* Pass all other errors straight through */
     295            0 :         default:
     296            0 :                 return ret;
     297              :         };
     298              : 
     299            0 :         if (!gkm_rpc_message_write_byte_array (cs->resp, array, len))
     300            0 :                 return PREP_ERROR;
     301              : 
     302            0 :         return CKR_OK;
     303              : }
     304              : 
     305              : static CK_RV
     306            0 : proto_read_ulong_buffer (CallState *cs, CK_ULONG_PTR* buffer, CK_ULONG* n_buffer)
     307              : {
     308              :         GkmRpcMessage *msg;
     309              :         uint32_t length;
     310              : 
     311            0 :         assert (cs);
     312            0 :         assert (buffer);
     313            0 :         assert (n_buffer);
     314              : 
     315            0 :         msg = cs->req;
     316              : 
     317              :         /* Check that we're supposed to be reading this at this point */
     318            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "fu"));
     319              : 
     320              :         /* The number of ulongs there's room for on the other end */
     321            0 :         if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &length))
     322            0 :                 return PARSE_ERROR;
     323              : 
     324            0 :         *n_buffer = length;
     325            0 :         *buffer = NULL;
     326              : 
     327              :         /* If set to zero, then they just want the length */
     328            0 :         if (!length)
     329            0 :                 return CKR_OK;
     330              : 
     331            0 :         *buffer = call_alloc (cs, length * sizeof (CK_ULONG));
     332            0 :         if (!*buffer)
     333            0 :                 return CKR_DEVICE_MEMORY;
     334              : 
     335            0 :         return CKR_OK;
     336              : }
     337              : 
     338              : static CK_RV
     339            0 : proto_write_ulong_array (CallState *cs, CK_ULONG_PTR array, CK_ULONG len, CK_RV ret)
     340              : {
     341            0 :         assert (cs);
     342              : 
     343              :         /*
     344              :          * When returning an ulong array, in many cases we need to pass
     345              :          * an invalid array along with a length, which signifies CKR_BUFFER_TOO_SMALL.
     346              :          */
     347              : 
     348            0 :         switch (ret) {
     349            0 :         case CKR_BUFFER_TOO_SMALL:
     350            0 :                 array = NULL;
     351              :                 /* fall through */
     352            0 :         case CKR_OK:
     353            0 :                 break;
     354              : 
     355              :         /* Pass all other errors straight through */
     356            0 :         default:
     357            0 :                 return ret;
     358              :         };
     359              : 
     360            0 :         if (!gkm_rpc_message_write_ulong_array (cs->resp, array, len))
     361            0 :                 return PREP_ERROR;
     362              : 
     363            0 :         return CKR_OK;
     364              : }
     365              : 
     366              : static CK_RV
     367            0 : proto_read_attribute_buffer (CallState *cs, CK_ATTRIBUTE_PTR* result, CK_ULONG* n_result)
     368              : {
     369              :         CK_ATTRIBUTE_PTR attrs;
     370              :         GkmRpcMessage *msg;
     371              :         uint32_t n_attrs, i;
     372              :         uint32_t value;
     373              : 
     374            0 :         assert (cs);
     375            0 :         assert (result);
     376            0 :         assert (n_result);
     377              : 
     378            0 :         msg = cs->req;
     379              : 
     380              :         /* Make sure this is in the rigth order */
     381            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "fA"));
     382              : 
     383              :         /* Read the number of attributes */
     384            0 :         if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &n_attrs))
     385            0 :                 return PARSE_ERROR;
     386              : 
     387              :         /* Allocate memory for the attribute structures */
     388            0 :         attrs = call_alloc (cs, n_attrs * sizeof (CK_ATTRIBUTE));
     389            0 :         if (!attrs)
     390            0 :                 return CKR_DEVICE_MEMORY;
     391              : 
     392              :         /* Now go through and fill in each one */
     393            0 :         for (i = 0; i < n_attrs; ++i) {
     394              : 
     395              :                 /* The attribute type */
     396            0 :                 if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value))
     397            0 :                         return PARSE_ERROR;
     398              : 
     399            0 :                 attrs[i].type = value;
     400              : 
     401              :                 /* The number of bytes to allocate */
     402            0 :                 if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value))
     403            0 :                         return PARSE_ERROR;
     404              : 
     405            0 :                 if (value == 0) {
     406            0 :                         attrs[i].pValue = NULL;
     407            0 :                         attrs[i].ulValueLen = 0;
     408              :                 } else {
     409            0 :                         attrs[i].pValue = call_alloc (cs, value);
     410            0 :                         if (!attrs[i].pValue)
     411            0 :                                 return CKR_DEVICE_MEMORY;
     412            0 :                         attrs[i].ulValueLen = value;
     413              :                 }
     414              :         }
     415              : 
     416            0 :         *result = attrs;
     417            0 :         *n_result = n_attrs;
     418            0 :         return CKR_OK;
     419              : }
     420              : 
     421              : static CK_RV
     422            0 : proto_read_attribute_array (CallState *cs, CK_ATTRIBUTE_PTR* result, CK_ULONG* n_result)
     423              : {
     424              :         CK_ATTRIBUTE_PTR attrs;
     425              :         const unsigned char *data;
     426              :         unsigned char valid;
     427              :         GkmRpcMessage *msg;
     428              :         uint32_t n_attrs, i;
     429              :         uint32_t value;
     430              :         size_t n_data;
     431              : 
     432            0 :         assert (cs);
     433            0 :         assert (result);
     434            0 :         assert (n_result);
     435              : 
     436            0 :         msg = cs->req;
     437              : 
     438              :         /* Make sure this is in the rigth order */
     439            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "aA"));
     440              : 
     441              :         /* Read the number of attributes */
     442            0 :         if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &n_attrs))
     443            0 :                 return PARSE_ERROR;
     444              : 
     445              :         /* Allocate memory for the attribute structures */
     446            0 :         attrs = call_alloc (cs, n_attrs * sizeof (CK_ATTRIBUTE));
     447            0 :         if (!attrs)
     448            0 :                 return CKR_DEVICE_MEMORY;
     449              : 
     450              :         /* Now go through and fill in each one */
     451            0 :         for (i = 0; i < n_attrs; ++i) {
     452              : 
     453              :                 /* The attribute type */
     454            0 :                 if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value))
     455            0 :                         return PARSE_ERROR;
     456              : 
     457            0 :                 attrs[i].type = value;
     458              : 
     459              :                 /* Whether this one is valid or not */
     460            0 :                 if (!egg_buffer_get_byte (&msg->buffer, msg->parsed, &msg->parsed, &valid))
     461            0 :                         return PARSE_ERROR;
     462              : 
     463            0 :                 if (valid) {
     464            0 :                         if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value))
     465            0 :                                 return PARSE_ERROR;
     466            0 :                         if (!egg_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data))
     467            0 :                                 return PARSE_ERROR;
     468              : 
     469            0 :                         if (data != NULL && n_data != value) {
     470            0 :                                 g_warning ("attribute length and data do not match");
     471            0 :                                 return PARSE_ERROR;
     472              :                         }
     473              : 
     474            0 :                         attrs[i].pValue = (CK_VOID_PTR)data;
     475            0 :                         attrs[i].ulValueLen = value;
     476              :                 } else {
     477            0 :                         attrs[i].pValue = NULL;
     478            0 :                         attrs[i].ulValueLen = -1;
     479              :                 }
     480              :         }
     481              : 
     482            0 :         *result = attrs;
     483            0 :         *n_result = n_attrs;
     484            0 :         return CKR_OK;
     485              : }
     486              : 
     487              : static CK_RV
     488            0 : proto_write_attribute_array (CallState *cs, CK_ATTRIBUTE_PTR array, CK_ULONG len, CK_RV ret)
     489              : {
     490            0 :         assert (cs);
     491              : 
     492              :         /*
     493              :          * When returning an attribute array, certain errors aren't
     494              :          * actually real errors, these are passed through to the other
     495              :          * side along with the attribute array.
     496              :          */
     497              : 
     498            0 :         switch (ret) {
     499            0 :         case CKR_ATTRIBUTE_SENSITIVE:
     500              :         case CKR_ATTRIBUTE_TYPE_INVALID:
     501              :         case CKR_BUFFER_TOO_SMALL:
     502              :         case CKR_OK:
     503            0 :                 break;
     504              : 
     505              :         /* Pass all other errors straight through */
     506            0 :         default:
     507            0 :                 return ret;
     508              :         };
     509              : 
     510            0 :         if (!gkm_rpc_message_write_attribute_array (cs->resp, array, len) ||
     511            0 :             !gkm_rpc_message_write_ulong (cs->resp, ret))
     512            0 :                 return PREP_ERROR;
     513              : 
     514            0 :         return CKR_OK;
     515              : }
     516              : 
     517              : static CK_RV
     518            0 : proto_read_null_string (CallState *cs, CK_UTF8CHAR_PTR* val)
     519              : {
     520              :         GkmRpcMessage *msg;
     521              :         const unsigned char *data;
     522              :         size_t n_data;
     523              : 
     524            0 :         assert (cs);
     525            0 :         assert (val);
     526              : 
     527            0 :         msg = cs->req;
     528              : 
     529              :         /* Check that we're supposed to have this at this point */
     530            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "z"));
     531              : 
     532            0 :         if (!egg_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data))
     533            0 :                 return PARSE_ERROR;
     534              : 
     535              :         /* Allocate a block of memory for it */
     536            0 :         *val = call_alloc (cs, n_data);
     537            0 :         if (!*val)
     538            0 :                 return CKR_DEVICE_MEMORY;
     539              : 
     540            0 :         memcpy (*val, data, n_data);
     541            0 :         (*val)[n_data] = 0;
     542              : 
     543            0 :         return CKR_OK;
     544              : }
     545              : 
     546              : static CK_RV
     547            0 : proto_read_mechanism (CallState *cs, CK_MECHANISM_PTR mech)
     548              : {
     549              :         GkmRpcMessage *msg;
     550              :         const unsigned char *data;
     551              :         uint32_t value;
     552              :         size_t n_data;
     553              : 
     554            0 :         assert (cs);
     555            0 :         assert (mech);
     556              : 
     557            0 :         msg = cs->req;
     558              : 
     559              :         /* Make sure this is in the right order */
     560            0 :         assert (!msg->signature || gkm_rpc_message_verify_part (msg, "M"));
     561              : 
     562              :         /* The mechanism type */
     563            0 :         if (!egg_buffer_get_uint32 (&msg->buffer, msg->parsed, &msg->parsed, &value))
     564            0 :                 return PARSE_ERROR;
     565              : 
     566              :         /* The mechanism data */
     567            0 :         if (!egg_buffer_get_byte_array (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data))
     568            0 :                 return PARSE_ERROR;
     569              : 
     570            0 :         mech->mechanism = value;
     571            0 :         mech->pParameter = (CK_VOID_PTR)data;
     572            0 :         mech->ulParameterLen = n_data;
     573            0 :         return CKR_OK;
     574              : }
     575              : 
     576              : static CK_RV
     577            2 : proto_write_info (CallState *cs, CK_INFO_PTR info)
     578              : {
     579              :         GkmRpcMessage *msg;
     580              : 
     581            2 :         assert (cs);
     582            2 :         assert (info);
     583              : 
     584            2 :         msg = cs->resp;
     585              : 
     586            4 :         if (!gkm_rpc_message_write_version (msg, &info->cryptokiVersion) ||
     587            4 :             !gkm_rpc_message_write_space_string (msg, info->manufacturerID, 32) ||
     588            4 :             !gkm_rpc_message_write_ulong (msg, info->flags) ||
     589            4 :             !gkm_rpc_message_write_space_string (msg, info->libraryDescription, 32) ||
     590            2 :             !gkm_rpc_message_write_version (msg, &info->libraryVersion))
     591            0 :                 return PREP_ERROR;
     592              : 
     593            2 :         return CKR_OK;
     594              : }
     595              : 
     596              : static CK_RV
     597            0 : proto_write_slot_info (CallState *cs, CK_SLOT_INFO_PTR info)
     598              : {
     599              :         GkmRpcMessage *msg;
     600              : 
     601            0 :         assert (cs);
     602            0 :         assert (info);
     603              : 
     604            0 :         msg = cs->resp;
     605              : 
     606            0 :         if (!gkm_rpc_message_write_space_string (msg, info->slotDescription, 64) ||
     607            0 :             !gkm_rpc_message_write_space_string (msg, info->manufacturerID, 32) ||
     608            0 :             !gkm_rpc_message_write_ulong (msg, info->flags) ||
     609            0 :             !gkm_rpc_message_write_version (msg, &info->hardwareVersion) ||
     610            0 :             !gkm_rpc_message_write_version (msg, &info->firmwareVersion))
     611            0 :                 return PREP_ERROR;
     612              : 
     613            0 :         return CKR_OK;
     614              : }
     615              : 
     616              : static CK_RV
     617            0 : proto_write_token_info (CallState *cs, CK_TOKEN_INFO_PTR info)
     618              : {
     619              :         GkmRpcMessage *msg;
     620              : 
     621            0 :         assert (cs);
     622            0 :         assert (info);
     623              : 
     624            0 :         msg = cs->resp;
     625              : 
     626            0 :         if (!gkm_rpc_message_write_space_string (msg, info->label, 32) ||
     627            0 :             !gkm_rpc_message_write_space_string (msg, info->manufacturerID, 32) ||
     628            0 :             !gkm_rpc_message_write_space_string (msg, info->model, 16) ||
     629            0 :             !gkm_rpc_message_write_space_string (msg, info->serialNumber, 16) ||
     630            0 :             !gkm_rpc_message_write_ulong (msg, info->flags) ||
     631            0 :             !gkm_rpc_message_write_ulong (msg, info->ulMaxSessionCount) ||
     632            0 :             !gkm_rpc_message_write_ulong (msg, info->ulSessionCount) ||
     633            0 :             !gkm_rpc_message_write_ulong (msg, info->ulMaxRwSessionCount) ||
     634            0 :             !gkm_rpc_message_write_ulong (msg, info->ulRwSessionCount) ||
     635            0 :             !gkm_rpc_message_write_ulong (msg, info->ulMaxPinLen) ||
     636            0 :             !gkm_rpc_message_write_ulong (msg, info->ulMinPinLen) ||
     637            0 :             !gkm_rpc_message_write_ulong (msg, info->ulTotalPublicMemory) ||
     638            0 :             !gkm_rpc_message_write_ulong (msg, info->ulFreePublicMemory) ||
     639            0 :             !gkm_rpc_message_write_ulong (msg, info->ulTotalPrivateMemory) ||
     640            0 :             !gkm_rpc_message_write_ulong (msg, info->ulFreePrivateMemory) ||
     641            0 :             !gkm_rpc_message_write_version (msg, &info->hardwareVersion) ||
     642            0 :             !gkm_rpc_message_write_version (msg, &info->firmwareVersion) ||
     643            0 :             !gkm_rpc_message_write_space_string (msg, info->utcTime, 16))
     644            0 :                 return PREP_ERROR;
     645              : 
     646            0 :         return CKR_OK;
     647              : }
     648              : 
     649              : static CK_RV
     650            0 : proto_write_mechanism_info (CallState *cs, CK_MECHANISM_INFO_PTR info)
     651              : {
     652              :         GkmRpcMessage *msg;
     653              : 
     654            0 :         assert (cs);
     655            0 :         assert (info);
     656              : 
     657            0 :         msg = cs->resp;
     658              : 
     659            0 :         if (!gkm_rpc_message_write_ulong (msg, info->ulMinKeySize) ||
     660            0 :             !gkm_rpc_message_write_ulong (msg, info->ulMaxKeySize) ||
     661            0 :             !gkm_rpc_message_write_ulong (msg, info->flags))
     662            0 :                 return PREP_ERROR;
     663              : 
     664            0 :         return CKR_OK;
     665              : }
     666              : 
     667              : static CK_RV
     668            0 : proto_write_session_info (CallState *cs, CK_SESSION_INFO_PTR info)
     669              : {
     670              :         GkmRpcMessage *msg;
     671              : 
     672            0 :         assert (cs);
     673            0 :         assert (info);
     674              : 
     675            0 :         msg = cs->resp;
     676              : 
     677            0 :         if (!gkm_rpc_message_write_ulong (msg, info->slotID) ||
     678            0 :             !gkm_rpc_message_write_ulong (msg, info->state) ||
     679            0 :             !gkm_rpc_message_write_ulong (msg, info->flags) ||
     680            0 :             !gkm_rpc_message_write_ulong (msg, info->ulDeviceError))
     681            0 :                 return PREP_ERROR;
     682              : 
     683            0 :         return CKR_OK;
     684              : }
     685              : 
     686              : /* -------------------------------------------------------------------
     687              :  * CALL MACROS
     688              :  */
     689              : 
     690              : #define BEGIN_CALL(call_id) \
     691              :         debug ((#call_id ": enter")); \
     692              :         assert (cs); \
     693              :         assert (pkcs11_module); \
     694              :         {  \
     695              :                 CK_ ## call_id _func = pkcs11_module-> call_id; \
     696              :                 CK_RV _ret = CKR_OK; \
     697              :                 if (!_func) { _ret = CKR_GENERAL_ERROR; goto _cleanup; }
     698              : 
     699              : #define PROCESS_CALL(args)\
     700              :         assert (gkm_rpc_message_is_verified (cs->req)); \
     701              :         _ret = _func args
     702              : 
     703              : #define END_CALL \
     704              :         _cleanup: \
     705              :                 debug (("ret: %d", _ret)); \
     706              :                 return _ret; \
     707              :         }
     708              : 
     709              : #define IN_BYTE(val) \
     710              :         if (!gkm_rpc_message_read_byte (cs->req, &val)) \
     711              :                 { _ret = PARSE_ERROR; goto _cleanup; }
     712              : 
     713              : #define IN_ULONG(val) \
     714              :         if (!gkm_rpc_message_read_ulong (cs->req, &val)) \
     715              :                 { _ret = PARSE_ERROR; goto _cleanup; }
     716              : 
     717              : #define IN_STRING(val) \
     718              :         _ret = proto_read_null_string (cs, &val); \
     719              :         if (_ret != CKR_OK) goto _cleanup;
     720              : 
     721              : #define IN_BYTE_BUFFER(buffer, buffer_len) \
     722              :         _ret = proto_read_byte_buffer (cs, &buffer, &buffer_len); \
     723              :         if (_ret != CKR_OK) goto _cleanup;
     724              : 
     725              : #define IN_BYTE_ARRAY(buffer, buffer_len) \
     726              :         _ret = proto_read_byte_array (cs, &buffer, &buffer_len); \
     727              :         if (_ret != CKR_OK) goto _cleanup;
     728              : 
     729              : #define IN_ULONG_BUFFER(buffer, buffer_len) \
     730              :         _ret = proto_read_ulong_buffer (cs, &buffer, &buffer_len); \
     731              :         if (_ret != CKR_OK) goto _cleanup;
     732              : 
     733              : #define IN_ATTRIBUTE_BUFFER(buffer, buffer_len) \
     734              :         _ret = proto_read_attribute_buffer (cs, &buffer, &buffer_len); \
     735              :         if (_ret != CKR_OK) goto _cleanup;
     736              : 
     737              : #define IN_ATTRIBUTE_ARRAY(attrs, n_attrs) \
     738              :         _ret = proto_read_attribute_array (cs, &attrs, &n_attrs); \
     739              :         if (_ret != CKR_OK) goto _cleanup;
     740              : 
     741              : #define IN_MECHANISM(mech) \
     742              :         _ret = proto_read_mechanism (cs, &mech); \
     743              :         if (_ret != CKR_OK) goto _cleanup;
     744              : 
     745              : 
     746              : #define OUT_ULONG(val) \
     747              :         if (_ret == CKR_OK && !gkm_rpc_message_write_ulong (cs->resp, val)) \
     748              :                 _ret = PREP_ERROR;
     749              : 
     750              : #define OUT_BYTE_ARRAY(array, len) \
     751              :         /* Note how we filter return codes */ \
     752              :         _ret = proto_write_byte_array (cs, array, len, _ret);
     753              : 
     754              : #define OUT_ULONG_ARRAY(array, len) \
     755              :         /* Note how we filter return codes */ \
     756              :         _ret = proto_write_ulong_array (cs, array, len, _ret);
     757              : 
     758              : #define OUT_ATTRIBUTE_ARRAY(array, len) \
     759              :         /* Note how we filter return codes */ \
     760              :         _ret = proto_write_attribute_array (cs, array, len, _ret);
     761              : 
     762              : #define OUT_INFO(val) \
     763              :         if (_ret == CKR_OK) \
     764              :                 _ret = proto_write_info (cs, &val);
     765              : 
     766              : #define OUT_SLOT_INFO(val) \
     767              :         if (_ret == CKR_OK) \
     768              :                 _ret = proto_write_slot_info (cs, &val);
     769              : 
     770              : #define OUT_TOKEN_INFO(val) \
     771              :         if (_ret == CKR_OK) \
     772              :                 _ret = proto_write_token_info (cs, &val);
     773              : 
     774              : #define OUT_MECHANISM_INFO(val) \
     775              :         if (_ret == CKR_OK) \
     776              :                 _ret = proto_write_mechanism_info (cs, &val);
     777              : 
     778              : #define OUT_SESSION_INFO(val) \
     779              :         if (_ret == CKR_OK) \
     780              :                 _ret = proto_write_session_info (cs, &val);
     781              : 
     782              : /* ---------------------------------------------------------------------------
     783              :  * DISPATCH SPECIFIC CALLS
     784              :  */
     785              : 
     786              : static CK_RV
     787            2 : rpc_C_Initialize (CallState *cs)
     788              : {
     789              :         CK_BYTE_PTR handshake;
     790              :         CK_ULONG n_handshake;
     791            2 :         CK_RV ret = CKR_OK;
     792              : 
     793              :         debug (("C_Initialize: enter"));
     794              : 
     795            2 :         assert (cs);
     796            2 :         assert (pkcs11_module);
     797              : 
     798            2 :         ret = proto_read_byte_array (cs, &handshake, &n_handshake);
     799            2 :         if (ret == CKR_OK) {
     800              : 
     801              :                 /* Check to make sure the header matches */
     802            2 :                 if (n_handshake != GKM_RPC_HANDSHAKE_LEN ||
     803            2 :                     memcmp (handshake, GKM_RPC_HANDSHAKE, n_handshake) != 0) {
     804            0 :                         gkm_rpc_warn ("invalid handshake received from connecting module");
     805            0 :                         ret = CKR_GENERAL_ERROR;
     806              :                 }
     807              : 
     808            2 :                 assert (gkm_rpc_message_is_verified (cs->req));
     809              :         }
     810              : 
     811              :         /*
     812              :          * We don't actually C_Initialize lower layers. It's assumed
     813              :          * that they'll already be initialzied by the code that loaded us.
     814              :          */
     815              : 
     816              :         debug (("ret: %d", ret));
     817            2 :         return ret;
     818              : }
     819              : 
     820              : static CK_RV
     821            2 : rpc_C_Finalize (CallState *cs)
     822              : {
     823              :         CK_SLOT_ID_PTR slots;
     824              :         CK_ULONG n_slots, i;
     825            2 :         CK_RV ret = CKR_OK;
     826              : 
     827              :         debug (("C_Finalize: enter"));
     828              : 
     829            2 :         assert (cs);
     830            2 :         assert (pkcs11_module);
     831              : 
     832              :         /*
     833              :          * We don't actually C_Finalize lower layers, since this would finalize
     834              :          * for all appartments, client applications. Anyway this is done by
     835              :          * the code that loaded us.
     836              :          *
     837              :          * But we do need to cleanup resources used by this client, so instead
     838              :          * we call C_CloseAllSessions for each slot for this client application.
     839              :          */
     840              : 
     841            2 :         if (cs->client->application.applicationId) {
     842            0 :                 ret = (pkcs11_module->C_GetSlotList) (TRUE, NULL, &n_slots);
     843            0 :                 if (ret == CKR_OK) {
     844            0 :                         slots = calloc (n_slots, sizeof (CK_SLOT_ID));
     845            0 :                         if (slots == NULL) {
     846            0 :                                 ret = CKR_DEVICE_MEMORY;
     847              :                         } else {
     848            0 :                                 ret = (pkcs11_module->C_GetSlotList) (TRUE, slots, &n_slots);
     849            0 :                                 for (i = 0; ret == CKR_OK && i < n_slots; ++i)
     850            0 :                                         ret = (pkcs11_module->C_CloseAllSessions) (slots[i] | cs->client->application.applicationId);
     851            0 :                                 free (slots);
     852              :                         }
     853              :                 }
     854              :         }
     855              : 
     856              :         debug (("ret: %d", ret));
     857            2 :         return ret;
     858              : }
     859              : 
     860              : static CK_RV
     861            2 : rpc_C_GetInfo (CallState *cs)
     862              : {
     863              :         CK_INFO info;
     864              : 
     865            2 :         BEGIN_CALL (C_GetInfo);
     866            2 :         PROCESS_CALL ((&info));
     867            2 :                 OUT_INFO (info);
     868            2 :         END_CALL;
     869              : }
     870              : 
     871              : static CK_RV
     872            0 : rpc_C_GetSlotList (CallState *cs)
     873              : {
     874              :         CK_BBOOL token_present;
     875              :         CK_SLOT_ID_PTR slot_list;
     876              :         CK_ULONG count;
     877              : 
     878            0 :         BEGIN_CALL (C_GetSlotList);
     879            0 :                 IN_BYTE (token_present);
     880            0 :                 IN_ULONG_BUFFER (slot_list, count);
     881            0 :         PROCESS_CALL ((token_present, slot_list, &count));
     882            0 :                 OUT_ULONG_ARRAY (slot_list, count);
     883            0 :         END_CALL;
     884              : }
     885              : 
     886              : static CK_RV
     887            0 : rpc_C_GetSlotInfo (CallState *cs)
     888              : {
     889              :         CK_SLOT_ID slot_id;
     890              :         CK_SLOT_INFO info;
     891              : 
     892              :         /* Slot id becomes appartment so lower layers can tell clients apart. */
     893              : 
     894            0 :         BEGIN_CALL (C_GetSlotInfo);
     895            0 :                 IN_ULONG (slot_id);
     896            0 :         PROCESS_CALL ((slot_id, &info));
     897            0 :                 OUT_SLOT_INFO (info);
     898            0 :         END_CALL;
     899              : }
     900              : 
     901              : static CK_RV
     902            0 : rpc_C_GetTokenInfo (CallState *cs)
     903              : {
     904              :         CK_SLOT_ID slot_id;
     905              :         CK_TOKEN_INFO info;
     906              : 
     907              :         /* Slot id becomes appartment so lower layers can tell clients apart. */
     908              : 
     909            0 :         BEGIN_CALL (C_GetTokenInfo);
     910            0 :                 IN_ULONG (slot_id);
     911            0 :         PROCESS_CALL ((slot_id, &info));
     912            0 :                 OUT_TOKEN_INFO (info);
     913            0 :         END_CALL;
     914              : }
     915              : 
     916              : static CK_RV
     917            0 : rpc_C_GetMechanismList (CallState *cs)
     918              : {
     919              :         CK_SLOT_ID slot_id;
     920              :         CK_MECHANISM_TYPE_PTR mechanism_list;
     921              :         CK_ULONG count;
     922              : 
     923              :         /* Slot id becomes appartment so lower layers can tell clients apart. */
     924              : 
     925            0 :         BEGIN_CALL (C_GetMechanismList);
     926            0 :                 IN_ULONG (slot_id);
     927            0 :                 IN_ULONG_BUFFER (mechanism_list, count);
     928            0 :         PROCESS_CALL ((slot_id, mechanism_list, &count));
     929            0 :                 OUT_ULONG_ARRAY (mechanism_list, count);
     930            0 :         END_CALL;
     931              : }
     932              : 
     933              : static CK_RV
     934            0 : rpc_C_GetMechanismInfo (CallState *cs)
     935              : {
     936              :         CK_SLOT_ID slot_id;
     937              :         CK_MECHANISM_TYPE type;
     938              :         CK_MECHANISM_INFO info;
     939              : 
     940              :         /* Slot id becomes appartment so lower layers can tell clients apart. */
     941              : 
     942            0 :         BEGIN_CALL (C_GetMechanismInfo);
     943            0 :                 IN_ULONG (slot_id);
     944            0 :                 IN_ULONG (type);
     945            0 :         PROCESS_CALL ((slot_id, type, &info));
     946            0 :                 OUT_MECHANISM_INFO (info);
     947            0 :         END_CALL;
     948              : }
     949              : 
     950              : static CK_RV
     951            0 : rpc_C_InitToken (CallState *cs)
     952              : {
     953              :         CK_SLOT_ID slot_id;
     954              :         CK_UTF8CHAR_PTR pin;
     955              :         CK_ULONG pin_len;
     956              :         CK_UTF8CHAR_PTR label;
     957              : 
     958              :         /* Slot id becomes appartment so lower layers can tell clients apart. */
     959              : 
     960            0 :         BEGIN_CALL (C_InitToken);
     961            0 :                 IN_ULONG (slot_id);
     962            0 :                 IN_BYTE_ARRAY (pin, pin_len);
     963            0 :                 IN_STRING (label);
     964            0 :         PROCESS_CALL ((slot_id, pin, pin_len, label));
     965            0 :         END_CALL;
     966              : }
     967              : 
     968              : static CK_RV
     969            0 : rpc_C_WaitForSlotEvent (CallState *cs)
     970              : {
     971              :         CK_FLAGS flags;
     972              :         CK_SLOT_ID slot_id;
     973              : 
     974              :         /* Get slot id from appartment lower layers use. */
     975              : 
     976            0 :         BEGIN_CALL (C_WaitForSlotEvent);
     977            0 :                 IN_ULONG (flags);
     978            0 :         PROCESS_CALL ((flags, &slot_id, NULL));
     979            0 :                 OUT_ULONG (slot_id);
     980            0 :         END_CALL;
     981              : }
     982              : 
     983              : static CK_RV
     984            0 : rpc_C_OpenSession (CallState *cs)
     985              : {
     986              :         CK_SLOT_ID slot_id;
     987              :         CK_FLAGS flags;
     988              :         CK_SESSION_HANDLE session;
     989              : 
     990              :         /* Slot id becomes appartment so lower layers can tell clients apart. */
     991              : 
     992              :         /*
     993              :          * IMPORTANT: When we open sessions on behalf of a client caller
     994              :          * we always specify CKF_G_APPLICATION_SESSION. This allows the module
     995              :          * to know whether they're talking to the daemon or a client app.
     996              :          *
     997              :          * This is a security feature.
     998              :          */
     999              : 
    1000            0 :         BEGIN_CALL (C_OpenSession);
    1001            0 :                 IN_ULONG (slot_id);
    1002            0 :                 IN_ULONG (flags);
    1003            0 :                 flags |= CKF_G_APPLICATION_SESSION;
    1004            0 :         PROCESS_CALL ((slot_id, flags, &cs->client->application, NULL, &session));
    1005            0 :                 OUT_ULONG (session);
    1006            0 :         END_CALL;
    1007              : }
    1008              : 
    1009              : 
    1010              : static CK_RV
    1011            0 : rpc_C_CloseSession (CallState *cs)
    1012              : {
    1013              :         CK_SESSION_HANDLE session;
    1014              : 
    1015            0 :         BEGIN_CALL (C_CloseSession);
    1016            0 :                 IN_ULONG (session);
    1017            0 :         PROCESS_CALL ((session));
    1018            0 :         END_CALL;
    1019              : }
    1020              : 
    1021              : static CK_RV
    1022            0 : rpc_C_CloseAllSessions (CallState *cs)
    1023              : {
    1024              :         CK_SLOT_ID slot_id;
    1025              : 
    1026              :         /* Slot id becomes appartment so lower layers can tell clients apart. */
    1027              : 
    1028            0 :         BEGIN_CALL (C_CloseAllSessions);
    1029            0 :                 IN_ULONG (slot_id);
    1030            0 :                 slot_id |= cs->client->application.applicationId;
    1031            0 :         PROCESS_CALL ((slot_id));
    1032            0 :         END_CALL;
    1033              : }
    1034              : 
    1035              : static CK_RV
    1036            0 : rpc_C_GetFunctionStatus (CallState *cs)
    1037              : {
    1038              :         CK_SESSION_HANDLE session;
    1039              : 
    1040            0 :         BEGIN_CALL (C_GetFunctionStatus);
    1041            0 :                 IN_ULONG (session);
    1042            0 :         PROCESS_CALL ((session));
    1043            0 :         END_CALL;
    1044              : }
    1045              : 
    1046              : static CK_RV
    1047            0 : rpc_C_CancelFunction (CallState *cs)
    1048              : {
    1049              :         CK_SESSION_HANDLE session;
    1050              : 
    1051            0 :         BEGIN_CALL (C_CancelFunction);
    1052            0 :                 IN_ULONG (session);
    1053            0 :         PROCESS_CALL ((session));
    1054            0 :         END_CALL;
    1055              : }
    1056              : 
    1057              : static CK_RV
    1058            0 : rpc_C_GetSessionInfo (CallState *cs)
    1059              : {
    1060              :         CK_SESSION_HANDLE session;
    1061              :         CK_SESSION_INFO info;
    1062              : 
    1063              :         /* Get slot id from appartment lower layers use. */
    1064              : 
    1065            0 :         BEGIN_CALL (C_GetSessionInfo);
    1066            0 :                 IN_ULONG (session);
    1067            0 :         PROCESS_CALL ((session, &info));
    1068            0 :                 OUT_SESSION_INFO (info);
    1069            0 :         END_CALL;
    1070              : }
    1071              : 
    1072              : static CK_RV
    1073            0 : rpc_C_InitPIN (CallState *cs)
    1074              : {
    1075              :         CK_SESSION_HANDLE session;
    1076              :         CK_UTF8CHAR_PTR pin;
    1077              :         CK_ULONG pin_len;
    1078              : 
    1079            0 :         BEGIN_CALL (C_InitPIN);
    1080            0 :                 IN_ULONG (session);
    1081            0 :                 IN_BYTE_ARRAY (pin, pin_len);
    1082            0 :         PROCESS_CALL ((session, pin, pin_len));
    1083            0 :         END_CALL;
    1084              : }
    1085              : 
    1086              : static CK_RV
    1087            0 : rpc_C_SetPIN (CallState *cs)
    1088              : {
    1089              :         CK_SESSION_HANDLE session;
    1090              :         CK_UTF8CHAR_PTR old_pin;
    1091              :         CK_ULONG old_len;
    1092              :         CK_UTF8CHAR_PTR new_pin;
    1093              :         CK_ULONG new_len;
    1094              : 
    1095            0 :         BEGIN_CALL (C_SetPIN);
    1096            0 :                 IN_ULONG (session);
    1097            0 :                 IN_BYTE_ARRAY (old_pin, old_len);
    1098            0 :                 IN_BYTE_ARRAY (new_pin, new_len);
    1099            0 :         PROCESS_CALL ((session, old_pin, old_len, new_pin, new_len));
    1100            0 :         END_CALL;
    1101              : }
    1102              : 
    1103              : static CK_RV
    1104            0 : rpc_C_GetOperationState (CallState *cs)
    1105              : {
    1106              :         CK_SESSION_HANDLE session;
    1107              :         CK_BYTE_PTR operation_state;
    1108              :         CK_ULONG operation_state_len;
    1109              : 
    1110            0 :         BEGIN_CALL (C_GetOperationState);
    1111            0 :                 IN_ULONG (session);
    1112            0 :                 IN_BYTE_BUFFER (operation_state, operation_state_len);
    1113            0 :         PROCESS_CALL ((session, operation_state, &operation_state_len));
    1114            0 :                 OUT_BYTE_ARRAY (operation_state, operation_state_len);
    1115            0 :         END_CALL;
    1116              : }
    1117              : 
    1118              : static CK_RV
    1119            0 : rpc_C_SetOperationState (CallState *cs)
    1120              : {
    1121              :         CK_SESSION_HANDLE session;
    1122              :         CK_BYTE_PTR operation_state;
    1123              :         CK_ULONG operation_state_len;
    1124              :         CK_OBJECT_HANDLE encryption_key;
    1125              :         CK_OBJECT_HANDLE authentication_key;
    1126              : 
    1127            0 :         BEGIN_CALL (C_SetOperationState);
    1128            0 :                 IN_ULONG (session);
    1129            0 :                 IN_BYTE_ARRAY (operation_state, operation_state_len);
    1130            0 :                 IN_ULONG (encryption_key);
    1131            0 :                 IN_ULONG (authentication_key);
    1132            0 :         PROCESS_CALL ((session, operation_state, operation_state_len, encryption_key, authentication_key));
    1133            0 :         END_CALL;
    1134              : }
    1135              : 
    1136              : static CK_RV
    1137            0 : rpc_C_Login (CallState *cs)
    1138              : {
    1139              :         CK_SESSION_HANDLE session;
    1140              :         CK_USER_TYPE user_type;
    1141              :         CK_UTF8CHAR_PTR pin;
    1142              :         CK_ULONG pin_len;
    1143              : 
    1144            0 :         BEGIN_CALL (C_Login);
    1145            0 :                 IN_ULONG (session);
    1146            0 :                 IN_ULONG (user_type);
    1147            0 :                 IN_BYTE_ARRAY (pin, pin_len);
    1148            0 :         PROCESS_CALL ((session, user_type, pin, pin_len));
    1149            0 :         END_CALL;
    1150              : }
    1151              : 
    1152              : static CK_RV
    1153            0 : rpc_C_Logout (CallState *cs)
    1154              : {
    1155              :         CK_SESSION_HANDLE session;
    1156              : 
    1157            0 :         BEGIN_CALL (C_Logout);
    1158            0 :                 IN_ULONG (session);
    1159            0 :         PROCESS_CALL ((session));
    1160            0 :         END_CALL;
    1161              : }
    1162              : 
    1163              : /* -----------------------------------------------------------------------------
    1164              :  * OBJECT OPERATIONS
    1165              :  */
    1166              : 
    1167              : static CK_RV
    1168            0 : rpc_C_CreateObject (CallState *cs)
    1169              : {
    1170              :         CK_SESSION_HANDLE session;
    1171              :         CK_ATTRIBUTE_PTR template;
    1172              :         CK_ULONG count;
    1173              :         CK_OBJECT_HANDLE new_object;
    1174              : 
    1175            0 :         BEGIN_CALL (C_CreateObject);
    1176            0 :                 IN_ULONG (session);
    1177            0 :                 IN_ATTRIBUTE_ARRAY (template, count);
    1178            0 :         PROCESS_CALL ((session, template, count, &new_object));
    1179            0 :                 OUT_ULONG (new_object);
    1180            0 :         END_CALL;
    1181              : }
    1182              : 
    1183              : static CK_RV
    1184            0 : rpc_C_CopyObject (CallState *cs)
    1185              : {
    1186              :         CK_SESSION_HANDLE session;
    1187              :         CK_OBJECT_HANDLE object;
    1188              :         CK_ATTRIBUTE_PTR template;
    1189              :         CK_ULONG count;
    1190              :         CK_OBJECT_HANDLE new_object;
    1191              : 
    1192            0 :         BEGIN_CALL (C_CopyObject);
    1193            0 :                 IN_ULONG (session);
    1194            0 :                 IN_ULONG (object);
    1195            0 :                 IN_ATTRIBUTE_ARRAY (template, count);
    1196            0 :         PROCESS_CALL ((session, object, template, count, &new_object));
    1197            0 :                 OUT_ULONG (new_object);
    1198            0 :         END_CALL;
    1199              : }
    1200              : 
    1201              : static CK_RV
    1202            0 : rpc_C_DestroyObject (CallState *cs)
    1203              : {
    1204              :         CK_SESSION_HANDLE session;
    1205              :         CK_OBJECT_HANDLE object;
    1206              : 
    1207            0 :         BEGIN_CALL (C_DestroyObject);
    1208            0 :                 IN_ULONG (session);
    1209            0 :                 IN_ULONG (object);
    1210            0 :         PROCESS_CALL ((session, object));
    1211            0 :         END_CALL;
    1212              : }
    1213              : 
    1214              : static CK_RV
    1215            0 : rpc_C_GetObjectSize (CallState *cs)
    1216              : {
    1217              :         CK_SESSION_HANDLE session;
    1218              :         CK_OBJECT_HANDLE object;
    1219              :         CK_ULONG size;
    1220              : 
    1221            0 :         BEGIN_CALL (C_GetObjectSize);
    1222            0 :                 IN_ULONG (session);
    1223            0 :                 IN_ULONG (object);
    1224            0 :         PROCESS_CALL ((session, object, &size));
    1225            0 :                 OUT_ULONG (size);
    1226            0 :         END_CALL;
    1227              : }
    1228              : 
    1229              : static CK_RV
    1230            0 : rpc_C_GetAttributeValue (CallState *cs)
    1231              : {
    1232              :         CK_SESSION_HANDLE session;
    1233              :         CK_OBJECT_HANDLE object;
    1234              :         CK_ATTRIBUTE_PTR template;
    1235              :         CK_ULONG count;
    1236              : 
    1237            0 :         BEGIN_CALL (C_GetAttributeValue);
    1238            0 :                 IN_ULONG (session);
    1239            0 :                 IN_ULONG (object);
    1240            0 :                 IN_ATTRIBUTE_BUFFER (template, count);
    1241            0 :         PROCESS_CALL ((session, object, template, count));
    1242            0 :                 OUT_ATTRIBUTE_ARRAY (template, count);
    1243            0 :         END_CALL;
    1244              : }
    1245              : 
    1246              : static CK_RV
    1247            0 : rpc_C_SetAttributeValue (CallState *cs)
    1248              : {
    1249              :         CK_SESSION_HANDLE session;
    1250              :         CK_OBJECT_HANDLE object;
    1251              :         CK_ATTRIBUTE_PTR template;
    1252              :         CK_ULONG count;
    1253              : 
    1254            0 :         BEGIN_CALL (C_SetAttributeValue);
    1255            0 :                 IN_ULONG (session);
    1256            0 :                 IN_ULONG (object);
    1257            0 :                 IN_ATTRIBUTE_ARRAY (template, count);
    1258            0 :         PROCESS_CALL ((session, object, template, count));
    1259            0 :         END_CALL;
    1260              : }
    1261              : 
    1262              : static CK_RV
    1263            0 : rpc_C_FindObjectsInit (CallState *cs)
    1264              : {
    1265              :         CK_SESSION_HANDLE session;
    1266              :         CK_ATTRIBUTE_PTR template;
    1267              :         CK_ULONG count;
    1268              : 
    1269            0 :         BEGIN_CALL (C_FindObjectsInit);
    1270            0 :                 IN_ULONG (session);
    1271            0 :                 IN_ATTRIBUTE_ARRAY (template, count);
    1272            0 :         PROCESS_CALL ((session, template, count));
    1273            0 :         END_CALL;
    1274              : }
    1275              : 
    1276              : static CK_RV
    1277            0 : rpc_C_FindObjects (CallState *cs)
    1278              : {
    1279              :         CK_SESSION_HANDLE session;
    1280              :         CK_OBJECT_HANDLE_PTR objects;
    1281              :         CK_ULONG max_object_count;
    1282              :         CK_ULONG object_count;
    1283              : 
    1284            0 :         BEGIN_CALL (C_FindObjects);
    1285            0 :                 IN_ULONG (session);
    1286            0 :                 IN_ULONG_BUFFER (objects, max_object_count);
    1287            0 :         PROCESS_CALL ((session, objects, max_object_count, &object_count));
    1288            0 :                 OUT_ULONG_ARRAY (objects, object_count);
    1289            0 :         END_CALL;
    1290              : }
    1291              : 
    1292              : static CK_RV
    1293            0 : rpc_C_FindObjectsFinal (CallState *cs)
    1294              : {
    1295              :         CK_SESSION_HANDLE session;
    1296              : 
    1297            0 :         BEGIN_CALL (C_FindObjectsFinal);
    1298            0 :                 IN_ULONG (session);
    1299            0 :         PROCESS_CALL ((session));
    1300            0 :         END_CALL;
    1301              : }
    1302              : 
    1303              : static CK_RV
    1304            0 : rpc_C_EncryptInit (CallState *cs)
    1305              : {
    1306              :         CK_SESSION_HANDLE session;
    1307              :         CK_MECHANISM mechanism;
    1308              :         CK_OBJECT_HANDLE key;
    1309              : 
    1310            0 :         BEGIN_CALL (C_EncryptInit);
    1311            0 :                 IN_ULONG (session);
    1312            0 :                 IN_MECHANISM (mechanism);
    1313            0 :                 IN_ULONG (key);
    1314            0 :         PROCESS_CALL ((session, &mechanism, key));
    1315            0 :         END_CALL;
    1316              : 
    1317              : }
    1318              : 
    1319              : static CK_RV
    1320            0 : rpc_C_Encrypt (CallState *cs)
    1321              : {
    1322              :         CK_SESSION_HANDLE session;
    1323              :         CK_BYTE_PTR data;
    1324              :         CK_ULONG data_len;
    1325              :         CK_BYTE_PTR encrypted_data;
    1326              :         CK_ULONG encrypted_data_len;
    1327              : 
    1328            0 :         BEGIN_CALL (C_Encrypt);
    1329            0 :                 IN_ULONG (session);
    1330            0 :                 IN_BYTE_ARRAY (data, data_len);
    1331            0 :                 IN_BYTE_BUFFER (encrypted_data, encrypted_data_len);
    1332            0 :         PROCESS_CALL ((session, data, data_len, encrypted_data, &encrypted_data_len));
    1333            0 :                 OUT_BYTE_ARRAY (encrypted_data, encrypted_data_len);
    1334            0 :         END_CALL;
    1335              : }
    1336              : 
    1337              : static CK_RV
    1338            0 : rpc_C_EncryptUpdate (CallState *cs)
    1339              : {
    1340              :         CK_SESSION_HANDLE session;
    1341              :         CK_BYTE_PTR part;
    1342              :         CK_ULONG part_len;
    1343              :         CK_BYTE_PTR encrypted_part;
    1344              :         CK_ULONG encrypted_part_len;
    1345              : 
    1346            0 :         BEGIN_CALL (C_EncryptUpdate);
    1347            0 :                 IN_ULONG (session);
    1348            0 :                 IN_BYTE_ARRAY (part, part_len);
    1349            0 :                 IN_BYTE_BUFFER (encrypted_part, encrypted_part_len);
    1350            0 :         PROCESS_CALL ((session, part, part_len, encrypted_part, &encrypted_part_len));
    1351            0 :                 OUT_BYTE_ARRAY (encrypted_part, encrypted_part_len);
    1352            0 :         END_CALL;
    1353              : }
    1354              : 
    1355              : static CK_RV
    1356            0 : rpc_C_EncryptFinal (CallState *cs)
    1357              : {
    1358              :         CK_SESSION_HANDLE session;
    1359              :         CK_BYTE_PTR last_encrypted_part;
    1360              :         CK_ULONG last_encrypted_part_len;
    1361              : 
    1362            0 :         BEGIN_CALL (C_EncryptFinal);
    1363            0 :                 IN_ULONG (session);
    1364            0 :                 IN_BYTE_BUFFER (last_encrypted_part, last_encrypted_part_len);
    1365            0 :         PROCESS_CALL ((session, last_encrypted_part, &last_encrypted_part_len));
    1366            0 :                 OUT_BYTE_ARRAY (last_encrypted_part, last_encrypted_part_len);
    1367            0 :         END_CALL;
    1368              : }
    1369              : 
    1370              : static CK_RV
    1371            0 : rpc_C_DecryptInit (CallState *cs)
    1372              : {
    1373              :         CK_SESSION_HANDLE session;
    1374              :         CK_MECHANISM mechanism;
    1375              :         CK_OBJECT_HANDLE key;
    1376              : 
    1377            0 :         BEGIN_CALL (C_DecryptInit);
    1378            0 :                 IN_ULONG (session);
    1379            0 :                 IN_MECHANISM (mechanism);
    1380            0 :                 IN_ULONG (key);
    1381            0 :         PROCESS_CALL ((session, &mechanism, key));
    1382            0 :         END_CALL;
    1383              : }
    1384              : 
    1385              : static CK_RV
    1386            0 : rpc_C_Decrypt (CallState *cs)
    1387              : {
    1388              :         CK_SESSION_HANDLE session;
    1389              :         CK_BYTE_PTR encrypted_data;
    1390              :         CK_ULONG encrypted_data_len;
    1391              :         CK_BYTE_PTR data;
    1392              :         CK_ULONG data_len;
    1393              : 
    1394            0 :         BEGIN_CALL (C_Decrypt);
    1395            0 :                 IN_ULONG (session);
    1396            0 :                 IN_BYTE_ARRAY (encrypted_data, encrypted_data_len);
    1397            0 :                 IN_BYTE_BUFFER (data, data_len);
    1398            0 :         PROCESS_CALL ((session, encrypted_data, encrypted_data_len, data, &data_len));
    1399            0 :                 OUT_BYTE_ARRAY (data, data_len);
    1400            0 :         END_CALL;
    1401              : }
    1402              : 
    1403              : static CK_RV
    1404            0 : rpc_C_DecryptUpdate (CallState *cs)
    1405              : {
    1406              :         CK_SESSION_HANDLE session;
    1407              :         CK_BYTE_PTR encrypted_part;
    1408              :         CK_ULONG encrypted_part_len;
    1409              :         CK_BYTE_PTR part;
    1410              :         CK_ULONG part_len;
    1411              : 
    1412            0 :         BEGIN_CALL (C_DecryptUpdate);
    1413            0 :                 IN_ULONG (session);
    1414            0 :                 IN_BYTE_ARRAY (encrypted_part, encrypted_part_len);
    1415            0 :                 IN_BYTE_BUFFER (part, part_len);
    1416            0 :         PROCESS_CALL ((session, encrypted_part, encrypted_part_len, part, &part_len));
    1417            0 :                 OUT_BYTE_ARRAY (part, part_len);
    1418            0 :         END_CALL;
    1419              : }
    1420              : 
    1421              : static CK_RV
    1422            0 : rpc_C_DecryptFinal (CallState *cs)
    1423              : {
    1424              :         CK_SESSION_HANDLE session;
    1425              :         CK_BYTE_PTR last_part;
    1426              :         CK_ULONG last_part_len;
    1427              : 
    1428            0 :         BEGIN_CALL (C_DecryptFinal);
    1429            0 :                 IN_ULONG (session);
    1430            0 :                 IN_BYTE_BUFFER (last_part, last_part_len);
    1431            0 :         PROCESS_CALL ((session, last_part, &last_part_len));
    1432            0 :                 OUT_BYTE_ARRAY (last_part, last_part_len);
    1433            0 :         END_CALL;
    1434              : }
    1435              : 
    1436              : static CK_RV
    1437            0 : rpc_C_DigestInit (CallState *cs)
    1438              : {
    1439              :         CK_SESSION_HANDLE session;
    1440              :         CK_MECHANISM mechanism;
    1441              : 
    1442            0 :         BEGIN_CALL (C_DigestInit);
    1443            0 :                 IN_ULONG (session);
    1444            0 :                 IN_MECHANISM (mechanism);
    1445            0 :         PROCESS_CALL ((session, &mechanism));
    1446            0 :         END_CALL;
    1447              : }
    1448              : 
    1449              : static CK_RV
    1450            0 : rpc_C_Digest (CallState *cs)
    1451              : {
    1452              :         CK_SESSION_HANDLE session;
    1453              :         CK_BYTE_PTR data;
    1454              :         CK_ULONG data_len;
    1455              :         CK_BYTE_PTR digest;
    1456              :         CK_ULONG digest_len;
    1457              : 
    1458            0 :         BEGIN_CALL (C_Digest);
    1459            0 :                 IN_ULONG (session);
    1460            0 :                 IN_BYTE_ARRAY (data, data_len);
    1461            0 :                 IN_BYTE_BUFFER (digest, digest_len);
    1462            0 :         PROCESS_CALL ((session, data, data_len, digest, &digest_len));
    1463            0 :                 OUT_BYTE_ARRAY (digest, digest_len);
    1464            0 :         END_CALL;
    1465              : }
    1466              : 
    1467              : static CK_RV
    1468            0 : rpc_C_DigestUpdate (CallState *cs)
    1469              : {
    1470              :         CK_SESSION_HANDLE session;
    1471              :         CK_BYTE_PTR part;
    1472              :         CK_ULONG part_len;
    1473              : 
    1474            0 :         BEGIN_CALL (C_DigestUpdate);
    1475            0 :                 IN_ULONG (session);
    1476            0 :                 IN_BYTE_ARRAY (part, part_len);
    1477            0 :         PROCESS_CALL ((session, part, part_len));
    1478            0 :         END_CALL;
    1479              : }
    1480              : 
    1481              : static CK_RV
    1482            0 : rpc_C_DigestKey (CallState *cs)
    1483              : {
    1484              :         CK_SESSION_HANDLE session;
    1485              :         CK_OBJECT_HANDLE key;
    1486              : 
    1487            0 :         BEGIN_CALL (C_DigestKey);
    1488            0 :                 IN_ULONG (session);
    1489            0 :                 IN_ULONG (key);
    1490            0 :         PROCESS_CALL ((session, key));
    1491            0 :         END_CALL;
    1492              : }
    1493              : 
    1494              : static CK_RV
    1495            0 : rpc_C_DigestFinal (CallState *cs)
    1496              : {
    1497              :         CK_SESSION_HANDLE session;
    1498              :         CK_BYTE_PTR digest;
    1499              :         CK_ULONG digest_len;
    1500              : 
    1501            0 :         BEGIN_CALL (C_DigestFinal);
    1502            0 :                 IN_ULONG (session);
    1503            0 :                 IN_BYTE_BUFFER (digest, digest_len);
    1504            0 :         PROCESS_CALL ((session, digest, &digest_len));
    1505            0 :                 OUT_BYTE_ARRAY (digest, digest_len);
    1506            0 :         END_CALL;
    1507              : }
    1508              : 
    1509              : static CK_RV
    1510            0 : rpc_C_SignInit (CallState *cs)
    1511              : {
    1512              :         CK_SESSION_HANDLE session;
    1513              :         CK_MECHANISM mechanism;
    1514              :         CK_OBJECT_HANDLE key;
    1515              : 
    1516            0 :         BEGIN_CALL (C_SignInit);
    1517            0 :                 IN_ULONG (session);
    1518            0 :                 IN_MECHANISM (mechanism);
    1519            0 :                 IN_ULONG (key);
    1520            0 :         PROCESS_CALL ((session, &mechanism, key));
    1521            0 :         END_CALL;
    1522              : }
    1523              : 
    1524              : static CK_RV
    1525            0 : rpc_C_Sign (CallState *cs)
    1526              : {
    1527              :         CK_SESSION_HANDLE session;
    1528              :         CK_BYTE_PTR part;
    1529              :         CK_ULONG part_len;
    1530              :         CK_BYTE_PTR signature;
    1531              :         CK_ULONG signature_len;
    1532              : 
    1533            0 :         BEGIN_CALL (C_Sign);
    1534            0 :                 IN_ULONG (session);
    1535            0 :                 IN_BYTE_ARRAY (part, part_len);
    1536            0 :                 IN_BYTE_BUFFER (signature, signature_len);
    1537            0 :         PROCESS_CALL ((session, part, part_len, signature, &signature_len));
    1538            0 :                 OUT_BYTE_ARRAY (signature, signature_len);
    1539            0 :         END_CALL;
    1540              : 
    1541              : }
    1542              : 
    1543              : static CK_RV
    1544            0 : rpc_C_SignUpdate (CallState *cs)
    1545              : {
    1546              :         CK_SESSION_HANDLE session;
    1547              :         CK_BYTE_PTR part;
    1548              :         CK_ULONG part_len;
    1549              : 
    1550            0 :         BEGIN_CALL (C_SignUpdate);
    1551            0 :                 IN_ULONG (session);
    1552            0 :                 IN_BYTE_ARRAY (part, part_len);
    1553            0 :         PROCESS_CALL ((session, part, part_len));
    1554            0 :         END_CALL;
    1555              : }
    1556              : 
    1557              : static CK_RV
    1558            0 : rpc_C_SignFinal (CallState *cs)
    1559              : {
    1560              :         CK_SESSION_HANDLE session;
    1561              :         CK_BYTE_PTR signature;
    1562              :         CK_ULONG signature_len;
    1563              : 
    1564            0 :         BEGIN_CALL (C_SignFinal);
    1565            0 :                 IN_ULONG (session);
    1566            0 :                 IN_BYTE_BUFFER (signature, signature_len);
    1567            0 :         PROCESS_CALL ((session, signature, &signature_len));
    1568            0 :                 OUT_BYTE_ARRAY (signature, signature_len);
    1569            0 :         END_CALL;
    1570              : }
    1571              : 
    1572              : static CK_RV
    1573            0 : rpc_C_SignRecoverInit (CallState *cs)
    1574              : {
    1575              :         CK_SESSION_HANDLE session;
    1576              :         CK_MECHANISM mechanism;
    1577              :         CK_OBJECT_HANDLE key;
    1578              : 
    1579            0 :         BEGIN_CALL (C_SignRecoverInit);
    1580            0 :                 IN_ULONG (session);
    1581            0 :                 IN_MECHANISM (mechanism);
    1582            0 :                 IN_ULONG (key);
    1583            0 :         PROCESS_CALL ((session, &mechanism, key));
    1584            0 :         END_CALL;
    1585              : }
    1586              : 
    1587              : static CK_RV
    1588            0 : rpc_C_SignRecover (CallState *cs)
    1589              : {
    1590              :         CK_SESSION_HANDLE session;
    1591              :         CK_BYTE_PTR data;
    1592              :         CK_ULONG data_len;
    1593              :         CK_BYTE_PTR signature;
    1594              :         CK_ULONG signature_len;
    1595              : 
    1596            0 :         BEGIN_CALL (C_SignRecover);
    1597            0 :                 IN_ULONG (session);
    1598            0 :                 IN_BYTE_ARRAY (data, data_len);
    1599            0 :                 IN_BYTE_BUFFER (signature, signature_len);
    1600            0 :         PROCESS_CALL ((session, data, data_len, signature, &signature_len));
    1601            0 :                 OUT_BYTE_ARRAY (signature, signature_len);
    1602            0 :         END_CALL;
    1603              : }
    1604              : 
    1605              : static CK_RV
    1606            0 : rpc_C_VerifyInit (CallState *cs)
    1607              : {
    1608              :         CK_SESSION_HANDLE session;
    1609              :         CK_MECHANISM mechanism;
    1610              :         CK_OBJECT_HANDLE key;
    1611              : 
    1612            0 :         BEGIN_CALL (C_VerifyInit);
    1613            0 :                 IN_ULONG (session);
    1614            0 :                 IN_MECHANISM (mechanism);
    1615            0 :                 IN_ULONG (key);
    1616            0 :         PROCESS_CALL ((session, &mechanism, key));
    1617            0 :         END_CALL;
    1618              : }
    1619              : 
    1620              : static CK_RV
    1621            0 : rpc_C_Verify (CallState *cs)
    1622              : {
    1623              :         CK_SESSION_HANDLE session;
    1624              :         CK_BYTE_PTR data;
    1625              :         CK_ULONG data_len;
    1626              :         CK_BYTE_PTR signature;
    1627              :         CK_ULONG signature_len;
    1628              : 
    1629            0 :         BEGIN_CALL (C_Verify);
    1630            0 :                 IN_ULONG (session);
    1631            0 :                 IN_BYTE_ARRAY (data, data_len);
    1632            0 :                 IN_BYTE_ARRAY (signature, signature_len);
    1633            0 :         PROCESS_CALL ((session, data, data_len, signature, signature_len));
    1634            0 :         END_CALL;
    1635              : }
    1636              : 
    1637              : static CK_RV
    1638            0 : rpc_C_VerifyUpdate (CallState *cs)
    1639              : {
    1640              :         CK_SESSION_HANDLE session;
    1641              :         CK_BYTE_PTR part;
    1642              :         CK_ULONG part_len;
    1643              : 
    1644            0 :         BEGIN_CALL (C_VerifyUpdate);
    1645            0 :                 IN_ULONG (session);
    1646            0 :                 IN_BYTE_ARRAY (part, part_len);
    1647            0 :         PROCESS_CALL ((session, part, part_len));
    1648            0 :         END_CALL;
    1649              : }
    1650              : 
    1651              : static CK_RV
    1652            0 : rpc_C_VerifyFinal (CallState *cs)
    1653              : {
    1654              :         CK_SESSION_HANDLE session;
    1655              :         CK_BYTE_PTR signature;
    1656              :         CK_ULONG signature_len;
    1657              : 
    1658            0 :         BEGIN_CALL (C_VerifyFinal);
    1659            0 :                 IN_ULONG (session);
    1660            0 :                 IN_BYTE_ARRAY (signature, signature_len);
    1661            0 :         PROCESS_CALL ((session, signature, signature_len));
    1662            0 :         END_CALL;
    1663              : }
    1664              : 
    1665              : static CK_RV
    1666            0 : rpc_C_VerifyRecoverInit (CallState *cs)
    1667              : {
    1668              :         CK_SESSION_HANDLE session;
    1669              :         CK_MECHANISM mechanism;
    1670              :         CK_OBJECT_HANDLE key;
    1671              : 
    1672            0 :         BEGIN_CALL (C_VerifyRecoverInit);
    1673            0 :                 IN_ULONG (session);
    1674            0 :                 IN_MECHANISM (mechanism);
    1675            0 :                 IN_ULONG (key);
    1676            0 :         PROCESS_CALL ((session, &mechanism, key));
    1677            0 :         END_CALL;
    1678              : }
    1679              : 
    1680              : static CK_RV
    1681            0 : rpc_C_VerifyRecover (CallState *cs)
    1682              : {
    1683              :         CK_SESSION_HANDLE session;
    1684              :         CK_BYTE_PTR signature;
    1685              :         CK_ULONG signature_len;
    1686              :         CK_BYTE_PTR data;
    1687              :         CK_ULONG data_len;
    1688              : 
    1689            0 :         BEGIN_CALL (C_VerifyRecover);
    1690            0 :                 IN_ULONG (session);
    1691            0 :                 IN_BYTE_ARRAY (signature, signature_len);
    1692            0 :                 IN_BYTE_BUFFER (data, data_len);
    1693            0 :         PROCESS_CALL ((session, signature, signature_len, data, &data_len));
    1694            0 :                 OUT_BYTE_ARRAY (data, data_len);
    1695            0 :         END_CALL;
    1696              : }
    1697              : 
    1698              : static CK_RV
    1699            0 : rpc_C_DigestEncryptUpdate (CallState *cs)
    1700              : {
    1701              :         CK_SESSION_HANDLE session;
    1702              :         CK_BYTE_PTR part;
    1703              :         CK_ULONG part_len;
    1704              :         CK_BYTE_PTR encrypted_part;
    1705              :         CK_ULONG encrypted_part_len;
    1706              : 
    1707            0 :         BEGIN_CALL (C_DigestEncryptUpdate);
    1708            0 :                 IN_ULONG (session);
    1709            0 :                 IN_BYTE_ARRAY (part, part_len);
    1710            0 :                 IN_BYTE_BUFFER (encrypted_part, encrypted_part_len);
    1711            0 :         PROCESS_CALL ((session, part, part_len, encrypted_part, &encrypted_part_len));
    1712            0 :                 OUT_BYTE_ARRAY (encrypted_part, encrypted_part_len);
    1713            0 :         END_CALL;
    1714              : }
    1715              : 
    1716              : static CK_RV
    1717            0 : rpc_C_DecryptDigestUpdate (CallState *cs)
    1718              : {
    1719              :         CK_SESSION_HANDLE session;
    1720              :         CK_BYTE_PTR encrypted_part;
    1721              :         CK_ULONG encrypted_part_len;
    1722              :         CK_BYTE_PTR part;
    1723              :         CK_ULONG part_len;
    1724              : 
    1725            0 :         BEGIN_CALL (C_DecryptDigestUpdate);
    1726            0 :                 IN_ULONG (session);
    1727            0 :                 IN_BYTE_ARRAY (encrypted_part, encrypted_part_len);
    1728            0 :                 IN_BYTE_BUFFER (part, part_len);
    1729            0 :         PROCESS_CALL ((session, encrypted_part, encrypted_part_len, part, &part_len));
    1730            0 :                 OUT_BYTE_ARRAY (part, part_len);
    1731            0 :         END_CALL;
    1732              : }
    1733              : 
    1734              : static CK_RV
    1735            0 : rpc_C_SignEncryptUpdate (CallState *cs)
    1736              : {
    1737              :         CK_SESSION_HANDLE session;
    1738              :         CK_BYTE_PTR part;
    1739              :         CK_ULONG part_len;
    1740              :         CK_BYTE_PTR encrypted_part;
    1741              :         CK_ULONG encrypted_part_len;
    1742              : 
    1743            0 :         BEGIN_CALL (C_SignEncryptUpdate);
    1744            0 :                 IN_ULONG (session);
    1745            0 :                 IN_BYTE_ARRAY (part, part_len);
    1746            0 :                 IN_BYTE_BUFFER (encrypted_part, encrypted_part_len);
    1747            0 :         PROCESS_CALL ((session, part, part_len, encrypted_part, &encrypted_part_len));
    1748            0 :                 OUT_BYTE_ARRAY (encrypted_part, encrypted_part_len);
    1749            0 :         END_CALL;
    1750              : }
    1751              : 
    1752              : static CK_RV
    1753            0 : rpc_C_DecryptVerifyUpdate (CallState *cs)
    1754              : {
    1755              :         CK_SESSION_HANDLE session;
    1756              :         CK_BYTE_PTR encrypted_part;
    1757              :         CK_ULONG encrypted_part_len;
    1758              :         CK_BYTE_PTR part;
    1759              :         CK_ULONG part_len;
    1760              : 
    1761            0 :         BEGIN_CALL (C_DecryptVerifyUpdate);
    1762            0 :                 IN_ULONG (session);
    1763            0 :                 IN_BYTE_ARRAY (encrypted_part, encrypted_part_len);
    1764            0 :                 IN_BYTE_BUFFER (part, part_len);
    1765            0 :         PROCESS_CALL ((session, encrypted_part, encrypted_part_len, part, &part_len));
    1766            0 :                 OUT_BYTE_ARRAY (part, part_len);
    1767            0 :         END_CALL;
    1768              : }
    1769              : 
    1770              : /* -----------------------------------------------------------------------------
    1771              :  * KEY OPERATIONS
    1772              :  */
    1773              : 
    1774              : static CK_RV
    1775            0 : rpc_C_GenerateKey (CallState *cs)
    1776              : {
    1777              :         CK_SESSION_HANDLE session;
    1778              :         CK_MECHANISM mechanism;
    1779              :         CK_ATTRIBUTE_PTR template;
    1780              :         CK_ULONG count;
    1781              :         CK_OBJECT_HANDLE key;
    1782              : 
    1783            0 :         BEGIN_CALL (C_GenerateKey);
    1784            0 :                 IN_ULONG (session);
    1785            0 :                 IN_MECHANISM (mechanism);
    1786            0 :                 IN_ATTRIBUTE_ARRAY (template, count);
    1787            0 :         PROCESS_CALL ((session, &mechanism, template, count, &key));
    1788            0 :                 OUT_ULONG (key);
    1789            0 :         END_CALL;
    1790              : }
    1791              : 
    1792              : static CK_RV
    1793            0 : rpc_C_GenerateKeyPair (CallState *cs)
    1794              : {
    1795              :         CK_SESSION_HANDLE session;
    1796              :         CK_MECHANISM mechanism;
    1797              :         CK_ATTRIBUTE_PTR public_key_template;
    1798              :         CK_ULONG public_key_attribute_count;
    1799              :         CK_ATTRIBUTE_PTR private_key_template;
    1800              :         CK_ULONG private_key_attribute_count;
    1801              :         CK_OBJECT_HANDLE public_key;
    1802              :         CK_OBJECT_HANDLE private_key;
    1803              : 
    1804            0 :         BEGIN_CALL (C_GenerateKeyPair);
    1805            0 :                 IN_ULONG (session);
    1806            0 :                 IN_MECHANISM (mechanism);
    1807            0 :                 IN_ATTRIBUTE_ARRAY (public_key_template, public_key_attribute_count);
    1808            0 :                 IN_ATTRIBUTE_ARRAY (private_key_template, private_key_attribute_count);
    1809            0 :         PROCESS_CALL ((session, &mechanism, public_key_template, public_key_attribute_count, private_key_template, private_key_attribute_count, &public_key, &private_key));
    1810            0 :                 OUT_ULONG (public_key);
    1811            0 :                 OUT_ULONG (private_key);
    1812            0 :         END_CALL;
    1813              : 
    1814              : }
    1815              : 
    1816              : static CK_RV
    1817            0 : rpc_C_WrapKey (CallState *cs)
    1818              : {
    1819              :         CK_SESSION_HANDLE session;
    1820              :         CK_MECHANISM mechanism;
    1821              :         CK_OBJECT_HANDLE wrapping_key;
    1822              :         CK_OBJECT_HANDLE key;
    1823              :         CK_BYTE_PTR wrapped_key;
    1824              :         CK_ULONG wrapped_key_len;
    1825              : 
    1826            0 :         BEGIN_CALL (C_WrapKey);
    1827            0 :                 IN_ULONG (session);
    1828            0 :                 IN_MECHANISM (mechanism);
    1829            0 :                 IN_ULONG (wrapping_key);
    1830            0 :                 IN_ULONG (key);
    1831            0 :                 IN_BYTE_BUFFER (wrapped_key, wrapped_key_len);
    1832            0 :         PROCESS_CALL ((session, &mechanism, wrapping_key, key, wrapped_key, &wrapped_key_len));
    1833            0 :                 OUT_BYTE_ARRAY (wrapped_key, wrapped_key_len);
    1834            0 :         END_CALL;
    1835              : }
    1836              : 
    1837              : static CK_RV
    1838            0 : rpc_C_UnwrapKey (CallState *cs)
    1839              : {
    1840              :         CK_SESSION_HANDLE session;
    1841              :         CK_MECHANISM mechanism;
    1842              :         CK_OBJECT_HANDLE unwrapping_key;
    1843              :         CK_BYTE_PTR wrapped_key;
    1844              :         CK_ULONG wrapped_key_len;
    1845              :         CK_ATTRIBUTE_PTR template;
    1846              :         CK_ULONG attribute_count;
    1847              :         CK_OBJECT_HANDLE key;
    1848              : 
    1849            0 :         BEGIN_CALL (C_UnwrapKey);
    1850            0 :                 IN_ULONG (session);
    1851            0 :                 IN_MECHANISM (mechanism);
    1852            0 :                 IN_ULONG (unwrapping_key);
    1853            0 :                 IN_BYTE_ARRAY (wrapped_key, wrapped_key_len);
    1854            0 :                 IN_ATTRIBUTE_ARRAY (template, attribute_count);
    1855            0 :         PROCESS_CALL ((session, &mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, attribute_count, &key));
    1856            0 :                 OUT_ULONG (key);
    1857            0 :         END_CALL;
    1858              : }
    1859              : 
    1860              : static CK_RV
    1861            0 : rpc_C_DeriveKey (CallState *cs)
    1862              : {
    1863              :         CK_SESSION_HANDLE session;
    1864              :         CK_MECHANISM mechanism;
    1865              :         CK_OBJECT_HANDLE base_key;
    1866              :         CK_ATTRIBUTE_PTR template;
    1867              :         CK_ULONG attribute_count;
    1868              :         CK_OBJECT_HANDLE key;
    1869              : 
    1870            0 :         BEGIN_CALL (C_DeriveKey);
    1871            0 :                 IN_ULONG (session);
    1872            0 :                 IN_MECHANISM (mechanism);
    1873            0 :                 IN_ULONG (base_key);
    1874            0 :                 IN_ATTRIBUTE_ARRAY (template, attribute_count);
    1875            0 :         PROCESS_CALL ((session, &mechanism, base_key, template, attribute_count, &key));
    1876            0 :                 OUT_ULONG (key);
    1877            0 :         END_CALL;
    1878              : }
    1879              : 
    1880              : static CK_RV
    1881            0 : rpc_C_SeedRandom (CallState *cs)
    1882              : {
    1883              :         CK_SESSION_HANDLE session;
    1884              :         CK_BYTE_PTR seed;
    1885              :         CK_ULONG seed_len;
    1886              : 
    1887            0 :         BEGIN_CALL (C_SeedRandom);
    1888            0 :                 IN_ULONG (session);
    1889            0 :                 IN_BYTE_ARRAY (seed, seed_len);
    1890            0 :         PROCESS_CALL ((session, seed, seed_len));
    1891            0 :         END_CALL;
    1892              : }
    1893              : 
    1894              : static CK_RV
    1895            0 : rpc_C_GenerateRandom (CallState *cs)
    1896              : {
    1897              :         CK_SESSION_HANDLE session;
    1898              :         CK_BYTE_PTR random_data;
    1899              :         CK_ULONG random_len;
    1900              : 
    1901            0 :         BEGIN_CALL (C_GenerateRandom);
    1902            0 :                 IN_ULONG (session);
    1903            0 :                 IN_BYTE_BUFFER (random_data, random_len);
    1904            0 :         PROCESS_CALL ((session, random_data, random_len));
    1905            0 :                 OUT_BYTE_ARRAY (random_data, random_len);
    1906            0 :         END_CALL;
    1907              : }
    1908              : 
    1909              : /* ---------------------------------------------------------------------------
    1910              :  * DISPATCH THREAD HANDLING
    1911              :  */
    1912              : 
    1913              : static int
    1914            6 : dispatch_call (CallState *cs)
    1915              : {
    1916              :         GkmRpcMessage *req, *resp;
    1917            6 :         CK_RV ret = CKR_OK;
    1918              : 
    1919            6 :         assert (cs);
    1920              : 
    1921            6 :         req = cs->req;
    1922            6 :         resp = cs->resp;
    1923              : 
    1924              :         /* This should have been checked by the parsing code */
    1925            6 :         assert (req->call_id > GKM_RPC_CALL_ERROR);
    1926            6 :         assert (req->call_id < GKM_RPC_CALL_MAX);
    1927              : 
    1928              :         /* Prepare a response for the function to fill in */
    1929            6 :         if (!gkm_rpc_message_prep (resp, req->call_id, GKM_RPC_RESPONSE)) {
    1930            0 :                 gkm_rpc_warn ("couldn't prepare message");
    1931            0 :                 return 0;
    1932              :         }
    1933              : 
    1934            6 :         switch(req->call_id) {
    1935              : 
    1936              :         #define CASE_CALL(name) \
    1937              :                 case GKM_RPC_CALL_##name: \
    1938              :                         ret = rpc_##name (cs); \
    1939              :                         break;
    1940            2 :         CASE_CALL(C_Initialize)
    1941            2 :         CASE_CALL(C_Finalize)
    1942            2 :         CASE_CALL(C_GetInfo)
    1943            0 :         CASE_CALL(C_GetSlotList)
    1944            0 :         CASE_CALL(C_GetSlotInfo)
    1945            0 :         CASE_CALL(C_GetTokenInfo)
    1946            0 :         CASE_CALL(C_GetMechanismList)
    1947            0 :         CASE_CALL(C_GetMechanismInfo)
    1948            0 :         CASE_CALL(C_InitToken)
    1949            0 :         CASE_CALL(C_WaitForSlotEvent)
    1950            0 :         CASE_CALL(C_OpenSession)
    1951            0 :         CASE_CALL(C_CloseSession)
    1952            0 :         CASE_CALL(C_CloseAllSessions)
    1953            0 :         CASE_CALL(C_GetFunctionStatus)
    1954            0 :         CASE_CALL(C_CancelFunction)
    1955            0 :         CASE_CALL(C_GetSessionInfo)
    1956            0 :         CASE_CALL(C_InitPIN)
    1957            0 :         CASE_CALL(C_SetPIN)
    1958            0 :         CASE_CALL(C_GetOperationState)
    1959            0 :         CASE_CALL(C_SetOperationState)
    1960            0 :         CASE_CALL(C_Login)
    1961            0 :         CASE_CALL(C_Logout)
    1962            0 :         CASE_CALL(C_CreateObject)
    1963            0 :         CASE_CALL(C_CopyObject)
    1964            0 :         CASE_CALL(C_DestroyObject)
    1965            0 :         CASE_CALL(C_GetObjectSize)
    1966            0 :         CASE_CALL(C_GetAttributeValue)
    1967            0 :         CASE_CALL(C_SetAttributeValue)
    1968            0 :         CASE_CALL(C_FindObjectsInit)
    1969            0 :         CASE_CALL(C_FindObjects)
    1970            0 :         CASE_CALL(C_FindObjectsFinal)
    1971            0 :         CASE_CALL(C_EncryptInit)
    1972            0 :         CASE_CALL(C_Encrypt)
    1973            0 :         CASE_CALL(C_EncryptUpdate)
    1974            0 :         CASE_CALL(C_EncryptFinal)
    1975            0 :         CASE_CALL(C_DecryptInit)
    1976            0 :         CASE_CALL(C_Decrypt)
    1977            0 :         CASE_CALL(C_DecryptUpdate)
    1978            0 :         CASE_CALL(C_DecryptFinal)
    1979            0 :         CASE_CALL(C_DigestInit)
    1980            0 :         CASE_CALL(C_Digest)
    1981            0 :         CASE_CALL(C_DigestUpdate)
    1982            0 :         CASE_CALL(C_DigestKey)
    1983            0 :         CASE_CALL(C_DigestFinal)
    1984            0 :         CASE_CALL(C_SignInit)
    1985            0 :         CASE_CALL(C_Sign)
    1986            0 :         CASE_CALL(C_SignUpdate)
    1987            0 :         CASE_CALL(C_SignFinal)
    1988            0 :         CASE_CALL(C_SignRecoverInit)
    1989            0 :         CASE_CALL(C_SignRecover)
    1990            0 :         CASE_CALL(C_VerifyInit)
    1991            0 :         CASE_CALL(C_Verify)
    1992            0 :         CASE_CALL(C_VerifyUpdate)
    1993            0 :         CASE_CALL(C_VerifyFinal)
    1994            0 :         CASE_CALL(C_VerifyRecoverInit)
    1995            0 :         CASE_CALL(C_VerifyRecover)
    1996            0 :         CASE_CALL(C_DigestEncryptUpdate)
    1997            0 :         CASE_CALL(C_DecryptDigestUpdate)
    1998            0 :         CASE_CALL(C_SignEncryptUpdate)
    1999            0 :         CASE_CALL(C_DecryptVerifyUpdate)
    2000            0 :         CASE_CALL(C_GenerateKey)
    2001            0 :         CASE_CALL(C_GenerateKeyPair)
    2002            0 :         CASE_CALL(C_WrapKey)
    2003            0 :         CASE_CALL(C_UnwrapKey)
    2004            0 :         CASE_CALL(C_DeriveKey)
    2005            0 :         CASE_CALL(C_SeedRandom)
    2006            0 :         CASE_CALL(C_GenerateRandom)
    2007              :         #undef CASE_CALL
    2008              : 
    2009            0 :         default:
    2010              :                 /* This should have been caught by the parse code */
    2011            0 :                 assert (0 && "Unchecked call");
    2012              :                 break;
    2013              :         };
    2014              : 
    2015            6 :         if (ret == CKR_OK) {
    2016              : 
    2017              :                 /* Parsing errors? */
    2018            6 :                 if (gkm_rpc_message_buffer_error (req)) {
    2019            0 :                         gkm_rpc_warn ("invalid request from module, probably too short");
    2020            0 :                         ret = PARSE_ERROR;
    2021              :                 }
    2022              : 
    2023              :                 /* Out of memory errors? */
    2024            6 :                 if (gkm_rpc_message_buffer_error (resp)) {
    2025            0 :                         gkm_rpc_warn ("out of memory error putting together message");
    2026            0 :                         ret = PREP_ERROR;
    2027              :                 }
    2028              :         }
    2029              : 
    2030              :         /* A filled in response */
    2031            6 :         if (ret == CKR_OK) {
    2032              : 
    2033              :                 /*
    2034              :                  * Since we're dealing with many many functions above generating
    2035              :                  * these messages we want to make sure each of them actually
    2036              :                  * does what it's supposed to.
    2037              :                  */
    2038              : 
    2039            6 :                 assert (gkm_rpc_message_is_verified (resp));
    2040            6 :                 assert (resp->call_type == GKM_RPC_RESPONSE);
    2041            6 :                 assert (resp->call_id == req->call_id);
    2042            6 :                 assert (gkm_rpc_calls[resp->call_id].response);
    2043            6 :                 assert (strcmp (gkm_rpc_calls[resp->call_id].response,
    2044              :                                 resp->signature) == 0);
    2045              : 
    2046              :         /* Fill in an error respnose */
    2047              :         } else {
    2048            0 :                 if (!gkm_rpc_message_prep (resp, GKM_RPC_CALL_ERROR, GKM_RPC_RESPONSE) ||
    2049            0 :                     !gkm_rpc_message_write_ulong (resp, (uint32_t)ret) ||
    2050            0 :                     gkm_rpc_message_buffer_error (resp)) {
    2051            0 :                         gkm_rpc_warn ("out of memory responding with error");
    2052            0 :                         return 0;
    2053              :                 }
    2054              :         }
    2055              : 
    2056            6 :         return 1;
    2057              : }
    2058              : 
    2059              : static int
    2060           14 : read_all (int sock, unsigned char* data, size_t len)
    2061              : {
    2062              :         int r;
    2063              : 
    2064           14 :         assert (sock >= 0);
    2065           14 :         assert (data);
    2066           14 :         assert (len > 0);
    2067              : 
    2068           26 :         while (len > 0) {
    2069              : 
    2070           14 :                 r = read (sock, data, len);
    2071              : 
    2072           14 :                 if (r == 0) {
    2073              :                         /* Connection was closed on client */
    2074            2 :                         return 0;
    2075           12 :                 } else if (r == -1) {
    2076            0 :                         if (errno != EAGAIN && errno != EINTR) {
    2077            0 :                                 gkm_rpc_warn ("couldn't receive data: %s", strerror (errno));
    2078            0 :                                 return 0;
    2079              :                         }
    2080              :                 } else {
    2081           12 :                         data += r;
    2082           12 :                         len -= r;
    2083              :                 }
    2084              :         }
    2085              : 
    2086           12 :         return 1;
    2087              : }
    2088              : 
    2089              : static int
    2090           12 : write_all (int sock, unsigned char* data, size_t len)
    2091              : {
    2092              :         int r;
    2093              : 
    2094           12 :         assert (sock >= 0);
    2095           12 :         assert (data);
    2096           12 :         assert (len > 0);
    2097              : 
    2098           24 :         while (len > 0) {
    2099              : 
    2100           12 :                 r = write (sock, data, len);
    2101              : 
    2102           12 :                 if (r == -1) {
    2103            0 :                         if (errno == EPIPE) {
    2104              :                                 /* Connection closed from client */
    2105            0 :                                 return 0;
    2106            0 :                         } else if (errno != EAGAIN && errno != EINTR) {
    2107            0 :                                 gkm_rpc_warn ("couldn't send data: %s", strerror (errno));
    2108            0 :                                 return 0;
    2109              :                         }
    2110              :                 } else {
    2111           12 :                         data += r;
    2112           12 :                         len -= r;
    2113              :                 }
    2114              :         }
    2115              : 
    2116           12 :         return 1;
    2117              : }
    2118              : 
    2119              : static void
    2120            2 : run_dispatch_loop (int sock)
    2121              : {
    2122              :         CallState cs;
    2123              :         pid_t pid;
    2124              :         uid_t uid;
    2125              :         unsigned char buf[4];
    2126              :         uint32_t len;
    2127              : 
    2128            2 :         assert (sock != -1);
    2129              : 
    2130            2 :         if (egg_unix_credentials_read (sock, &pid, &uid) < 0) {
    2131            0 :                 gkm_rpc_warn ("couldn't read socket credentials");
    2132            0 :                 return;
    2133              :         }
    2134              : 
    2135              :         /* Setup our buffers */
    2136            2 :         if (!call_init (&cs, uid, pid)) {
    2137            0 :                 gkm_rpc_warn ("out of memory");
    2138            0 :                 return;
    2139              :         }
    2140              : 
    2141              :         /* The main thread loop */
    2142              :         while (TRUE) {
    2143              : 
    2144            8 :                 call_reset (&cs);
    2145              : 
    2146              :                 /* Read the number of bytes ... */
    2147            8 :                 if (!read_all (sock, buf, 4))
    2148            2 :                         break;
    2149              : 
    2150              :                 /* Calculate the number of bytes */
    2151            6 :                 len = egg_buffer_decode_uint32 (buf);
    2152            6 :                 if (len >= 0x0FFFFFFF) {
    2153            0 :                         gkm_rpc_warn ("invalid message size from module: %u bytes", len);
    2154            0 :                         break;
    2155              :                 }
    2156              : 
    2157              :                 /* Allocate memory */
    2158            6 :                 egg_buffer_reserve (&cs.req->buffer, cs.req->buffer.len + len);
    2159            6 :                 if (egg_buffer_has_error (&cs.req->buffer)) {
    2160            0 :                         gkm_rpc_warn ("error allocating buffer for message");
    2161            0 :                         break;
    2162              :                 }
    2163              : 
    2164              :                 /* ... and read/parse in the actual message */
    2165            6 :                 if (!read_all (sock, cs.req->buffer.buf, len))
    2166            0 :                         break;
    2167              : 
    2168            6 :                 egg_buffer_add_empty (&cs.req->buffer, len);
    2169              : 
    2170            6 :                 if (!gkm_rpc_message_parse (cs.req, GKM_RPC_REQUEST))
    2171            0 :                         break;
    2172              : 
    2173              :                 /* ... send for processing ... */
    2174            6 :                 if (!dispatch_call (&cs))
    2175            0 :                         break;
    2176              : 
    2177              :                 /* .. send back response length, and then response data */
    2178            6 :                 egg_buffer_encode_uint32 (buf, cs.resp->buffer.len);
    2179           12 :                 if(!write_all (sock, buf, 4) ||
    2180            6 :                    !write_all (sock, cs.resp->buffer.buf, cs.resp->buffer.len))
    2181              :                         break;
    2182              :         }
    2183              : 
    2184              :         /*
    2185              :          * Close all sessions for the client application
    2186              :          *
    2187              :          * EXTENSION: In our extended application PKCS#11 model
    2188              :          * C_CloseAllSessions accepts an application identifier as well
    2189              :          * as slot ids. Calling with an application identifier closes all
    2190              :          * sessions for just that application identifier.
    2191              :          */
    2192            2 :         pthread_mutex_lock (&clients_mutex);
    2193              : 
    2194            2 :         if (!--cs.client->refcount) {
    2195            2 :                 ClientInstance **cl = &clients;
    2196              : 
    2197            2 :                 while (*cl) {
    2198            2 :                         if (*cl == cs.client) {
    2199            2 :                                 *cl = cs.client->next;
    2200            2 :                                 break;
    2201              :                         }
    2202            0 :                         cl = &(*cl)->next;
    2203              :                 }
    2204            2 :                 if (cs.client->application.applicationId)
    2205            0 :                         (pkcs11_module->C_CloseAllSessions) (cs.client->application.applicationId);
    2206            2 :                 free (cs.client);
    2207            2 :                 cs.client = NULL;
    2208              :         }
    2209              : 
    2210            2 :         pthread_mutex_unlock (&clients_mutex);
    2211              : 
    2212            2 :         call_uninit (&cs);
    2213              : }
    2214              : 
    2215              : static void*
    2216            2 : run_dispatch_thread (void *arg)
    2217              : {
    2218            2 :         int *sock = arg;
    2219            2 :         assert (*sock != -1);
    2220              : 
    2221            2 :         run_dispatch_loop (*sock);
    2222              : 
    2223              :         /* The thread closes the socket and marks as done */
    2224            2 :         assert (*sock != -1);
    2225            2 :         close (*sock);
    2226            2 :         *sock = -1;
    2227              : 
    2228            2 :         return NULL;
    2229              : }
    2230              : 
    2231              : /* ---------------------------------------------------------------------------
    2232              :  * MAIN THREAD
    2233              :  */
    2234              : 
    2235              : typedef struct _DispatchState {
    2236              :         struct _DispatchState *next;
    2237              :         GThread *thread;
    2238              :         int socket;
    2239              : } DispatchState;
    2240              : 
    2241              : /* The main daemon socket that we're listening on */
    2242              : static int pkcs11_socket = -1;
    2243              : 
    2244              : /* The unix socket path, that we listen on */
    2245              : static char *pkcs11_socket_path = NULL;
    2246              : 
    2247              : /* A linked list of dispatcher threads */
    2248              : static DispatchState *pkcs11_dispatchers = NULL;
    2249              : 
    2250              : void
    2251            2 : gkm_rpc_layer_accept (void)
    2252              : {
    2253              :         struct sockaddr_un addr;
    2254              :         DispatchState *ds, **here;
    2255            2 :         GError *error = NULL;
    2256              :         socklen_t addrlen;
    2257              :         int new_fd;
    2258              : 
    2259            2 :         assert (pkcs11_socket != -1);
    2260              : 
    2261              :         /* Cleanup any completed dispatch threads */
    2262            2 :         for (here = &pkcs11_dispatchers, ds = *here; ds != NULL; ds = *here) {
    2263            0 :                 if (ds->socket == -1) {
    2264            0 :                         g_thread_join (ds->thread);
    2265            0 :                         *here = ds->next;
    2266            0 :                         free (ds);
    2267              :                 } else {
    2268            0 :                         here = &ds->next;
    2269              :                 }
    2270              :         }
    2271              : 
    2272            2 :         addrlen = sizeof (addr);
    2273            2 :         new_fd = accept (pkcs11_socket, (struct sockaddr*) &addr, &addrlen);
    2274            2 :         if (new_fd < 0) {
    2275            0 :                 gkm_rpc_warn ("cannot accept pkcs11 connection: %s", strerror (errno));
    2276            0 :                 return;
    2277              :         }
    2278              : 
    2279            2 :         ds = calloc (1, sizeof (DispatchState));
    2280            2 :         if (ds == NULL) {
    2281            0 :                 gkm_rpc_warn ("out of memory");
    2282            0 :                 close (new_fd);
    2283            0 :                 return;
    2284              :         }
    2285              : 
    2286            2 :         ds->socket = new_fd;
    2287              : 
    2288            2 :         ds->thread = g_thread_new ("dispatch", run_dispatch_thread, &(ds->socket));
    2289            2 :         if (!ds->thread) {
    2290            0 :                 gkm_rpc_warn ("couldn't start thread: %s", egg_error_message (error));
    2291            0 :                 close (new_fd);
    2292            0 :                 free (ds);
    2293            0 :                 return;
    2294              :         }
    2295              : 
    2296            2 :         ds->next = pkcs11_dispatchers;
    2297            2 :         pkcs11_dispatchers = ds;
    2298              : }
    2299              : 
    2300              : int
    2301           27 : gkm_rpc_layer_initialize (CK_FUNCTION_LIST_PTR module)
    2302              : {
    2303           27 :         assert (module);
    2304              : 
    2305              :         /* cannot be called more than once */
    2306           27 :         assert (!pkcs11_module);
    2307           27 :         pkcs11_module = module;
    2308           27 :         return 1;
    2309              : }
    2310              : 
    2311              : void
    2312           27 : gkm_rpc_layer_uninitialize (void)
    2313              : {
    2314              :         DispatchState *ds, *next;
    2315              : 
    2316           27 :         if (!pkcs11_module)
    2317            0 :                 return;
    2318              : 
    2319              :         /* Close our main listening socket */
    2320           27 :         if (pkcs11_socket != -1)
    2321            0 :                 close (pkcs11_socket);
    2322           27 :         pkcs11_socket = -1;
    2323              : 
    2324              :         /* Delete our unix socket */
    2325           27 :         if(pkcs11_socket_path) {
    2326            0 :                 unlink (pkcs11_socket_path);
    2327            0 :                 free (pkcs11_socket_path);
    2328            0 :                 pkcs11_socket_path = NULL;
    2329              :         }
    2330              : 
    2331           27 :         ds = pkcs11_dispatchers;
    2332           27 :         pkcs11_dispatchers = NULL;
    2333              : 
    2334              :         /* Stop all of the dispatch threads */
    2335           27 :         for (; ds; ds = next) {
    2336            0 :                 next = ds->next;
    2337              : 
    2338              :                 /* Forcibly shutdown the connection */
    2339            0 :                 if (ds->socket)
    2340            0 :                         shutdown (ds->socket, SHUT_RDWR);
    2341            0 :                 g_thread_join (ds->thread);
    2342              : 
    2343              :                 /* This is always closed by dispatch thread */
    2344            0 :                 assert (ds->socket == -1);
    2345            0 :                 free (ds);
    2346              :         }
    2347              : 
    2348           27 :         pkcs11_module = NULL;
    2349              : }
    2350              : 
    2351              : int
    2352           11 : gkm_rpc_layer_startup (const char *prefix)
    2353              : {
    2354              :         struct sockaddr_un addr;
    2355              :         int sock;
    2356              : 
    2357              : #ifdef _DEBUG
    2358          759 :         GKM_RPC_CHECK_CALLS ();
    2359              : #endif
    2360              : 
    2361           11 :         assert (prefix);
    2362              : 
    2363              :         /* cannot be called more than once */
    2364           11 :         assert (pkcs11_socket == -1);
    2365           11 :         assert (pkcs11_dispatchers == NULL);
    2366              : 
    2367           11 :         free (pkcs11_socket_path);
    2368           11 :         pkcs11_socket_path = malloc (strlen (prefix) + strlen ("/pkcs11") + 1);
    2369           11 :         if (pkcs11_socket_path == NULL) {
    2370            0 :                 gkm_rpc_warn ("couldn't allocate memory");
    2371            0 :                 return -1;
    2372              :         }
    2373           11 :         sprintf (pkcs11_socket_path, "%s/pkcs11", prefix);
    2374              : 
    2375           11 :         sock = socket(AF_UNIX, SOCK_STREAM, 0);
    2376           11 :         if (sock < 0) {
    2377            0 :                 gkm_rpc_warn ("couldn't create pkcs11 socket: %s", strerror (errno));
    2378            0 :                 return -1;
    2379              :         }
    2380              : 
    2381           11 :         memset(&addr, 0, sizeof(addr));
    2382           11 :         addr.sun_family = AF_UNIX;
    2383           11 :         unlink (pkcs11_socket_path);
    2384           11 :         g_strlcpy (addr.sun_path, pkcs11_socket_path, sizeof (addr.sun_path));
    2385           11 :         if (bind (sock, (struct sockaddr*)&addr, sizeof (addr)) < 0) {
    2386            0 :                 gkm_rpc_warn ("couldn't bind to pkcs11 socket: %s: %s",
    2387            0 :                                   pkcs11_socket_path, strerror (errno));
    2388            0 :                 return -1;
    2389              :         }
    2390              : 
    2391           11 :         if (listen (sock, 128) < 0) {
    2392            0 :                 gkm_rpc_warn ("couldn't listen on pkcs11 socket: %s: %s",
    2393            0 :                                   pkcs11_socket_path, strerror (errno));
    2394            0 :                 return -1;
    2395              :         }
    2396              : 
    2397           11 :         pkcs11_socket = sock;
    2398           11 :         pkcs11_dispatchers = NULL;
    2399              : 
    2400           11 :         return sock;
    2401              : }
    2402              : 
    2403              : void
    2404           11 : gkm_rpc_layer_shutdown (void)
    2405              : {
    2406              :         DispatchState *ds, *next;
    2407              : 
    2408              :         /* Close our main listening socket */
    2409           11 :         if (pkcs11_socket != -1)
    2410           11 :                 close (pkcs11_socket);
    2411           11 :         pkcs11_socket = -1;
    2412              : 
    2413              :         /* Delete our unix socket */
    2414           11 :         if(pkcs11_socket_path) {
    2415           11 :                 unlink (pkcs11_socket_path);
    2416           11 :                 free (pkcs11_socket_path);
    2417           11 :                 pkcs11_socket_path = NULL;
    2418              :         }
    2419              : 
    2420           11 :         ds = pkcs11_dispatchers;
    2421           11 :         pkcs11_dispatchers = NULL;
    2422              : 
    2423              :         /* Stop all of the dispatch threads */
    2424           13 :         for (; ds; ds = next) {
    2425            2 :                 next = ds->next;
    2426              : 
    2427              :                 /* Forcibly shutdown the connection */
    2428            2 :                 if (ds->socket)
    2429            2 :                         shutdown (ds->socket, SHUT_RDWR);
    2430            2 :                 g_thread_join (ds->thread);
    2431              : 
    2432              :                 /* This is always closed by dispatch thread */
    2433            2 :                 assert (ds->socket == -1);
    2434            2 :                 free (ds);
    2435              :         }
    2436           11 : }
        

Generated by: LCOV version 2.0-1