⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crypt-gpgme.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 5 页
字号:
  mutt_mktemp (tempfile);  fp = safe_fopen (tempfile, "w+");  if (!fp)    {      mutt_perror (tempfile);      return NULL;    }  err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)         ? gpgme_error_from_errno (errno) : 0);  if (!err)    {      char buf[4096];      while ((nread = gpgme_data_read (data, buf, sizeof (buf))))        {          if (fwrite (buf, nread, 1, fp) != 1)            {              mutt_perror (tempfile);              fclose (fp);              unlink (tempfile);              return NULL;            }        }    }  if (ret_fp)    rewind (fp);  else    fclose (fp);  if (nread == -1)    {      mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));      unlink (tempfile);      fclose (fp);      return NULL;    }  if (ret_fp)    *ret_fp = fp;  return safe_strdup (tempfile);}/* Create a GpgmeRecipientSet from the keys in the string KEYLIST.   The keys must be space delimited. */static gpgme_key_t *create_recipient_set (const char *keylist,                                          gpgme_protocol_t protocol){  int err;  const char *s;  char buf[100];  int i;  gpgme_key_t *rset = NULL;  unsigned int rset_n = 0;  gpgme_key_t key = NULL;  gpgme_ctx_t context = NULL;  err = gpgme_new (&context);  if (! err)    err = gpgme_set_protocol (context, protocol);  if (! err)    {      s = keylist;      do {	while (*s == ' ')	  s++;	for (i=0; *s && *s != ' ' && i < sizeof(buf)-1;)	  buf[i++] = *s++;	buf[i] = 0;	if (*buf)	  {	    if (i>1 && buf[i-1] == '!') 	      {		/* The user selected to override the valididy of that		   key. */		buf[i-1] = 0;	    		err = gpgme_get_key (context, buf, &key, 0);		if (! err)		  key->uids->validity = GPGME_VALIDITY_FULL;		buf[i-1] = '!';	      }	    else	      err = gpgme_get_key (context, buf, &key, 0);	    if (! err)	      {		safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));		rset[rset_n++] = key;	      }	    else	      {		mutt_error (_("error adding recipient `%s': %s\n"),			    buf, gpgme_strerror (err));		FREE (&rset);		return NULL;	      }	  }      } while (*s);    }  /* NULL terminate.  */  safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));  rset[rset_n++] = NULL;    if (context)    gpgme_release (context);  return rset;}/* Make sure that the correct signer is set. Returns 0 on success. */static int set_signer (gpgme_ctx_t ctx, int for_smime){  char *signid = for_smime ? SmimeDefaultKey: PgpSignAs;  gpgme_error_t err;  gpgme_ctx_t listctx;  gpgme_key_t key, key2;  if (!signid || !*signid)    return 0;  listctx = create_gpgme_context (for_smime);  err = gpgme_op_keylist_start (listctx, signid, 1);  if (!err)    err = gpgme_op_keylist_next (listctx, &key);  if (err)    {      gpgme_release (listctx);      mutt_error (_("secret key `%s' not found: %s\n"),                  signid, gpgme_strerror (err));      return -1;    }  err = gpgme_op_keylist_next (listctx, &key2);  if (!err)    {      gpgme_key_release (key);      gpgme_key_release (key2);      gpgme_release (listctx);      mutt_error (_("ambiguous specification of secret key `%s'\n"),                  signid);      return -1;    }  gpgme_op_keylist_end (listctx);  gpgme_release (listctx);  gpgme_signers_clear (ctx);  err = gpgme_signers_add (ctx, key);  gpgme_key_release (key);  if (err)    {      mutt_error (_("error setting secret key `%s': %s\n"),                  signid, gpgme_strerror (err));      return -1;    }  return 0;}/* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET   and return an allocated filename to a temporary file containing the   enciphered text.  With USE_SMIME set to true, the smime backend is   used.  With COMBINED_SIGNED a PGP message is signed and   encrypted.  Returns NULL in case of error */static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t *rset,                                   int use_smime, int combined_signed){  int err;  gpgme_ctx_t ctx;  gpgme_data_t ciphertext;  char *outfile;  ctx = create_gpgme_context (use_smime);  if (!use_smime)       gpgme_set_armor (ctx, 1);  ciphertext = create_gpgme_data ();  if (combined_signed)    {      if (set_signer (ctx, use_smime))        {          gpgme_data_release (ciphertext);          gpgme_release (ctx);          return NULL;        }      err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,                                   plaintext, ciphertext);    }  else    err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,                            plaintext, ciphertext);  mutt_need_hard_redraw ();  if (err)    {      mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err));      gpgme_data_release (ciphertext);      gpgme_release (ctx);      return NULL;    }  gpgme_release (ctx);  outfile = data_object_to_tempfile (ciphertext, NULL);  gpgme_data_release (ciphertext);  return outfile;}/* Find the "micalg" parameter from the last Gpgme operation on   context CTX.  It is expected that this operation was a sign   operation.  Return the algorithm name as a C string in buffer BUF   which must have been allocated by the caller with size BUFLEN.   Returns 0 on success or -1 in case of an error.  The return string   is truncted to BUFLEN - 1. */static int get_micalg (gpgme_ctx_t ctx, char *buf, size_t buflen){  gpgme_sign_result_t result = NULL;  const char *algorithm_name = NULL;  if (!buflen)    return -1;  *buf = 0;  result = gpgme_op_sign_result (ctx);  if (result)    {      algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo);      if (algorithm_name)	{	  strncpy (buf, algorithm_name, buflen - 1);	  buf[buflen - 1] = 0;	}    }  return *buf? 0:-1;}static void print_time(time_t t, STATE *s){  char p[STRING];  setlocale (LC_TIME, "");#ifdef HAVE_LANGINFO_D_T_FMT  strftime (p, sizeof (p), nl_langinfo (D_T_FMT), localtime (&t));#else  strftime (p, sizeof (p), "%c", localtime (&t));#endif  setlocale (LC_TIME, "C");  state_attach_puts (p, s);}/*  * Implementation of `sign_message'. *//* Sign the MESSAGE in body A either using OpenPGP or S/MIME when   USE_SMIME is passed as true.  Returns the new body or NULL on   error. */static BODY *sign_message (BODY *a, int use_smime){  BODY *t;  char *sigfile;  int err = 0;  char buf[100];  gpgme_ctx_t ctx;  gpgme_data_t message, signature;  convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */  message = body_to_data_object (a, 1);  if (!message)     return NULL;  signature = create_gpgme_data ();  ctx = create_gpgme_context (use_smime);  if (!use_smime)    gpgme_set_armor (ctx, 1);  if (set_signer (ctx, use_smime))    {      gpgme_data_release (signature);      gpgme_release (ctx);      return NULL;    }  err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH );  mutt_need_hard_redraw ();  gpgme_data_release (message);  if (err)    {      gpgme_data_release (signature);      gpgme_release (ctx);      mutt_error (_("error signing data: %s\n"), gpgme_strerror (err));      return NULL;    }  sigfile = data_object_to_tempfile (signature, NULL);  gpgme_data_release (signature);  if (!sigfile)    {      gpgme_release (ctx);      return NULL;    }  t = mutt_new_body ();  t->type = TYPEMULTIPART;  t->subtype = safe_strdup ("signed");  t->encoding = ENC7BIT;  t->use_disp = 0;  t->disposition = DISPINLINE;  mutt_generate_boundary (&t->parameter);  mutt_set_parameter ("protocol",                      use_smime? "application/pkcs7-signature"                               : "application/pgp-signature",                      &t->parameter);  /* Get the micalg from gpgme.  Old gpgme versions don't support this     for S/MIME so we assume sha-1 in this case. */  if (!get_micalg (ctx, buf, sizeof buf))    mutt_set_parameter ("micalg", buf, &t->parameter);  else if (use_smime)    mutt_set_parameter ("micalg", "sha1", &t->parameter);  gpgme_release (ctx);  t->parts = a;  a = t;  t->parts->next = mutt_new_body ();  t = t->parts->next;  t->type = TYPEAPPLICATION;  if (use_smime)    {      t->subtype = safe_strdup ("pkcs7-signature");      mutt_set_parameter ("name", "smime.p7s", &t->parameter);      t->encoding = ENCBASE64;       t->use_disp = 1;      t->disposition = DISPATTACH;      t->d_filename = safe_strdup ("smime.p7s");    }  else    {      t->subtype = safe_strdup ("pgp-signature");      t->use_disp = 0;      t->disposition = DISPINLINE;      t->encoding = ENC7BIT;    }  t->filename = sigfile;  t->unlink = 1; /* ok to remove this file after sending. */  return a;}BODY *pgp_gpgme_sign_message (BODY *a){  return sign_message (a, 0);}BODY *smime_gpgme_sign_message (BODY *a){  return sign_message (a, 1);}/* * Implementation of `encrypt_message'. *//* Encrypt the mail body A to all keys given as space separated keyids   or fingerprints in KEYLIST and return the encrypted body.  */BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign){  char *outfile = NULL;  BODY *t;  gpgme_key_t *rset = NULL;  gpgme_data_t plaintext;    rset = create_recipient_set (keylist, GPGME_PROTOCOL_OpenPGP);  if (!rset)    return NULL;    if (sign)    convert_to_7bit (a);  plaintext = body_to_data_object (a, 0);  if (!plaintext)    {      FREE (&rset);      return NULL;    }    outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);  gpgme_data_release (plaintext);  FREE (&rset);  if (!outfile)      return NULL;  t = mutt_new_body ();  t->type = TYPEMULTIPART;  t->subtype = safe_strdup ("encrypted");  t->encoding = ENC7BIT;  t->use_disp = 0;  t->disposition = DISPINLINE;  mutt_generate_boundary(&t->parameter);  mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter);    t->parts = mutt_new_body ();  t->parts->type = TYPEAPPLICATION;  t->parts->subtype = safe_strdup ("pgp-encrypted");  t->parts->encoding = ENC7BIT;  t->parts->next = mutt_new_body ();  t->parts->next->type = TYPEAPPLICATION;  t->parts->next->subtype = safe_strdup ("octet-stream");  t->parts->next->encoding = ENC7BIT;  t->parts->next->filename = outfile;  t->parts->next->use_disp = 1;  t->parts->next->disposition = DISPINLINE;  t->parts->next->unlink = 1; /* delete after sending the message */  t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime                                                           can save */  return t;}/* * Implementation of `smime_build_smime_entity'. *//* Encrypt the mail body A to all keys given as space separated   fingerprints in KEYLIST and return the S/MIME encrypted body.  */BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist){  char *outfile = NULL;  BODY *t;  gpgme_key_t *rset = NULL;  gpgme_data_t plaintext;  rset = create_recipient_set (keylist, GPGME_PROTOCOL_CMS);  if (!rset)    return NULL;  plaintext = body_to_data_object (a, 0);  if (!plaintext)    {      FREE (&rset);      return NULL;    }  outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);  gpgme_data_release (plaintext);  FREE (&rset);  if (!outfile)       return NULL;  t = mutt_new_body ();  t->type = TYPEAPPLICATION;  t->subtype = safe_strdup ("pkcs7-mime");  mutt_set_parameter ("name", "smime.p7m", &t->parameter);  mutt_set_parameter ("smime-type", "enveloped-data", &t->parameter);  t->encoding = ENCBASE64;  /* The output of OpenSSL SHOULD be binary */  t->use_disp = 1;  t->disposition = DISPATTACH;  t->d_filename = safe_strdup ("smime.p7m");  t->filename = outfile;  t->unlink = 1; /*delete after sending the message */  t->parts=0;  t->next=0;    return t;}/*  * Implementation of `verify_one'. *//* Display the common attributes of the signature summary SUM.   Return 1 if there is is a severe warning. */static int show_sig_summary (unsigned long sum,                              gpgme_ctx_t ctx, gpgme_key_t key, int idx,                              STATE *s){  int severe = 0;  if ((sum & GPGME_SIGSUM_KEY_REVOKED))    {      state_attach_puts (_("Warning: One of the keys has been revoked\n"),s);      severe = 1;    }  if ((sum & GPGME_SIGSUM_KEY_EXPIRED))    {      time_t at = key->subkeys->expires ? key->subkeys->expires : 0;      if (at)        {          state_attach_puts (_("Warning: The key used to create the "                               "signature expired at: "), s);          print_time (at , s);          state_attach_puts ("\n", s);        }      else        state_attach_puts (_("Warning: At least one certification key "

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -