aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keyserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keyserver.c')
-rw-r--r--g10/keyserver.c310
1 files changed, 67 insertions, 243 deletions
diff --git a/g10/keyserver.c b/g10/keyserver.c
index 7e5f28731..eb1fc0686 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -34,21 +34,13 @@
#include "options.h"
#include "memory.h"
#include "keydb.h"
-#include "cipher.h"
#include "status.h"
+#include "exec.h"
#include "i18n.h"
#include "util.h"
#include "main.h"
#include "hkp.h"
-#ifndef HAVE_MKDTEMP
-char *mkdtemp(char *template);
-#endif
-
-#if !(defined(HAVE_FORK) && defined(HAVE_PIPE))
-#define KEYSERVER_TEMPFILE_ONLY
-#endif
-
#define KEYSERVER_PROTO_VERSION 0
#define GET 0
@@ -74,7 +66,7 @@ parse_keyserver_options(char *options)
opt.keyserver_options.include_disabled=1;
else if(strcasecmp(tok,"no-include-disabled")==0)
opt.keyserver_options.include_disabled=0;
-#ifdef KEYSERVER_TEMPFILE_ONLY
+#ifdef EXEC_TEMPFILE_ONLY
else if(strcasecmp(tok,"use-temp-files")==0 ||
strcasecmp(tok,"no-use-temp-files")==0)
log_info(_("Warning: keyserver option \"%s\" is not used "
@@ -261,167 +253,75 @@ print_keyinfo(int count,char *keystring,u32 *keyid)
return 0;
}
+#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\""
+#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\""
static int
-keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
+keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count,int *prog)
{
- int ret=KEYSERVER_INTERNAL_ERROR,i,to[2]={-1,-1},from[2]={-1,-1};
- pid_t child=0;
+ int ret=0,i,gotversion=0;
STRLIST temp;
unsigned int maxlen=256,buflen;
- char *filename=NULL,*tempfile_in=NULL,*tempfile_out=NULL,*searchstr=NULL;
- char *tempdir=NULL;
+ char *command=NULL,*searchstr=NULL;
byte *line=NULL;
- FILE *tochild=NULL;
- IOBUF fromchild=NULL;
- int gotversion=0,madedir=0;
-
-#ifndef __MINGW32__
- /* Don't allow to be setuid when we are going to create temporary
- files or directories - yes, this is a bit paranoid */
- if (getuid() != geteuid() )
- BUG ();
-#endif
-
- if(opt.keyserver_disable && !opt.no_perm_warn)
- {
- log_info(_("keyserver scheme \"%s\" disabled due to unsafe "
- "options file permissions\n"),opt.keyserver_scheme);
+ struct exec_info *spawn;
- return KEYSERVER_SCHEME_NOT_FOUND;
- }
+#ifdef EXEC_TEMPFILE_ONLY
+ opt.keyserver_options.use_temp_files=1;
+#endif
/* Build the filename for the helper to execute */
- filename=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1);
-
-
- strcpy(filename,"gpgkeys_");
- strcat(filename,opt.keyserver_scheme);
+ command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1);
+ strcpy(command,"gpgkeys_");
+ strcat(command,opt.keyserver_scheme);
if(opt.keyserver_options.use_temp_files)
{
- const char *tmp=get_temp_dir();
-
- tempdir=m_alloc(strlen(tmp)+1+10+1);
- sprintf(tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp);
-
- if(mkdtemp(tempdir)==NULL)
+ if(opt.keyserver_options.keep_temp_files)
{
- log_error(_("%s: can't create temp directory: %s\n"),
- tempdir,strerror(errno));
- goto fail;
+ command=m_realloc(command,strlen(command)+
+ strlen(KEYSERVER_ARGS_KEEP)+1);
+ strcat(command,KEYSERVER_ARGS_KEEP);
}
-
- madedir=1;
-
- tempfile_in=m_alloc(strlen(tempdir)+1+10+1);
- sprintf(tempfile_in,"%s" DIRSEP_S "ksrvin" EXTSEP_S "txt",tempdir);
-
- tempfile_out=m_alloc(strlen(tempdir)+1+11+1);
- sprintf(tempfile_out,"%s" DIRSEP_S "ksrvout" EXTSEP_S "txt",tempdir);
-
- tochild=fopen(tempfile_in,"w");
- if(tochild==NULL)
+ else
{
- log_error(_("%s: can't create: %s\n"),tempfile_in,strerror(errno));
- goto fail;
+ command=m_realloc(command,strlen(command)+
+ strlen(KEYSERVER_ARGS_NOKEEP)+1);
+ strcat(command,KEYSERVER_ARGS_NOKEEP);
}
+
+ ret=exec_write(&spawn,NULL,command,0,0);
}
else
- {
- if(pipe(to)==-1)
- goto fail;
-
- if(pipe(from)==-1)
- goto fail;
-
- if((child=fork())==-1)
- goto fail;
+ ret=exec_write(&spawn,command,NULL,0,0);
- if(child==0)
- {
- /* I'm the child */
-
- /* implied close of STDERR */
- if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
- _exit(KEYSERVER_INTERNAL_ERROR);
-
- close(from[0]);
- from[0]=-1;
-
- /* implied close of STDOUT */
- if(dup2(from[1],STDOUT_FILENO)==-1)
- _exit(KEYSERVER_INTERNAL_ERROR);
-
- close(to[1]);
- to[1]=-1;
-
- /* implied close of STDIN */
- if(dup2(to[0],STDIN_FILENO)==-1)
- _exit(KEYSERVER_INTERNAL_ERROR);
-
- execlp(filename,filename,NULL);
-
- /* If we get this far the exec failed. Clean up and return. */
-
- if(opt.keyserver_options.verbose>2)
- log_error(_("unable to execute %s: %s\n"),
- filename,strerror(errno));
-
- if(errno==ENOENT)
- _exit(KEYSERVER_SCHEME_NOT_FOUND);
-
- _exit(KEYSERVER_INTERNAL_ERROR);
- }
-
- /* I'm the parent */
-
- close(to[0]);
- to[0]=-1;
-
- tochild=fdopen(to[1],"w");
- if(tochild==NULL)
- {
- ret=G10ERR_WRITE_FILE;
- close(to[1]);
- goto fail;
- }
-
- close(from[1]);
- from[1]=-1;
-
- fromchild=iobuf_fdopen(from[0],"r");
- if(fromchild==NULL)
- {
- ret=G10ERR_READ_FILE;
- goto fail;
- }
- }
+ if(ret)
+ goto fail;
- fprintf(tochild,"# This is a gpg keyserver communications file\n");
- fprintf(tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
- fprintf(tochild,"PROGRAM %s\n",VERSION);
- fprintf(tochild,"HOST %s\n",opt.keyserver_host);
+ fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n");
+ fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
+ fprintf(spawn->tochild,"PROGRAM %s\n",VERSION);
+ fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host);
if(atoi(opt.keyserver_port)>0)
- fprintf(tochild,"PORT %s\n",opt.keyserver_port);
+ fprintf(spawn->tochild,"PORT %s\n",opt.keyserver_port);
/* Write options */
- fprintf(tochild,"OPTION %sinclude-revoked\n",
+ fprintf(spawn->tochild,"OPTION %sinclude-revoked\n",
opt.keyserver_options.include_revoked?"":"no-");
- fprintf(tochild,"OPTION %sinclude-disabled\n",
+ fprintf(spawn->tochild,"OPTION %sinclude-disabled\n",
opt.keyserver_options.include_disabled?"":"no-");
for(i=0;i<opt.keyserver_options.verbose;i++)
- fprintf(tochild,"OPTION verbose\n");
+ fprintf(spawn->tochild,"OPTION verbose\n");
temp=opt.keyserver_options.other;
for(;temp;temp=temp->next)
- fprintf(tochild,"OPTION %s\n",temp->d);
+ fprintf(spawn->tochild,"OPTION %s\n",temp->d);
switch(action)
{
@@ -429,15 +329,15 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
{
int i;
- fprintf(tochild,"COMMAND GET\n\n");
+ fprintf(spawn->tochild,"COMMAND GET\n\n");
/* Which keys do we want? */
for(i=0;i<count;i++)
- fprintf(tochild,"0x%08lX%08lX\n",
+ fprintf(spawn->tochild,"0x%08lX%08lX\n",
(ulong)kidlist[i][0],(ulong)kidlist[i][1]);
- fprintf(tochild,"\n");
+ fprintf(spawn->tochild,"\n");
break;
}
@@ -447,7 +347,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
STRLIST key,temp;
/* Note the extra \n here to send an empty keylist block */
- fprintf(tochild,"COMMAND SEND\n\n\n");
+ fprintf(spawn->tochild,"COMMAND SEND\n\n\n");
for(key=list;key!=NULL;key=key->next)
{
@@ -467,10 +367,10 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
{
iobuf_flush_temp(buffer);
- fprintf(tochild,"KEY %s BEGIN\n",key->d);
+ fprintf(spawn->tochild,"KEY %s BEGIN\n",key->d);
fwrite(iobuf_get_temp_buffer(buffer),
- iobuf_get_temp_length(buffer),1,tochild);
- fprintf(tochild,"KEY %s END\n",key->d);
+ iobuf_get_temp_length(buffer),1,spawn->tochild);
+ fprintf(spawn->tochild,"KEY %s END\n",key->d);
iobuf_close(buffer);
}
@@ -485,14 +385,14 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
{
STRLIST key;
- fprintf(tochild,"COMMAND SEARCH\n\n");
+ fprintf(spawn->tochild,"COMMAND SEARCH\n\n");
/* Which keys do we want? Remember that the gpgkeys_ program
is going to lump these together into a search string. */
for(key=list;key!=NULL;key=key->next)
{
- fprintf(tochild,"%s\n",key->d);
+ fprintf(spawn->tochild,"%s\n",key->d);
if(key!=list)
{
searchstr=m_realloc(searchstr,
@@ -508,7 +408,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
strcat(searchstr,key->d);
}
- fprintf(tochild,"\n");
+ fprintf(spawn->tochild,"\n");
break;
}
@@ -518,52 +418,16 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
break;
}
- /* Done sending */
- fclose(tochild);
- tochild=NULL;
- to[1]=-1;
-
- if(opt.keyserver_options.use_temp_files)
- {
- char *command=m_alloc(strlen(filename)+2+
- strlen(tempfile_in)+6+
- strlen(tempfile_out)+2);
-
- sprintf(command,"%s -o \"%s\" \"%s\"",filename,tempfile_out,tempfile_in);
-
- ret=system(command);
-
- m_free(command);
-
- ret=WEXITSTATUS(ret);
-
- if(ret==127)
- {
- log_error(_("unable to exec keyserver program\n"));
- goto fail;
- }
-
- if(ret==-1)
- {
- log_error(_("internal system error while calling keyserver: %s\n"),
- strerror(errno));
- goto fail;
- }
-
- fromchild=iobuf_open(tempfile_out);
- if(fromchild==NULL)
- {
- log_error(_("unable to read keyserver response: %s\n"),
- strerror(errno));
- goto fail;
- }
- }
+ /* Done sending, so start reading. */
+ ret=exec_read(spawn);
+ if(ret)
+ goto fail;
/* Now handle the response */
do
{
- if(iobuf_read_line(fromchild,&line,&buflen,&maxlen)==0)
+ if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
{
ret=G10ERR_READ_FILE;
goto fail; /* i.e. EOF */
@@ -612,7 +476,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
do this could be to continue parsing this line-by-line and
make a temp iobuf for each key. */
- import_keys_stream(fromchild,
+ import_keys_stream(spawn->fromchild,
opt.keyserver_options.fast_import,stats_handle);
import_print_stats(stats_handle);
@@ -634,7 +498,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
/* Look for the COUNT line */
do
{
- if(iobuf_read_line(fromchild,&line,&buflen,&maxlen)==0)
+ if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
{
ret=G10ERR_READ_FILE;
goto fail; /* i.e. EOF */
@@ -642,7 +506,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
}
while(sscanf(line,"COUNT %d\n",&count)!=1);
- keyserver_search_prompt(fromchild,count,searchstr);
+ keyserver_search_prompt(spawn->fromchild,count,searchstr);
break;
}
@@ -652,54 +516,9 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
break;
}
- iobuf_close(fromchild);
- fromchild=NULL;
- ret=0;
+ *prog=exec_finish(spawn);
fail:
- if(tochild!=NULL)
- {
- fclose(tochild);
- to[1]=-1;
- }
-
- if(fromchild!=NULL)
- {
- iobuf_close(fromchild);
- from[0]=-1;
- }
-
- if(from[0]>-1)
- close(from[0]);
- if(from[1]>-1)
- close(from[1]);
-
- if(to[0]>-1)
- close(to[0]);
- if(to[1]>-1)
- close(to[1]);
-
- if(child>0)
- {
- int rc;
-
- waitpid(child,&rc,0);
- if(ret==0 && WIFEXITED(rc))
- ret=WEXITSTATUS(rc);
- }
-
- m_free(filename);
-
- if(madedir && !opt.keyserver_options.keep_temp_files)
- {
- unlink(tempfile_in);
- unlink(tempfile_out);
- rmdir(tempdir);
- }
-
- m_free(tempfile_in);
- m_free(tempfile_out);
- m_free(tempdir);
return ret;
}
@@ -707,11 +526,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
static int
keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count)
{
- int rc=0;
-
-#ifdef KEYSERVER_TEMPFILE_ONLY
- opt.keyserver_options.use_temp_files=1;
-#endif
+ int rc=0,ret=0;
if(opt.keyserver_scheme==NULL ||
opt.keyserver_host==NULL ||
@@ -749,10 +564,13 @@ keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count)
/* It's not the internal HKP code, so try and spawn a handler for it */
- if((rc=keyserver_spawn(action,list,kidlist,count)))
+ if((rc=keyserver_spawn(action,list,kidlist,count,&ret))==0)
{
- switch(rc)
+ switch(ret)
{
+ case KEYSERVER_OK:
+ break;
+
case KEYSERVER_SCHEME_NOT_FOUND:
log_error(_("no handler for keyserver scheme \"%s\"\n"),
opt.keyserver_scheme);
@@ -767,6 +585,12 @@ keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count)
/* This is not the best error code for this */
return G10ERR_INVALID_URI;
}
+ else
+ {
+ log_error(_("keyserver communications error\n"));
+
+ return rc;
+ }
return 0;
}