diff options
Diffstat (limited to '')
| -rw-r--r-- | src/gpgme-json.c | 177 | 
1 files changed, 177 insertions, 0 deletions
| diff --git a/src/gpgme-json.c b/src/gpgme-json.c index f1a857d4..e8858064 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -1174,6 +1174,182 @@ op_decrypt (cjson_t request, cjson_t result) +static const char hlp_sign[] = +  "op:     \"sign\"\n" +  "keys:   Array of strings with the fingerprints of the signing key.\n" +  "        For a single key a String may be used instead of an array.\n" +  "data:   Input data. \n" +  "\n" +  "Optional parameters:\n" +  "protocol:      Either \"openpgp\" (default) or \"cms\".\n" +  "chunksize:     Max number of bytes in the resulting \"data\".\n" +  "sender:        The mail address of the sender.\n" +  "mode:          A string with the signing mode can be:\n" +  "               detached (default)\n" +  "               opaque\n" +  "               clearsign\n" +  "\n" +  "Optional boolean flags (default is false):\n" +  "base64:        Input data is base64 encoded.\n" +  "armor:         Request output in armored format.\n" +  "\n" +  "Response on success:\n" +  "type:   \"signature\"\n" +  "data:   Unless armor mode is used a Base64 encoded binary\n" +  "        signature.  In armor mode a string with an armored\n" +  "        OpenPGP or a PEM message.\n" +  "base64: Boolean indicating whether data is base64 encoded.\n" +  "more:   Optional boolean indicating that \"getmore\" is required."; +static gpg_error_t +op_sign (cjson_t request, cjson_t result) +{ +  gpg_error_t err; +  gpgme_ctx_t ctx = NULL; +  gpgme_protocol_t protocol; +  size_t chunksize; +  int opt_base64; +  char *keystring = NULL; +  cjson_t j_input; +  gpgme_data_t input = NULL; +  gpgme_data_t output = NULL; +  int abool; +  cjson_t j_tmp; +  gpgme_sig_mode_t mode = GPGME_SIG_MODE_DETACH; +  gpgme_ctx_t keylist_ctx = NULL; +  gpgme_key_t key = NULL; + +  if ((err = get_protocol (request, &protocol))) +    goto leave; +  ctx = get_context (protocol); +  if ((err = get_chunksize (request, &chunksize))) +    goto leave; + +  if ((err = get_boolean_flag (request, "base64", 0, &opt_base64))) +    goto leave; + +  if ((err = get_boolean_flag (request, "armor", 0, &abool))) +    goto leave; +  gpgme_set_armor (ctx, abool); + +  j_tmp = cJSON_GetObjectItem (request, "mode"); +  if (j_tmp && cjson_is_string (j_tmp)) +    { +      if (!strcmp (j_tmp->valuestring, "opaque")) +        { +          mode = GPGME_SIG_MODE_NORMAL; +        } +      else if (!strcmp (j_tmp->valuestring, "clearsign")) +        { +          mode = GPGME_SIG_MODE_CLEAR; +        } +    } + +  j_tmp = cJSON_GetObjectItem (request, "sender"); +  if (j_tmp && cjson_is_string (j_tmp)) +    { +      gpgme_set_sender (ctx, j_tmp->valuestring); +    } + +  /* Get the keys.  */ +  err = get_keys (request, &keystring); +  if (err) +    { +      /* Provide a custom error response.  */ +      error_object (result, "Error getting keys: %s", gpg_strerror (err)); +      goto leave; +    } + +  /* Do a keylisting and add the keys */ +  if ((err = gpgme_new (&keylist_ctx))) +    goto leave; +  gpgme_set_protocol (keylist_ctx, protocol); +  gpgme_set_keylist_mode (keylist_ctx, GPGME_KEYLIST_MODE_LOCAL); + +  err = gpgme_op_keylist_start (ctx, keystring, 1); +  if (err) +    { +      error_object (result, "Error listing keys: %s", gpg_strerror (err)); +      goto leave; +    } +  while (!(err = gpgme_op_keylist_next (ctx, &key))) +    { +      if ((err = gpgme_signers_add (ctx, key))) +        { +          error_object (result, "Error adding signer: %s", gpg_strerror (err)); +          goto leave; +        } +      gpgme_key_unref (key); +    } + +  /* Get the data.  Note that INPUT is a shallow data object with the +   * storage hold in REQUEST.  */ +  j_input = cJSON_GetObjectItem (request, "data"); +  if (!j_input) +    { +      err = gpg_error (GPG_ERR_NO_DATA); +      goto leave; +    } +  if (!cjson_is_string (j_input)) +    { +      err = gpg_error (GPG_ERR_INV_VALUE); +      goto leave; +    } +  if (opt_base64) +    { +      err = data_from_base64_string (&input, j_input); +      if (err) +        { +          error_object (result, "Error decoding Base-64 encoded 'data': %s", +                        gpg_strerror (err)); +          goto leave; +        } +    } +  else +    { +      err = gpgme_data_new_from_mem (&input, j_input->valuestring, +                                     strlen (j_input->valuestring), 0); +      if (err) +        { +          error_object (result, "Error getting 'data': %s", gpg_strerror (err)); +          goto leave; +        } +    } + +  /* Create an output data object.  */ +  err = gpgme_data_new (&output); +  if (err) +    { +      error_object (result, "Error creating output data object: %s", +                    gpg_strerror (err)); +      goto leave; +    } + +  /* Sign. */ +  err = gpgme_op_sign (ctx, input, output, mode); +  if (err) +    { +      error_object (result, "Signing failed: %s", gpg_strerror (err)); +      goto leave; +    } + +  gpgme_data_release (input); +  input = NULL; + +  /* We need to base64 if armoring has not been requested.  */ +  err = make_data_object (result, output, chunksize, +                          "ciphertext", !gpgme_get_armor (ctx)); +  output = NULL; + + leave: +  xfree (keystring); +  release_context (ctx); +  release_context (keylist_ctx); +  gpgme_data_release (input); +  gpgme_data_release (output); +  return err; +} + +  static const char hlp_getmore[] =    "op:     \"getmore\"\n"    "\n" @@ -1309,6 +1485,7 @@ process_request (const char *request)    } optbl[] = {      { "encrypt", op_encrypt, hlp_encrypt },      { "decrypt", op_decrypt, hlp_decrypt }, +    { "sign",    op_sign,    hlp_sign },      { "getmore", op_getmore, hlp_getmore },      { "help",    op_help,    hlp_help },      { NULL } | 
