/* This functions builds an index of the keyring into a separate file with the name keyring.ext.idx. It contains the offset of all public- and public subkeys. The format of the file is: -------- 4 octets offset of the packet 8 octets keyid 20 octets fingerprint -------- We store the keyid and the fingerprint due to the fact we can't get the keyid from a v3 fingerprint directly. */ static int keydb_idx_build( const char * file ) { cdk_packet_t pkt; cdk_stream_t inp, out = NULL; byte buf[8], fpr[20]; char * fname; u32 keyid[2]; int rc, pos; if( !file ) return CDK_Inv_Value; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; fname = keydb_idx_mkname( file ); if( !fname ) { rc = CDK_Out_Of_Core; goto leave; } rc = cdk_stream_open( file, &inp ); if( !rc ) rc = cdk_stream_create( fname, &out ); if( rc ) goto leave; while( !cdk_stream_eof( inp ) ) { pos = cdk_stream_tell( inp ); rc = cdk_pkt_read( inp, pkt ); if( rc ) break; if( pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ) { _cdk_u32tobuf( pos, buf ); cdk_stream_write( out, buf, 4 ); cdk_pk_get_keyid( pkt->pkt.public_key, keyid ); _cdk_u32tobuf( keyid[0], buf ); _cdk_u32tobuf( keyid[1], buf + 4 ); cdk_stream_write( out, buf, 8 ); cdk_pk_get_fingerprint( pkt->pkt.public_key, fpr ); cdk_stream_write( out, fpr, 20 ); } cdk_pkt_free( pkt ); cdk_pkt_init( pkt ); } cdk_stream_close( out ); leave: cdk_stream_close( inp ); cdk_free( fname ); cdk_free( pkt ); return rc; }
/** * cdk_stream_tmp_from_mem: * @buf: the buffer which shall be written to the temp stream. * @buflen: how large the buffer is * @r_out: the new stream with the given contents. * * Creates a new tempory stream with the given contests. */ cdk_error_t cdk_stream_tmp_from_mem (const void *buf, size_t buflen, cdk_stream_t * r_out) { cdk_stream_t s; cdk_error_t rc; int nwritten; *r_out = NULL; rc = cdk_stream_tmp_new (&s); if (rc) { gnutls_assert (); return rc; } nwritten = cdk_stream_write (s, buf, buflen); if (nwritten == EOF) { cdk_stream_close (s); gnutls_assert (); return s->error; } cdk_stream_seek (s, 0); *r_out = s; return 0; }
/** * cdk_stream_kick_off: * @inp: the input stream * @out: the output stream. * * Passes the entire data from @inp into the output stream @out * with all the activated filters. */ cdk_error_t cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out) { byte buf[BUFSIZE]; int nread, nwritten; cdk_error_t rc; if (!inp || !out) { gnutls_assert (); return CDK_Inv_Value; } rc = CDK_Success; while (!cdk_stream_eof (inp)) { nread = cdk_stream_read (inp, buf, DIM (buf)); if (!nread || nread == EOF) break; nwritten = cdk_stream_write (out, buf, nread); if (!nwritten || nwritten == EOF) { /* In case of errors, we leave the loop. */ rc = inp->error; break; } } wipemem (buf, sizeof (buf)); return rc; }
static int stream_write (cdk_stream_t s, const void *buf, size_t buflen) { int nwritten; nwritten = cdk_stream_write (s, buf, buflen); if (nwritten == EOF) return _cdk_stream_get_errno (s); return 0; }
int cdk_stream_putc( cdk_stream_t s, int c ) { unsigned char buf[2]; int nwritten; if( !s ) return EOF; buf[0] = c; nwritten = cdk_stream_write( s, buf, 1 ); if( nwritten == EOF ) { s->error = CDK_File_Error; return EOF; } return 0; }
int cdk_stream_putc (cdk_stream_t s, int c) { byte buf[2]; int nwritten; if (!s) { gnutls_assert (); return EOF; } buf[0] = c; nwritten = cdk_stream_write (s, buf, 1); if (nwritten == EOF) return EOF; return 0; }
cdk_stream_t cdk_stream_tmp_from_mem( const void * buf, size_t count ) { cdk_stream_t s; int nwritten; s = cdk_stream_tmp( ); if( !s ) return NULL; nwritten = cdk_stream_write( s, buf, count ); if( nwritten == EOF ) { cdk_stream_close( s ); return NULL; } cdk_stream_seek( s, 0 ); return s; }
cdk_error_t cdk_stream_kick_off( cdk_stream_t inp, cdk_stream_t out ) { byte buf[8192]; int nread, nwritten; int rc = 0; if( !inp || !out ) return CDK_Inv_Value; while( !cdk_stream_eof( inp ) ) { nread = cdk_stream_read( inp, buf, sizeof buf-1 ); if( nread == EOF ) break; nwritten = cdk_stream_write( out, buf, nread ); if( nwritten == EOF ) rc = CDK_File_Error; } wipemem( buf, sizeof buf ); return rc; }
int _cdk_stream_puts( cdk_stream_t s, const char * buf ) { return cdk_stream_write( s, buf, strlen( buf ) ); }
static cdk_error_t literal_decode (void *data, FILE * in, FILE * out) { literal_filter_t *pfx = data; cdk_stream_t si, so; cdk_packet_t pkt; cdk_pkt_literal_t pt; byte buf[BUFSIZE]; ssize_t nread; int bufsize; cdk_error_t rc; _cdk_log_debug ("literal filter: decode\n"); if (!pfx || !in || !out) return CDK_Inv_Value; rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si); if (rc) return rc; cdk_pkt_new (&pkt); rc = cdk_pkt_read (si, pkt); if (rc || pkt->pkttype != CDK_PKT_LITERAL) { cdk_pkt_release (pkt); cdk_stream_close (si); return !rc ? CDK_Inv_Packet : rc; } rc = _cdk_stream_fpopen (out, STREAMCTL_WRITE, &so); if (rc) { cdk_pkt_release (pkt); cdk_stream_close (si); return rc; } pt = pkt->pkt.literal; pfx->mode = pt->mode; if (pfx->filename && pt->namelen > 0) { /* The name in the literal packet is more authorative. */ cdk_free (pfx->filename); pfx->filename = dup_trim_filename (pt->name); } else if (!pfx->filename && pt->namelen > 0) pfx->filename = dup_trim_filename (pt->name); else if (!pt->namelen && !pfx->filename && pfx->orig_filename) { /* In this case, we need to derrive the output file name from the original name and cut off the OpenPGP extension. If this is not possible, we return an error. */ if (!stristr (pfx->orig_filename, ".gpg") && !stristr (pfx->orig_filename, ".pgp") && !stristr (pfx->orig_filename, ".asc")) { cdk_pkt_release (pkt); cdk_stream_close (si); cdk_stream_close (so); _cdk_log_debug ("literal filter: no file name and no PGP extension\n"); return CDK_Inv_Mode; } _cdk_log_debug ("literal filter: derrive file name from original\n"); pfx->filename = dup_trim_filename (pfx->orig_filename); pfx->filename[strlen (pfx->filename) - 4] = '\0'; } while (!feof (in)) { _cdk_log_debug ("literal_decode: part on %d size %lu\n", (int) pfx->blkmode.on, (unsigned long)pfx->blkmode.size); if (pfx->blkmode.on) bufsize = pfx->blkmode.size; else bufsize = pt->len < DIM (buf) ? pt->len : DIM (buf); nread = cdk_stream_read (pt->buf, buf, bufsize); if (nread == EOF) { rc = CDK_File_Error; break; } if (pfx->md_initialized) _gnutls_hash (&pfx->md, buf, nread); cdk_stream_write (so, buf, nread); pt->len -= nread; if (pfx->blkmode.on) { pfx->blkmode.size = _cdk_pkt_read_len (in, &pfx->blkmode.on); if ((ssize_t) pfx->blkmode.size == EOF) return CDK_Inv_Packet; } if (pt->len <= 0 && !pfx->blkmode.on) break; } cdk_stream_close (si); cdk_stream_close (so); cdk_pkt_release (pkt); return rc; }
static cdk_error_t file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output) { cdk_stream_t inp = NULL, out = NULL, tmp = NULL; digest_hd_st md; char buf[512], chk[512]; const char *s; int i, is_signed = 0, nbytes; int digest_algo = 0; int err; cdk_error_t rc; memset(&md, 0, sizeof(md)); if (output) { rc = cdk_stream_create (output, &out); if (rc) return rc; } rc = cdk_stream_open (file, &inp); if (rc) { if (output) cdk_stream_close (out); return rc; } s = "-----BEGIN PGP SIGNED MESSAGE-----"; while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (!strncmp (buf, s, strlen (s))) { is_signed = 1; break; } } if (cdk_stream_eof (inp) && !is_signed) { rc = CDK_Armor_Error; goto leave; } while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (nbytes == 1) /* Empty line */ break; else if (!strncmp (buf, "Hash: ", 6)) { for (i = 0; digest_table[i].name; i++) { if (!strcmp (buf + 6, digest_table[i].name)) { digest_algo = digest_table[i].algo; break; } } } } if (digest_algo && _gnutls_hash_get_algo_len (digest_algo) <= 0) { rc = CDK_Inv_Algo; goto leave; } if (!digest_algo) digest_algo = GNUTLS_DIG_MD5; err = _gnutls_hash_init (&md, digest_algo); if (err < 0) { rc = map_gnutls_error (err); goto leave; } s = "-----BEGIN PGP SIGNATURE-----"; while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (!strncmp (buf, s, strlen (s))) break; else { cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1); i = strncmp (chk, s, strlen (s)); if (strlen (buf) == 0 && i == 0) continue; /* skip last '\n' */ _cdk_trim_string (buf, i == 0 ? 0 : 1); _gnutls_hash (&md, buf, strlen (buf)); } if (!strncmp (buf, "- ", 2)) /* FIXME: handle it recursive. */ memmove (buf, buf + 2, nbytes - 2); if (out) { if (strstr (buf, "\r\n")) buf[strlen (buf) - 2] = '\0'; cdk_stream_write (out, buf, strlen (buf)); _cdk_stream_puts (out, _cdk_armor_get_lineend ()); } } /* We create a temporary stream object to store the signature data in there. */ rc = cdk_stream_tmp_new (&tmp); if (rc) goto leave; s = "-----BEGIN PGP SIGNATURE-----\n"; _cdk_stream_puts (tmp, s); while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (nbytes < (int) (DIM (buf) - 3)) { buf[nbytes - 1] = '\n'; buf[nbytes] = '\0'; } cdk_stream_write (tmp, buf, nbytes); } /* FIXME: This code is not very elegant. */ cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ); cdk_stream_seek (tmp, 0); cdk_stream_set_armor_flag (tmp, 0); cdk_stream_read (tmp, NULL, 0); /* the digest handle will be closed there. */ rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, &md); leave: _gnutls_hash_deinit (&md, NULL); cdk_stream_close (out); cdk_stream_close (tmp); cdk_stream_close (inp); return rc; }
static int literal_decode( void * opaque, FILE * in, FILE * out ) { literal_filter_t * pfx = opaque; cdk_stream_t si, so; CDK_PACKET pkt; cdk_pkt_literal_t pt; byte buf[8192]; size_t nread; int rc, bufsize; _cdk_log_debug( "literal filter: decode\n" ); if (!pfx || !in || !out) return CDK_Inv_Value; si = _cdk_stream_fpopen( in, STREAMCTL_READ ); if (!si) return CDK_Out_Of_Core; so = _cdk_stream_fpopen( out, STREAMCTL_WRITE ); if( !so ) { cdk_stream_close( si ); return CDK_Out_Of_Core; } cdk_pkt_init( &pkt ); rc = cdk_pkt_read( si, &pkt ); if( pkt.pkttype != CDK_PKT_LITERAL ) { if( pkt.pkttype ) cdk_pkt_free( &pkt ); return rc; } pt = pkt.pkt.literal; pfx->mode = pt->mode; pfx->filename = cdk_strdup( pt->name? pt->name : " " ); if( !pfx->filename ) { cdk_pkt_free( &pkt ); return CDK_Out_Of_Core; } while( !feof( in ) ) { _cdk_log_debug( "partial on=%d size=%lu\n", pfx->blkmode.on, pfx->blkmode.size ); if( pfx->blkmode.on ) bufsize = pfx->blkmode.size; else bufsize = pt->len < sizeof buf-1? pt->len : sizeof buf-1; nread = cdk_stream_read( pt->buf, buf, bufsize ); if( nread == EOF ) { rc = CDK_File_Error; break; } if( pfx->md ) cdk_md_write (pfx->md, buf, nread); cdk_stream_write( so, buf, nread ); pt->len -= nread; if( pfx->blkmode.on ) { pfx->blkmode.size = _cdk_pkt_read_len( in, &pfx->blkmode.on ); if( pfx->blkmode.size == (size_t)EOF ) return CDK_Inv_Packet; } if( pt->len <= 0 && !pfx->blkmode.on ) break; } cdk_stream_close( si ); cdk_stream_close( so ); cdk_pkt_free( &pkt ); return rc; }