diff options
author | Werner Koch <[email protected]> | 2006-06-30 13:19:49 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2006-06-30 13:19:49 +0000 |
commit | 640d5a8c53289f396ae018a4c36e2e8894261329 (patch) | |
tree | f2aecb490c84becc776ae45f32b027672a69ed19 /keyserver/gpgkeys_curl.c | |
parent | A couple of fixes. gpg2's key generation does now work. (diff) | |
download | gnupg-640d5a8c53289f396ae018a4c36e2e8894261329.tar.gz gnupg-640d5a8c53289f396ae018a4c36e2e8894261329.zip |
Added keyserver directory from trunk
Diffstat (limited to '')
-rw-r--r-- | keyserver/gpgkeys_curl.c | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/keyserver/gpgkeys_curl.c b/keyserver/gpgkeys_curl.c new file mode 100644 index 000000000..9e4b56729 --- /dev/null +++ b/keyserver/gpgkeys_curl.c @@ -0,0 +1,369 @@ +/* gpgkeys_curl.c - fetch a key via libcurl + * Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#else +#include "curl-shim.h" +#endif +#include "keyserver.h" +#include "ksutil.h" + +extern char *optarg; +extern int optind; + +static FILE *input,*output,*console; +static CURL *curl; +static struct ks_options *opt; + +static int +get_key(char *getkey) +{ + CURLcode res; + char errorbuffer[CURL_ERROR_SIZE]; + char request[MAX_URL]; + struct curl_writer_ctx ctx; + + memset(&ctx,0,sizeof(ctx)); + + if(strncmp(getkey,"0x",2)==0) + getkey+=2; + + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + + sprintf(request,"%s://%s%s%s%s",opt->scheme,opt->host, + opt->port?":":"",opt->port?opt->port:"",opt->path?opt->path:"/"); + + curl_easy_setopt(curl,CURLOPT_URL,request); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer); + ctx.stream=output; + curl_easy_setopt(curl,CURLOPT_FILE,&ctx); + curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer); + + res=curl_easy_perform(curl); + if(res!=CURLE_OK) + { + fprintf(console,"gpgkeys: %s fetch error %d: %s\n",opt->scheme, + res,errorbuffer); + fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res)); + } + else + { + curl_writer_finalize(&ctx); + if(!ctx.flags.done) + { + fprintf(console,"gpgkeys: no key data found for %s\n",request); + fprintf(output,"\nKEY 0x%s FAILED %d\n", + getkey,KEYSERVER_KEY_NOT_FOUND); + } + else + fprintf(output,"\nKEY 0x%s END\n",getkey); + } + + return curl_err_to_gpg_err(res); +} + +static void +show_help (FILE *fp) +{ + fprintf (fp,"-h\thelp\n"); + fprintf (fp,"-V\tversion\n"); + fprintf (fp,"-o\toutput to this file\n"); +} + +int +main(int argc,char *argv[]) +{ + int arg,ret=KEYSERVER_INTERNAL_ERROR; + char line[MAX_LINE]; + char *thekey=NULL; + long follow_redirects=5; + char *proxy=NULL; + + console=stderr; + + /* Kludge to implement standard GNU options. */ + if (argc > 1 && !strcmp (argv[1], "--version")) + { + fputs ("gpgkeys_curl (GnuPG) " VERSION"\n", stdout); + return 0; + } + else if (argc > 1 && !strcmp (argv[1], "--help")) + { + show_help (stdout); + return 0; + } + + while((arg=getopt(argc,argv,"hVo:"))!=-1) + switch(arg) + { + default: + case 'h': + show_help (console); + return KEYSERVER_OK; + + case 'V': + fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION); + return KEYSERVER_OK; + + case 'o': + output=fopen(optarg,"wb"); + if(output==NULL) + { + fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n", + optarg,strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + + break; + } + + if(argc>optind) + { + input=fopen(argv[optind],"r"); + if(input==NULL) + { + fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n", + argv[optind],strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + } + + if(input==NULL) + input=stdin; + + if(output==NULL) + output=stdout; + + opt=init_ks_options(); + if(!opt) + return KEYSERVER_NO_MEMORY; + + /* Get the command and info block */ + + while(fgets(line,MAX_LINE,input)!=NULL) + { + int err; + char option[MAX_OPTION+1]; + + if(line[0]=='\n') + break; + + err=parse_ks_options(line,opt); + if(err>0) + { + ret=err; + goto fail; + } + else if(err==0) + continue; + + if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1) + { + int no=0; + char *start=&option[0]; + + option[MAX_OPTION]='\0'; + + if(strncasecmp(option,"no-",3)==0) + { + no=1; + start=&option[3]; + } + + if(strncasecmp(start,"http-proxy",10)==0) + { + /* Safe to not check the return code of strdup() here. + If it fails, we simply won't use a proxy. */ + if(no) + { + free(proxy); + proxy=strdup(""); + } + else if(start[10]=='=') + { + if(strlen(&start[11])<MAX_PROXY) + { + free(proxy); + proxy=strdup(&start[11]); + } + } + } + else if(strncasecmp(start,"follow-redirects",16)==0) + { + if(no) + follow_redirects=0; + else if(start[16]=='=') + follow_redirects=atoi(&start[17]); + else if(start[16]=='\0') + follow_redirects=-1; + } + + continue; + } + } + + if(!opt->scheme) + { + fprintf(console,"gpgkeys: no scheme supplied!\n"); + ret=KEYSERVER_SCHEME_NOT_FOUND; + goto fail; + } + + if(!opt->host) + { + fprintf(console,"gpgkeys: no keyserver host provided\n"); + goto fail; + } + + if(opt->timeout && register_timeout()==-1) + { + fprintf(console,"gpgkeys: unable to register timeout handler\n"); + return KEYSERVER_INTERNAL_ERROR; + } + + curl_global_init(CURL_GLOBAL_DEFAULT); + curl=curl_easy_init(); + if(!curl) + { + fprintf(console,"gpgkeys: unable to initialize curl\n"); + ret=KEYSERVER_INTERNAL_ERROR; + goto fail; + } + + if(follow_redirects) + { + curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1); + if(follow_redirects>0) + curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects); + } + + if(opt->auth) + curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth); + + if(opt->debug) + { + fprintf(console,"gpgkeys: curl version = %s\n",curl_version()); + curl_easy_setopt(curl,CURLOPT_STDERR,console); + curl_easy_setopt(curl,CURLOPT_VERBOSE,1); + } + + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,opt->flags.check_cert); + curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file); + + if(proxy) + curl_easy_setopt(curl,CURLOPT_PROXY,proxy); + + /* If it's a GET or a SEARCH, the next thing to come in is the + keyids. If it's a SEND, then there are no keyids. */ + + if(opt->action==KS_GET) + { + /* Eat the rest of the file */ + for(;;) + { + if(fgets(line,MAX_LINE,input)==NULL) + break; + else + { + if(line[0]=='\n' || line[0]=='\0') + break; + + if(!thekey) + { + thekey=strdup(line); + if(!thekey) + { + fprintf(console,"gpgkeys: out of memory while " + "building key list\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + /* Trim the trailing \n */ + thekey[strlen(line)-1]='\0'; + } + } + } + } + else + { + fprintf(console, + "gpgkeys: this keyserver type only supports key retrieval\n"); + goto fail; + } + + if(!thekey) + { + fprintf(console,"gpgkeys: invalid keyserver instructions\n"); + goto fail; + } + + /* Send the response */ + + fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION); + fprintf(output,"PROGRAM %s\n\n",VERSION); + + if(opt->verbose) + { + fprintf(console,"Scheme:\t\t%s\n",opt->scheme); + fprintf(console,"Host:\t\t%s\n",opt->host); + if(opt->port) + fprintf(console,"Port:\t\t%s\n",opt->port); + if(opt->path) + fprintf(console,"Path:\t\t%s\n",opt->path); + fprintf(console,"Command:\tGET\n"); + } + + set_timeout(opt->timeout); + + ret=get_key(thekey); + + fail: + + free(thekey); + + if(input!=stdin) + fclose(input); + + if(output!=stdout) + fclose(output); + + free_ks_options(opt); + + if(curl) + curl_easy_cleanup(curl); + + free(proxy); + + curl_global_cleanup(); + + return ret; +} |