Add verify function
This commit is contained in:
parent
b9bf49968b
commit
36966ea498
@ -18,6 +18,7 @@ libgpgme_la_SOURCES = \
|
|||||||
data.c recipient.c \
|
data.c recipient.c \
|
||||||
wait.c wait.h \
|
wait.c wait.h \
|
||||||
encrypt.c \
|
encrypt.c \
|
||||||
|
verify.c \
|
||||||
rungpg.c rungpg.h status-table.h \
|
rungpg.c rungpg.h status-table.h \
|
||||||
gpgme.c errors.c
|
gpgme.c errors.c
|
||||||
|
|
||||||
|
@ -25,16 +25,34 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "rungpg.h" /* for GpgObject */
|
#include "rungpg.h" /* for GpgObject */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RESULT_TYPE_NONE = 0,
|
||||||
|
RESULT_TYPE_VERIFY,
|
||||||
|
} ResultType;
|
||||||
|
|
||||||
|
|
||||||
/* Currently we need it at several places, so we put the definition
|
/* Currently we need it at several places, so we put the definition
|
||||||
* into this header file */
|
* into this header file */
|
||||||
struct gpgme_context_s {
|
struct gpgme_context_s {
|
||||||
int initialized;
|
int initialized;
|
||||||
int pending; /* a gpg request is still pending */
|
int pending; /* a gpg request is still pending */
|
||||||
|
|
||||||
|
/* at some points we need to allocate memory but we are not
|
||||||
|
* able to handle a malloc problem at that point, so we set this
|
||||||
|
* flag to indicate this condition */
|
||||||
|
int out_of_core;
|
||||||
|
|
||||||
GpgObject gpg; /* the running gpg process */
|
GpgObject gpg; /* the running gpg process */
|
||||||
|
|
||||||
int verbosity; /* level of verbosity to use */
|
int verbosity; /* level of verbosity to use */
|
||||||
int use_armor; /* use armoring */
|
int use_armor; /* use armoring */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ResultType result_type;
|
||||||
|
union {
|
||||||
|
VerifyResult verify;
|
||||||
|
} result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +62,8 @@ struct gpgme_data_s {
|
|||||||
GpgmeDataType type;
|
GpgmeDataType type;
|
||||||
GpgmeDataMode mode;
|
GpgmeDataMode mode;
|
||||||
size_t readpos;
|
size_t readpos;
|
||||||
|
size_t writepos;
|
||||||
|
size_t private_len;
|
||||||
char *private_buffer;
|
char *private_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
82
gpgme/data.c
82
gpgme/data.c
@ -27,6 +27,9 @@
|
|||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ALLOC_CHUNK 1024
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpgme_new_data:
|
* gpgme_new_data:
|
||||||
* @r_dh: Returns a new data object.
|
* @r_dh: Returns a new data object.
|
||||||
@ -59,8 +62,10 @@ gpgme_new_data ( GpgmeData *r_dh, const char *buffer, size_t size, int copy )
|
|||||||
xfree (dh);
|
xfree (dh);
|
||||||
return mk_error (Out_Of_Core);
|
return mk_error (Out_Of_Core);
|
||||||
}
|
}
|
||||||
|
dh->private_len = size;
|
||||||
memcpy (dh->private_buffer, buffer, size );
|
memcpy (dh->private_buffer, buffer, size );
|
||||||
dh->data = dh->private_buffer;
|
dh->data = dh->private_buffer;
|
||||||
|
dh->writepos = size;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dh->data = buffer;
|
dh->data = buffer;
|
||||||
@ -113,24 +118,95 @@ _gpgme_query_data_mode ( GpgmeData dh )
|
|||||||
return dh->mode;
|
return dh->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GpgmeError
|
||||||
|
gpgme_rewind_data ( GpgmeData dh )
|
||||||
|
{
|
||||||
|
if ( !dh )
|
||||||
|
return mk_error (Invalid_Value);
|
||||||
|
/* Fixme: We should check whether rewinding does make sense for the
|
||||||
|
* data type */
|
||||||
|
dh->readpos = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GpgmeError
|
||||||
|
gpgme_read_data ( GpgmeData dh, char *buffer, size_t length, size_t *nread )
|
||||||
|
{
|
||||||
|
size_t nbytes;
|
||||||
|
|
||||||
|
if ( !dh )
|
||||||
|
return mk_error (Invalid_Value);
|
||||||
|
nbytes = dh->len - dh->readpos;
|
||||||
|
if ( !nbytes ) {
|
||||||
|
*nread = 0;
|
||||||
|
return mk_error(EOF);
|
||||||
|
}
|
||||||
|
if (nbytes > length)
|
||||||
|
nbytes = length;
|
||||||
|
memcpy ( buffer, dh->data + dh->readpos, nbytes );
|
||||||
|
*nread = nbytes;
|
||||||
|
dh->readpos += nbytes;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GpgmeError
|
GpgmeError
|
||||||
_gpgme_append_data ( GpgmeData dh, const char *buf, size_t length )
|
_gpgme_append_data ( GpgmeData dh, const char *buffer, size_t length )
|
||||||
{
|
{
|
||||||
assert (dh);
|
assert (dh);
|
||||||
|
|
||||||
if ( dh->type == GPGME_DATA_TYPE_NONE ) {
|
if ( dh->type == GPGME_DATA_TYPE_NONE ) {
|
||||||
/* convert it to a mem data type */
|
/* convert it to a mem data type */
|
||||||
|
assert (!dh->private_buffer);
|
||||||
|
dh->type = GPGME_DATA_TYPE_MEM;
|
||||||
|
dh->private_len = length < ALLOC_CHUNK? ALLOC_CHUNK : length;
|
||||||
|
dh->private_buffer = xtrymalloc ( dh->private_len );
|
||||||
|
if (!dh->private_buffer) {
|
||||||
|
dh->private_len = 0;
|
||||||
|
return mk_error (Out_Of_Core);
|
||||||
|
}
|
||||||
|
dh->writepos = 0;
|
||||||
|
dh->data = dh->private_buffer;
|
||||||
}
|
}
|
||||||
else if ( dh->type != GPGME_DATA_TYPE_MEM ) {
|
else if ( dh->type != GPGME_DATA_TYPE_MEM )
|
||||||
return mk_error (Invalid_Type);
|
return mk_error (Invalid_Type);
|
||||||
}
|
|
||||||
|
|
||||||
if ( dh->mode != GPGME_DATA_MODE_INOUT
|
if ( dh->mode != GPGME_DATA_MODE_INOUT
|
||||||
&& dh->mode != GPGME_DATA_MODE_IN )
|
&& dh->mode != GPGME_DATA_MODE_IN )
|
||||||
return mk_error (Invalid_Mode);
|
return mk_error (Invalid_Mode);
|
||||||
|
|
||||||
|
if ( !dh->private_buffer ) {
|
||||||
|
/* we have to copy it now */
|
||||||
|
assert (dh->data);
|
||||||
|
dh->private_len = dh->len+length;
|
||||||
|
if (dh->private_len < ALLOC_CHUNK)
|
||||||
|
dh->private_len = ALLOC_CHUNK;
|
||||||
|
dh->private_buffer = xtrymalloc ( dh->private_len );
|
||||||
|
if (!dh->private_buffer) {
|
||||||
|
dh->private_len = 0;
|
||||||
|
return mk_error (Out_Of_Core);
|
||||||
|
}
|
||||||
|
dh->writepos = 0;
|
||||||
|
dh->data = dh->private_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate more memory if needed */
|
||||||
|
if ( dh->writepos + length > dh->private_len ) {
|
||||||
|
char *p;
|
||||||
|
size_t newlen = dh->private_len
|
||||||
|
+ (dh->len < ALLOC_CHUNK? ALLOC_CHUNK : length);
|
||||||
|
p = xtryrealloc ( dh->private_buffer, newlen );
|
||||||
|
if ( !p )
|
||||||
|
return mk_error (Out_Of_Core);
|
||||||
|
dh->private_buffer = p;
|
||||||
|
dh->private_len = newlen;
|
||||||
|
dh->data = dh->private_buffer;
|
||||||
|
assert ( !(dh->writepos + length > dh->private_len) );
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy ( dh->private_buffer + dh->writepos, buffer, length );
|
||||||
|
dh->writepos += length;
|
||||||
|
dh->len += length;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ encrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
|||||||
|
|
||||||
|
|
||||||
GpgmeError
|
GpgmeError
|
||||||
gpgme_req_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
gpgme_start_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
||||||
GpgmeData plain, GpgmeData ciph )
|
GpgmeData plain, GpgmeData ciph )
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -87,7 +87,7 @@ gpgme_req_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
|||||||
_gpgme_gpg_add_arg ( c->gpg, "--output" );
|
_gpgme_gpg_add_arg ( c->gpg, "--output" );
|
||||||
_gpgme_gpg_add_arg ( c->gpg, "-" );
|
_gpgme_gpg_add_arg ( c->gpg, "-" );
|
||||||
_gpgme_gpg_add_data ( c->gpg, ciph, 1 );
|
_gpgme_gpg_add_data ( c->gpg, ciph, 1 );
|
||||||
|
_gpgme_gpg_add_arg ( c->gpg, "--" );
|
||||||
_gpgme_gpg_add_data ( c->gpg, plain, 0 );
|
_gpgme_gpg_add_data ( c->gpg, plain, 0 );
|
||||||
|
|
||||||
/* and kick off the process */
|
/* and kick off the process */
|
||||||
@ -102,18 +102,6 @@ gpgme_req_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GpgmeError
|
|
||||||
gpgme_wait_encrypt ( GpgmeCtx c, GpgmeData *r_out )
|
|
||||||
{
|
|
||||||
wait_on_request_or_fail (c);
|
|
||||||
|
|
||||||
fprintf (stderr,"gpgme_wait_encrypt: main\n");
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpgme_encrypt:
|
* gpgme_encrypt:
|
||||||
* @c: The context
|
* @c: The context
|
||||||
@ -131,9 +119,11 @@ GpgmeError
|
|||||||
gpgme_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
gpgme_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
||||||
GpgmeData in, GpgmeData out )
|
GpgmeData in, GpgmeData out )
|
||||||
{
|
{
|
||||||
int rc = gpgme_req_encrypt ( c, recp, in, out );
|
int rc = gpgme_start_encrypt ( c, recp, in, out );
|
||||||
if ( !rc )
|
if ( !rc ) {
|
||||||
rc = gpgme_wait_encrypt ( c, NULL );
|
gpgme_wait (c, 1);
|
||||||
|
c->pending = 0;
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "ops.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpgme_new_context:
|
* gpgme_new_context:
|
||||||
@ -58,10 +58,28 @@ gpgme_new_context (GpgmeCtx *r_ctx)
|
|||||||
void
|
void
|
||||||
gpgme_release_context ( GpgmeCtx c )
|
gpgme_release_context ( GpgmeCtx c )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
_gpgme_gpg_release_object ( c->gpg );
|
||||||
|
_gpgme_release_result ( c );
|
||||||
xfree ( c );
|
xfree ( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_gpgme_release_result ( GpgmeCtx c )
|
||||||
|
{
|
||||||
|
switch (c->result_type) {
|
||||||
|
case RESULT_TYPE_NONE:
|
||||||
|
break;
|
||||||
|
case RESULT_TYPE_VERIFY:
|
||||||
|
_gpgme_release_verify_result ( c->result.verify );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c->result.verify = NULL;
|
||||||
|
c->result_type = RESULT_TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -81,12 +99,6 @@ gpgme_release_context ( GpgmeCtx c )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ typedef struct gpgme_recipient_set_s *GpgmeRecipientSet;
|
|||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
GPGME_EOF = -1,
|
||||||
GPGME_No_Error = 0,
|
GPGME_No_Error = 0,
|
||||||
GPGME_General_Error = 1,
|
GPGME_General_Error = 1,
|
||||||
GPGME_Out_Of_Core = 2,
|
GPGME_Out_Of_Core = 2,
|
||||||
@ -81,12 +82,16 @@ GpgmeError gpgme_new_data ( GpgmeData *r_dh,
|
|||||||
const char *buffer, size_t size, int copy );
|
const char *buffer, size_t size, int copy );
|
||||||
void gpgme_release_data ( GpgmeData dh );
|
void gpgme_release_data ( GpgmeData dh );
|
||||||
GpgmeDataType gpgme_query_data_type ( GpgmeData dh );
|
GpgmeDataType gpgme_query_data_type ( GpgmeData dh );
|
||||||
|
GpgmeError gpgme_rewind_data ( GpgmeData dh );
|
||||||
|
GpgmeError gpgme_read_data ( GpgmeData dh,
|
||||||
|
char *buffer, size_t length, size_t *nread );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Basic GnuPG functions */
|
/* Basic GnuPG functions */
|
||||||
GpgmeError gpgme_req_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
GpgmeError gpgme_start_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
||||||
GpgmeData in, GpgmeData out );
|
GpgmeData in, GpgmeData out );
|
||||||
GpgmeError gpgme_wait_encrypt ( GpgmeCtx c, GpgmeData *r_out );
|
GpgmeError gpgme_start_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text );
|
||||||
|
|
||||||
|
|
||||||
/* Key management functions */
|
/* Key management functions */
|
||||||
@ -99,6 +104,7 @@ GpgmeError gpgme_wait_encrypt ( GpgmeCtx c, GpgmeData *r_out );
|
|||||||
/* Convenience functions for syncronous usage */
|
/* Convenience functions for syncronous usage */
|
||||||
GpgmeError gpgme_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
GpgmeError gpgme_encrypt ( GpgmeCtx c, GpgmeRecipientSet recp,
|
||||||
GpgmeData in, GpgmeData out );
|
GpgmeData in, GpgmeData out );
|
||||||
|
GpgmeError gpgme_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text );
|
||||||
|
|
||||||
|
|
||||||
/* miscellaneous functions */
|
/* miscellaneous functions */
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
/*-- gpgme.c --*/
|
||||||
|
void _gpgme_release_result ( GpgmeCtx c );
|
||||||
|
|
||||||
|
|
||||||
/*-- recipient.c --*/
|
/*-- recipient.c --*/
|
||||||
void _gpgme_append_gpg_args_from_recipients (
|
void _gpgme_append_gpg_args_from_recipients (
|
||||||
@ -33,8 +36,11 @@ void _gpgme_append_gpg_args_from_recipients (
|
|||||||
/*-- data.c --*/
|
/*-- data.c --*/
|
||||||
GpgmeDataMode _gpgme_query_data_mode ( GpgmeData dh );
|
GpgmeDataMode _gpgme_query_data_mode ( GpgmeData dh );
|
||||||
void _gpgme_set_data_mode ( GpgmeData dh, GpgmeDataMode mode );
|
void _gpgme_set_data_mode ( GpgmeData dh, GpgmeDataMode mode );
|
||||||
|
GpgmeError _gpgme_append_data ( GpgmeData dh,
|
||||||
|
const char *buffer, size_t length );
|
||||||
|
|
||||||
|
/*-- verify.c --*/
|
||||||
|
void _gpgme_release_verify_result ( VerifyResult res );
|
||||||
|
|
||||||
|
|
||||||
#endif /* OPS_H */
|
#endif /* OPS_H */
|
||||||
|
144
gpgme/rungpg.c
144
gpgme/rungpg.c
@ -29,6 +29,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "gpgme.h"
|
#include "gpgme.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -84,6 +85,7 @@ struct gpg_object_s {
|
|||||||
|
|
||||||
static void kill_gpg ( GpgObject gpg );
|
static void kill_gpg ( GpgObject gpg );
|
||||||
static void free_argv ( char **argv );
|
static void free_argv ( char **argv );
|
||||||
|
static void free_fd_data_map ( struct fd_data_map_s *fd_data_map );
|
||||||
static int gpg_status_handler ( void *opaque, pid_t pid, int fd );
|
static int gpg_status_handler ( void *opaque, pid_t pid, int fd );
|
||||||
static int gpg_inbound_handler ( void *opaque, pid_t pid, int fd );
|
static int gpg_inbound_handler ( void *opaque, pid_t pid, int fd );
|
||||||
static int gpg_outbound_handler ( void *opaque, pid_t pid, int fd );
|
static int gpg_outbound_handler ( void *opaque, pid_t pid, int fd );
|
||||||
@ -96,7 +98,6 @@ GpgmeError
|
|||||||
_gpgme_gpg_new_object ( GpgObject *r_gpg )
|
_gpgme_gpg_new_object ( GpgObject *r_gpg )
|
||||||
{
|
{
|
||||||
GpgObject gpg;
|
GpgObject gpg;
|
||||||
char buf[20];
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
gpg = xtrycalloc ( 1, sizeof *gpg );
|
gpg = xtrycalloc ( 1, sizeof *gpg );
|
||||||
@ -109,9 +110,6 @@ _gpgme_gpg_new_object ( GpgObject *r_gpg )
|
|||||||
gpg->status.fd[0] = -1;
|
gpg->status.fd[0] = -1;
|
||||||
gpg->status.fd[1] = -1;
|
gpg->status.fd[1] = -1;
|
||||||
|
|
||||||
/* The name of the beast will be gpg - so put it into argv[0] */
|
|
||||||
_gpgme_gpg_add_arg ( gpg, "gpg" );
|
|
||||||
|
|
||||||
/* allocate the read buffer for the status pipe */
|
/* allocate the read buffer for the status pipe */
|
||||||
gpg->status.bufsize = 1024;
|
gpg->status.bufsize = 1024;
|
||||||
gpg->status.readpos = 0;
|
gpg->status.readpos = 0;
|
||||||
@ -128,8 +126,13 @@ _gpgme_gpg_new_object ( GpgObject *r_gpg )
|
|||||||
}
|
}
|
||||||
gpg->status.eof = 0;
|
gpg->status.eof = 0;
|
||||||
_gpgme_gpg_add_arg ( gpg, "--status-fd" );
|
_gpgme_gpg_add_arg ( gpg, "--status-fd" );
|
||||||
sprintf ( buf, "%d", gpg->status.fd[1]);
|
{
|
||||||
_gpgme_gpg_add_arg ( gpg, buf );
|
char buf[25];
|
||||||
|
sprintf ( buf, "%d", gpg->status.fd[1]);
|
||||||
|
_gpgme_gpg_add_arg ( gpg, buf );
|
||||||
|
}
|
||||||
|
_gpgme_gpg_add_arg ( gpg, "--batch" );
|
||||||
|
_gpgme_gpg_add_arg ( gpg, "--no-tty" );
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@ -153,8 +156,7 @@ _gpgme_gpg_release_object ( GpgObject gpg )
|
|||||||
close (gpg->status.fd[0]);
|
close (gpg->status.fd[0]);
|
||||||
if (gpg->status.fd[1] != -1 )
|
if (gpg->status.fd[1] != -1 )
|
||||||
close (gpg->status.fd[1]);
|
close (gpg->status.fd[1]);
|
||||||
/* fixme: walk over the data map and close all fds */
|
free_fd_data_map (gpg->fd_data_map);
|
||||||
xfree (gpg->fd_data_map);
|
|
||||||
kill_gpg (gpg); /* fixme: should be done asyncronously */
|
kill_gpg (gpg); /* fixme: should be done asyncronously */
|
||||||
xfree (gpg);
|
xfree (gpg);
|
||||||
}
|
}
|
||||||
@ -162,6 +164,7 @@ _gpgme_gpg_release_object ( GpgObject gpg )
|
|||||||
static void
|
static void
|
||||||
kill_gpg ( GpgObject gpg )
|
kill_gpg ( GpgObject gpg )
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if ( gpg->running ) {
|
if ( gpg->running ) {
|
||||||
/* still running? Must send a killer */
|
/* still running? Must send a killer */
|
||||||
kill ( gpg->pid, SIGTERM);
|
kill ( gpg->pid, SIGTERM);
|
||||||
@ -172,6 +175,7 @@ kill_gpg ( GpgObject gpg )
|
|||||||
}
|
}
|
||||||
gpg->running = 0;
|
gpg->running = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -238,6 +242,21 @@ free_argv ( char **argv )
|
|||||||
xfree (argv);
|
xfree (argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_fd_data_map ( struct fd_data_map_s *fd_data_map )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; fd_data_map[i].data; i++ ) {
|
||||||
|
if ( fd_data_map[i].fd != -1 )
|
||||||
|
close (fd_data_map[i].fd);
|
||||||
|
if ( fd_data_map[i].peer_fd != -1 )
|
||||||
|
close (fd_data_map[i].peer_fd);
|
||||||
|
/* don't realease data because this is only a reference */
|
||||||
|
}
|
||||||
|
xfree (fd_data_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static GpgmeError
|
static GpgmeError
|
||||||
build_argv ( GpgObject gpg )
|
build_argv ( GpgObject gpg )
|
||||||
@ -246,22 +265,32 @@ build_argv ( GpgObject gpg )
|
|||||||
struct fd_data_map_s *fd_data_map;
|
struct fd_data_map_s *fd_data_map;
|
||||||
size_t datac=0, argc=0;
|
size_t datac=0, argc=0;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
int need_special = 0;
|
||||||
|
|
||||||
if ( gpg->argv ) {
|
if ( gpg->argv ) {
|
||||||
free_argv ( gpg->argv );
|
free_argv ( gpg->argv );
|
||||||
gpg->argv = NULL;
|
gpg->argv = NULL;
|
||||||
}
|
}
|
||||||
/* fixme: release fd_data_map */
|
if (gpg->fd_data_map) {
|
||||||
|
free_fd_data_map (gpg->fd_data_map);
|
||||||
|
gpg->fd_data_map = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc++; /* for argv[0] */
|
||||||
for ( a=gpg->arglist; a; a = a->next ) {
|
for ( a=gpg->arglist; a; a = a->next ) {
|
||||||
argc++;
|
argc++;
|
||||||
if (a->data) {
|
if (a->data) {
|
||||||
fprintf (stderr, "build_argv: data\n" );
|
/*fprintf (stderr, "build_argv: data\n" );*/
|
||||||
datac++;
|
datac++;
|
||||||
|
if ( a->dup_to == -1 )
|
||||||
|
need_special = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
|
||||||
}
|
}
|
||||||
else
|
|
||||||
fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );
|
|
||||||
}
|
}
|
||||||
|
if ( need_special )
|
||||||
|
argc++;
|
||||||
|
|
||||||
argv = xtrycalloc ( argc+1, sizeof *argv );
|
argv = xtrycalloc ( argc+1, sizeof *argv );
|
||||||
if (!argv)
|
if (!argv)
|
||||||
@ -273,6 +302,22 @@ build_argv ( GpgObject gpg )
|
|||||||
}
|
}
|
||||||
|
|
||||||
argc = datac = 0;
|
argc = datac = 0;
|
||||||
|
argv[argc] = xtrystrdup ( "gpg" ); /* argv[0] */
|
||||||
|
if (!argv[argc]) {
|
||||||
|
xfree (fd_data_map);
|
||||||
|
free_argv (argv);
|
||||||
|
return mk_error (Out_Of_Core);
|
||||||
|
}
|
||||||
|
argc++;
|
||||||
|
if ( need_special ) {
|
||||||
|
argv[argc] = xtrystrdup ( "--enable-special-filenames" );
|
||||||
|
if (!argv[argc]) {
|
||||||
|
xfree (fd_data_map);
|
||||||
|
free_argv (argv);
|
||||||
|
return mk_error (Out_Of_Core);
|
||||||
|
}
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
for ( a=gpg->arglist; a; a = a->next ) {
|
for ( a=gpg->arglist; a; a = a->next ) {
|
||||||
if ( a->data ) {
|
if ( a->data ) {
|
||||||
switch ( _gpgme_query_data_mode (a->data) ) {
|
switch ( _gpgme_query_data_mode (a->data) ) {
|
||||||
@ -328,6 +373,16 @@ build_argv ( GpgObject gpg )
|
|||||||
}
|
}
|
||||||
fd_data_map[datac].data = a->data;
|
fd_data_map[datac].data = a->data;
|
||||||
fd_data_map[datac].dup_to = a->dup_to;
|
fd_data_map[datac].dup_to = a->dup_to;
|
||||||
|
if ( a->dup_to == -1 ) {
|
||||||
|
argv[argc] = xtrymalloc ( 25 );
|
||||||
|
if (!argv[argc]) {
|
||||||
|
xfree (fd_data_map);
|
||||||
|
free_argv (argv);
|
||||||
|
return mk_error (Out_Of_Core);
|
||||||
|
}
|
||||||
|
sprintf ( argv[argc], "-&%d", fd_data_map[datac].peer_fd );
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
datac++;
|
datac++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -337,8 +392,8 @@ build_argv ( GpgObject gpg )
|
|||||||
free_argv (argv);
|
free_argv (argv);
|
||||||
return mk_error (Out_Of_Core);
|
return mk_error (Out_Of_Core);
|
||||||
}
|
}
|
||||||
|
argc++;
|
||||||
}
|
}
|
||||||
argc++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpg->argv = argv;
|
gpg->argv = argv;
|
||||||
@ -372,6 +427,11 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( !pid ) { /* child */
|
if ( !pid ) { /* child */
|
||||||
|
int duped_stdin = 0;
|
||||||
|
int duped_stderr = 0;
|
||||||
|
|
||||||
|
close (gpg->status.fd[0]);
|
||||||
|
|
||||||
for (i=0; gpg->fd_data_map[i].data; i++ ) {
|
for (i=0; gpg->fd_data_map[i].data; i++ ) {
|
||||||
close (gpg->fd_data_map[i].fd);
|
close (gpg->fd_data_map[i].fd);
|
||||||
gpg->fd_data_map[i].fd = -1;
|
gpg->fd_data_map[i].fd = -1;
|
||||||
@ -382,20 +442,49 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
|
|||||||
strerror (errno));
|
strerror (errno));
|
||||||
_exit (8);
|
_exit (8);
|
||||||
}
|
}
|
||||||
|
if ( gpg->fd_data_map[i].dup_to == 0 )
|
||||||
|
duped_stdin=1;
|
||||||
|
if ( gpg->fd_data_map[i].dup_to == 2 )
|
||||||
|
duped_stderr=1;
|
||||||
close ( gpg->fd_data_map[i].peer_fd );
|
close ( gpg->fd_data_map[i].peer_fd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( gpg->status.fd[0] != -1 )
|
if( !duped_stdin || !duped_stderr ) {
|
||||||
close (gpg->status.fd[0]);
|
int fd = open ( "/dev/null", O_RDONLY );
|
||||||
|
if ( fd == -1 ) {
|
||||||
|
fprintf (stderr,"can't open `/dev/null': %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
_exit (8);
|
||||||
|
}
|
||||||
|
/* Make sure that gpg has a connected stdin */
|
||||||
|
if ( !duped_stdin ) {
|
||||||
|
if ( dup2 ( fd, 0 ) == -1 ) {
|
||||||
|
fprintf (stderr,"dup2(/dev/null, 0) failed: %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
_exit (8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* We normally don't want all the normal output */
|
||||||
|
if ( !duped_stderr ) {
|
||||||
|
if ( dup2 ( fd, 2 ) == -1 ) {
|
||||||
|
fprintf (stderr,"dup2(dev/null, 2) failed: %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
_exit (8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: dup /dev/null to stdin if nothing is connected to stdin */
|
execv ("./gpg", gpg->argv );
|
||||||
execv ("/usr/local/bin/gpg", gpg->argv );
|
fprintf (stderr,"exec of gpg failed\n");
|
||||||
fprintf (stderr,"exec of gpg failed\n"); fflush (stderr);
|
|
||||||
_exit (8);
|
_exit (8);
|
||||||
}
|
}
|
||||||
|
/* parent */
|
||||||
gpg->pid = pid;
|
gpg->pid = pid;
|
||||||
|
|
||||||
|
/*_gpgme_register_term_handler ( closure, closure_value, pid );*/
|
||||||
|
|
||||||
if ( gpg->status.fd[1] != -1 )
|
if ( gpg->status.fd[1] != -1 )
|
||||||
close (gpg->status.fd[1]);
|
close (gpg->status.fd[1]);
|
||||||
if ( _gpgme_register_pipe_handler ( opaque, gpg_status_handler,
|
if ( _gpgme_register_pipe_handler ( opaque, gpg_status_handler,
|
||||||
@ -424,7 +513,6 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
|
|||||||
|
|
||||||
gpg->running = 1;
|
gpg->running = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -432,6 +520,7 @@ static int
|
|||||||
gpg_inbound_handler ( void *opaque, pid_t pid, int fd )
|
gpg_inbound_handler ( void *opaque, pid_t pid, int fd )
|
||||||
{
|
{
|
||||||
GpgmeData dh = opaque;
|
GpgmeData dh = opaque;
|
||||||
|
GpgmeError err;
|
||||||
int nread;
|
int nread;
|
||||||
char buf[200];
|
char buf[200];
|
||||||
|
|
||||||
@ -449,6 +538,18 @@ gpg_inbound_handler ( void *opaque, pid_t pid, int fd )
|
|||||||
else if (!nread)
|
else if (!nread)
|
||||||
return 1; /* eof */
|
return 1; /* eof */
|
||||||
|
|
||||||
|
/* We could improve this with a GpgmeData function which takes
|
||||||
|
* the read function or provides a memory area for writing to it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
err = _gpgme_append_data ( dh, buf, nread );
|
||||||
|
if ( err ) {
|
||||||
|
fprintf (stderr, "_gpgme_append_data failed: %s\n",
|
||||||
|
gpgme_strerror(err));
|
||||||
|
/* Fixme: we should close the pipe or read it to /dev/null in
|
||||||
|
* this case. Returnin EOF is not sufficient */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -520,8 +621,11 @@ gpg_status_handler ( void *opaque, pid_t pid, int fd )
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
status_cmp (const struct status_table_s *a, const struct status_table_s *b)
|
status_cmp (const void *ap, const void *bp)
|
||||||
{
|
{
|
||||||
|
const struct status_table_s *a = ap;
|
||||||
|
const struct status_table_s *b = bp;
|
||||||
|
|
||||||
return strcmp (a->name, b->name);
|
return strcmp (a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,11 @@ struct gpg_object_s;
|
|||||||
typedef struct gpg_object_s *GpgObject;
|
typedef struct gpg_object_s *GpgObject;
|
||||||
|
|
||||||
|
|
||||||
|
/*-- verify.c --*/
|
||||||
|
struct verify_result_s;
|
||||||
|
typedef struct verify_result_s *VerifyResult;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* TYPES_H */
|
#endif /* TYPES_H */
|
||||||
|
|
||||||
|
198
gpgme/verify.c
Normal file
198
gpgme/verify.c
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/* verify.c - signature verification
|
||||||
|
* Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GPGME is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "ops.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VERIFY_STATUS_NONE = 0,
|
||||||
|
VERIFY_STATUS_NOSIG,
|
||||||
|
VERIFY_STATUS_NOKEY,
|
||||||
|
VERIFY_STATUS_ERROR,
|
||||||
|
VERIFY_STATUS_BAD,
|
||||||
|
VERIFY_STATUS_GOOD
|
||||||
|
} VerifyStatus;
|
||||||
|
|
||||||
|
struct verify_result_s {
|
||||||
|
VerifyStatus status;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_gpgme_release_verify_result ( VerifyResult res )
|
||||||
|
{
|
||||||
|
xfree (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
verify_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
|
||||||
|
{
|
||||||
|
if ( ctx->out_of_core )
|
||||||
|
return;
|
||||||
|
if ( ctx->result_type == RESULT_TYPE_NONE ) {
|
||||||
|
assert ( !ctx->result.verify );
|
||||||
|
ctx->result.verify = xtrycalloc ( 1, sizeof *ctx->result.verify );
|
||||||
|
if ( !ctx->result.verify ) {
|
||||||
|
ctx->out_of_core = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx->result_type = RESULT_TYPE_VERIFY;
|
||||||
|
}
|
||||||
|
assert ( ctx->result_type == RESULT_TYPE_VERIFY );
|
||||||
|
|
||||||
|
/* FIXME: For now we handle only one signature */
|
||||||
|
/* FIXME: Collect useful information */
|
||||||
|
switch (code) {
|
||||||
|
case STATUS_GOODSIG:
|
||||||
|
ctx->result.verify->status = VERIFY_STATUS_GOOD;
|
||||||
|
break;
|
||||||
|
case STATUS_BADSIG:
|
||||||
|
ctx->result.verify->status = VERIFY_STATUS_BAD;
|
||||||
|
break;
|
||||||
|
case STATUS_ERRSIG:
|
||||||
|
ctx->result.verify->status = VERIFY_STATUS_ERROR;
|
||||||
|
/* FIXME: distinguish between a regular error and a missing key.
|
||||||
|
* this is encoded in the args. */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* ignore all other codes */
|
||||||
|
fprintf (stderr, "verify_status: code=%d not handled\n", code );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GpgmeError
|
||||||
|
gpgme_start_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text )
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fail_on_pending_request( c );
|
||||||
|
c->pending = 1;
|
||||||
|
|
||||||
|
_gpgme_release_result (c);
|
||||||
|
c->out_of_core = 0;
|
||||||
|
|
||||||
|
/* create a process object.
|
||||||
|
* To optimize this, we should reuse an existing one and
|
||||||
|
* run gpg in the new --pipemode (I started with this but it is
|
||||||
|
* not yet finished) */
|
||||||
|
if ( c->gpg ) {
|
||||||
|
_gpgme_gpg_release_object ( c->gpg );
|
||||||
|
c->gpg = NULL;
|
||||||
|
}
|
||||||
|
rc = _gpgme_gpg_new_object ( &c->gpg );
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
_gpgme_gpg_set_status_handler ( c->gpg, verify_status_handler, c );
|
||||||
|
|
||||||
|
/* build the commandline */
|
||||||
|
_gpgme_gpg_add_arg ( c->gpg, "--verify" );
|
||||||
|
for ( i=0; i < c->verbosity; i++ )
|
||||||
|
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
|
||||||
|
|
||||||
|
|
||||||
|
/* Check the supplied data */
|
||||||
|
if ( gpgme_query_data_type (sig) == GPGME_DATA_TYPE_NONE ) {
|
||||||
|
rc = mk_error (No_Data);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if ( text && gpgme_query_data_type (text) == GPGME_DATA_TYPE_NONE ) {
|
||||||
|
rc = mk_error (No_Data);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
_gpgme_set_data_mode (sig, GPGME_DATA_MODE_OUT );
|
||||||
|
if (text) /* detached signature */
|
||||||
|
_gpgme_set_data_mode (text, GPGME_DATA_MODE_OUT );
|
||||||
|
/* Tell the gpg object about the data */
|
||||||
|
_gpgme_gpg_add_arg ( c->gpg, "--" );
|
||||||
|
_gpgme_gpg_add_data ( c->gpg, sig, -1 );
|
||||||
|
if (text)
|
||||||
|
_gpgme_gpg_add_data ( c->gpg, text, 0 );
|
||||||
|
|
||||||
|
/* and kick off the process */
|
||||||
|
rc = _gpgme_gpg_spawn ( c->gpg, c );
|
||||||
|
|
||||||
|
leave:
|
||||||
|
if (rc) {
|
||||||
|
c->pending = 0;
|
||||||
|
_gpgme_gpg_release_object ( c->gpg ); c->gpg = NULL;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GpgmeError
|
||||||
|
gpgme_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text )
|
||||||
|
{
|
||||||
|
int rc = gpgme_start_verify ( c, sig, text );
|
||||||
|
if ( !rc ) {
|
||||||
|
gpgme_wait (c, 1);
|
||||||
|
if ( c->result_type != RESULT_TYPE_VERIFY )
|
||||||
|
rc = mk_error (General_Error);
|
||||||
|
else if ( c->out_of_core )
|
||||||
|
rc = mk_error (Out_Of_Core);
|
||||||
|
else {
|
||||||
|
assert ( c->result.verify );
|
||||||
|
switch ( c->result.verify->status ) {
|
||||||
|
case VERIFY_STATUS_NONE:
|
||||||
|
fputs ("Verification Status: None\n", stdout);
|
||||||
|
break;
|
||||||
|
case VERIFY_STATUS_NOSIG:
|
||||||
|
fputs ("Verification Status: No Signature\n", stdout);
|
||||||
|
break;
|
||||||
|
case VERIFY_STATUS_GOOD:
|
||||||
|
fputs ("Verification Status: Good\n", stdout);
|
||||||
|
break;
|
||||||
|
case VERIFY_STATUS_BAD:
|
||||||
|
fputs ("Verification Status: Bad\n", stdout);
|
||||||
|
break;
|
||||||
|
case VERIFY_STATUS_NOKEY:
|
||||||
|
fputs ("Verification Status: No Key\n", stdout);
|
||||||
|
break;
|
||||||
|
case VERIFY_STATUS_ERROR:
|
||||||
|
fputs ("Verification Status: Error\n", stdout);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c->pending = 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
65
gpgme/wait.c
65
gpgme/wait.c
@ -98,6 +98,53 @@ queue_item_from_context ( GpgmeCtx ctx )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
propagate_term_results ( const struct wait_queue_item_s *first_q )
|
||||||
|
{
|
||||||
|
struct wait_queue_item_s *q;
|
||||||
|
|
||||||
|
for (q=wait_queue; q; q = q->next) {
|
||||||
|
if ( q->used && q != first_q && !q->exited
|
||||||
|
&& q->pid == first_q->pid ) {
|
||||||
|
q->exited = first_q->exited;
|
||||||
|
q->exit_status = first_q->exit_status;
|
||||||
|
q->exit_signal = first_q->exit_signal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
count_active_fds ( pid_t pid )
|
||||||
|
{
|
||||||
|
struct wait_queue_item_s *q;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (q=wait_queue; q; q = q->next) {
|
||||||
|
if ( q->used && q->active && q->pid == pid )
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* remove the given process from the queue */
|
||||||
|
static void
|
||||||
|
remove_process ( pid_t pid )
|
||||||
|
{
|
||||||
|
struct wait_queue_item_s *q;
|
||||||
|
|
||||||
|
for (q=wait_queue; q; q = q->next) {
|
||||||
|
if ( q->used ) {
|
||||||
|
close (q->fd);
|
||||||
|
q->handler = NULL;
|
||||||
|
q->ctx = NULL;
|
||||||
|
q->used = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpgme_wait:
|
* gpgme_wait:
|
||||||
* @c:
|
* @c:
|
||||||
@ -127,7 +174,9 @@ gpgme_wait ( GpgmeCtx c, int hang )
|
|||||||
q = queue_item_from_context ( c );
|
q = queue_item_from_context ( c );
|
||||||
assert (q);
|
assert (q);
|
||||||
|
|
||||||
if ( waitpid ( q->pid, &status, WNOHANG ) == q->pid ) {
|
if (q->exited)
|
||||||
|
;
|
||||||
|
else if ( waitpid ( q->pid, &status, WNOHANG ) == q->pid ) {
|
||||||
q->exited = 1;
|
q->exited = 1;
|
||||||
if ( WIFSIGNALED (status) ) {
|
if ( WIFSIGNALED (status) ) {
|
||||||
q->exit_status = 4; /* Need some value here */
|
q->exit_status = 4; /* Need some value here */
|
||||||
@ -140,8 +189,18 @@ gpgme_wait ( GpgmeCtx c, int hang )
|
|||||||
q->exited++;
|
q->exited++;
|
||||||
q->exit_status = 4;
|
q->exit_status = 4;
|
||||||
}
|
}
|
||||||
/* okay, the process has terminated - we are ready */
|
propagate_term_results (q);
|
||||||
hang = 0;
|
}
|
||||||
|
|
||||||
|
if ( q->exited ) {
|
||||||
|
if ( !count_active_fds (q->pid) ) {
|
||||||
|
/* Hmmm, as long as we don't have a callback for
|
||||||
|
* the exit status, we have no use for these
|
||||||
|
* values and therefore we can remove this from
|
||||||
|
* the queue */
|
||||||
|
remove_process (q->pid);
|
||||||
|
hang = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (hang);
|
} while (hang);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Process this file with automake to create Makefile.in
|
## Process this file with automake to create Makefile.in
|
||||||
|
|
||||||
TESTS = t-encrypt
|
TESTS = t-encrypt t-verify
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
|
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
|
||||||
|
|
||||||
|
@ -31,6 +31,23 @@
|
|||||||
exit (1); } \
|
exit (1); } \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_data ( GpgmeData dh )
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
size_t nread;
|
||||||
|
GpgmeError err;
|
||||||
|
|
||||||
|
err = gpgme_rewind_data ( dh );
|
||||||
|
fail_if_err (err);
|
||||||
|
while ( !(err = gpgme_read_data ( dh, buf, 100, &nread )) ) {
|
||||||
|
fwrite ( buf, nread, 1, stdout );
|
||||||
|
}
|
||||||
|
if (err != GPGME_EOF)
|
||||||
|
fail_if_err (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv )
|
main (int argc, char **argv )
|
||||||
@ -40,10 +57,11 @@ main (int argc, char **argv )
|
|||||||
GpgmeData in, out;
|
GpgmeData in, out;
|
||||||
GpgmeRecipientSet rset;
|
GpgmeRecipientSet rset;
|
||||||
|
|
||||||
|
do {
|
||||||
err = gpgme_new_context (&ctx);
|
err = gpgme_new_context (&ctx);
|
||||||
fail_if_err (err);
|
fail_if_err (err);
|
||||||
|
|
||||||
err = gpgme_new_data ( &in, "Hallo Leute", 11, 0 );
|
err = gpgme_new_data ( &in, "Hallo Leute\n", 12, 0 );
|
||||||
fail_if_err (err);
|
fail_if_err (err);
|
||||||
|
|
||||||
err = gpgme_new_data ( &out, NULL, 0,0 );
|
err = gpgme_new_data ( &out, NULL, 0,0 );
|
||||||
@ -53,16 +71,24 @@ main (int argc, char **argv )
|
|||||||
fail_if_err (err);
|
fail_if_err (err);
|
||||||
err = gpgme_add_recipient (rset, "Bob");
|
err = gpgme_add_recipient (rset, "Bob");
|
||||||
fail_if_err (err);
|
fail_if_err (err);
|
||||||
|
err = gpgme_add_recipient (rset, "Alpha");
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
|
||||||
err = gpgme_encrypt (ctx, rset, in, out );
|
err = gpgme_encrypt (ctx, rset, in, out );
|
||||||
fail_if_err (err);
|
fail_if_err (err);
|
||||||
|
|
||||||
|
fflush (NULL);
|
||||||
|
fputs ("Begin Result:\n", stdout );
|
||||||
|
print_data (out);
|
||||||
|
fputs ("End Result.\n", stdout );
|
||||||
|
|
||||||
gpgme_release_recipient_set (rset);
|
gpgme_release_recipient_set (rset);
|
||||||
gpgme_release_data (in);
|
gpgme_release_data (in);
|
||||||
gpgme_release_data (out);
|
gpgme_release_data (out);
|
||||||
gpgme_release_context (ctx);
|
gpgme_release_context (ctx);
|
||||||
|
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
85
tests/t-verify.c
Normal file
85
tests/t-verify.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* t-verify.c - regression test
|
||||||
|
* Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GPGME is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "../gpgme/gpgme.h"
|
||||||
|
|
||||||
|
static const char test_text1[] = "Just GNU it!\n";
|
||||||
|
static const char test_text1f[]= "Just GNU it?\n";
|
||||||
|
static const char test_sig1[] =
|
||||||
|
"-----BEGIN PGP SIGNATURE-----\n"
|
||||||
|
"\n"
|
||||||
|
"iEYEABECAAYFAjoKgjIACgkQLXJ8x2hpdzQMSwCeO/xUrhysZ7zJKPf/FyXA//u1\n"
|
||||||
|
"ZgIAn0204PBR7yxSdQx6CFxugstNqmRv\n"
|
||||||
|
"=yku6\n"
|
||||||
|
"-----END PGP SIGNATURE-----\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
#define fail_if_err(a) do { if(a) { \
|
||||||
|
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
|
||||||
|
__FILE__, __LINE__, gpgme_strerror(a)); \
|
||||||
|
exit (1); } \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv )
|
||||||
|
{
|
||||||
|
GpgmeCtx ctx;
|
||||||
|
GpgmeError err;
|
||||||
|
GpgmeData sig, text;
|
||||||
|
|
||||||
|
err = gpgme_new_context (&ctx);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
do {
|
||||||
|
err = gpgme_new_data ( &text, test_text1, strlen (test_text1), 0 );
|
||||||
|
fail_if_err (err);
|
||||||
|
err = gpgme_new_data ( &sig, test_sig1, strlen (test_sig1), 0 );
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
puts ("checking a valid message:\n");
|
||||||
|
err = gpgme_verify (ctx, sig, text );
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
puts ("checking a manipulated message:\n");
|
||||||
|
gpgme_release_data (text);
|
||||||
|
err = gpgme_new_data ( &text, test_text1f, strlen (test_text1f), 0 );
|
||||||
|
fail_if_err (err);
|
||||||
|
gpgme_rewind_data ( sig );
|
||||||
|
err = gpgme_verify (ctx, sig, text );
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
gpgme_release_data (sig);
|
||||||
|
gpgme_release_data (text);
|
||||||
|
|
||||||
|
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
|
||||||
|
gpgme_release_context (ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user