Example #1
0
void GPGWrapper::init()
{
    if (initialized)
        return;

    initialized = true;

    gpgme_check_version(NULL);
    setlocale(LC_ALL, "");
    gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
#ifdef LC_MESSAGES
    gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
#endif

    gpgme_error_t error = gpgme_new(&context);
    fail_if_err(error, L"Nie uda³o siê zainicjowaæ kontekstu GPG.");

    gpgme_set_textmode(context, 1);
    gpgme_set_armor(context, 1);

    error = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
    fail_if_err(error, L"Nie zainstalowano OpenPGP.");

    error = gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP);
    fail_if_err(error, L"Nie uda³o siê ustawiæ OpenPGP.");

    privateKey = getPrivateKey(privateKeyId.c_str());
    error = gpgme_signers_add(context, privateKey);
    fail_if_err(error, L"Nie uda³o siê ustawiæ klucza prywatnego.");
}
QalfCrypto::QalfCrypto() {
	gpgme_error_t result = gpgme_new(&context) ;
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
	result = gpgme_set_protocol(context,GPGME_PROTOCOL_OpenPGP) ;
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
	gpgme_set_armor(context,1) ;
	gpgme_set_textmode(context,1) ;
}
/**
 * seahorse_service_crypto_sign_text:
 * @crypto: SeahorseServiceCrypto
 * @signer: the signer keyid
 * @flags: 0 (ignored)
 * @cleartext: the text to sign
 * @crypttext: the clear text signature (out) (GPGME_SIG_MODE_CLEAR)
 * @error: an error to return
 *
 * DBus: SignText
 *
 * Signs the @cleartext and returns the signature in @crypttext
 *
 * Returns: TRUE on success
 */
gboolean
seahorse_service_crypto_sign_text (SeahorseServiceCrypto *crypto, const char *signer, 
                                   int flags, const char *cleartext, char **crypttext,
                                   GError **error)
{
    SeahorseObject *signkey = NULL;
    gpgme_error_t gerr;
    SeahorseGpgmeOperation *pop; 
    gpgme_data_t plain, cipher;
    gboolean ret = TRUE;
    
    /* 
     * TODO: Once we support different kinds of keys that support encryption
     * then all this logic will need to change. 
     */
    
    /* The signer */
    if (!signer || !signer[0]) 
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("No signer specified"));
    
    signkey = seahorse_context_object_from_dbus (SCTX_APP (), signer);
    if (!signkey) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, 
                     _("Invalid or unrecognized signer: %s"), signer);
        return FALSE;
    }
        
    if (!SEAHORSE_IS_GPGME_KEY (signkey) || 
        !(seahorse_object_get_flags (signkey) & SEAHORSE_FLAG_CAN_SIGN)) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("Key is not valid for signing: %s"), signer);
        return FALSE;
    }
    
    pop = seahorse_gpgme_operation_new (NULL);
    
    /* new data from text */
    gerr = gpgme_data_new_from_mem (&plain, cleartext, strlen (cleartext), FALSE);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
    gerr = gpgme_data_new (&cipher);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
   
    /* encrypt with armor */
    gpgme_set_textmode (pop->gctx, TRUE);
    gpgme_set_armor (pop->gctx, TRUE);

    /* Do the signage */
    gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey)));
    gerr = gpgme_op_sign_start (pop->gctx, plain, cipher, GPGME_SIG_MODE_CLEAR);

    /* Frees cipher */
    ret = process_crypto_result (pop, gerr, cipher, crypttext, NULL, error);
    
    g_object_unref (pop);
    gpgme_data_release (plain);
    return ret;
}
static gboolean
encrypt_sign_start (SeahorseToolMode *mode, const gchar *uri, gpgme_data_t uridata,
                    SeahorsePGPOperation *pop, GError **err)
{
    gpgme_data_t cipher;
    gpgme_error_t gerr;
    gchar *touri;

    g_assert (mode->recipients && mode->recipients[0]);

    /* File to encrypt to */
    touri = seahorse_util_add_suffix (uri, SEAHORSE_CRYPT_SUFFIX,
                                      _("Choose Encrypted File Name for '%s'"));
    if (!touri)
        return FALSE;

    /* Open necessary files, release these with the operation */
    cipher = seahorse_vfs_data_create (touri, SEAHORSE_VFS_WRITE | SEAHORSE_VFS_DELAY, err);
    g_free (touri);
    if (!cipher)
        return FALSE;
    g_object_set_data_full (G_OBJECT (pop), "cipher-data", cipher,
                            (GDestroyNotify)gpgme_data_release);

    gpgme_set_armor (pop->gctx, seahorse_gconf_get_boolean (ARMOR_KEY));
    gpgme_set_textmode (pop->gctx, FALSE);

    /* Start actual encryption */
    gpgme_signers_clear (pop->gctx);
    if (mode->signer) {
        gpgme_signers_add (pop->gctx, mode->signer);
        gerr = gpgme_op_encrypt_sign_start (pop->gctx, mode->recipients,
                                            GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher);

    } else {
        gerr = gpgme_op_encrypt_start (pop->gctx, mode->recipients,
                                       GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher);
    }

    if (gerr != 0) {
        seahorse_util_gpgme_to_error (gerr, err);
        return FALSE;
    }

    return TRUE;
}
Example #5
0
static int
pygpgme_context_set_textmode(PyGpgmeContext *self, PyObject *value)
{
    int textmode;

    if (value == NULL) {
        PyErr_SetString(PyExc_AttributeError, "Can not delete attribute");
        return -1;
    }

    textmode = PyInt_AsLong(value) != 0;
    if (PyErr_Occurred())
        return -1;

    gpgme_set_textmode(self->ctx, textmode);
    return 0;
}
Example #6
0
int 
main (int argc, char *argv[])
{
  gpgme_ctx_t ctx;
  gpgme_error_t err;
  gpgme_data_t in, out;
  gpgme_sign_result_t result;

  init_gpgme (GPGME_PROTOCOL_CMS);

  err = gpgme_new (&ctx);
  fail_if_err (err);

  gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
  gpgme_set_textmode (ctx, 1);
  gpgme_set_armor (ctx, 1);

  err = gpgme_data_new_from_mem (&in, "Hallo Leute!\n", 13, 0);
  fail_if_err (err);

  /* First a normal signature.  */
  err = gpgme_data_new (&out);
  fail_if_err (err);
  err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL);
  fail_if_err (err);
  result = gpgme_op_sign_result (ctx);
  check_result (result, GPGME_SIG_MODE_NORMAL);
  print_data (out);
  gpgme_data_release (out);
    
  /* Now a detached signature.  */ 
  gpgme_data_seek (in, 0, SEEK_SET);
  err = gpgme_data_new (&out);
  fail_if_err (err);
  err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_DETACH);
  fail_if_err (err);
  result = gpgme_op_sign_result (ctx);
  check_result (result, GPGME_SIG_MODE_DETACH);
  print_data (out);
  gpgme_data_release (out);

  gpgme_data_release (in);
  gpgme_release (ctx);
  return 0;
}
Example #7
0
File: gpg.c Project: comotion/cpm
/* #############################################################################
 *
 * Description    encrypt the given buffer and return the encrypted data with
 *                an updated size information
 * Author         Harry Brueckner
 * Date           2005-03-31
 * Arguments      char* buffer      - buffer to encrypt
 *                int size          - size of the buffer
 *                char** newbuffer  - pointer to the new buffer which holds the
 *                                    encrypted data
 *                int* newsize      - size of the returned buffer
 *                PASSPHRASE_FN password_cb   - callback function pointer used
 *                                              to get the current passphrase
 *                SHOWERROR_FN showerror_cb   - callback function pointer used
 *                                              to display errors
 * Return         0 if ok, otherwise 1
 */
int gpgEncrypt(char* buffer, int size, char** newbuffer, int* newsize,
    PASSPHRASE_FN password_cb, SHOWERROR_FN showerror_cb)
  {
    gpgme_ctx_t         context;
    gpgme_data_t        input,
                        output;
    gpgme_encrypt_result_t  result;
    gpgme_error_t       error;
    gpgme_key_t*        key = NULL;
    gpgme_key_t         tkey = NULL;
    gpgme_sign_result_t sign_result;
    int                 i,
                        keys = 0,
                        showerror = 1;
    char*               agent;
    char*               fpr;
    char*               tmpbuffer = NULL;

    TRACE(99, "gpgEncrypt()", NULL);

    /* we set our passphrase callback function */
    passphrase_callback = password_cb;

    /* we initialize the external size data */
    newsize[0] = 0;

    error = gpgme_new(&context);

    if (!error)
      {
        gpgme_set_textmode(context, 1);
        gpgme_set_armor(context, 1);

        /* Flawfinder: ignore */
        agent = getenv("GPG_AGENT_INFO");
        if (!(agent && strchr(agent, ':')))
          {
            retries = 0;
            gpgme_set_passphrase_cb(context, gpgRequestPassphrase, NULL);
          }
      }

    if (!error)
      { error = gpgme_data_new_from_mem(&input, buffer, size, 0); }

    if (!error)
      { error = gpgme_data_new(&output); }

    if (!error)
      { gpgme_signers_clear(context); }

    if (!error)
      {
        /* allocate the keys */
        keys = keyCount();
        key = memAlloc(__FILE__, __LINE__, sizeof(gpgme_key_t) * (keys + 1));
        key[keys] = NULL;
        signers = 0;
        for (i = 0; i < keys && !error; i++)
          {   /* add all keys */
            fpr = gpgGetFingerprint(keyGet(i), LIST_SECRET);
            if (fpr)
              {
                error = gpgme_get_key(context, fpr, &tkey, LIST_SECRET);
                if (tkey -> secret);
                  {
                    error = gpgme_signers_add(context, tkey);
                    signers++;
                  }

                memFreeString(__FILE__, __LINE__, fpr);
              }

            fpr = gpgGetFingerprint(keyGet(i), LIST_ALL);
            if (fpr)
              {
                error = gpgme_get_key(context, fpr, &key[i], LIST_ALL);
                memFreeString(__FILE__, __LINE__, fpr);
              }
          }
      }

    if (signers > 1)
      {   /* as soon as we get two signers, we must no longer cache anything */
        config -> keeppassphrase = 0;
        clearPassphrase(1);
      }

    /* encrypt and sign the data */
    if (!error)
      {
        error = gpgme_op_encrypt_sign(context, key, GPGME_ENCRYPT_ALWAYS_TRUST,
            input, output);
      }

    /* we don't need the passphrase any longer */
    clearPassphrase(0);

    if (!error)
      { result = gpgme_op_encrypt_result(context); }
    if (!error &&
        result -> invalid_recipients)
      {
        tmpbuffer = memAlloc(__FILE__, __LINE__, STDBUFFERLENGTH);
        snprintf(tmpbuffer, STDBUFFERLENGTH,
            _("Invalid recipient encountered: %s"),
            result -> invalid_recipients -> fpr);
        (showerror_cb)(_("GpgMe error"), tmpbuffer);
        memFree(__FILE__, __LINE__, tmpbuffer, STDBUFFERLENGTH);

        showerror = 0;
        error = 1;
      }

    if (!error)
      {
        sign_result = gpgme_op_sign_result(context);
        error = gpgCheckSignResult(showerror_cb, sign_result,
            GPGME_SIG_MODE_NORMAL);
        showerror = !error;
      }

    if (!error)
      { tmpbuffer = gpgData2Char(output, newsize); }

    /* free the keys again */
    i = 0;
    while (key && keys && key[i])
      { gpgme_key_unref(key[i++]); }
    memFree(__FILE__, __LINE__, key, sizeof(gpgme_key_t) * (keys + 1));

    gpgme_data_release(input);
    gpgme_data_release(output);
    gpgme_release(context);

    *newbuffer = tmpbuffer;

    if (error)
      {
        if (showerror)
          { (showerror_cb)(_("GpgMe encrypt error"), gpgme_strerror(error)); }
        return 1;
      }
    else
        return 0;
  }
Example #8
0
static gboolean pgpinline_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr)
{
    MimeInfo *msgcontent;
    gchar *textstr, *tmp;
    FILE *fp;
    gchar *sigcontent;
    gpgme_ctx_t ctx;
    gpgme_data_t gpgtext, gpgsig;
    size_t len;
    gpgme_error_t err;
    struct passphrase_cb_info_s info;
    gpgme_sign_result_t result = NULL;

    memset (&info, 0, sizeof info);

    /* get content node from message */
    msgcontent = (MimeInfo *) mimeinfo->node->children->data;
    if (msgcontent->type == MIMETYPE_MULTIPART) {
        if (!msgcontent->node->children) {
            debug_print("msgcontent->node->children NULL, bailing\n");
            privacy_set_error(_("Malformed message"));
            return FALSE;
        }
        msgcontent = (MimeInfo *) msgcontent->node->children->data;
    }
    /* get rid of quoted-printable or anything */
    procmime_decode_content(msgcontent);

    fp = my_tmpfile();
    if (fp == NULL) {
        perror("my_tmpfile");
        privacy_set_error(_("Couldn't create temporary file."));
        return FALSE;
    }
    procmime_write_mimeinfo(msgcontent, fp);
    rewind(fp);

    /* read temporary file into memory */
    textstr = fp_read_noconv(fp);

    fclose(fp);

    gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0);
    gpgme_data_new(&gpgsig);
    if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) {
        debug_print(("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
        privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
        return FALSE;
    }
    gpgme_set_textmode(ctx, 1);
    gpgme_set_armor(ctx, 1);

    if (!sgpgme_setup_signers(ctx, account, from_addr)) {
        gpgme_release(ctx);
        return FALSE;
    }

    prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent);
    if (!getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent) {
        info.c = ctx;
        gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info);
    }

    err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_CLEAR);
    if (err != GPG_ERR_NO_ERROR) {
        if (err == GPG_ERR_CANCELED) {
            /* ignore cancelled signing */
            privacy_reset_error();
            debug_print("gpgme_op_sign cancelled\n");
        } else {
            privacy_set_error(_("Data signing failed, %s"), gpgme_strerror(err));
            debug_print("gpgme_op_sign error : %x\n", err);
        }
        gpgme_release(ctx);
        return FALSE;
    }
    result = gpgme_op_sign_result(ctx);
    if (result && result->signatures) {
        gpgme_new_signature_t sig = result->signatures;
        while (sig) {
            debug_print("valid signature: %s\n", sig->fpr);
            sig = sig->next;
        }
    } else if (result && result->invalid_signers) {
        gpgme_invalid_key_t invalid = result->invalid_signers;
        while (invalid) {
            g_warning("invalid signer: %s (%s)", invalid->fpr,
                      gpgme_strerror(invalid->reason));
            privacy_set_error(_("Data signing failed due to invalid signer: %s"),
                              gpgme_strerror(invalid->reason));
            invalid = invalid->next;
        }
        gpgme_release(ctx);
        return FALSE;
    } else {
        /* can't get result (maybe no signing key?) */
        debug_print("gpgme_op_sign_result error\n");
        privacy_set_error(_("Data signing failed, no results."));
        gpgme_release(ctx);
        return FALSE;
    }


    sigcontent = sgpgme_data_release_and_get_mem(gpgsig, &len);

    if (sigcontent == NULL || len <= 0) {
        g_warning("sgpgme_data_release_and_get_mem failed");
        privacy_set_error(_("Data signing failed, no contents."));
        gpgme_data_release(gpgtext);
        g_free(textstr);
        g_free(sigcontent);
        gpgme_release(ctx);
        return FALSE;
    }

    tmp = g_malloc(len+1);
    g_memmove(tmp, sigcontent, len+1);
    tmp[len] = '\0';
    gpgme_data_release(gpgtext);
    g_free(textstr);
    g_free(sigcontent);

    if (msgcontent->content == MIMECONTENT_FILE &&
            msgcontent->data.filename != NULL) {
        if (msgcontent->tmp == TRUE)
            claws_unlink(msgcontent->data.filename);
        g_free(msgcontent->data.filename);
    }
    msgcontent->data.mem = g_strdup(tmp);
    msgcontent->content = MIMECONTENT_MEM;
    g_free(tmp);

    /* avoid all sorts of clear-signing problems with non ascii
     * chars
     */
    procmime_encode_content(msgcontent, ENC_BASE64);
    gpgme_release(ctx);

    return TRUE;
}
Example #9
0
static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
{
    MimeInfo *decinfo, *parseinfo;
    gpgme_data_t cipher, plain;
    FILE *dstfp;
    gchar *fname;
    gchar *textdata = NULL;
    static gint id = 0;
    const gchar *src_codeset = NULL;
    gpgme_verify_result_t sigstat = 0;
    PrivacyDataPGP *data = NULL;
    gpgme_ctx_t ctx;
    gchar *chars;
    size_t len;
    const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----";
    const gchar *end_indicator = "-----END PGP MESSAGE-----";
    gchar *pos;

    if (gpgme_new(&ctx) != GPG_ERR_NO_ERROR)
        return NULL;

    gpgme_set_textmode(ctx, 1);
    gpgme_set_armor(ctx, 1);

    cm_return_val_if_fail(mimeinfo != NULL, NULL);
    cm_return_val_if_fail(pgpinline_is_encrypted(mimeinfo), NULL);

    if (procmime_mimeinfo_parent(mimeinfo) == NULL ||
            mimeinfo->type != MIMETYPE_TEXT) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't parse mime part."));
        return NULL;
    }

    textdata = get_part_as_string(mimeinfo);
    if (!textdata) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't get text data."));
        return NULL;
    }

    debug_print("decrypting '%s'\n", textdata);
    gpgme_data_new_from_mem(&cipher, textdata, (size_t)strlen(textdata), 1);

    plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx);
    if (sigstat && !sigstat->signatures)
        sigstat = NULL;

    gpgme_data_release(cipher);

    if (plain == NULL) {
        gpgme_release(ctx);
        return NULL;
    }

    fname = g_strdup_printf("%s%cplaintext.%08x",
                            get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id);

    if ((dstfp = g_fopen(fname, "wb")) == NULL) {
        FILE_OP_ERROR(fname, "fopen");
        privacy_set_error(_("Couldn't open decrypted file %s"), fname);
        g_free(fname);
        gpgme_data_release(plain);
        gpgme_release(ctx);
        return NULL;
    }

    src_codeset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
    if (src_codeset == NULL)
        src_codeset = CS_ISO_8859_1;

    if (fprintf(dstfp, "MIME-Version: 1.0\r\n"
                "Content-Type: text/plain; charset=%s\r\n"
                "Content-Transfer-Encoding: 8bit\r\n"
                "\r\n",
                src_codeset) < 0) {
        FILE_OP_ERROR(fname, "fprintf");
        privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
        goto FILE_ERROR;
    }

    /* Store any part before encrypted text */
    pos = pgp_locate_armor_header(textdata, begin_indicator);
    if (pos != NULL && (pos - textdata) > 0) {
        if (fwrite(textdata, 1, pos - textdata, dstfp) < pos - textdata) {
            FILE_OP_ERROR(fname, "fwrite");
            privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
            goto FILE_ERROR;
        }
    }

    if (fwrite(_("\n--- Start of PGP/Inline encrypted data ---\n"), 1,
               strlen(_("\n--- Start of PGP/Inline encrypted data ---\n")),
               dstfp) < strlen(_("\n--- Start of PGP/Inline encrypted data ---\n"))) {
        FILE_OP_ERROR(fname, "fwrite");
        privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
        goto FILE_ERROR;
    }
    chars = sgpgme_data_release_and_get_mem(plain, &len);
    if (len > 0) {
        if (fwrite(chars, 1, len, dstfp) < len) {
            FILE_OP_ERROR(fname, "fwrite");
            g_free(chars);
            privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
            goto FILE_ERROR;
        }
    }
    g_free(chars);
    /* Store any part after encrypted text */
    if (fwrite(_("--- End of PGP/Inline encrypted data ---\n"), 1,
               strlen(_("--- End of PGP/Inline encrypted data ---\n")),
               dstfp) < strlen(_("--- End of PGP/Inline encrypted data ---\n"))) {
        FILE_OP_ERROR(fname, "fwrite");
        privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
        goto FILE_ERROR;
    }
    if (pos != NULL) {
        pos = pgp_locate_armor_header(pos, end_indicator);
        if (pos != NULL && *pos != '\0') {
            pos += strlen(end_indicator);
            if (fwrite(pos, 1, strlen(pos), dstfp) < strlen(pos)) {
                FILE_OP_ERROR(fname, "fwrite");
                privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
                goto FILE_ERROR;
            }
        }
    }

    if (fclose(dstfp) == EOF) {
        FILE_OP_ERROR(fname, "fclose");
        privacy_set_error(_("Couldn't close decrypted file %s"), fname);
        g_free(fname);
        gpgme_data_release(plain);
        gpgme_release(ctx);
        return NULL;
    }

    parseinfo = procmime_scan_file(fname);
    g_free(fname);

    if (parseinfo == NULL) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't scan decrypted file."));
        return NULL;
    }
    decinfo = g_node_first_child(parseinfo->node) != NULL ?
              g_node_first_child(parseinfo->node)->data : NULL;

    if (decinfo == NULL) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't scan decrypted file parts."));
        return NULL;
    }

    g_node_unlink(decinfo->node);
    procmime_mimeinfo_free_all(parseinfo);

    decinfo->tmp = TRUE;

    if (sigstat != GPGME_SIG_STAT_NONE) {
        if (decinfo->privacy != NULL) {
            data = (PrivacyDataPGP *) decinfo->privacy;
        } else {
            data = pgpinline_new_privacydata();
            decinfo->privacy = (PrivacyData *) data;
        }
        if (data != NULL) {
            data->done_sigtest = TRUE;
            data->is_signed = TRUE;
            data->sigstatus = sigstat;
            if (data->ctx)
                gpgme_release(data->ctx);
            data->ctx = ctx;
        }
    } else
        gpgme_release(ctx);

    return decinfo;

FILE_ERROR:
    fclose(dstfp);
    g_free(fname);
    gpgme_data_release(plain);
    gpgme_release(ctx);
    return NULL;
}
Example #10
0
static gint pgpinline_check_signature(MimeInfo *mimeinfo)
{
    PrivacyDataPGP *data = NULL;
    gchar *textdata = NULL, *tmp = NULL;
    gpgme_data_t plain = NULL, cipher = NULL;
    gpgme_error_t err;

    cm_return_val_if_fail(mimeinfo != NULL, 0);

    if (procmime_mimeinfo_parent(mimeinfo) == NULL) {
        privacy_set_error(_("Incorrect part"));
        return 0; /* not parent */
    }
    if (mimeinfo->type != MIMETYPE_TEXT) {
        privacy_set_error(_("Not a text part"));
        debug_print("type %d\n", mimeinfo->type);
        return 0;
    }
    cm_return_val_if_fail(mimeinfo->privacy != NULL, 0);
    data = (PrivacyDataPGP *) mimeinfo->privacy;

    textdata = get_part_as_string(mimeinfo);

    if (!textdata) {
        g_free(textdata);
        privacy_set_error(_("Couldn't get text data."));
        return 0;
    }

    /* gtk2: convert back from utf8 */
    tmp = conv_codeset_strdup(textdata, CS_UTF_8,
                              procmime_mimeinfo_get_parameter(mimeinfo, "charset"));
    if (!tmp) {
        tmp = conv_codeset_strdup(textdata, CS_UTF_8,
                                  conv_get_locale_charset_str_no_utf8());
    }
    if (!tmp) {
        g_warning("Can't convert charset to anything sane");
        tmp = conv_codeset_strdup(textdata, CS_UTF_8, CS_US_ASCII);
    }
    g_free(textdata);

    if (!tmp) {
        privacy_set_error(_("Couldn't convert text data to any sane charset."));
        return 0;
    }
    textdata = g_strdup(tmp);
    g_free(tmp);

    if ((err = gpgme_new(&data->ctx)) != GPG_ERR_NO_ERROR) {
        debug_print(("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
        privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
        g_free(textdata);
        return 0;
    }
    gpgme_set_textmode(data->ctx, 1);
    gpgme_set_armor(data->ctx, 1);

    gpgme_data_new_from_mem(&plain, textdata, (size_t)strlen(textdata), 1);
    gpgme_data_new(&cipher);

    data->sigstatus = sgpgme_verify_signature(data->ctx, plain, NULL, cipher);

    gpgme_data_release(plain);
    gpgme_data_release(cipher);

    g_free(textdata);

    return 0;
}
QString QalfCrypto::sign(QString &message, QString &key) {
	gpgme_key_t gpgkey ;
	gpgme_data_t signature ;
	gpgme_data_t msg ;
	gpgme_verify_result_t verification ;
	gpgme_signature_t signatures ;
 	gpgme_error_t result  ;
	char  * buffer ;
		
	gpgme_set_passphrase_cb(context,&passphrase_callback,NULL) ;
	result = gpgme_set_protocol(context,GPGME_PROTOCOL_OpenPGP) ;
	Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR) ;
	gpgme_set_armor(context,1) ;
	gpgme_set_textmode(context,1) ;

	gpgme_signers_clear(context) ;
	result = gpgme_set_keylist_mode(context,GPGME_KEYLIST_MODE_LOCAL) ;

	// retrieving key
	result = gpgme_get_key(context, key.toAscii().data(),&gpgkey,1) ;
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
	Q_ASSERT(gpgkey != 0) ;

	// signing
	result = gpgme_signers_add(context,gpgkey) ;
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
	
	result = gpgme_data_new(&signature);
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;

	int message_length = message.toAscii().size() ;
	char * message_char = (char *) calloc(message_length+1,sizeof(char)) ;
	memcpy(message_char,message.toAscii().data(),message_length) ;
// 	printf("memcmp : %d\n",memcmp(message_char,"1fc36e1d41a93c1d79f6872198f426129320d287",message_length+1)) ;
	result = gpgme_data_new_from_mem(&msg,message_char,message_length,0) ;
	
	gpgme_data_seek(signature,0,SEEK_SET) ;
	gpgme_data_seek(msg,0,SEEK_SET) ;
	
	result = gpgme_op_sign(context, msg,signature, GPGME_SIG_MODE_DETACH) ;
	Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR || gpgme_err_code(result) == GPG_ERR_BAD_PASSPHRASE || gpgme_err_code(result) == GPG_ERR_CANCELED) ;
	
// 	gpgme_data_seek(signature,0,SEEK_SET) ;
// 	gpgme_data_seek(msg,0,SEEK_SET) ;
// 	
// 	result = gpgme_op_verify (context, signature, msg , 0) ;
// 	Q_ASSERT(gpgme_err_code(result) != GPG_ERR_INV_VALUE) ;
// 	Q_ASSERT(gpgme_err_code(result) != GPG_ERR_NO_DATA) ;
// 	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
// 	
// 	verification = gpgme_op_verify_result(context) ;
// 	Q_ASSERT(verification != 0) ;
// 	
// 	signatures = verification->signatures ;
// 	Q_ASSERT(verification->signatures != 0) ;
// 	result = signatures->status ;
// 	printf("status : %d\n",gpgme_err_code(result)) ;
// 	printf("signature summary : %d\n",signatures->summary) ;
// 	Q_ASSERT(signatures->summary == GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN) ;
// 	
	QString signatureStr ;
	buffer = (char *) calloc(2048,sizeof(char)) ;
	gpgme_data_seek(signature,0,SEEK_SET) ;
	gpgme_data_read(signature,buffer,2048) ;

	signatureStr += buffer ;

	qDebug() << "signature" << signatureStr ;
	
	gpgme_data_release(signature) ;
	gpgme_key_unref(gpgkey) ;
	gpgme_data_release(msg) ;
	return signatureStr ;
}
/**
 * seahorse_service_crypto_verify_text:
 * @crypto: #SeahorseServiceCrypto context
 * @ktype: "openpgp"
 * @flags: FLAG_QUIET for no notification
 * @crypttext: the text to decrypt
 * @cleartext: the plaintext after verification (out)
 * @signer: the signer if the text is signed (out)
 * @error: a potential error (out)
 *
 * DBus: VerifyText
 *
 * Decrypts the @crypttext and returns it in @cleartext. If the text
 * was signed, the signed is returned.
 *
 * Returns: TRUE on success
 */
gboolean
seahorse_service_crypto_verify_text (SeahorseServiceCrypto *crypto, 
                                     const gchar *ktype, int flags, 
                                     const gchar *crypttext, gchar **cleartext,
                                     char **signer, GError **error)
{
    gpgme_verify_result_t status;
    gpgme_error_t gerr;
    SeahorseGpgmeOperation *pop; 
    gpgme_data_t plain, cipher;
    gboolean ret = TRUE;
    GQuark keyid;
    
    if (!g_str_equal (ktype, g_quark_to_string (SEAHORSE_PGP))) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("Invalid key type for verifying: %s"), ktype);
        return FALSE;        
    }

    /* 
     * TODO: Once we support different kinds of keys that support encryption
     * then all this logic will need to change. 
     */

    pop = seahorse_gpgme_operation_new (NULL);
    
    /* new data from text */
    gerr = gpgme_data_new_from_mem (&cipher, crypttext, strlen (crypttext), FALSE);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
    gerr = gpgme_data_new (&plain);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
   
    /* encrypt with armor */
    gpgme_set_textmode (pop->gctx, TRUE);
    gpgme_set_armor (pop->gctx, TRUE);

    /* Do the decryption */
    gerr = gpgme_op_verify_start (pop->gctx, cipher, NULL, plain);

    /* Frees plain */
    ret = process_crypto_result (pop, gerr, plain, cleartext, NULL, error);
    
    if (ret) {
        *signer = NULL;
        status = gpgme_op_verify_result (pop->gctx);
    
        if (status->signatures) {
            if (!(flags & FLAG_QUIET))
                notify_signatures (NULL, status);
            if (status->signatures->summary & GPGME_SIGSUM_GREEN ||
                status->signatures->summary & GPGME_SIGSUM_VALID ||
                status->signatures->summary & GPGME_SIGSUM_KEY_MISSING) {
                keyid = seahorse_pgp_key_canonize_id (status->signatures->fpr);
                *signer = seahorse_context_id_to_dbus (SCTX_APP (), keyid);
            }
        }
    }
    
    g_object_unref (pop);
    gpgme_data_release (cipher);
    return TRUE;
}
/**
* crypto: the crypto service (#SeahorseServiceCrypto)
* recipients: A list of recipients (keyids "openpgp:B8098FB063E2C811")
*             Must be empty when symmetric encryption is used.
* signer: optional, the keyid of the signer
* flags: FLAG_SYMMETRIC to perform symmetric encryption
* cleartext: the text to encrypt
* clearlength: Length of the cleartext
* crypttext: the encrypted text (out)
* cryptlength: the length of this text (out)
* textmode: TRUE if gpgme should use textmode
* ascii_armor: TRUE if GPGME should use ascii armor
* error: The Error
*
* Handles encryption in a generic way. Can be used by several DBus APIs
*
* Returns TRUE on success
**/
static gboolean
crypto_encrypt_generic (SeahorseServiceCrypto *crypto,
                        const char **recipients, const char *signer,
                        int flags, const char *cleartext, gsize clearlength,
                        char **crypttext, gsize *cryptlength, gboolean textmode,
                        gboolean ascii_armor, GError **error)
{
	GList *recipkeys = NULL;
	SeahorseGpgmeOperation *pop;
	SeahorseObject *signkey = NULL;
	SeahorseObject *skey;
	gpgme_key_t *recips;
	gboolean symmetric = FALSE;
	gpgme_data_t plain, cipher;
	gpgme_error_t gerr;
	gboolean ret = TRUE;
	GSettings *settings;
	gchar *keyid;

	if ((flags & FLAG_SYMMETRIC) == FLAG_SYMMETRIC)
		symmetric = TRUE;

	if (symmetric && recipients[0] != NULL) {
		g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
		             _("Recipients specified for symmetric encryption"));
		return FALSE;
	}

	/* The signer */
	if (signer && signer[0]) {
		signkey = seahorse_context_object_from_dbus (SCTX_APP (), signer);
		if (!signkey) {
			g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
			             _("Invalid or unrecognized signer: %s"), signer);
			return FALSE;
		}

		if (!SEAHORSE_IS_GPGME_KEY (signkey) ||
			!(seahorse_object_get_flags (signkey) & SEAHORSE_FLAG_CAN_SIGN)) {
			g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
			             _("Key is not valid for signing: %s"), signer);
			return FALSE;
		}
	}

	if (!symmetric) {
		/* The recipients */
		for( ; recipients[0]; recipients++)
		{
			skey = seahorse_context_object_from_dbus (SCTX_APP (), recipients[0]);
			if (!skey) {
				g_list_free (recipkeys);
				g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
					     _("Invalid or unrecognized recipient: %s"), recipients[0]);
				return FALSE;
			}

			if (!SEAHORSE_IS_GPGME_KEY (skey) ||
				!(seahorse_object_get_flags (skey) & SEAHORSE_FLAG_CAN_ENCRYPT)) {
				g_list_free (recipkeys);
				g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
					     _("Key is not a valid recipient for encryption: %s"), recipients[0]);
				return FALSE;
			}

			recipkeys = g_list_prepend (recipkeys, SEAHORSE_PGP_KEY (skey));
		}

		if (!recipkeys) {
			g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
				     _("No recipients specified"));
			return FALSE;
		}
	}

	pop = seahorse_gpgme_operation_new (NULL);

	/* new data form text */
	gerr = gpgme_data_new_from_mem (&plain, cleartext, clearlength, FALSE);
	g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
	gerr = gpgme_data_new (&cipher);
	g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);

	/* encrypt with armor */
	gpgme_set_textmode (pop->gctx, textmode);
	gpgme_set_armor (pop->gctx, ascii_armor);

	if (symmetric) {
		/* gpgme_op_encrypt{_sign,}_start() will perform symmetric encryption
		 * when no recipients are specified. */
		recips = NULL;
	} else {
		/* Add the default key if set and necessary */
		settings = g_settings_new ("org.gnome.crypto.pgp");
		if (g_settings_get_boolean (settings, "encrypt-to-self")) {
			keyid = g_settings_get_string (settings, "default-key");
			if (keyid && keyid[0]) {
				skey = seahorse_context_find_object (NULL, g_quark_from_string (keyid),
								     SEAHORSE_LOCATION_LOCAL);
				if (SEAHORSE_IS_PGP_KEY (skey))
					recipkeys = g_list_append (recipkeys, skey);
			}
			g_free (keyid);
		}
		g_object_unref (settings);

		/* Make keys into the right format for GPGME */
		recips = keylist_to_keys (recipkeys);
		g_list_free (recipkeys);
	}

	/* Do the encryption */
	if (signkey) {
		gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey)));
		gerr = gpgme_op_encrypt_sign_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST,
		                                    plain, cipher);
	} else {
		gerr = gpgme_op_encrypt_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST,
		                               plain, cipher);
	}
	free_keys (recips);

	/* Frees cipher */
	ret = process_crypto_result (pop, gerr, cipher, crypttext, cryptlength, error);
	g_object_unref (pop);
	gpgme_data_release (plain);
	return ret;
}
Example #14
0
/** \brief Encrypt data
 *
 * \param recipients Array of User ID for which the matter shall be
 *        encrypted using their public keys.
 * \param sign_for User ID of the signer or NULL if the matter shall not be
 *        signed.  Note that combined signing and encryption is allowed \em
 *        only in OpenPGP single-part (i.e. RFC 2440) mode.
 * \param istream GMime input stream.
 * \param ostream GMime output stream.
 * \param protocol GpgME crypto protocol to use for encryption.
 * \param singlepart_mode TRUE indicates single-part mode (integrated
 *        signature), FALSE a detached signature.
 * \param trust_all_keys TRUE if all low-truct keys shall be accepted for
 *        encryption.  Otherwise, the function will use the global callback
 *        to ask the user whether a low-trust key shall be accepted.
 * \param parent Parent window to be passed to the callback functions.
 * \param error Filled with error information on error.
 * \return 0 on success, or -1 on error.
 *
 * Encrypt the passed matter and write the result to the output stream.
 * Combined signing and encryption is allowed for single-part OpenPGP mode
 * only.
 */
int
libbalsa_gpgme_encrypt(GPtrArray * recipients, const char *sign_for,
		       GMimeStream * istream, GMimeStream * ostream,
		       gpgme_protocol_t protocol, gboolean singlepart_mode,
		       gboolean trust_all_keys, GtkWindow * parent,
		       GError ** error)
{
    gpgme_ctx_t ctx;
    gpgme_error_t err;
    gpgme_key_t *rcpt_keys;
    gpgme_data_t plain;
    gpgme_data_t crypt;
    struct gpgme_data_cbs cbs = {
	(gpgme_data_read_cb_t) g_mime_gpgme_stream_rd,	/* read method */
	(gpgme_data_write_cb_t) g_mime_gpgme_stream_wr,	/* write method */
	NULL,			/* seek method */
	cb_data_release		/* release method */
    };

    /* paranoia checks */
    g_return_val_if_fail(recipients != NULL, -1);
    g_return_val_if_fail(GMIME_IS_STREAM(istream), -1);
    g_return_val_if_fail(GMIME_IS_STREAM(ostream), GPGME_MD_NONE);
    g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP ||
			 protocol == GPGME_PROTOCOL_CMS, -1);

    /* create the GpgME context */
    if ((err =
	 gpgme_new_with_protocol(&ctx, protocol, parent,
				 error)) != GPG_ERR_NO_ERROR)
	return -1;

    /* sign & encrypt is valid only for single-part OpenPGP */
    if (sign_for != NULL
	&& (!singlepart_mode || protocol != GPGME_PROTOCOL_OpenPGP)) {
	if (error)
	    g_set_error(error, GPGME_ERROR_QUARK, GPG_ERR_INV_ENGINE,
			_
			("combined signing and encryption is defined only for RFC 2440"));
	gpgme_release(ctx);
	return -1;
    }

    /* if requested, find the secret key for "userid" */
    if (sign_for && !gpgme_add_signer(ctx, sign_for, parent, error)) {
	gpgme_release(ctx);
	return -1;
    }

    /* build the list of recipients */
    if (!
	(rcpt_keys =
	 gpgme_build_recipients(ctx, recipients, trust_all_keys, parent,
				error))) {
	gpgme_release(ctx);
	return -1;
    }

    /* create the data objects */
    if (protocol == GPGME_PROTOCOL_OpenPGP) {
	gpgme_set_armor(ctx, 1);
	gpgme_set_textmode(ctx, singlepart_mode);
    } else {
	gpgme_set_armor(ctx, 0);
	gpgme_set_textmode(ctx, 0);
    }
    if ((err =
	 gpgme_data_new_from_cbs(&plain, &cbs,
				 istream)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not get data from stream"));
	release_keylist(rcpt_keys);
	gpgme_release(ctx);
	return -1;
    }
    if ((err =
	 gpgme_data_new_from_cbs(&crypt, &cbs,
				 ostream)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not create new data object"));
	release_keylist(rcpt_keys);
	gpgme_data_release(plain);
	gpgme_release(ctx);
	return -1;
    }

    /* do the encrypt or sign and encrypt operation
     * Note: we set "always trust" here, as if we detected an untrusted key
     * earlier, the user already accepted it */
    if (sign_for)
	err =
	    gpgme_op_encrypt_sign(ctx, rcpt_keys,
				  GPGME_ENCRYPT_ALWAYS_TRUST, plain,
				  crypt);
    else
	err =
	    gpgme_op_encrypt(ctx, rcpt_keys, GPGME_ENCRYPT_ALWAYS_TRUST,
			     plain, crypt);

    release_keylist(rcpt_keys);
    gpgme_data_release(plain);
    gpgme_data_release(crypt);
    gpgme_release(ctx);
    if (err != GPG_ERR_NO_ERROR) {
	if (sign_for)
	    g_set_error_from_gpgme(error, err,
				   _("signing and encryption failed"));
	else
	    g_set_error_from_gpgme(error, err, _("encryption failed"));
	return -1;
    } else
	return 0;
}
Example #15
0
/**
* crypto: the crypto service (#SeahorseServiceCrypto)
* recipients: A list of recipients (keyids "openpgp:B8098FB063E2C811")
* signer: optional, the keyid of the signer
* flags: 0, not used
* cleartext: the text to encrypt
* clearlength: Length of the cleartext
* crypttext: the encrypted text (out)
* cryptlength: the length of this text (out)
* textmode: TRUE if gpgme should use textmode
* ascii_armor: TRUE if GPGME should use ascii armor
* error: The Error
*
* Handles encryption in a generic way. Can be used by several DBus APIs
*
* Returns TRUE on success
**/
static gboolean
crypto_encrypt_generic (SeahorseServiceCrypto *crypto,
                        const char **recipients, const char *signer,
                        int flags, const char *cleartext, gsize clearlength,
                        char **crypttext, gsize *cryptlength, gboolean textmode,
                        gboolean ascii_armor, GError **error)
{
    GList *recipkeys = NULL;
    SeahorseGpgmeOperation *pop; 
    SeahorseObject *signkey = NULL;
    SeahorseObject *skey;
    gpgme_key_t *recips;
    gpgme_data_t plain, cipher;
    gpgme_error_t gerr;
    gboolean ret = TRUE;
    
    /* 
     * TODO: Once we support different kinds of keys that support encryption
     * then all this logic will need to change. 
     */
    /* The signer */
    if (signer && signer[0]) {
        signkey = seahorse_context_object_from_dbus (SCTX_APP (), signer);
        if (!signkey) {
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, 
                         _("Invalid or unrecognized signer: %s"), signer);
            return FALSE;
        }
        
        if (!SEAHORSE_IS_GPGME_KEY (signkey) || 
            !(seahorse_object_get_flags (signkey) & SEAHORSE_FLAG_CAN_SIGN)) {
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                         _("Key is not valid for signing: %s"), signer);
            return FALSE;
        }
    }
    /* The recipients */
    for( ; recipients[0]; recipients++)
    {
        skey = seahorse_context_object_from_dbus (SCTX_APP (), recipients[0]);
        if (!skey) {
            g_list_free (recipkeys);
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, 
                         _("Invalid or unrecognized recipient: %s"), recipients[0]);
            return FALSE;
        }
        
        if (!SEAHORSE_IS_GPGME_KEY (skey) ||
            !(seahorse_object_get_flags (skey) & SEAHORSE_FLAG_CAN_ENCRYPT)) {
            g_list_free (recipkeys);
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                         _("Key is not a valid recipient for encryption: %s"), recipients[0]);
            return FALSE;
        }
        
        recipkeys = g_list_prepend (recipkeys, SEAHORSE_PGP_KEY (skey));
    }
    
    if (!recipkeys) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("No recipients specified"));
        return FALSE;
    }
    pop = seahorse_gpgme_operation_new (NULL);
    
    /* new data form text */
    gerr = gpgme_data_new_from_mem (&plain, cleartext, clearlength, FALSE);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
    gerr = gpgme_data_new (&cipher);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
   
    /* encrypt with armor */
    gpgme_set_textmode (pop->gctx, textmode);
    gpgme_set_armor (pop->gctx, ascii_armor);

    /* Add the default key if set and necessary */
    if (seahorse_gconf_get_boolean (ENCRYPTSELF_KEY)) {
        skey = SEAHORSE_OBJECT (seahorse_context_get_default_key (SCTX_APP ()));
        if (SEAHORSE_IS_PGP_KEY (skey))
            recipkeys = g_list_append (recipkeys, skey);
    }

    /* Make keys into the right format for GPGME */
    recips = keylist_to_keys (recipkeys);
    g_list_free (recipkeys);
    
    /* Do the encryption */
    if (signkey) {
        gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey)));
        gerr = gpgme_op_encrypt_sign_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, 
                                            plain, cipher);
    } else {
        gerr = gpgme_op_encrypt_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, 
                                       plain, cipher);
    }
    free_keys (recips);

    /* Frees cipher */
    ret = process_crypto_result (pop, gerr, cipher, crypttext, cryptlength, error);
    g_object_unref (pop);
    gpgme_data_release (plain);
    return ret;
}
Example #16
0
gboolean pgpmime_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr)
{
	MimeInfo *msgcontent, *sigmultipart, *newinfo;
	gchar *textstr, *micalg = NULL;
	FILE *fp;
	gchar *boundary = NULL;
	gchar *sigcontent;
	gpgme_ctx_t ctx;
	gpgme_data_t gpgtext, gpgsig;
	gpgme_error_t err;
	size_t len;
	struct passphrase_cb_info_s info;
	gpgme_sign_result_t result = NULL;
	gchar *test_msg;
	
	fp = my_tmpfile();
	if (fp == NULL) {
		perror("my_tmpfile");
		privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno));
		return FALSE;
	}
	procmime_write_mimeinfo(mimeinfo, fp);
	rewind(fp);

	/* read temporary file into memory */
	test_msg = file_read_stream_to_str(fp);
	claws_fclose(fp);
	
	memset (&info, 0, sizeof info);

	/* remove content node from message */
	msgcontent = (MimeInfo *) mimeinfo->node->children->data;
	g_node_unlink(msgcontent->node);

	/* create temporary multipart for content */
	sigmultipart = procmime_mimeinfo_new();
	sigmultipart->type = MIMETYPE_MULTIPART;
	sigmultipart->subtype = g_strdup("signed");
	
	do {
		g_free(boundary);
		boundary = generate_mime_boundary("Sig");
	} while (strstr(test_msg, boundary) != NULL);
	
	g_free(test_msg);

	g_hash_table_insert(sigmultipart->typeparameters, g_strdup("boundary"),
                            g_strdup(boundary));
	g_hash_table_insert(sigmultipart->typeparameters, g_strdup("protocol"),
                            g_strdup("application/pgp-signature"));
	g_node_append(sigmultipart->node, msgcontent->node);
	g_node_append(mimeinfo->node, sigmultipart->node);

	/* write message content to temporary file */
	fp = my_tmpfile();
	if (fp == NULL) {
		perror("my_tmpfile");
		privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno));
		return FALSE;
	}
	procmime_write_mimeinfo(sigmultipart, fp);
	rewind(fp);

	/* read temporary file into memory */
	textstr = get_canonical_content(fp, boundary);

	g_free(boundary);
	claws_fclose(fp);

	gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0);
	gpgme_data_new(&gpgsig);
	if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) {
		debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err));
		privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
		return FALSE;
	}
	gpgme_set_textmode(ctx, 1);
	gpgme_set_armor(ctx, 1);
	gpgme_signers_clear (ctx);

	if (!sgpgme_setup_signers(ctx, account, from_addr)) {
		gpgme_release(ctx);
		return FALSE;
	}

	prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent);
	if (g_getenv("GPG_AGENT_INFO") && prefs_gpg_get_config()->use_gpg_agent) {
		debug_print("GPG_AGENT_INFO environment defined, running without passphrase callback\n");
	} else {
   		info.c = ctx;
    		gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info);
	}

	err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_DETACH);
	if (err != GPG_ERR_NO_ERROR) {
		if (err == GPG_ERR_CANCELED) {
			/* ignore cancelled signing */
			privacy_reset_error();
			debug_print("gpgme_op_sign cancelled\n");
		} else {
			privacy_set_error(_("Data signing failed, %s"), gpgme_strerror(err));
			debug_print("gpgme_op_sign error : %x\n", err);
		}
		gpgme_release(ctx);
		return FALSE;
	}
	result = gpgme_op_sign_result(ctx);
	if (result && result->signatures) {
		gpgme_new_signature_t sig = result->signatures;
		if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
			gchar *down_algo = g_ascii_strdown(gpgme_hash_algo_name(
				result->signatures->hash_algo), -1);
			micalg = g_strdup_printf("pgp-%s", down_algo);
			g_free(down_algo);
		} else {
			micalg = g_strdup(gpgme_hash_algo_name(
				result->signatures->hash_algo));
		}
		while (sig) {
			debug_print("valid signature: %s\n", sig->fpr);
			sig = sig->next;
		}
	} else if (result && result->invalid_signers) {
		gpgme_invalid_key_t invalid = result->invalid_signers;
		while (invalid) {
			g_warning("invalid signer: %s (%s)", invalid->fpr, 
				gpgme_strerror(invalid->reason));
			privacy_set_error(_("Data signing failed due to invalid signer: %s"), 
				gpgme_strerror(invalid->reason));
			invalid = invalid->next;
		}
		gpgme_release(ctx);
		return FALSE;
	} else {
		/* can't get result (maybe no signing key?) */
		debug_print("gpgme_op_sign_result error\n");
		privacy_set_error(_("Data signing failed, no results."));
		gpgme_release(ctx);
		return FALSE;
	}

	sigcontent = sgpgme_data_release_and_get_mem(gpgsig, &len);
	gpgme_data_release(gpgtext);
	g_free(textstr);

	if (sigcontent == NULL || len <= 0) {
		g_warning("sgpgme_data_release_and_get_mem failed");
		privacy_set_error(_("Data signing failed, no contents."));
		g_free(micalg);
		g_free(sigcontent);
		return FALSE;
	}

	/* add signature */
	g_hash_table_insert(sigmultipart->typeparameters, g_strdup("micalg"),
                            micalg);

	newinfo = procmime_mimeinfo_new();
	newinfo->type = MIMETYPE_APPLICATION;
	newinfo->subtype = g_strdup("pgp-signature");
	newinfo->description = g_strdup(_("OpenPGP digital signature"));
	newinfo->content = MIMECONTENT_MEM;
	newinfo->data.mem = g_malloc(len + 1);
	g_memmove(newinfo->data.mem, sigcontent, len);
	newinfo->data.mem[len] = '\0';
	g_node_append(sigmultipart->node, newinfo->node);

	g_free(sigcontent);
	gpgme_release(ctx);

	return TRUE;
}