예제 #1
0
static int smime_decrypt(struct mailprivacy * privacy,
    mailmessage * msg,
    struct mailmime * mime, struct mailmime ** result)
{
  char smime_filename[PATH_MAX];
  char quoted_smime_filename[PATH_MAX];
  char description_filename[PATH_MAX];
  char decrypted_filename[PATH_MAX];
  char command[PATH_MAX];
  struct mailmime * description_mime;
  struct mailmime * decrypted_mime;
  int r;
  int res;
  int sign_ok;
  struct mailmime * multipart;
  char * smime_cert;
  char * smime_key;
  char quoted_smime_cert[PATH_MAX];
  char quoted_smime_key[PATH_MAX];
  char * email;
  chashiter * iter;
  
  /* fetch the whole multipart and write it to a file */
  
  r = mailprivacy_fetch_mime_body_to_file(privacy,
      smime_filename, sizeof(smime_filename),
      msg, mime);
  if (r != MAIL_NO_ERROR) {
    res = r;
    goto err;
  }
  
  /* we are in a safe directory */
  
  r = mailprivacy_get_tmp_filename(privacy, decrypted_filename,
      sizeof(decrypted_filename));
  if (r != MAIL_NO_ERROR) {
    res = MAIL_ERROR_FILE;
    goto unlink_smime;
  }
  
  /* description */
  
  r = mailprivacy_get_tmp_filename(privacy, description_filename,
      sizeof(description_filename));
  if (r != MAIL_NO_ERROR) {
    res = MAIL_ERROR_FILE;
    goto unlink_decrypted;
  }
  
  sign_ok = 0;
  for(iter = chash_begin(private_keys) ; iter != NULL ;
      iter = chash_next(private_keys, iter)) {
    chashdatum key;
    char email_buf[BUF_SIZE];
    
    chash_key(iter, &key);
    
    if (key.len >= sizeof(email_buf))
      continue;
    
    strncpy(email_buf, key.data, key.len);
    email_buf[key.len] = '\0';
    email = email_buf;
    
    /* get encryption key */
    
    smime_key = get_private_key_file(email);
    smime_cert = get_cert_file(email);
    if ((smime_cert == NULL) || (smime_key == NULL)) {
      res = MAIL_ERROR_INVAL;
      goto unlink_description;
    }
  
    r = mail_quote_filename(quoted_smime_cert, sizeof(quoted_smime_cert),
        smime_cert);
    if (r < 0) {
      res = MAIL_ERROR_MEMORY;
      goto unlink_description;
    }
  
    r = mail_quote_filename(quoted_smime_key, sizeof(quoted_smime_key),
        smime_key);
    if (r < 0) {
      res = MAIL_ERROR_MEMORY;
      goto unlink_description;
    }
  
    /* run the command */
  
    r = mail_quote_filename(quoted_smime_filename,
        sizeof(quoted_smime_filename), smime_filename);
    if (r < 0) {
      res = MAIL_ERROR_MEMORY;
      goto unlink_description;
    }
    
    sign_ok = 0;
    snprintf(command, sizeof(command),
        "openssl smime -decrypt -passin fd:0 -in '%s' -inkey '%s' -recip '%s'",
        quoted_smime_filename, quoted_smime_key, quoted_smime_cert);
    
    unlink(description_filename);
    r = smime_command_passphrase(privacy, msg, command,
        email, decrypted_filename, description_filename);
    switch (r) {
    case NO_ERROR_SMIME:
      sign_ok = 1;
      break;
    case ERROR_SMIME_CHECK:
    case ERROR_SMIME_NOPASSPHRASE:
      sign_ok = 0;
      break;
    case ERROR_SMIME_COMMAND:
      res = MAIL_ERROR_COMMAND;
      goto unlink_description;
    case ERROR_SMIME_FILE:
      res = MAIL_ERROR_FILE;
      goto unlink_description;
    }
    
    if (sign_ok) {
      break;
    }
  }
  
  if (!sign_ok) {
    if (chash_count(private_keys) == 0) {
      FILE * description_f;
      
      description_f = mailprivacy_get_tmp_file(privacy, description_filename,
          sizeof(description_filename));
      if (description_f == NULL) {
        res = MAIL_ERROR_FILE;
        goto unlink_decrypted;
      }
      fprintf(description_f, SMIME_DECRYPT_FAILED);
      fclose(description_f);
    }
  }
  else {
    mailprivacy_smime_encryption_id_list_clear(privacy, msg);
  }
  
  /* building multipart */

  r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart);
  if (r != MAILIMF_NO_ERROR) {
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }
  
  /* building the description part */
  
  description_mime = mailprivacy_new_file_part(privacy,
      description_filename,
      "text/plain", MAILMIME_MECHANISM_8BIT);
  if (description_mime == NULL) {
    mailprivacy_mime_clear(multipart);
    mailmime_free(multipart);
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }
  
  /* adds the description part */
  
  r = mailmime_smart_add_part(multipart, description_mime);
  if (r != MAIL_NO_ERROR) {
    mailprivacy_mime_clear(description_mime);
    mailmime_free(description_mime);
    mailprivacy_mime_clear(multipart);
    mailmime_free(multipart);
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }
  
  /* building the decrypted part */
  
  r = mailprivacy_get_part_from_file(privacy, 1, 0,
      decrypted_filename, &decrypted_mime);
  if (r == MAIL_NO_ERROR) {
    /* adds the decrypted part */
    
    r = mailmime_smart_add_part(multipart, decrypted_mime);
    if (r != MAIL_NO_ERROR) {
      mailprivacy_mime_clear(decrypted_mime);
      mailmime_free(decrypted_mime);
      mailprivacy_mime_clear(multipart);
      mailmime_free(multipart);
      res = MAIL_ERROR_MEMORY;
      goto unlink_description;
    }
  }
  
  unlink(description_filename);
  unlink(decrypted_filename);
  unlink(smime_filename);
  
  * result = multipart;
  
  return MAIL_NO_ERROR;
  
 unlink_description:
  unlink(description_filename);
 unlink_decrypted:
  unlink(decrypted_filename);
 unlink_smime:
  unlink(smime_filename);
 err:
  return res;
}
예제 #2
0
static int
smime_verify(struct mailprivacy * privacy,
    mailmessage * msg,
    struct mailmime * mime, struct mailmime ** result)
{
  char smime_filename[PATH_MAX];
  char quoted_smime_filename[PATH_MAX];
  int res;
  int r;
  char command[PATH_MAX];
  int sign_ok;
  struct mailmime * description_mime;
  char description_filename[PATH_MAX];
  struct mailmime * multipart;
  char stripped_filename[PATH_MAX];
  struct mailmime * stripped_mime;
  char check_CA[PATH_MAX];
  char quoted_CAfile[PATH_MAX];
  char noverify[PATH_MAX];
  
  if (store_cert)
    get_cert_from_sig(privacy, msg, mime);
  
  * check_CA = '\0';
  if (CAfile != NULL) {
    r = mail_quote_filename(quoted_CAfile, sizeof(quoted_CAfile), CAfile);
    if (r < 0) {
      res = MAIL_ERROR_MEMORY;
      goto err;
    }
    
    snprintf(check_CA, sizeof(check_CA), "-CAfile '%s'", quoted_CAfile);
  }
  
  * noverify = '\0';
  if (!CA_check) {
    snprintf(noverify, sizeof(noverify), "-noverify");
  }
  
  /* fetch the whole multipart and write it to a file */
  
  r = mailprivacy_fetch_mime_body_to_file(privacy,
      smime_filename, sizeof(smime_filename),
      msg, mime);
  if (r != MAIL_NO_ERROR) {
    res = r;
    goto err;
  }
  
  r = mailprivacy_get_tmp_filename(privacy,stripped_filename,
      sizeof(stripped_filename));
  if (r != MAIL_NO_ERROR) {
    res = r;
    goto unlink_smime;
  }
  
  /* description */
  
  r = mailprivacy_get_tmp_filename(privacy, description_filename,
      sizeof(description_filename));
  if (r != MAIL_NO_ERROR) {
    res = r;
    goto unlink_stripped;
  }
  
  /* run the command */

  r = mail_quote_filename(quoted_smime_filename,
      sizeof(quoted_smime_filename), smime_filename);
  if (r < 0) {
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }

  sign_ok = 0;
  snprintf(command, sizeof(command), "openssl smime -verify -in '%s' %s %s",
      quoted_smime_filename, check_CA, noverify);
  
  r = smime_command_passphrase(privacy, msg, command,
      NULL, stripped_filename, description_filename);
  switch (r) {
  case NO_ERROR_SMIME:
    sign_ok = 1;
    break;
  case ERROR_SMIME_NOPASSPHRASE:
  case ERROR_SMIME_CHECK:
    sign_ok = 0;
    break;
  case ERROR_SMIME_COMMAND:
    res = MAIL_ERROR_COMMAND;
    goto unlink_description;
  case ERROR_SMIME_FILE:
    res = MAIL_ERROR_FILE;
    goto unlink_description;
  }
  
  /* building multipart */
  
  r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart);
  if (r != MAILIMF_NO_ERROR) {
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }
  
  /* building the description part */
  
  description_mime = mailprivacy_new_file_part(privacy,
      description_filename,
      "text/plain", MAILMIME_MECHANISM_8BIT);
  if (description_mime == NULL) {
    mailprivacy_mime_clear(multipart);
    mailmime_free(multipart);
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }
  
  /* adds the description part */
  
  r = mailmime_smart_add_part(multipart, description_mime);
  if (r != MAIL_NO_ERROR) {
    mailprivacy_mime_clear(description_mime);
    mailmime_free(description_mime);
    mailprivacy_mime_clear(multipart);
    mailmime_free(multipart);
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }
  
  /* insert the signed part */
  if (!sign_ok) {
    if (mime->mm_type == MAILMIME_MULTIPLE) {
      clistiter * child_iter;
      struct mailmime * child;
      
      child_iter = clist_begin(mime->mm_data.mm_multipart.mm_mp_list);
      child = clist_content(child_iter);
      
      r = mailprivacy_fetch_mime_body_to_file(privacy,
          stripped_filename, sizeof(stripped_filename),
          msg, child);
    }
  }
  
  r = mailprivacy_get_part_from_file(privacy, 1, 0,
      stripped_filename, &stripped_mime);
  if (r != MAIL_NO_ERROR) {
    mailprivacy_mime_clear(multipart);
    mailmime_free(multipart);
    res = r;
    goto unlink_description;
  }
  
  r = mailmime_smart_add_part(multipart, stripped_mime);
  if (r != MAIL_NO_ERROR) {
    mailprivacy_mime_clear(stripped_mime);
    mailmime_free(stripped_mime);
    mailprivacy_mime_clear(multipart);
    mailmime_free(multipart);
    res = MAIL_ERROR_MEMORY;
    goto unlink_description;
  }
  
  unlink(description_filename);
  unlink(stripped_filename);
  /* unlink(smime_filename); */
  
  * result = multipart;
  
  return MAIL_NO_ERROR;
  
 unlink_description:
  unlink(description_filename);
 unlink_stripped:
  unlink(stripped_filename);
 unlink_smime:
  unlink(smime_filename);
 err:
  return res;
}
예제 #3
0
static struct mailmime *
mime_add_alternative(struct mailprivacy * privacy,
    mailmessage * msg,
    struct mailmime * mime,
    struct mailmime * alternative)
{
  struct mailmime * multipart;
  int r;
  struct mailmime * mime_copy;
  char original_filename[PATH_MAX];
  
  if (mime->mm_parent == NULL)
    goto err;
  
  r = mailmime_new_with_content("multipart/alternative", NULL, &multipart);
  if (r != MAILIMF_NO_ERROR)
    goto err;
  
  r = mailmime_smart_add_part(multipart, alternative);
  if (r != MAILIMF_NO_ERROR) {
    goto free_multipart;
  }

  /* get copy of mime part "mime" and set parts */
  
  r = mailprivacy_fetch_mime_body_to_file(privacy,
      original_filename, sizeof(original_filename),
      msg, mime);
  if (r != MAIL_NO_ERROR)
    goto detach_alternative;
  
  r = mailprivacy_get_part_from_file(privacy, 0, 0,
      original_filename, &mime_copy);
  unlink(original_filename);
  if (r != MAIL_NO_ERROR) {
    goto detach_alternative;
  }
  
  r = mailmime_smart_add_part(multipart, mime_copy);
  if (r != MAILIMF_NO_ERROR) {
    goto free_mime_copy;
  }
  
  r = recursive_register_mime(privacy, multipart);
  if (r != MAIL_NO_ERROR)
    goto detach_mime_copy;
  
  mailmime_substitute(mime, multipart);
  
  mailmime_free(mime);
  
  return multipart;
  
 detach_mime_copy:
  mailprivacy_recursive_unregister_mime(privacy, multipart);
  mailmime_remove_part(alternative);
 free_mime_copy:
  mailprivacy_mime_clear(mime_copy);
  mailmime_free(mime_copy);
 detach_alternative:
  mailmime_remove_part(alternative);
 free_multipart:
  mailmime_free(multipart);
 err:
  return NULL;
}