static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) { int rc = 0; IOBUF a = iobuf_temp(); assert( enc->version == 4 ); switch( enc->s2k.mode ) { case 0: case 1: case 3: break; default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); } iobuf_put( a, enc->version ); iobuf_put( a, enc->cipher_algo ); iobuf_put( a, enc->s2k.mode ); iobuf_put( a, enc->s2k.hash_algo ); if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) { iobuf_write(a, enc->s2k.salt, 8 ); if( enc->s2k.mode == 3 ) iobuf_put(a, enc->s2k.count); } if( enc->seskeylen ) iobuf_write(a, enc->seskey, enc->seskeylen ); write_header(out, ctb, iobuf_get_temp_length(a) ); rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; }
/* * Write the mpi A to OUT. */ gpg_error_t gpg_mpi_write (iobuf_t out, gcry_mpi_t a) { int rc; if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { unsigned int nbits; const void *p; p = gcry_mpi_get_opaque (a, &nbits); rc = iobuf_write (out, p, (nbits+7)/8); } else { char buffer[(MAX_EXTERN_MPI_BITS+7)/8+2]; /* 2 is for the mpi length. */ size_t nbytes; nbytes = DIM(buffer); rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); if( !rc ) rc = iobuf_write( out, buffer, nbytes ); else if (gpg_err_code(rc) == GPG_ERR_TOO_SHORT ) { log_info ("mpi too large (%u bits)\n", gcry_mpi_get_nbits (a)); /* The buffer was too small. We better tell the user about the MPI. */ rc = gpg_error (GPG_ERR_TOO_LARGE); } } return rc; }
/**************** * This filter is used to en/de-cipher data with a conventional algorithm */ int cipher_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; cipher_filter_context_t *cfx = opaque; int rc=0; if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */ rc = -1; /* not yet used */ } else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ assert(a); if( !cfx->header ) { write_header( cfx, a ); } if( cfx->mdc_hash ) md_write( cfx->mdc_hash, buf, size ); cipher_encrypt( cfx->cipher_hd, buf, buf, size); if( iobuf_write( a, buf, size ) ) rc = G10ERR_WRITE_FILE; } else if( control == IOBUFCTRL_FREE ) { if( cfx->mdc_hash ) { byte *hash; int hashlen = md_digest_length( md_get_algo( cfx->mdc_hash ) ); byte temp[22]; assert( hashlen == 20 ); /* we must hash the prefix of the MDC packet here */ temp[0] = 0xd3; temp[1] = 0x14; md_putc( cfx->mdc_hash, temp[0] ); md_putc( cfx->mdc_hash, temp[1] ); md_final( cfx->mdc_hash ); hash = md_read( cfx->mdc_hash, 0 ); memcpy(temp+2, hash, 20); cipher_encrypt( cfx->cipher_hd, temp, temp, 22 ); md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL; if( iobuf_write( a, temp, 22 ) ) log_error("writing MDC packet failed\n" ); } cipher_close(cfx->cipher_hd); } else if( control == IOBUFCTRL_DESC ) { *(char**)buf = "cipher_filter"; } return rc; }
static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { if( uid->photo ) { write_header(out, ctb, uid->photolen); if( iobuf_write( out, uid->photo, uid->photolen ) ) return G10ERR_WRITE_FILE; } else { write_header(out, ctb, uid->len); if( iobuf_write( out, uid->name, uid->len ) ) return G10ERR_WRITE_FILE; } return 0; }
static void handle_proxy_request(struct proxy_request *conn, int client_fd) { if (conn->fd <= 0) errx(EXIT_FAILURE, "no proxy socket"); printf("SENDING: "); fflush(stdout); iobuf_write(&conn->request, STDOUT_FILENO); /* write out header */ iobuf_write(&conn->request, conn->fd); copydata(conn->fd, client_fd); close(conn->fd); }
/* XXX: hacktastic but should return a valid file from pacman's cache */ static void handle_file_request(const char *path, int client_fd) { struct iobuf buf; struct stat st; int ret; iobuf_init(&buf, 10); iobuf_append(&buf, "HTTP/1.1 ", 9); iobuf_append(&buf, "200 ", 4); iobuf_append(&buf, "OK\r\n", 4); _cleanup_free_ char *filename = joinpath(".", path, NULL); _cleanup_free_ char *content_length = NULL; _cleanup_close_ int fd = open(filename, O_RDONLY); if (fd < 0) err(EXIT_FAILURE, "couldn't access %s", filename); fstat(fd, &st); ssize_t nbytes_w = asprintf(&content_length, "%s: %zd\r\n", "Content-Length", st.st_size); if (nbytes_w < 0) err(1, "failed to allocate memory for Content-Length"); iobuf_append(&buf, content_length, nbytes_w); iobuf_append(&buf, "\r\n", 2); /* write out header */ iobuf_write(&buf, client_fd); ret = sendfile(client_fd, fd, NULL, st.st_size); if (ret < 0) err(EXIT_FAILURE, "failed to send file %s across socket", filename); }
static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) { int i, rc = 0; u32 n; byte buf[1000]; /* this buffer has the plaintext! */ int nbytes; write_header(out, ctb, calc_plaintext( pt ) ); iobuf_put(out, pt->mode ); iobuf_put(out, pt->namelen ); for(i=0; i < pt->namelen; i++ ) iobuf_put(out, pt->name[i] ); rc = write_32(out, pt->timestamp ); if (rc) return rc; n = 0; while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { rc = iobuf_write (out, buf, nbytes); if (rc) break; n += nbytes; } wipememory(buf,1000); /* burn the buffer */ if( (ctb&0x40) && !pt->len ) iobuf_set_partial_block_mode(out, 0 ); /* turn off partial */ if( pt->len && n != pt->len ) log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", (ulong)n, (ulong)pt->len ); return rc; }
/* * Write the sexp A to OUT. */ static int sexp_write (iobuf_t out, gcry_sexp_t a) { int max_len = 2000; char buffer[max_len]; size_t nbytes; int rc; int len; len = gcry_sexp_sprint (a, 1, buffer, max_len); printf("after sexp sprint %d \n", len); if( len!=0 ) { nbytes = 0; while(buffer[nbytes]!=0) { printf("%c",buffer[nbytes]); nbytes++; } rc = iobuf_write( out, buffer, len ); printf("\n finished writing buf\n"); } else if (gpg_err_code(rc) == GPG_ERR_TOO_SHORT ) { log_info ("mpi too large (%u bits)\n", gcry_mpi_get_nbits (a)); /* The buffer was too small. We better tell the user about the MPI. */ rc = gpg_error (GPG_ERR_TOO_LARGE); } return rc; }
static void http_cb(struct http_req *req, struct http_response *res, void *arg) { struct httptr_req *treq = arg; struct tr_response tres = {0, NULL, -1 }; switch (res->type) { case HTTP_T_ERR: tres.type = TR_RES_BAD; tr_result(treq->tr, &tres); httptr_free(treq); break; case HTTP_T_DATA: if (treq->buf.off + res->v.data.l > MAX_DOWNLOAD) { tres.type = TR_RES_BAD; tr_result(treq->tr, &tres); httptr_cancel(treq); break; } if (!iobuf_write(&treq->buf, res->v.data.p, res->v.data.l)) btpd_err("Out of memory.\n"); break; case HTTP_T_DONE: if (treq->event == TR_EV_STOPPED) { tres.type = TR_RES_OK; tr_result(treq->tr, &tres); } else { parse_reply(treq->tp, &tres, treq->buf.buf, treq->buf.off); tr_result(treq->tr, &tres); } httptr_free(treq); break; default: break; } }
static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { int rc; if( uid->attrib_data ) { write_header(out, ctb, uid->attrib_len); rc = iobuf_write( out, uid->attrib_data, uid->attrib_len ); } else { write_header2( out, ctb, uid->len, 2 ); rc = iobuf_write( out, uid->name, uid->len ); } return 0; }
static int do_comment( IOBUF out, int ctb, PKT_comment *rem ) { if( !opt.no_comment ) { write_header(out, ctb, rem->len); if( iobuf_write( out, rem->data, rem->len ) ) return G10ERR_WRITE_FILE; } return 0; }
static void write_header( cipher_filter_context_t *cfx, IOBUF a ) { PACKET pkt; PKT_encrypted ed; byte temp[18]; unsigned blocksize; unsigned nprefix; blocksize = cipher_get_blocksize( cfx->dek->algo ); if( blocksize < 8 || blocksize > 16 ) log_fatal("unsupported blocksize %u\n", blocksize ); memset( &ed, 0, sizeof ed ); ed.len = cfx->datalen; ed.extralen = blocksize+2; ed.new_ctb = !ed.len && !RFC1991; if( cfx->dek->use_mdc ) { ed.mdc_method = DIGEST_ALGO_SHA1; cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 ); if ( DBG_HASHING ) md_start_debug( cfx->mdc_hash, "creatmdc" ); } { char buf[20]; sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo); write_status_text (STATUS_BEGIN_ENCRYPTION, buf); } init_packet( &pkt ); pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED; pkt.pkt.encrypted = &ed; if( build_packet( a, &pkt )) log_bug("build_packet(ENCR_DATA) failed\n"); nprefix = blocksize; randomize_buffer( temp, nprefix, 1 ); temp[nprefix] = temp[nprefix-2]; temp[nprefix+1] = temp[nprefix-1]; print_cipher_algo_note( cfx->dek->algo ); cfx->cipher_hd = cipher_open( cfx->dek->algo, cfx->dek->use_mdc? CIPHER_MODE_CFB : CIPHER_MODE_AUTO_CFB, 1 ); /* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/ cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen ); cipher_setiv( cfx->cipher_hd, NULL, 0 ); /* log_hexdump( "prefix", temp, nprefix+2 ); */ if( cfx->mdc_hash ) /* hash the "IV" */ md_write( cfx->mdc_hash, temp, nprefix+2 ); cipher_encrypt( cfx->cipher_hd, temp, temp, nprefix+2); cipher_sync( cfx->cipher_hd ); iobuf_write(a, temp, nprefix+2); cfx->header=1; }
static gpg_error_t write_fake_data (IOBUF out, gcry_mpi_t a) { unsigned int n; void *p; if (!a) return 0; p = gcry_mpi_get_opaque ( a, &n); return iobuf_write (out, p, (n+7)/8 ); }
static void write_fake_data( IOBUF out, MPI a ) { if( a ) { int i; void *p; p = mpi_get_opaque( a, &i ); iobuf_write( out, p, i ); } }
void io_dispatch(int fd, short ev, void *humppa) { struct io *io = humppa; size_t w; ssize_t n; int saved_errno; io_frame_enter("io_dispatch", io, ev); if (ev == EV_TIMEOUT) { io_callback(io, IO_TIMEOUT); goto leave; } if (ev & EV_WRITE && (w = io_queued(io))) { if ((n = iobuf_write(&io->iobuf, io->sock)) < 0) { if (n == IOBUF_WANT_WRITE) /* kqueue bug? */ goto read; if (n == IOBUF_CLOSED) io_callback(io, IO_DISCONNECTED); else { saved_errno = errno; io->error = strerror(errno); errno = saved_errno; io_callback(io, IO_ERROR); } goto leave; } if (w > io->lowat && w - n <= io->lowat) io_callback(io, IO_LOWAT); } read: if (ev & EV_READ) { iobuf_normalize(&io->iobuf); if ((n = iobuf_read(&io->iobuf, io->sock)) < 0) { if (n == IOBUF_CLOSED) io_callback(io, IO_DISCONNECTED); else { saved_errno = errno; io->error = strerror(errno); errno = saved_errno; io_callback(io, IO_ERROR); } goto leave; } if (n) io_callback(io, IO_DATAIN); } leave: io_frame_leave(io); }
int iobuf_flush(struct iobuf *io, int fd) { ssize_t s; while (io->queued) if ((s = iobuf_write(io, fd)) < 0) return (s); return (0); }
static void write_fake_data (IOBUF out, gcry_mpi_t a) { if (a) { unsigned int n; void *p; p = gcry_mpi_get_opaque ( a, &n ); iobuf_write (out, p, (n+7)/8 ); } }
/* * Write the mpi A to OUT. */ gpg_error_t gpg_mpi_write (iobuf_t out, gcry_mpi_t a) { int rc; if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { unsigned int nbits; const unsigned char *p; unsigned char lenhdr[2]; /* gcry_log_debugmpi ("a", a); */ p = gcry_mpi_get_opaque (a, &nbits); if (p) { /* Strip leading zero bits. */ for (; nbits >= 8 && !*p; p++, nbits -= 8) ; if (nbits >= 8 && !(*p & 0x80)) if (--nbits >= 7 && !(*p & 0x40)) if (--nbits >= 6 && !(*p & 0x20)) if (--nbits >= 5 && !(*p & 0x10)) if (--nbits >= 4 && !(*p & 0x08)) if (--nbits >= 3 && !(*p & 0x04)) if (--nbits >= 2 && !(*p & 0x02)) if (--nbits >= 1 && !(*p & 0x01)) --nbits; } /* gcry_log_debug (" [%u bit]\n", nbits); */ /* gcry_log_debughex (" ", p, (nbits+7)/8); */ lenhdr[0] = nbits >> 8; lenhdr[1] = nbits; rc = iobuf_write (out, lenhdr, 2); if (!rc && p) rc = iobuf_write (out, p, (nbits+7)/8); } else {
static int peer_write_cb(struct peer *p) { int rv; struct msg_t *msg = NULL,*next = NULL; thread_mutex_lock(p->sq_mutex); msg = BTPDQ_FIRST(&p->send_queue); //拼包,分批防止饥饿 while(msg && p->sendbuf.off < MAX_SENDBUF){ next = BTPDQ_NEXT(msg,msg_entry); BTPDQ_REMOVE(&p->send_queue,msg,msg_entry); iobuf_write(p->allocator,&p->sendbuf,msg->buf,msg->len); mfree(p->allocator,msg->buf); mfree(p->allocator,msg); msg = next; } if(p->sendbuf.off <= 0) { fdev_disable(&p->ioev,EV_WRITE); thread_mutex_unlock(p->sq_mutex); return 0; } thread_mutex_unlock(p->sq_mutex); rv = write(p->sd,p->sendbuf.buf,p->sendbuf.off); while((rv >= 0) || (rv < 0 && errno == EINTR)) { if(rv > 0) iobuf_consumed(&p->sendbuf,rv); if(p->sendbuf.off <= 0) break; rv = write(p->sd,p->sendbuf.buf,p->sendbuf.off); } if(rv < 0 && errno != EAGAIN) { return -1; } thread_mutex_lock(p->sq_mutex); if(BTPDQ_EMPTY(&p->send_queue) && p->sendbuf.off <= 0) { fdev_disable(&p->ioev,EV_WRITE); } thread_mutex_unlock(p->sq_mutex); return 0; }
/**************** * write an mpi to out. */ int mpi_write( IOBUF out, MPI a ) { int rc; unsigned nbits = mpi_get_nbits(a); byte *p, *buf; unsigned n; if( nbits > MAX_EXTERN_MPI_BITS ) log_bug("mpi_encode: mpi too large (%u bits)\n", nbits); iobuf_put(out, (nbits >>8) ); iobuf_put(out, (nbits) ); p = buf = mpi_get_buffer( a, &n, NULL ); rc = iobuf_write( out, p, n ); xfree(buf); return rc; }
/* * Write the mpi A to OUT. */ static int mpi_write (iobuf_t out, gcry_mpi_t a) { char buffer[(MAX_EXTERN_MPI_BITS+7)/8+2]; /* 2 is for the mpi length. */ size_t nbytes; int rc; nbytes = DIM(buffer); rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); if( !rc ) rc = iobuf_write( out, buffer, nbytes ); else if (gpg_err_code(rc) == GPG_ERR_TOO_SHORT ) { log_info ("mpi too large (%u bits)\n", gcry_mpi_get_nbits (a)); /* The buffer was too small. We better tell the user about the MPI. */ rc = gpg_error (GPG_ERR_TOO_LARGE); } return rc; }
static int do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a ) { int zrc; unsigned n; do { #ifndef __riscos__ zs->next_out = zfx->outbuf; #else /* __riscos__ */ zs->next_out = (Bytef *) zfx->outbuf; #endif /* __riscos__ */ zs->avail_out = zfx->outbufsize; if( DBG_FILTER ) log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n", (unsigned)zs->avail_in, (unsigned)zs->avail_out, flush ); zrc = deflate( zs, flush ); if( zrc == Z_STREAM_END && flush == Z_FINISH ) ; else if( zrc != Z_OK ) { if( zs->msg ) log_fatal("zlib deflate problem: %s\n", zs->msg ); else log_fatal("zlib deflate problem: rc=%d\n", zrc ); } n = zfx->outbufsize - zs->avail_out; if( DBG_FILTER ) log_debug("leave deflate: " "avail_in=%u, avail_out=%u, n=%u, zrc=%d\n", (unsigned)zs->avail_in, (unsigned)zs->avail_out, (unsigned)n, zrc ); if( iobuf_write( a, zfx->outbuf, n ) ) { log_debug("deflate: iobuf_write failed\n"); return G10ERR_WRITE_FILE; } } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) ); return 0; }
static int do_compress(compress_filter_context_t *zfx, bz_stream *bzs, int flush, IOBUF a) { int rc; int zrc; unsigned n; do { bzs->next_out = zfx->outbuf; bzs->avail_out = zfx->outbufsize; if( DBG_FILTER ) log_debug("enter bzCompress: avail_in=%u, avail_out=%u, flush=%d\n", (unsigned)bzs->avail_in, (unsigned)bzs->avail_out, flush ); zrc = BZ2_bzCompress( bzs, flush ); if( zrc == BZ_STREAM_END && flush == BZ_FINISH ) ; else if( zrc != BZ_RUN_OK && zrc != BZ_FINISH_OK ) log_fatal("bz2lib deflate problem: rc=%d\n", zrc ); n = zfx->outbufsize - bzs->avail_out; if( DBG_FILTER ) log_debug("leave bzCompress:" " avail_in=%u, avail_out=%u, n=%u, zrc=%d\n", (unsigned)bzs->avail_in, (unsigned)bzs->avail_out, (unsigned)n, zrc ); if( (rc=iobuf_write( a, zfx->outbuf, n )) ) { log_debug("bzCompress: iobuf_write failed\n"); return rc; } } while( bzs->avail_in || (flush == BZ_FINISH && zrc != BZ_STREAM_END) ); return 0; }
CURLcode curl_easy_perform(CURL *curl) { int rc; CURLcode err=CURLE_OK; const char *errstr=NULL; char *proxy=NULL; struct http_srv srv; memset(&srv,0,sizeof(srv)); /* Emulate the libcurl proxy behavior. If the calling program set a proxy, use it. If it didn't set a proxy or set it to NULL, check for one in the environment. If the calling program explicitly set a null-string proxy the http code doesn't use a proxy at all. */ if(curl->proxy) proxy=curl->proxy; else proxy=getenv(HTTP_PROXY_ENV); if(curl->srvtag) srv.srvtag=curl->srvtag; if(curl->flags.verbose) { fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null"); fprintf(curl->errors,"* HTTP URL is \"%s\"\n",curl->url); if(srv.srvtag) fprintf(curl->errors, "* SRV tag is \"%s\": host and port may be overridden\n", srv.srvtag); fprintf(curl->errors,"* HTTP auth is \"%s\"\n", curl->auth?curl->auth:"null"); fprintf(curl->errors,"* HTTP method is %s\n", curl->flags.post?"POST":"GET"); } if(curl->flags.post) { rc=http_open(&curl->hd,HTTP_REQ_POST,curl->url,curl->auth,0,proxy, &srv,curl->headers?curl->headers->list:NULL); if(rc==0) { char content_len[50]; unsigned int post_len=strlen(curl->postfields); if(curl->flags.verbose && srv.used_server && srv.used_port) fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", srv.used_server, srv.used_port); iobuf_writestr(curl->hd.fp_write, "Content-Type: application/x-www-form-urlencoded\r\n"); sprintf(content_len,"Content-Length: %u\r\n",post_len); iobuf_writestr(curl->hd.fp_write,content_len); http_start_data(&curl->hd); iobuf_write(curl->hd.fp_write,curl->postfields,post_len); rc=http_wait_response(&curl->hd,&curl->status); if(rc==0 && curl->flags.failonerror && curl->status>=300) err=CURLE_HTTP_RETURNED_ERROR; } } else { rc=http_open(&curl->hd,HTTP_REQ_GET,curl->url,curl->auth,0,proxy, &srv,curl->headers?curl->headers->list:NULL); if(rc==0) { if(curl->flags.verbose && srv.used_server && srv.used_port) fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", srv.used_server, srv.used_port); rc=http_wait_response(&curl->hd,&curl->status); if(rc==0) { if(curl->flags.failonerror && curl->status>=300) err=CURLE_HTTP_RETURNED_ERROR; else { unsigned int maxlen=1024,buflen,len; byte *line=NULL; while((len=iobuf_read_line(curl->hd.fp_read, &line,&buflen,&maxlen))) { size_t ret; maxlen=1024; ret=(curl->writer)(line,len,1,curl->file); if(ret!=len) { err=CURLE_WRITE_ERROR; break; } } xfree(line); http_close(&curl->hd); } } else http_close(&curl->hd); } } free (srv.used_server); switch(rc) { case 0: break; case G10ERR_INVALID_URI: err=CURLE_UNSUPPORTED_PROTOCOL; break; case G10ERR_NETWORK: errstr=strerror(errno); err=CURLE_COULDNT_CONNECT; break; default: errstr=g10_errstr(rc); err=CURLE_COULDNT_CONNECT; break; } return handle_error(curl,err,errstr); }
static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) { int rc = 0; int i, nskey, npkey; IOBUF a = iobuf_temp(); /* Build in a self-enlarging buffer. */ /* Write the version number - if none is specified, use 3 */ if ( !sk->version ) iobuf_put ( a, 3 ); else iobuf_put ( a, sk->version ); write_32 (a, sk->timestamp ); /* v3 needs the expiration time. */ if ( sk->version < 4 ) { u16 ndays; if ( sk->expiredate ) ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); else ndays = 0; write_16(a, ndays); } iobuf_put (a, sk->pubkey_algo ); /* Get number of secret and public parameters. They are held in one array first the public ones, then the secret ones. */ nskey = pubkey_get_nskey ( sk->pubkey_algo ); npkey = pubkey_get_npkey ( sk->pubkey_algo ); /* If we don't have any public parameters - which is the case if we don't know the algorithm used - the parameters are stored as one blob in a faked (opaque) MPI. */ if ( !npkey ) { write_fake_data( a, sk->skey[0] ); goto leave; } assert ( npkey < nskey ); /* Writing the public parameters is easy. */ for (i=0; i < npkey; i++ ) if ((rc = mpi_write (a, sk->skey[i]))) goto leave; /* Build the header for protected (encrypted) secret parameters. */ if ( sk->is_protected ) { if ( is_RSA(sk->pubkey_algo) && sk->version < 4 && !sk->protect.s2k.mode ) { /* The simple rfc1991 (v3) way. */ iobuf_put (a, sk->protect.algo ); iobuf_write (a, sk->protect.iv, sk->protect.ivlen ); } else { /* OpenPGP protection according to rfc2440. */ iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff ); iobuf_put(a, sk->protect.algo ); if ( sk->protect.s2k.mode >= 1000 ) { /* These modes are not possible in OpenPGP, we use them to implement our extensions, 101 can be seen as a private/experimental extension (this is not specified in rfc2440 but the same scheme is used for all other algorithm identifiers) */ iobuf_put(a, 101 ); iobuf_put(a, sk->protect.s2k.hash_algo ); iobuf_write(a, "GNU", 3 ); iobuf_put(a, sk->protect.s2k.mode - 1000 ); } else { iobuf_put(a, sk->protect.s2k.mode ); iobuf_put(a, sk->protect.s2k.hash_algo ); } if ( sk->protect.s2k.mode == 1 || sk->protect.s2k.mode == 3 ) iobuf_write (a, sk->protect.s2k.salt, 8 ); if ( sk->protect.s2k.mode == 3 ) iobuf_put (a, sk->protect.s2k.count ); /* For our special modes 1001, 1002 we do not need an IV. */ if ( sk->protect.s2k.mode != 1001 && sk->protect.s2k.mode != 1002 ) iobuf_write (a, sk->protect.iv, sk->protect.ivlen ); } } else iobuf_put (a, 0 ); if ( sk->protect.s2k.mode == 1001 ) ; /* GnuPG extension - don't write a secret key at all. */ else if ( sk->protect.s2k.mode == 1002 ) { /* GnuPG extension - divert to OpenPGP smartcard. */ iobuf_put(a, sk->protect.ivlen ); /* Length of the serial number or 0 for no serial number. */ /* The serial number gets stored in the IV field. */ iobuf_write(a, sk->protect.iv, sk->protect.ivlen); } else if ( sk->is_protected && sk->version >= 4 ) { /* The secret key is protected - write it out as it is. */ byte *p; unsigned int ndatabits; assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE)); p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits ); iobuf_write (a, p, (ndatabits+7)/8 ); } else if ( sk->is_protected ) { /* The secret key is protected the old v4 way. */ for ( ; i < nskey; i++ ) { byte *p; unsigned int ndatabits; assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits); iobuf_write (a, p, (ndatabits+7)/8); } write_16(a, sk->csum ); } else { /* Non-protected key. */ for ( ; i < nskey; i++ ) if ( (rc = mpi_write (a, sk->skey[i]))) goto leave; write_16 (a, sk->csum ); } leave: if (!rc) { /* Build the header of the packet - which we must do after writing all the other stuff, so that we know the length of the packet */ write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes); /* And finally write it out the real stream */ rc = iobuf_write_temp( out, a ); } iobuf_close(a); /* Close the remporary buffer */ return rc; }
static int peer_read_cb(struct peer *p) { ssize_t rv; int need_kill = 0; char buf[BUF_SIZE]; rv = read(p->sd,buf,BUF_SIZE); while((rv > 0) || (rv < 0 && errno == EINTR)) { if(rv > 0) iobuf_write(p->allocator,&p->recvbuf,buf,rv); if(rv == BUF_SIZE)//分段处理,防止饥饿 { break; } rv = read(p->sd,buf,BUF_SIZE); } if(rv == 0) { if(p->recvbuf.off <=0) { return -1; } else need_kill = 1; } if(rv < 0 && errno != EAGAIN) { return -1; } uint32_t off = 0; if(p->ns->data_func && p->recvbuf.off > 0) { while((rv = p->ns->data_func(p->ns,p->id,p->recvbuf.buf,p->recvbuf.off,&off)) == 0) { if(off > p->recvbuf.off) { return -1; } //回调方式 if(p->ns->msg_func) { p->ns->msg_func(p->ns,p->id,p->recvbuf.buf,off); iobuf_consumed(&p->recvbuf,off); continue; } struct msg_t *msg = (struct msg_t *)mmalloc(p->ns->allocator, sizeof(struct msg_t)); uint32_t size = off + 1; msg->buf = (uint8_t *)mmalloc(p->ns->allocator,size); memset(msg->buf,0,size); bcopy(p->recvbuf.buf,msg->buf,off); msg->len = off; msg->peer_id = p->id; msg->type = MSG_DATA; queue_push(p->ns->recv_queue,msg); /* thread_mutex_lock(p->ns->recv_mutex); BTPDQ_INSERT_TAIL(&p->ns->recv_queue, msg, msg_entry); thread_mutex_unlock(p->ns->recv_mutex);*/ iobuf_consumed(&p->recvbuf,off); } } if(need_kill) { return -1; } return 0; }
/**************** * Filter to do a complete public key encryption. */ int encrypt_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; encrypt_filter_context_t *efx = opaque; int rc=0; if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */ BUG(); /* not used */ } else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ if( !efx->header_okay ) { efx->cfx.dek = xmalloc_secure_clear( sizeof *efx->cfx.dek ); if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ efx->cfx.dek->algo = select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,-1,NULL); if( efx->cfx.dek->algo == -1 ) { /* because 3DES is implicitly in the prefs, this can only * happen if we do not have any public keys in the list */ efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO; } } else { if(!opt.expert && select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM, opt.def_cipher_algo, NULL)!=opt.def_cipher_algo) log_info(_("forcing symmetric cipher %s (%d) " "violates recipient preferences\n"), cipher_algo_to_string(opt.def_cipher_algo), opt.def_cipher_algo); efx->cfx.dek->algo = opt.def_cipher_algo; } efx->cfx.dek->use_mdc = use_mdc(efx->pk_list,efx->cfx.dek->algo); make_session_key( efx->cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", efx->cfx.dek->key, efx->cfx.dek->keylen ); rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a ); if( rc ) return rc; if(efx->symkey_s2k && efx->symkey_dek) { rc=write_symkey_enc(efx->symkey_s2k,efx->symkey_dek, efx->cfx.dek,a); if(rc) return rc; } iobuf_push_filter( a, cipher_filter, &efx->cfx ); efx->header_okay = 1; } rc = iobuf_write( a, buf, size ); } else if( control == IOBUFCTRL_FREE ) { xfree(efx->symkey_dek); xfree(efx->symkey_s2k); } else if( control == IOBUFCTRL_DESC ) { *(char**)buf = "encrypt_filter"; } return rc; }
/**************** * 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; }
void cmd_add(int argc, char **argv) { int ch, topdir = 0, start = 1, nfile, nloaded = 0; size_t dirlen = 0, labellen = 0; char *dir = NULL, *name = NULL, *glabel = NULL, *label; while ((ch = getopt_long(argc, argv, "NTd:l:n:", add_opts, NULL)) != -1) { switch (ch) { case 'N': start = 0; break; case 'T': topdir = 1; break; case 'd': dir = optarg; if ((dirlen = strlen(dir)) == 0) diemsg("bad option value for -d.\n"); break; case 'l': glabel = optarg; if ((labellen = strlen(dir)) == 0) diemsg("bad option value for -l.\n"); break; case 'n': name = optarg; break; default: usage_add(); } } argc -= optind; argv += optind; if (argc < 1 || dir == NULL) usage_add(); btpd_connect(); char *mi; size_t mi_size; enum ipc_err code; char dpath[PATH_MAX]; struct iobuf iob; for (nfile = 0; nfile < argc; nfile++) { if ((mi = mi_load(argv[nfile], &mi_size)) == NULL) { fprintf(stderr, "error loading '%s' (%s).\n", argv[nfile], strerror(errno)); continue; } iob = iobuf_init(PATH_MAX); iobuf_write(&iob, dir, dirlen); if (topdir && !mi_simple(mi)) { size_t tdlen; const char *td = benc_dget_mem(benc_dget_dct(mi, "info"), "name", &tdlen); iobuf_swrite(&iob, "/"); iobuf_write(&iob, td, tdlen); } iobuf_swrite(&iob, "\0"); if ((errno = make_abs_path(iob.buf, dpath)) != 0) { fprintf(stderr, "make_abs_path '%s' failed (%s).\n", dpath, strerror(errno)); iobuf_free(&iob); continue; } if(NULL == glabel) label = benc_dget_str(mi, "announce", NULL); else label = glabel; code = btpd_add(ipc, mi, mi_size, dpath, name, label); if ((code == IPC_OK) && start) { struct ipc_torrent tspec; tspec.by_hash = 1; mi_info_hash(mi, tspec.u.hash); code = btpd_start(ipc, &tspec); } if (code != IPC_OK) { fprintf(stderr, "command failed for '%s' (%s).\n", argv[nfile], ipc_strerror(code)); } else { nloaded++; } iobuf_free(&iob); } if (nloaded != nfile) { diemsg("error loaded %d of %d files.\n", nloaded, nfile); } }
/* 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; }