Exemple #1
0
/*
 * Try to open a file without the extension ".sig" or ".asc"
 * Return NULL if such a file is not available.
 */
iobuf_t
open_sigfile (const char *sigfilename, progress_filter_context_t *pfx)
{
  iobuf_t a = NULL;
  char *buf;

  buf = get_matching_datafile (sigfilename);
  if (buf)
    {
      a = iobuf_open (buf);
      if (a && is_secured_file (iobuf_get_fd (a)))
        {
          iobuf_close (a);
          a = NULL;
          gpg_err_set_errno (EPERM);
        }
      if (a)
        log_info (_("assuming signed data in '%s'\n"), buf);
      if (a && pfx)
        handle_progress (pfx, a, buf);
      xfree (buf);
    }

  return a;
}
Exemple #2
0
int main(int argc, char **argv)
{
	gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
	int l;
	int ret;
	armor_filter_context_t *afx = NULL;

	while (fgets(passphrase, N, stdin) != NULL && status == 0) {
		IOBUF a;
		struct stat sb;
		unlink("output");
		l = strlen(passphrase);
		passphrase[l - 1] = 0;
		status = 1;
		a = iobuf_open(argv[1]);
		if( use_armor_filter( a ) ) {
			afx = new_armor_context ();
			push_armor_filter (afx, a);
		}
		proc_packets(NULL, a);
		ret = stat("output", &sb);
		if (status == 1 && sb.st_size > 0 && ret != -1) {
			printf("Found Password : %s\n", passphrase);
			exit(0);
		} else {
			status = 0;
		}
		iobuf_close(a);
	}
	return -1;
}
Exemple #3
0
/****************
 * Check if the file is compressed.
 **/
int
is_file_compressed( const char *s, int *ret_rc )
{
    IOBUF a;
    byte buf[4];
    int i, rc = 0;

    struct magic_compress_s {
        size_t len;
        byte magic[4];
    } magic[] = {
        { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
        { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
        { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
    };
    
    if ( !s || *s == '-' || !ret_rc )
        return 0; /* We can't check stdin or no file was given */

    a = iobuf_open( s );
    if ( a == NULL ) {
        *ret_rc = G10ERR_OPEN_FILE;
        return 0;
    }

    if ( iobuf_get_filelength( a ) < 4 ) {
        *ret_rc = 0;
        goto leave;
    }

    if ( iobuf_read( a, buf, 4 ) == -1 ) {
        *ret_rc = G10ERR_READ_FILE;
        goto leave;
    }

    for ( i = 0; i < DIM( magic ); i++ ) {
        if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
            *ret_rc = 0;
            rc = 1;
            break;
        }
    }

leave:    
    iobuf_close( a );
    return rc;
}
Exemple #4
0
/****************
 * Take file and write it out with armor
 */
int
enarmor_file( const char *fname )
{
    armor_filter_context_t *afx;
    IOBUF inp = NULL, out = NULL;
    int rc = 0;
    int c;

    afx = new_armor_context ();

    /* prepare iobufs */
    inp = iobuf_open(fname);
    if (inp && is_secured_file (iobuf_get_fd (inp)))
      {
        iobuf_close (inp);
        inp = NULL;
        errno = EPERM;
      }
    if (!inp) {
        rc = gpg_error_from_syserror ();
	log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]",
                  strerror(errno) );
	goto leave;
    }


    if( (rc = open_outfile( fname, 1, &out )) )
	goto leave;

    afx->what = 4;
    afx->hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n";
    push_armor_filter ( afx, out );

    while( (c = iobuf_get(inp)) != -1 )
	iobuf_put( out, c );


  leave:
    if( rc )
	iobuf_cancel(out);
    else
	iobuf_close(out);
    iobuf_close(inp);
    release_armor_context (afx);
    return rc;
}
Exemple #5
0
static int
verify_one_file (ctrl_t ctrl, const char *name )
{
    IOBUF fp;
    armor_filter_context_t *afx = NULL;
    progress_filter_context_t *pfx = new_progress_context ();
    int rc;

    print_file_status( STATUS_FILE_START, name, 1 );
    fp = iobuf_open(name);
    if (fp)
      iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
    if (fp && is_secured_file (iobuf_get_fd (fp)))
      {
        iobuf_close (fp);
        fp = NULL;
        gpg_err_set_errno (EPERM);
      }
    if( !fp ) {
        rc = gpg_error_from_syserror ();
	log_error(_("can't open '%s': %s\n"),
                  print_fname_stdin(name), strerror (errno));
	print_file_status( STATUS_FILE_ERROR, name, 1 );
        goto leave;
    }
    handle_progress (pfx, fp, name);

    if( !opt.no_armor ) {
	if( use_armor_filter( fp ) ) {
            afx = new_armor_context ();
	    push_armor_filter (afx, fp);
	}
    }

    rc = proc_signature_packets (ctrl, NULL, fp, NULL, name );
    iobuf_close(fp);
    write_status( STATUS_FILE_DONE );

    reset_literals_seen();

 leave:
    release_armor_context (afx);
    release_progress_context (pfx);
    return rc;
}
Exemple #6
0
static int
prepare_search (KEYRING_HANDLE hd)
{
    if (hd->current.error)
        return hd->current.error; /* still in error state */

    if (hd->current.kr && !hd->current.eof) {
        if ( !hd->current.iobuf )
            return G10ERR_GENERAL; /* position invalid after a modify */
        return 0; /* okay */
    }

    if (!hd->current.kr && hd->current.eof)
        return -1; /* still EOF */

    if (!hd->current.kr) { /* start search with first keyring */
        hd->current.kr = hd->resource;
        if (!hd->current.kr) {
            hd->current.eof = 1;
            return -1; /* keyring not available */
        }
        assert (!hd->current.iobuf);
    }
    else { /* EOF */
        iobuf_close (hd->current.iobuf);
        hd->current.iobuf = NULL;
        hd->current.kr = NULL;
        hd->current.eof = 1;
        return -1;
    }

    hd->current.eof = 0;
    hd->current.iobuf = iobuf_open (hd->current.kr->fname);
    if (!hd->current.iobuf)
      {
        hd->current.error = gpg_error_from_syserror ();
        log_error(_("can't open `%s'\n"), hd->current.kr->fname );
        return hd->current.error;
      }

    return 0;
}
/****************
 * Encrypt the file with the given userids (or ask if none
 * is supplied).
 */
int
encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
{
    IOBUF inp = NULL, out = NULL;
    PACKET pkt;
    PKT_plaintext *pt = NULL;
    DEK *symkey_dek = NULL;
    STRING2KEY *symkey_s2k = NULL;
    int rc = 0, rc2 = 0;
    u32 filesize;
    cipher_filter_context_t cfx;
    armor_filter_context_t afx;
    compress_filter_context_t zfx;
    text_filter_context_t tfx;
    progress_filter_context_t pfx;
    PK_LIST pk_list,work_list;
    int do_compress = opt.compress_algo && !RFC1991;

    memset( &cfx, 0, sizeof cfx);
    memset( &afx, 0, sizeof afx);
    memset( &zfx, 0, sizeof zfx);
    memset( &tfx, 0, sizeof tfx);
    init_packet(&pkt);

    if(use_symkey
       && (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
      return rc;

    if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
	return rc;

    if(PGP2) {
      for(work_list=pk_list; work_list; work_list=work_list->next)
	if(!(is_RSA(work_list->pk->pubkey_algo) &&
	     nbits_from_pk(work_list->pk)<=2048))
	  {
	    log_info(_("you can only encrypt to RSA keys of 2048 bits or "
		       "less in --pgp2 mode\n"));
	    compliance_failure();
	    break;
	  }
    }

    /* prepare iobufs */
    inp = iobuf_open(filename);
    if (inp)
      iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */
    if (inp && is_secured_file (iobuf_get_fd (inp)))
      {
        iobuf_close (inp);
        inp = NULL;
        errno = EPERM;
      }
    if( !inp ) {
	log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]",
					strerror(errno) );
	rc = G10ERR_OPEN_FILE;
	goto leave;
    }
    else if( opt.verbose )
	log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");

    handle_progress (&pfx, inp, filename);

    if( opt.textmode )
	iobuf_push_filter( inp, text_filter, &tfx );

    if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
	goto leave;

    if( opt.armor )
	iobuf_push_filter( out, armor_filter, &afx );

    /* create a session key */
    cfx.dek = xmalloc_secure_clear (sizeof *cfx.dek);
    if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
	cfx.dek->algo = select_algo_from_prefs(pk_list,PREFTYPE_SYM,-1,NULL);
	/* The only way select_algo_from_prefs can fail here is when
           mixing v3 and v4 keys, as v4 keys have an implicit
           preference entry for 3DES, and the pk_list cannot be empty.
           In this case, use 3DES anyway as it's the safest choice -
           perhaps the v3 key is being used in an OpenPGP
           implementation and we know that the implementation behind
           any v4 key can handle 3DES. */
	if( cfx.dek->algo == -1 ) {
	    cfx.dek->algo = CIPHER_ALGO_3DES;

	    if( PGP2 ) {
	      log_info(_("unable to use the IDEA cipher for all of the keys "
			 "you are encrypting to.\n"));
	      compliance_failure();
	    }
	}
    }
    else {
      if(!opt.expert &&
	 select_algo_from_prefs(pk_list,PREFTYPE_SYM,
				opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
	log_info(_("WARNING: forcing symmetric cipher %s (%d)"
		   " violates recipient preferences\n"),
		 cipher_algo_to_string(opt.def_cipher_algo),
		 opt.def_cipher_algo);

      cfx.dek->algo = opt.def_cipher_algo;
    }

    cfx.dek->use_mdc=use_mdc(pk_list,cfx.dek->algo);

    /* Only do the is-file-already-compressed check if we are using a
       MDC.  This forces compressed files to be re-compressed if we do
       not have a MDC to give some protection against chosen
       ciphertext attacks. */

    if (do_compress && cfx.dek->use_mdc && is_file_compressed(filename, &rc2) )
      {
        if (opt.verbose)
          log_info(_("`%s' already compressed\n"), filename);
        do_compress = 0;        
      }
    if (rc2)
      {
        rc = rc2;
        goto leave;
      }

    make_session_key( cfx.dek );
    if( DBG_CIPHER )
	log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );

    rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
    if( rc  )
	goto leave;

    /* We put the passphrase (if any) after any public keys as this
       seems to be the most useful on the recipient side - there is no
       point in prompting a user for a passphrase if they have the
       secret key needed to decrypt. */
    if(use_symkey && (rc=write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out)))
      goto leave;

    if (!opt.no_literal) {
	/* setup the inner packet */
	if( filename || opt.set_filename ) {
	    char *s = make_basename( opt.set_filename ? opt.set_filename
						      : filename,
				     iobuf_get_real_fname( inp ) );
	    pt = xmalloc( sizeof *pt + strlen(s) - 1 );
	    pt->namelen = strlen(s);
	    memcpy(pt->name, s, pt->namelen );
	    xfree(s);
	}
	else { /* no filename */
	    pt = xmalloc( sizeof *pt - 1 );
	    pt->namelen = 0;
	}
    }

    if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
      {
        off_t tmpsize;
        int overflow;

	if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
             && !overflow )
          log_info(_("WARNING: `%s' is an empty file\n"), filename );
        /* We can't encode the length of very large files because
           OpenPGP uses only 32 bit for file sizes.  So if the the
           size of a file is larger than 2^32 minus some bytes for
           packet headers, we switch to partial length encoding. */
        if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
          filesize = tmpsize;
        else
          filesize = 0;
      }
    else
      filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */

    if (!opt.no_literal) {
	pt->timestamp = make_timestamp();
	pt->mode = opt.textmode ? 't' : 'b';
	pt->len = filesize;
	pt->new_ctb = !pt->len && !RFC1991;
	pt->buf = inp;
	pkt.pkttype = PKT_PLAINTEXT;
	pkt.pkt.plaintext = pt;
	cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
    }
    else
	cfx.datalen = filesize && !do_compress ? filesize : 0;

    /* register the cipher filter */
    iobuf_push_filter( out, cipher_filter, &cfx );

    /* register the compress filter */
    if( do_compress ) {
	int compr_algo = opt.compress_algo;

	if(compr_algo==-1)
	  {
	    if((compr_algo=
		select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1)
	      compr_algo=DEFAULT_COMPRESS_ALGO;
	    /* Theoretically impossible to get here since uncompressed
	       is implicit. */
	  }
	else if(!opt.expert &&
		select_algo_from_prefs(pk_list,PREFTYPE_ZIP,
				       compr_algo,NULL)!=compr_algo)
	  log_info(_("WARNING: forcing compression algorithm %s (%d)"
		     " violates recipient preferences\n"),
		   compress_algo_to_string(compr_algo),compr_algo);

	/* algo 0 means no compression */
	if( compr_algo )
	  {
            if (cfx.dek && cfx.dek->use_mdc)
              zfx.new_ctb = 1;
	    push_compress_filter(out,&zfx,compr_algo);
	  }
    }

    /* do the work */
    if (!opt.no_literal) {
	if( (rc = build_packet( out, &pkt )) )
	    log_error("build_packet failed: %s\n", g10_errstr(rc) );
    }
    else {
	/* user requested not to create a literal packet, so we copy
           the plain data */
	byte copy_buffer[4096];
	int  bytes_copied;
	while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
	    if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
		rc = G10ERR_WRITE_FILE;
		log_error("copying input to output failed: %s\n",
                          g10_errstr(rc) );
		break;
	    }
	wipememory(copy_buffer, 4096); /* burn buffer */
    }

    /* finish the stuff */
  leave:
    iobuf_close(inp);
    if( rc )
	iobuf_cancel(out);
    else {
	iobuf_close(out); /* fixme: check returncode */
        write_status( STATUS_END_ENCRYPTION );
    }
    if( pt )
	pt->buf = NULL;
    free_packet(&pkt);
    xfree(cfx.dek);
    xfree(symkey_dek);
    xfree(symkey_s2k);
    release_pk_list( pk_list );
    return rc;
}
/* We don't want to use use_seskey yet because older gnupg versions
   can't handle it, and there isn't really any point unless we're
   making a message that can be decrypted by a public key or
   passphrase. */
static int
encode_simple( const char *filename, int mode, int use_seskey )
{
    IOBUF inp, out;
    PACKET pkt;
    PKT_plaintext *pt = NULL;
    STRING2KEY *s2k = NULL;
    byte enckey[33];
    int rc = 0;
    int seskeylen = 0;
    u32 filesize;
    cipher_filter_context_t cfx;
    armor_filter_context_t afx;
    compress_filter_context_t zfx;
    text_filter_context_t tfx;
    progress_filter_context_t pfx;
    int do_compress = !RFC1991 && default_compress_algo();

    memset( &cfx, 0, sizeof cfx);
    memset( &afx, 0, sizeof afx);
    memset( &zfx, 0, sizeof zfx);
    memset( &tfx, 0, sizeof tfx);
    init_packet(&pkt);
    
    /* prepare iobufs */
    inp = iobuf_open(filename);
    if (inp)
      iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */
    if (inp && is_secured_file (iobuf_get_fd (inp)))
      {
        iobuf_close (inp);
        inp = NULL;
        errno = EPERM;
      }
    if( !inp ) {
	log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]",
                  strerror(errno) );
	return G10ERR_OPEN_FILE;
    }

    handle_progress (&pfx, inp, filename);

    if( opt.textmode )
	iobuf_push_filter( inp, text_filter, &tfx );

    /* Due the the fact that we use don't use an IV to encrypt the
       session key we can't use the new mode with RFC1991 because
       it has no S2K salt. RFC1991 always uses simple S2K. */
    if ( RFC1991 && use_seskey )
        use_seskey = 0;
    
    cfx.dek = NULL;
    if( mode ) {
	s2k = xmalloc_clear( sizeof *s2k );
	s2k->mode = RFC1991? 0:opt.s2k_mode;
	s2k->hash_algo=S2K_DIGEST_ALGO;
	cfx.dek = passphrase_to_dek( NULL, 0,
				     default_cipher_algo(), s2k, 2,
                                     NULL, NULL);
	if( !cfx.dek || !cfx.dek->keylen ) {
	    rc = G10ERR_PASSPHRASE;
	    xfree(cfx.dek);
	    xfree(s2k);
	    iobuf_close(inp);
	    log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
	    return rc;
	}
        if (use_seskey && s2k->mode != 1 && s2k->mode != 3) {
            use_seskey = 0;
            log_info (_("can't use a symmetric ESK packet "
                        "due to the S2K mode\n"));
        }

        if ( use_seskey )
	  {
	    DEK *dek = NULL;
            seskeylen = cipher_get_keylen( default_cipher_algo() ) / 8;
            encode_seskey( cfx.dek, &dek, enckey );
            xfree( cfx.dek ); cfx.dek = dek;
	  }

	if(opt.verbose)
	  log_info(_("using cipher %s\n"),
		   cipher_algo_to_string(cfx.dek->algo));

	cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
    }

    if (do_compress && cfx.dek && cfx.dek->use_mdc
	&& is_file_compressed(filename, &rc))
      {
        if (opt.verbose)
          log_info(_("`%s' already compressed\n"), filename);
        do_compress = 0;        
      }

    if( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
	iobuf_cancel(inp);
	xfree(cfx.dek);
	xfree(s2k);
	return rc;
    }

    if( opt.armor )
	iobuf_push_filter( out, armor_filter, &afx );

    if( s2k && !RFC1991 ) {
	PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 );
	enc->version = 4;
	enc->cipher_algo = cfx.dek->algo;
	enc->s2k = *s2k;
        if ( use_seskey && seskeylen ) {
            enc->seskeylen = seskeylen + 1; /* algo id */
            memcpy( enc->seskey, enckey, seskeylen + 1 );
        }
	pkt.pkttype = PKT_SYMKEY_ENC;
	pkt.pkt.symkey_enc = enc;
	if( (rc = build_packet( out, &pkt )) )
	    log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
	xfree(enc);
    }

    if (!opt.no_literal)
      pt=setup_plaintext_name(filename,inp);

    /* Note that PGP 5 has problems decrypting symmetrically encrypted
       data if the file length is in the inner packet. It works when
       only partial length headers are use.  In the past, we always
       used partial body length here, but since PGP 2, PGP 6, and PGP
       7 need the file length, and nobody should be using PGP 5
       nowadays anyway, this is now set to the file length.  Note also
       that this only applies to the RFC-1991 style symmetric
       messages, and not the RFC-2440 style.  PGP 6 and 7 work with
       either partial length or fixed length with the new style
       messages. */

    if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
      {
        off_t tmpsize;
        int overflow;

	if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
             && !overflow )
          log_info(_("WARNING: `%s' is an empty file\n"), filename );
        /* We can't encode the length of very large files because
           OpenPGP uses only 32 bit for file sizes.  So if the the
           size of a file is larger than 2^32 minus some bytes for
           packet headers, we switch to partial length encoding. */
        if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
          filesize = tmpsize;
        else
          filesize = 0;
      }
    else
      filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */

    if (!opt.no_literal) {
	pt->timestamp = make_timestamp();
	pt->mode = opt.textmode? 't' : 'b';
	pt->len = filesize;
	pt->new_ctb = !pt->len && !RFC1991;
	pt->buf = inp;
	pkt.pkttype = PKT_PLAINTEXT;
	pkt.pkt.plaintext = pt;
	cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
    }
    else
      {
        cfx.datalen = filesize && !do_compress ? filesize : 0;
        pkt.pkttype = 0;
        pkt.pkt.generic = NULL;
      }

    /* register the cipher filter */
    if( mode )
	iobuf_push_filter( out, cipher_filter, &cfx );
    /* register the compress filter */
    if( do_compress )
      {
        if (cfx.dek && cfx.dek->use_mdc)
          zfx.new_ctb = 1;
	push_compress_filter(out,&zfx,default_compress_algo());
      }

    /* do the work */
    if (!opt.no_literal) {
	if( (rc = build_packet( out, &pkt )) )
	    log_error("build_packet failed: %s\n", g10_errstr(rc) );
    }
    else {
	/* user requested not to create a literal packet,
	 * so we copy the plain data */
	byte copy_buffer[4096];
	int  bytes_copied;
	while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
	    if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
		rc = G10ERR_WRITE_FILE;
		log_error("copying input to output failed: %s\n", g10_errstr(rc) );
		break;
	    }
	wipememory(copy_buffer, 4096); /* burn buffer */
    }

    /* finish the stuff */
    iobuf_close(inp);
    if (rc)
	iobuf_cancel(out);
    else {
	iobuf_close(out); /* fixme: check returncode */
        if (mode)
            write_status( STATUS_END_ENCRYPTION );
    }
    if (pt)
	pt->buf = NULL;
    free_packet(&pkt);
    xfree(cfx.dek);
    xfree(s2k);
    return rc;
}
Exemple #9
0
int
exec_read(struct exec_info *info)
{
  int ret=G10ERR_GENERAL;

  fclose(info->tochild);
  info->tochild=NULL;

  if(info->flags.use_temp_files)
    {
      if(DBG_EXTPROG)
	log_debug("system() command is %s\n",info->command);

#if defined (_WIN32)
      info->progreturn=w32_system(info->command);
#else
      info->progreturn=system(info->command);
#endif

      if(info->progreturn==-1)
	{
	  log_error(_("system error while calling external program: %s\n"),
		    strerror(errno));
	  info->progreturn=127;
	  goto fail;
	}

#if defined(WIFEXITED) && defined(WEXITSTATUS)
      if(WIFEXITED(info->progreturn))
	info->progreturn=WEXITSTATUS(info->progreturn);
      else
	{
	  log_error(_("unnatural exit of external program\n"));
	  info->progreturn=127;
	  goto fail;
	}
#else
      /* If we don't have the macros, do the best we can. */
      info->progreturn = (info->progreturn & 0xff00) >> 8;
#endif

      /* 127 is the magic value returned from system() to indicate
         that the shell could not be executed, or from /bin/sh to
         indicate that the program could not be executed. */

      if(info->progreturn==127)
	{
	  log_error(_("unable to execute external program\n"));
	  goto fail;
	}

      if(!info->flags.writeonly)
	{
	  info->fromchild=iobuf_open(info->tempfile_out);
          if (info->fromchild
              && is_secured_file (iobuf_get_fd (info->fromchild)))
            {
              iobuf_close (info->fromchild);
              info->fromchild = NULL;
              errno = EPERM;
            }
	  if(info->fromchild==NULL)
	    {
              ret = gpg_error_from_syserror ();
	      log_error(_("unable to read external program response: %s\n"),
			strerror(errno));
	      goto fail;
	    }

	  /* Do not cache this iobuf on close */
	  iobuf_ioctl(info->fromchild,3,1,NULL);
	}
    }

  ret=0;

 fail:
  return ret;
}
Exemple #10
0
int
verify_signatures (ctrl_t ctrl, int nfiles, char **files )
{
    IOBUF fp;
    armor_filter_context_t *afx = NULL;
    progress_filter_context_t *pfx = new_progress_context ();
    const char *sigfile;
    int i, rc;
    strlist_t sl;

    /* Decide whether we should handle a detached or a normal signature,
     * which is needed so that the code later can hash the correct data and
     * not have a normal signature act as detached signature and ignoring the
     * indended signed material from the 2nd file or stdin.
     * 1. gpg <file        - normal
     * 2. gpg file         - normal (or detached)
     * 3. gpg file <file2  - detached
     * 4. gpg file file2   - detached
     * The question is how decide between case 2 and 3?  The only way
     * we can do it is by reading one byte from stdin and then unget
     * it; the problem here is that we may be reading from the
     * terminal (which could be detected using isatty() but won't work
     * when under contol of a pty using program (e.g. expect)) and
     * might get us in trouble when stdin is used for another purpose
     * (--passphrase-fd 0).  So we have to break with the behaviour
     * prior to gpg 1.0.4 by assuming that case 3 is a normal
     * signature (where file2 is ignored and require for a detached
     * signature to indicate signed material comes from stdin by using
     * case 4 with a file2 of "-".
     *
     * Actually we don't have to change anything here but can handle
     * that all quite easily in mainproc.c
     */

    sigfile = nfiles? *files : NULL;

    /* open the signature file */
    fp = iobuf_open(sigfile);
    if (fp && is_secured_file (iobuf_get_fd (fp)))
      {
        iobuf_close (fp);
        fp = NULL;
        gpg_err_set_errno (EPERM);
      }
    if( !fp ) {
        rc = gpg_error_from_syserror ();
	log_error(_("can't open '%s': %s\n"),
                  print_fname_stdin(sigfile), gpg_strerror (rc));
        goto leave;
    }
    handle_progress (pfx, fp, sigfile);

    if ( !opt.no_armor && use_armor_filter( fp ) )
      {
        afx = new_armor_context ();
	push_armor_filter (afx, fp);
      }

    sl = NULL;
    for(i=nfiles-1 ; i > 0 ; i-- )
	add_to_strlist( &sl, files[i] );
    rc = proc_signature_packets (ctrl, NULL, fp, sl, sigfile );
    free_strlist(sl);
    iobuf_close(fp);
    if( (afx && afx->no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) {
	log_error(_("the signature could not be verified.\n"
		   "Please remember that the signature file (.sig or .asc)\n"
		   "should be the first file given on the command line.\n") );
	rc = 0;
    }

 leave:
    release_armor_context (afx);
    release_progress_context (pfx);
    return rc;
}
Exemple #11
0
static int
prepare_search (KEYRING_HANDLE hd)
{
    if (hd->current.error) {
        /* If the last key was a legacy key, we simply ignore the error so that
           we can easily use search_next.  */
        if (gpg_err_code (hd->current.error) == GPG_ERR_LEGACY_KEY)
          {
            if (DBG_LOOKUP)
              log_debug ("%s: last error was GPG_ERR_LEGACY_KEY, clearing\n",
                         __func__);
            hd->current.error = 0;
          }
        else
          {
            if (DBG_LOOKUP)
              log_debug ("%s: returning last error: %s\n",
                         __func__, gpg_strerror (hd->current.error));
            return hd->current.error; /* still in error state */
          }
    }

    if (hd->current.kr && !hd->current.eof) {
        if ( !hd->current.iobuf )
          {
            if (DBG_LOOKUP)
              log_debug ("%s: missing iobuf!\n", __func__);
            return GPG_ERR_GENERAL; /* Position invalid after a modify.  */
          }
        return 0; /* okay */
    }

    if (!hd->current.kr && hd->current.eof)
      {
        if (DBG_LOOKUP)
          log_debug ("%s: EOF!\n", __func__);
        return -1; /* still EOF */
      }

    if (!hd->current.kr) { /* start search with first keyring */
        hd->current.kr = hd->resource;
        if (!hd->current.kr) {
          if (DBG_LOOKUP)
            log_debug ("%s: keyring not available!\n", __func__);
          hd->current.eof = 1;
          return -1; /* keyring not available */
        }
        log_assert (!hd->current.iobuf);
    }
    else { /* EOF */
        if (DBG_LOOKUP)
          log_debug ("%s: EOF\n", __func__);
        iobuf_close (hd->current.iobuf);
        hd->current.iobuf = NULL;
        hd->current.kr = NULL;
        hd->current.eof = 1;
        return -1;
    }

    hd->current.eof = 0;
    hd->current.iobuf = iobuf_open (hd->current.kr->fname);
    if (!hd->current.iobuf)
      {
        hd->current.error = gpg_error_from_syserror ();
        log_error(_("can't open '%s'\n"), hd->current.kr->fname );
        return hd->current.error;
      }

    return 0;
}
Exemple #12
0
/*
 * Encrypt the file with the given userids (or ask if none is
 * supplied).  Either FILENAME or FILEFD must be given, but not both.
 * The caller may provide a checked list of public keys in
 * PROVIDED_PKS; if not the function builds a list of keys on its own.
 *
 * Note that FILEFD is currently only used by cmd_encrypt in the
 * not yet finished server.c.
 */
int
encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
               strlist_t remusr, int use_symkey, pk_list_t provided_keys,
               int outputfd)
{
  iobuf_t inp = NULL;
  iobuf_t out = NULL;
  PACKET pkt;
  PKT_plaintext *pt = NULL;
  DEK *symkey_dek = NULL;
  STRING2KEY *symkey_s2k = NULL;
  int rc = 0, rc2 = 0;
  u32 filesize;
  cipher_filter_context_t cfx;
  armor_filter_context_t *afx = NULL;
  compress_filter_context_t zfx;
  text_filter_context_t tfx;
  progress_filter_context_t *pfx;
  PK_LIST pk_list;
  int do_compress;
  int compliant;

  if (filefd != -1 && filename)
    return gpg_error (GPG_ERR_INV_ARG);  /* Both given.  */

  do_compress = !!opt.compress_algo;

  pfx = new_progress_context ();
  memset( &cfx, 0, sizeof cfx);
  memset( &zfx, 0, sizeof zfx);
  memset( &tfx, 0, sizeof tfx);
  init_packet(&pkt);

  if (use_symkey
      && (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
    {
      release_progress_context (pfx);
      return rc;
    }

  if (provided_keys)
    pk_list = provided_keys;
  else
    {
      if ((rc = build_pk_list (ctrl, remusr, &pk_list)))
        {
          release_progress_context (pfx);
          return rc;
        }
    }

  /* Prepare iobufs. */
#ifdef HAVE_W32_SYSTEM
  if (filefd == -1)
    inp = iobuf_open (filename);
  else
    {
      inp = NULL;
      gpg_err_set_errno (ENOSYS);
    }
#else
  if (filefd == GNUPG_INVALID_FD)
    inp = iobuf_open (filename);
  else
    inp = iobuf_fdopen_nc (FD2INT(filefd), "rb");
#endif
  if (inp)
    iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
  if (inp && is_secured_file (iobuf_get_fd (inp)))
    {
      iobuf_close (inp);
      inp = NULL;
      gpg_err_set_errno (EPERM);
    }
  if (!inp)
    {
      char xname[64];

      rc = gpg_error_from_syserror ();
      if (filefd != -1)
        snprintf (xname, sizeof xname, "[fd %d]", filefd);
      else if (!filename)
        strcpy (xname, "[stdin]");
      else
        *xname = 0;
      log_error (_("can't open '%s': %s\n"),
                 *xname? xname : filename, gpg_strerror (rc) );
      goto leave;
    }

  if (opt.verbose)
    log_info (_("reading from '%s'\n"), iobuf_get_fname_nonnull (inp));

  handle_progress (pfx, inp, filename);

  if (opt.textmode)
    iobuf_push_filter (inp, text_filter, &tfx);

  rc = open_outfile (outputfd, filename, opt.armor? 1:0, 0, &out);
  if (rc)
    goto leave;

  if (opt.armor)
    {
      afx = new_armor_context ();
      push_armor_filter (afx, out);
    }

  /* Create a session key. */
  cfx.dek = xmalloc_secure_clear (sizeof *cfx.dek);
  if (!opt.def_cipher_algo)
    {
      /* Try to get it from the prefs.  */
      cfx.dek->algo = select_algo_from_prefs (pk_list, PREFTYPE_SYM, -1, NULL);
      /* The only way select_algo_from_prefs can fail here is when
         mixing v3 and v4 keys, as v4 keys have an implicit preference
         entry for 3DES, and the pk_list cannot be empty.  In this
         case, use 3DES anyway as it's the safest choice - perhaps the
         v3 key is being used in an OpenPGP implementation and we know
         that the implementation behind any v4 key can handle 3DES. */
      if (cfx.dek->algo == -1)
        {
          cfx.dek->algo = CIPHER_ALGO_3DES;
        }

      /* In case 3DES has been selected, print a warning if any key
         does not have a preference for AES.  This should help to
         indentify why encrypting to several recipients falls back to
         3DES. */
      if (opt.verbose && cfx.dek->algo == CIPHER_ALGO_3DES)
        warn_missing_aes_from_pklist (pk_list);
    }
  else
    {
      if (!opt.expert
          && (select_algo_from_prefs (pk_list, PREFTYPE_SYM,
                                      opt.def_cipher_algo, NULL)
              != opt.def_cipher_algo))
        {
          log_info(_("WARNING: forcing symmetric cipher %s (%d)"
                     " violates recipient preferences\n"),
                   openpgp_cipher_algo_name (opt.def_cipher_algo),
                   opt.def_cipher_algo);
        }

      cfx.dek->algo = opt.def_cipher_algo;
    }

  /* Check compliance.  */
  if (! gnupg_cipher_is_allowed (opt.compliance, 1, cfx.dek->algo,
                                 GCRY_CIPHER_MODE_CFB))
    {
      log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
		 openpgp_cipher_algo_name (cfx.dek->algo),
		 gnupg_compliance_option_string (opt.compliance));
      rc = gpg_error (GPG_ERR_CIPHER_ALGO);
      goto leave;
    }

  if (!gnupg_rng_is_compliant (opt.compliance))
    {
      rc = gpg_error (GPG_ERR_FORBIDDEN);
      log_error (_("%s is not compliant with %s mode\n"),
                 "RNG",
                 gnupg_compliance_option_string (opt.compliance));
      write_status_error ("random-compliance", rc);
      goto leave;
    }

  compliant = gnupg_cipher_is_compliant (CO_DE_VS, cfx.dek->algo,
                                         GCRY_CIPHER_MODE_CFB);

  {
    pk_list_t pkr;

    for (pkr = pk_list; pkr; pkr = pkr->next)
      {
        PKT_public_key *pk = pkr->pk;
        unsigned int nbits = nbits_from_pk (pk);

        if (!gnupg_pk_is_compliant (opt.compliance,
                                    pk->pubkey_algo, pk->pkey, nbits, NULL))
          log_info (_("WARNING: key %s is not suitable for encryption"
                      " in %s mode\n"),
                    keystr_from_pk (pk),
                    gnupg_compliance_option_string (opt.compliance));

        if (compliant
            && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
                                       nbits, NULL))
          compliant = 0;
      }

  }

  if (compliant)
    write_status_strings (STATUS_ENCRYPTION_COMPLIANCE_MODE,
                          gnupg_status_compliance_flag (CO_DE_VS),
                          NULL);

  cfx.dek->use_aead = use_aead (pk_list, cfx.dek->algo);
  if (!cfx.dek->use_aead)
    cfx.dek->use_mdc = !!use_mdc (pk_list, cfx.dek->algo);

  /* Only do the is-file-already-compressed check if we are using a
   * MDC or AEAD.  This forces compressed files to be re-compressed if
   * we do not have a MDC to give some protection against chosen
   * ciphertext attacks. */
  if (do_compress
      && (cfx.dek->use_mdc || cfx.dek->use_aead)
      && is_file_compressed (filename, &rc2))
    {
      if (opt.verbose)
        log_info(_("'%s' already compressed\n"), filename);
      do_compress = 0;
    }
  if (rc2)
    {
      rc = rc2;
      goto leave;
    }

  make_session_key (cfx.dek);
  if (DBG_CRYPTO)
    log_printhex (cfx.dek->key, cfx.dek->keylen, "DEK is: ");

  rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out);
  if (rc)
    goto leave;

  /* We put the passphrase (if any) after any public keys as this
   * seems to be the most useful on the recipient side - there is no
   * point in prompting a user for a passphrase if they have the
   * secret key needed to decrypt.  */
  if (use_symkey && (rc = write_symkey_enc (symkey_s2k, cfx.dek->use_aead,
                                            symkey_dek, cfx.dek, out)))
    goto leave;

  if (!opt.no_literal)
    pt = setup_plaintext_name (filename, inp);

  /* Get the size of the file if possible, i.e., if it is a real file.  */
  if (filename && *filename
      && !iobuf_is_pipe_filename (filename) && !opt.textmode )
    {
      off_t tmpsize;
      int overflow;

      if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
           && !overflow && opt.verbose)
        log_info(_("WARNING: '%s' is an empty file\n"), filename );
      /* We can't encode the length of very large files because
         OpenPGP uses only 32 bit for file sizes.  So if the size
         of a file is larger than 2^32 minus some bytes for packet
         headers, we switch to partial length encoding. */
      if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
        filesize = tmpsize;
      else
        filesize = 0;
    }
  else
    filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */

  if (!opt.no_literal)
    {
      pt->timestamp = make_timestamp();
      pt->mode = opt.mimemode? 'm' : opt.textmode ? 't' : 'b';
      pt->len = filesize;
      pt->new_ctb = !pt->len;
      pt->buf = inp;
      pkt.pkttype = PKT_PLAINTEXT;
      pkt.pkt.plaintext = pt;
      cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
    }
  else
    cfx.datalen = filesize && !do_compress ? filesize : 0;

  /* Register the cipher filter. */
  iobuf_push_filter (out,
                     cfx.dek->use_aead? cipher_filter_aead
                     /**/             : cipher_filter_cfb,
                     &cfx);

  /* Register the compress filter. */
  if (do_compress)
    {
      int compr_algo = opt.compress_algo;

      if (compr_algo == -1)
        {
          compr_algo = select_algo_from_prefs (pk_list, PREFTYPE_ZIP, -1, NULL);
          if (compr_algo == -1)
            compr_algo = DEFAULT_COMPRESS_ALGO;
          /* Theoretically impossible to get here since uncompressed
             is implicit.  */
        }
      else if (!opt.expert
               && select_algo_from_prefs(pk_list, PREFTYPE_ZIP,
                                         compr_algo, NULL) != compr_algo)
        {
          log_info (_("WARNING: forcing compression algorithm %s (%d)"
                      " violates recipient preferences\n"),
                    compress_algo_to_string(compr_algo), compr_algo);
        }

      /* Algo 0 means no compression. */
      if (compr_algo)
        {
          if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead))
            zfx.new_ctb = 1;
          push_compress_filter (out,&zfx,compr_algo);
        }
    }

  /* Do the work. */
  if (!opt.no_literal)
    {
      if ((rc = build_packet( out, &pkt )))
        log_error ("build_packet failed: %s\n", gpg_strerror (rc));
    }
  else
    {
      /* User requested not to create a literal packet, so we copy the
         plain data. */
      byte copy_buffer[4096];
      int  bytes_copied;
      while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
        {
          rc = iobuf_write (out, copy_buffer, bytes_copied);
          if (rc)
            {
              log_error ("copying input to output failed: %s\n",
                         gpg_strerror (rc));
              break;
            }
        }
      wipememory (copy_buffer, 4096); /* Burn the buffer. */
    }

  /* Finish the stuff. */
 leave:
  iobuf_close (inp);
  if (rc)
    iobuf_cancel (out);
  else
    {
      iobuf_close (out); /* fixme: check returncode */
      write_status (STATUS_END_ENCRYPTION);
    }
  if (pt)
    pt->buf = NULL;
  free_packet (&pkt, NULL);
  xfree (cfx.dek);
  xfree (symkey_dek);
  xfree (symkey_s2k);
  if (!provided_keys)
    release_pk_list (pk_list);
  release_armor_context (afx);
  release_progress_context (pfx);
  return rc;
}
Exemple #13
0
/* We don't want to use use_seskey yet because older gnupg versions
   can't handle it, and there isn't really any point unless we're
   making a message that can be decrypted by a public key or
   passphrase. */
static int
encrypt_simple (const char *filename, int mode, int use_seskey)
{
  iobuf_t inp, out;
  PACKET pkt;
  PKT_plaintext *pt = NULL;
  STRING2KEY *s2k = NULL;
  void *enckey = NULL;
  size_t enckeylen = 0;
  int rc = 0;
  u32 filesize;
  cipher_filter_context_t cfx;
  armor_filter_context_t  *afx = NULL;
  compress_filter_context_t zfx;
  text_filter_context_t tfx;
  progress_filter_context_t *pfx;
  int do_compress = !!default_compress_algo();

  if (!gnupg_rng_is_compliant (opt.compliance))
    {
      rc = gpg_error (GPG_ERR_FORBIDDEN);
      log_error (_("%s is not compliant with %s mode\n"),
                 "RNG",
                 gnupg_compliance_option_string (opt.compliance));
      write_status_error ("random-compliance", rc);
      return rc;
    }

  pfx = new_progress_context ();
  memset( &cfx, 0, sizeof cfx);
  memset( &zfx, 0, sizeof zfx);
  memset( &tfx, 0, sizeof tfx);
  init_packet(&pkt);

  /* Prepare iobufs. */
  inp = iobuf_open(filename);
  if (inp)
    iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
  if (inp && is_secured_file (iobuf_get_fd (inp)))
    {
      iobuf_close (inp);
      inp = NULL;
      gpg_err_set_errno (EPERM);
    }
  if (!inp)
    {
      rc = gpg_error_from_syserror ();
      log_error(_("can't open '%s': %s\n"), filename? filename: "[stdin]",
                strerror(errno) );
      release_progress_context (pfx);
      return rc;
    }

  handle_progress (pfx, inp, filename);

  if (opt.textmode)
    iobuf_push_filter( inp, text_filter, &tfx );

  cfx.dek = NULL;
  if ( mode )
    {
      int canceled;
      aead_algo_t aead_algo;

      s2k = xmalloc_clear( sizeof *s2k );
      s2k->mode = opt.s2k_mode;
      s2k->hash_algo = S2K_DIGEST_ALGO;
      cfx.dek = passphrase_to_dek (default_cipher_algo (), s2k, 1, 0,
                                   NULL, &canceled);
      if ( !cfx.dek || !cfx.dek->keylen )
        {
          rc = gpg_error (canceled? GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE);
          xfree (cfx.dek);
          xfree (s2k);
          iobuf_close (inp);
          log_error (_("error creating passphrase: %s\n"), gpg_strerror (rc));
          release_progress_context (pfx);
          return rc;
        }
      if (use_seskey && s2k->mode != 1 && s2k->mode != 3)
        {
          use_seskey = 0;
          log_info (_("can't use a symmetric ESK packet "
                      "due to the S2K mode\n"));
        }

      /* See whether we want to use AEAD.  */
      aead_algo = use_aead (NULL, cfx.dek->algo);

      if ( use_seskey )
        {
          DEK *dek = NULL;

          rc = encrypt_seskey (cfx.dek, aead_algo, &dek, &enckey, &enckeylen);
          if (rc)
            {
              xfree (cfx.dek);
              xfree (s2k);
              iobuf_close (inp);
              release_progress_context (pfx);
              return rc;
            }
          /* Replace key in DEK.  */
          xfree (cfx.dek);
          cfx.dek = dek;
        }

      if (aead_algo)
        cfx.dek->use_aead = aead_algo;
      else
        cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo);

      if (opt.verbose)
        log_info(_("using cipher %s.%s\n"),
                 openpgp_cipher_algo_name (cfx.dek->algo),
                 cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead)
                 /**/             : "CFB");
    }

  if (do_compress
      && cfx.dek
      && (cfx.dek->use_mdc || cfx.dek->use_aead)
      && is_file_compressed(filename, &rc))
    {
      if (opt.verbose)
        log_info(_("'%s' already compressed\n"), filename);
      do_compress = 0;
    }

  if ( rc || (rc = open_outfile (-1, filename, opt.armor? 1:0, 0, &out )))
    {
      iobuf_cancel (inp);
      xfree (cfx.dek);
      xfree (s2k);
      release_progress_context (pfx);
      return rc;
    }

  if ( opt.armor )
    {
      afx = new_armor_context ();
      push_armor_filter (afx, out);
    }

  if ( s2k )
    {
      /* Fixme: This is quite similar to write_symkey_enc.  */
      PKT_symkey_enc *enc = xmalloc_clear (sizeof *enc + enckeylen);
      enc->version = cfx.dek->use_aead ? 5 : 4;
      enc->cipher_algo = cfx.dek->algo;
      enc->aead_algo = cfx.dek->use_aead;
      enc->s2k = *s2k;
      if (enckeylen)
        {
          enc->seskeylen = enckeylen;
          memcpy (enc->seskey, enckey, enckeylen);
        }
      pkt.pkttype = PKT_SYMKEY_ENC;
      pkt.pkt.symkey_enc = enc;
      if ((rc = build_packet( out, &pkt )))
        log_error("build symkey packet failed: %s\n", gpg_strerror (rc) );
      xfree (enc);
      xfree (enckey);
      enckey = NULL;
    }

  if (!opt.no_literal)
    pt = setup_plaintext_name (filename, inp);

  /* Note that PGP 5 has problems decrypting symmetrically encrypted
     data if the file length is in the inner packet. It works when
     only partial length headers are use.  In the past, we always used
     partial body length here, but since PGP 2, PGP 6, and PGP 7 need
     the file length, and nobody should be using PGP 5 nowadays
     anyway, this is now set to the file length.  Note also that this
     only applies to the RFC-1991 style symmetric messages, and not
     the RFC-2440 style.  PGP 6 and 7 work with either partial length
     or fixed length with the new style messages. */

  if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
    {
      off_t tmpsize;
      int overflow;

      if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
           && !overflow && opt.verbose)
        log_info(_("WARNING: '%s' is an empty file\n"), filename );
      /* We can't encode the length of very large files because
         OpenPGP uses only 32 bit for file sizes.  So if the
         size of a file is larger than 2^32 minus some bytes for
         packet headers, we switch to partial length encoding. */
      if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
        filesize = tmpsize;
      else
        filesize = 0;
    }
  else
    filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */

  if (!opt.no_literal)
    {
      /* Note that PT has been initialized above in !no_literal mode.  */
      pt->timestamp = make_timestamp();
      pt->mode = opt.mimemode? 'm' : opt.textmode? 't' : 'b';
      pt->len = filesize;
      pt->new_ctb = !pt->len;
      pt->buf = inp;
      pkt.pkttype = PKT_PLAINTEXT;
      pkt.pkt.plaintext = pt;
      cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
    }
  else
    {
      cfx.datalen = filesize && !do_compress ? filesize : 0;
      pkt.pkttype = 0;
      pkt.pkt.generic = NULL;
    }

  /* Register the cipher filter. */
  if (mode)
    iobuf_push_filter (out,
                       cfx.dek->use_aead? cipher_filter_aead
                       /**/             : cipher_filter_cfb,
                       &cfx );

  /* Register the compress filter. */
  if ( do_compress )
    {
      if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead))
        zfx.new_ctb = 1;
      push_compress_filter (out, &zfx, default_compress_algo());
    }

  /* Do the work. */
  if (!opt.no_literal)
    {
      if ( (rc = build_packet( out, &pkt )) )
        log_error("build_packet failed: %s\n", gpg_strerror (rc) );
    }
  else
    {
      /* User requested not to create a literal packet, so we copy the
         plain data.  */
    byte copy_buffer[4096];
    int  bytes_copied;
    while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
      if ( (rc=iobuf_write(out, copy_buffer, bytes_copied)) ) {
        log_error ("copying input to output failed: %s\n",
                   gpg_strerror (rc) );
        break;
      }
    wipememory (copy_buffer, 4096); /* burn buffer */
    }

  /* Finish the stuff.  */
  iobuf_close (inp);
  if (rc)
    iobuf_cancel(out);
  else
    {
      iobuf_close (out); /* fixme: check returncode */
      if (mode)
        write_status ( STATUS_END_ENCRYPTION );
    }
  if (pt)
    pt->buf = NULL;
  free_packet (&pkt, NULL);
  xfree (enckey);
  xfree (cfx.dek);
  xfree (s2k);
  release_armor_context (afx);
  release_progress_context (pfx);
  return rc;
}
Exemple #14
0
/*
 * Return the last found keyring.  Caller must free it.
 * The returned keyblock has the kbode flag bit 0 set for the node with
 * the public key used to locate the keyblock or flag bit 1 set for
 * the user ID node.
 */
int
keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
    PACKET *pkt;
    int rc;
    KBNODE keyblock = NULL, node, lastnode;
    IOBUF a;
    int in_cert = 0;
    int pk_no = 0;
    int uid_no = 0;
    int save_mode;

    if (ret_kb)
        *ret_kb = NULL;

    if (!hd->found.kr)
        return -1; /* no successful search */

    a = iobuf_open (hd->found.kr->fname);
    if (!a)
      {
	log_error(_("can't open `%s'\n"), hd->found.kr->fname);
	return G10ERR_KEYRING_OPEN;
      }

    if (iobuf_seek (a, hd->found.offset) ) {
        log_error ("can't seek `%s'\n", hd->found.kr->fname);
	iobuf_close(a);
	return G10ERR_KEYRING_OPEN;
    }

    pkt = xmalloc (sizeof *pkt);
    init_packet (pkt);
    hd->found.n_packets = 0;;
    lastnode = NULL;
    save_mode = set_packet_list_mode(0);
    while ((rc=parse_packet (a, pkt)) != -1) {
        hd->found.n_packets++;
        if (rc == G10ERR_UNKNOWN_PACKET) {
	    free_packet (pkt);
	    init_packet (pkt);
	    continue;
	}
	if (rc) {
            log_error ("keyring_get_keyblock: read error: %s\n",
                       g10_errstr(rc) );
            rc = G10ERR_INV_KEYRING;
            break;
        }

        /* Filter allowed packets.  */
        switch (pkt->pkttype){
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
          case PKT_USER_ID:
          case PKT_ATTRIBUTE:
          case PKT_SIGNATURE:
            break; /* Allowed per RFC.  */
          case PKT_RING_TRUST:
          case PKT_OLD_COMMENT:
          case PKT_COMMENT:
          case PKT_GPG_CONTROL:
            break; /* Allowed by us.  */

          default:
	    log_error ("skipped packet of type %d in keyring\n",
                       (int)pkt->pkttype);
	    free_packet(pkt);
	    init_packet(pkt);
	    continue;
        }

        if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                        || pkt->pkttype == PKT_SECRET_KEY)) {
            hd->found.n_packets--; /* fix counter */
            break; /* ready */
        }

        in_cert = 1;
        if (pkt->pkttype == PKT_RING_TRUST)
          {
            /*(this code is duplicated after the loop)*/
            if ( lastnode
                 && lastnode->pkt->pkttype == PKT_SIGNATURE
                 && (pkt->pkt.ring_trust->sigcache & 1) ) {
                /* This is a ring trust packet with a checked signature
                 * status cache following directly a signature paket.
                 * Set the cache status into that signature packet.
                 *
                 * We do not use cached signatures made with MD5 to
                 * avoid using a cached status created with an older
                 * version of gpg.  */
                PKT_signature *sig = lastnode->pkt->pkt.signature;

                if (sig->digest_algo != DIGEST_ALGO_MD5)
                  {
                    sig->flags.checked = 1;
                    sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
                  }
            }
            /* Reset LASTNODE, so that we set the cache status only from
             * the ring trust packet immediately following a signature. */
            lastnode = NULL;
	    free_packet(pkt);
	    init_packet(pkt);
	    continue;
          }


        node = lastnode = new_kbnode (pkt);
        if (!keyblock)
          keyblock = node;
        else
          add_kbnode (keyblock, node);
        switch (pkt->pkttype)
          {
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
            if (++pk_no == hd->found.pk_no)
              node->flag |= 1;
            break;

          case PKT_USER_ID:
            if (++uid_no == hd->found.uid_no)
              node->flag |= 2;
            break;

          default:
            break;
          }

        pkt = xmalloc (sizeof *pkt);
        init_packet(pkt);
    }
    set_packet_list_mode(save_mode);

    if (rc == -1 && keyblock)
	rc = 0; /* got the entire keyblock */

    if (rc || !ret_kb)
	release_kbnode (keyblock);
    else {
        /*(duplicated from the loop body)*/
        if ( pkt && pkt->pkttype == PKT_RING_TRUST
             && lastnode
             && lastnode->pkt->pkttype == PKT_SIGNATURE
             && (pkt->pkt.ring_trust->sigcache & 1) ) {
            PKT_signature *sig = lastnode->pkt->pkt.signature;
            if (sig->digest_algo != DIGEST_ALGO_MD5)
              {
                sig->flags.checked = 1;
                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
              }
        }
	*ret_kb = keyblock;
    }
    free_packet (pkt);
    xfree (pkt);
    iobuf_close(a);

    /* Make sure that future search operations fail immediately when
     * we know that we are working on a invalid keyring
     */
    if (rc == G10ERR_INV_KEYRING)
        hd->current.error = rc;

    return rc;
}
Exemple #15
0
/* Generate a new photo id packet, or return NULL if canceled.
   FIXME:  Should we add a duplicates check similar to generate_user_id? */
PKT_user_id *
generate_photo_id(PKT_public_key *pk,const char *photo_name)
{
  PKT_user_id *uid;
  int error=1,i;
  unsigned int len;
  char *filename;
  byte *photo=NULL;
  byte header[16];
  IOBUF file;
  int overflow;

  header[0]=0x10; /* little side of photo header length */
  header[1]=0;    /* big side of photo header length */
  header[2]=1;    /* 1 == version of photo header */
  header[3]=1;    /* 1 == JPEG */

  for(i=4;i<16;i++) /* The reserved bytes */
    header[i]=0;

#define EXTRA_UID_NAME_SPACE 71
  uid=xmalloc_clear(sizeof(*uid)+71);

  if(photo_name && *photo_name)
    filename=make_filename(photo_name,(void *)NULL);
  else
    {
      tty_printf(_("\nPick an image to use for your photo ID."
		   "  The image must be a JPEG file.\n"
		   "Remember that the image is stored within your public key."
		   "  If you use a\n"
		   "very large picture, your key will become very large"
		   " as well!\n"
		   "Keeping the image close to 240x288 is a good size"
		   " to use.\n"));
      filename=NULL;
    }

  while(photo==NULL)
    {
      if(filename==NULL)
	{
	  char *tempname;

	  tty_printf("\n");

	  tty_enable_completion(NULL);

	  tempname=cpr_get("photoid.jpeg.add",
			   _("Enter JPEG filename for photo ID: "));

	  tty_disable_completion();

	  filename=make_filename(tempname,(void *)NULL);

	  xfree(tempname);

	  if(strlen(filename)==0)
	    goto scram;
	}

      file=iobuf_open(filename);
      if (file && is_secured_file (iobuf_get_fd (file)))
        {
          iobuf_close (file);
          file = NULL;
          errno = EPERM;
        }
      if(!file)
	{
	  log_error(_("unable to open JPEG file `%s': %s\n"),
		    filename,strerror(errno));
	  xfree(filename);
	  filename=NULL;
	  continue;
	}

      
      len=iobuf_get_filelength(file, &overflow);
      if(len>6144 || overflow)
	{
	  tty_printf( _("This JPEG is really large (%d bytes) !\n"),len);
	  if(!cpr_get_answer_is_yes("photoid.jpeg.size",
			    _("Are you sure you want to use it? (y/N) ")))
	  {
	    iobuf_close(file);
	    xfree(filename);
	    filename=NULL;
	    continue;
	  }
	}

      photo=xmalloc(len);
      iobuf_read(file,photo,len);
      iobuf_close(file);

      /* Is it a JPEG? */
      if(photo[0]!=0xFF || photo[1]!=0xD8 ||
	 photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F')
	{
	  log_error(_("`%s' is not a JPEG file\n"),filename);
	  xfree(photo);
	  photo=NULL;
	  xfree(filename);
	  filename=NULL;
	  continue;
	}

      /* Build the packet */
      build_attribute_subpkt(uid,1,photo,len,header,16);
      parse_attribute_subpkts(uid);
      make_attribute_uidname(uid, EXTRA_UID_NAME_SPACE);

      /* Showing the photo is not safe when noninteractive since the
         "user" may not be able to dismiss a viewer window! */
      if(opt.command_fd==-1)
	{
	  show_photos(uid->attribs,uid->numattribs,pk,NULL,uid);
	  switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
					 _("Is this photo correct (y/N/q)? ")))
	    {
	    case -1:
	      goto scram;
	    case 0:
	      free_attributes(uid);
	      xfree(photo);
	      photo=NULL;
	      xfree(filename);
	      filename=NULL;
	      continue;
	    }
	}
    }

  error=0;
  uid->ref=1;

 scram:
  xfree(filename);
  xfree(photo);

  if(error)
    {
      free_attributes(uid);
      xfree(uid);
      return NULL;
    }

  return uid;
}
/*
 * Return the last found keyring.  Caller must free it.
 * The returned keyblock has the kbode flag bit 0 set for the node with
 * the public key used to locate the keyblock or flag bit 1 set for 
 * the user ID node.
 */
int
keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
    PACKET *pkt;
    int rc;
    KBNODE keyblock = NULL, node, lastnode;
    IOBUF a;
    int in_cert = 0;
    int pk_no = 0;
    int uid_no = 0;
    int save_mode;

    if (ret_kb)
        *ret_kb = NULL;

    if (!hd->found.kr)
        return -1; /* no successful search */

    a = iobuf_open (hd->found.kr->fname);
    if (!a)
      {
	log_error(_("can't open `%s'\n"), hd->found.kr->fname);
	return G10ERR_KEYRING_OPEN;
      }

    if (iobuf_seek (a, hd->found.offset) ) {
        log_error ("can't seek `%s'\n", hd->found.kr->fname);
	iobuf_close(a);
	return G10ERR_KEYRING_OPEN;
    }

    pkt = xmalloc (sizeof *pkt);
    init_packet (pkt);
    hd->found.n_packets = 0;;
    lastnode = NULL;
    save_mode = set_packet_list_mode(0);
    while ((rc=parse_packet (a, pkt)) != -1) {
        hd->found.n_packets++;
        if (rc == G10ERR_UNKNOWN_PACKET) {
	    free_packet (pkt);
	    init_packet (pkt);
	    continue;
	}
	if (rc) {  
            log_error ("keyring_get_keyblock: read error: %s\n",
                       g10_errstr(rc) );
            rc = G10ERR_INV_KEYRING;
            break;
        }
	if (pkt->pkttype == PKT_COMPRESSED) {
	    log_error ("skipped compressed packet in keyring\n");
	    free_packet(pkt);
	    init_packet(pkt);
	    continue;
        }

        if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                        || pkt->pkttype == PKT_SECRET_KEY)) {
            hd->found.n_packets--; /* fix counter */
            break; /* ready */
        }

        in_cert = 1;
        if (pkt->pkttype == PKT_RING_TRUST) {
            /*(this code is duplicated after the loop)*/
            if ( lastnode 
                 && lastnode->pkt->pkttype == PKT_SIGNATURE
                 && (pkt->pkt.ring_trust->sigcache & 1) ) {
                /* this is a ring trust packet with a checked signature 
                 * status cache following directly a signature paket.
                 * Set the cache status into that signature packet */
                PKT_signature *sig = lastnode->pkt->pkt.signature;
                
                sig->flags.checked = 1;
                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
            }
            /* reset lastnode, so that we set the cache status only from
             * the ring trust packet immediately folling a signature */
            lastnode = NULL;
        }
        else {
            node = lastnode = new_kbnode (pkt);
            if (!keyblock)
                keyblock = node;
            else
                add_kbnode (keyblock, node);

            if ( pkt->pkttype == PKT_PUBLIC_KEY
                 || pkt->pkttype == PKT_PUBLIC_SUBKEY
                 || pkt->pkttype == PKT_SECRET_KEY
                 || pkt->pkttype == PKT_SECRET_SUBKEY) {
                if (++pk_no == hd->found.pk_no)
                    node->flag |= 1;
            }
            else if ( pkt->pkttype == PKT_USER_ID) {
                if (++uid_no == hd->found.uid_no)
                    node->flag |= 2;
            }
        }

        pkt = xmalloc (sizeof *pkt);
        init_packet(pkt);
    }
    set_packet_list_mode(save_mode);

    if (rc == -1 && keyblock) 
	rc = 0; /* got the entire keyblock */

    if (rc || !ret_kb)
	release_kbnode (keyblock);
    else {
        /*(duplicated form the loop body)*/
        if ( pkt && pkt->pkttype == PKT_RING_TRUST
             && lastnode 
             && lastnode->pkt->pkttype == PKT_SIGNATURE
             && (pkt->pkt.ring_trust->sigcache & 1) ) {
            PKT_signature *sig = lastnode->pkt->pkt.signature;
            sig->flags.checked = 1;
            sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
        }
	*ret_kb = keyblock;
    }
    free_packet (pkt);
    xfree (pkt);
    iobuf_close(a);

    /* Make sure that future search operations fail immediately when
     * we know that we are working on a invalid keyring 
     */
    if (rc == G10ERR_INV_KEYRING)
        hd->current.error = rc;

    return rc;
}
Exemple #17
0
/*
 * Return the last found keyblock.  Caller must free it.
 * The returned keyblock has the kbode flag bit 0 set for the node with
 * the public key used to locate the keyblock or flag bit 1 set for
 * the user ID node.
 */
int
keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
    PACKET *pkt;
    struct parse_packet_ctx_s parsectx;
    int rc;
    KBNODE keyblock = NULL, node, lastnode;
    IOBUF a;
    int in_cert = 0;
    int pk_no = 0;
    int uid_no = 0;
    int save_mode;

    if (ret_kb)
        *ret_kb = NULL;

    if (!hd->found.kr)
        return -1; /* no successful search */

    a = iobuf_open (hd->found.kr->fname);
    if (!a)
      {
	log_error(_("can't open '%s'\n"), hd->found.kr->fname);
	return GPG_ERR_KEYRING_OPEN;
      }

    if (iobuf_seek (a, hd->found.offset) ) {
        log_error ("can't seek '%s'\n", hd->found.kr->fname);
	iobuf_close(a);
	return GPG_ERR_KEYRING_OPEN;
    }

    pkt = xmalloc (sizeof *pkt);
    init_packet (pkt);
    init_parse_packet (&parsectx, a);
    hd->found.n_packets = 0;
    lastnode = NULL;
    save_mode = set_packet_list_mode(0);
    while ((rc=parse_packet (&parsectx, pkt)) != -1) {
        hd->found.n_packets = parsectx.n_parsed_packets;
        if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
	    free_packet (pkt, &parsectx);
	    init_packet (pkt);
	    continue;
	}
        if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
          {
            if (in_cert)
              /* It is not this key that is problematic, but the
                 following key.  */
              {
                rc = 0;
                hd->found.n_packets --;
              }
            else
              /* Upper layer needs to handle this.  */
              {
              }
            break;
          }
	if (rc) {
            log_error ("keyring_get_keyblock: read error: %s\n",
                       gpg_strerror (rc) );
            rc = GPG_ERR_INV_KEYRING;
            break;
        }

        /* Filter allowed packets.  */
        switch (pkt->pkttype)
          {
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
          case PKT_USER_ID:
          case PKT_ATTRIBUTE:
          case PKT_SIGNATURE:
            break; /* Allowed per RFC.  */
          case PKT_RING_TRUST:
          case PKT_OLD_COMMENT:
          case PKT_COMMENT:
          case PKT_GPG_CONTROL:
            break; /* Allowed by us.  */

          default:
	    log_info ("skipped packet of type %d in keyring\n",
                      (int)pkt->pkttype);
	    free_packet(pkt, &parsectx);
	    init_packet(pkt);
	    continue;
          }

        if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                        || pkt->pkttype == PKT_SECRET_KEY)) {
            hd->found.n_packets--; /* fix counter */
            break; /* ready */
        }

        in_cert = 1;
        node = lastnode = new_kbnode (pkt);
        if (!keyblock)
          keyblock = node;
        else
          add_kbnode (keyblock, node);
        switch (pkt->pkttype)
          {
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
            if (++pk_no == hd->found.pk_no)
              node->flag |= 1;
            break;

          case PKT_USER_ID:
            if (++uid_no == hd->found.uid_no)
              node->flag |= 2;
            break;

          default:
            break;
          }

        pkt = xmalloc (sizeof *pkt);
        init_packet(pkt);
    }
    set_packet_list_mode(save_mode);

    if (rc == -1 && keyblock)
	rc = 0; /* got the entire keyblock */

    if (rc || !ret_kb)
	release_kbnode (keyblock);
    else {
        *ret_kb = keyblock;
    }
    free_packet (pkt, &parsectx);
    deinit_parse_packet (&parsectx);
    xfree (pkt);
    iobuf_close(a);

    /* Make sure that future search operations fail immediately when
     * we know that we are working on a invalid keyring
     */
    if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING)
        hd->current.error = rc;

    return rc;
}