* gpgkeys_ldap.c (main): Fix three wrong calls to fail_all(). Noted
[gnupg.git] / keyserver / gpgkeys_curl.c
index d252200..bccfeaf 100644 (file)
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
+#ifdef FAKE_CURL
+#include "curl-shim.h"
+#else
 #include <curl/curl.h>
 #include <curl/curl.h>
+#endif
 #include "keyserver.h"
 #include "ksutil.h"
 
 extern char *optarg;
 extern int optind;
 
 #include "keyserver.h"
 #include "ksutil.h"
 
 extern char *optarg;
 extern int optind;
 
-static int verbose=0;
-static char scheme[MAX_SCHEME+1];
-static char auth[MAX_AUTH+1];
-static char host[MAX_HOST+1];
-static char port[MAX_PORT+1];
-static char path[URLMAX_PATH+1];
 static char proxy[MAX_PROXY+1];
 static char proxy[MAX_PROXY+1];
-static FILE *input, *output, *console;
+static FILE *input,*output,*console;
 static CURL *curl;
 static CURL *curl;
-static char request[MAX_URL];
+static struct ks_options *opt;
 
 static int
 curl_err_to_gpg_err(CURLcode error)
 
 static int
 curl_err_to_gpg_err(CURLcode error)
@@ -55,12 +53,55 @@ curl_err_to_gpg_err(CURLcode error)
     }
 }
 
     }
 }
 
-/* We wrap fwrite so to avoid DLL problems on Win32 (see curl faq for
-   more). */
 static size_t
 writer(const void *ptr,size_t size,size_t nmemb,void *stream)
 {
 static size_t
 writer(const void *ptr,size_t size,size_t nmemb,void *stream)
 {
-  return fwrite(ptr,size,nmemb,stream);
+  const char *buf=ptr;
+  size_t i;
+  static int markeridx=0,begun=0,done=0;
+  static const char *marker=BEGIN;
+
+  /* scan the incoming data for our marker */
+  for(i=0;!done && i<(size*nmemb);i++)
+    {
+      if(buf[i]==marker[markeridx])
+       {
+         markeridx++;
+         if(marker[markeridx]=='\0')
+           {
+             if(begun)
+               done=1;
+             else
+               {
+                 /* We've found the BEGIN marker, so now we're looking
+                    for the END marker. */
+                 begun=1;
+                 marker=END;
+                 markeridx=0;
+                 fprintf(output,BEGIN);
+                 continue;
+               }
+           }
+       }
+      else
+       markeridx=0;
+
+      if(begun)
+       {
+         /* Canonicalize CRLF to just LF by stripping CRs.  This
+            actually makes sense, since on Unix-like machines LF is
+            correct, and on win32-like machines, our output buffer is
+            opened in textmode and will re-canonicalize line endings
+            back to CRLF.  Since we only need to handle armored keys,
+            we don't have to worry about odd cases like CRCRCR and
+            the like. */
+
+         if(buf[i]!='\r')
+           fputc(buf[i],output);
+       }
+    }
+
+  return size*nmemb;
 }
 
 static int
 }
 
 static int
@@ -68,35 +109,33 @@ get_key(char *getkey)
 {
   CURLcode res;
   char errorbuffer[CURL_ERROR_SIZE];
 {
   CURLcode res;
   char errorbuffer[CURL_ERROR_SIZE];
+  char request[MAX_URL];
 
   if(strncmp(getkey,"0x",2)==0)
     getkey+=2;
 
   fprintf(output,"KEY 0x%s BEGIN\n",getkey);
 
 
   if(strncmp(getkey,"0x",2)==0)
     getkey+=2;
 
   fprintf(output,"KEY 0x%s BEGIN\n",getkey);
 
-  sprintf(request,"%s://%s%s%s%s%s%s%s",scheme,auth[0]?auth:"",auth[0]?"@":"",
-         host,port[0]?":":"",port[0]?port:"",path[0]?"":"/",path);
+  sprintf(request,"%s://%s%s%s%s%s%s",opt->scheme,
+         opt->auth?opt->auth:"",
+         opt->auth?"@":"",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,writer);
   curl_easy_setopt(curl,CURLOPT_FILE,output);
   curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
 
 
   curl_easy_setopt(curl,CURLOPT_URL,request);
   curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,writer);
   curl_easy_setopt(curl,CURLOPT_FILE,output);
   curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
 
-  if(verbose>1)
-    {
-      curl_easy_setopt(curl,CURLOPT_STDERR,console);
-      curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
-    }
-
   res=curl_easy_perform(curl);
   if(res!=0)
     {
   res=curl_easy_perform(curl);
   if(res!=0)
     {
-      fprintf(console,"gpgkeys: %s fetch error %d: %s\n",scheme,
+      fprintf(console,"gpgkeys: %s fetch error %d: %s\n",opt->scheme,
              res,errorbuffer);
              res,errorbuffer);
-      fprintf(output,"KEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
+      fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
     }
   else
     }
   else
-    fprintf(output,"KEY 0x%s END\n",getkey);
+    fprintf(output,"\nKEY 0x%s END\n",getkey);
 
   return KEYSERVER_OK;
 }
 
   return KEYSERVER_OK;
 }
@@ -112,10 +151,9 @@ show_help (FILE *fp)
 int
 main(int argc,char *argv[])
 {
 int
 main(int argc,char *argv[])
 {
-  int arg,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
+  int arg,ret=KEYSERVER_INTERNAL_ERROR;
   char line[MAX_LINE];
   char *thekey=NULL;
   char line[MAX_LINE];
   char *thekey=NULL;
-  unsigned int timeout=DEFAULT_KEYSERVER_TIMEOUT;
   long follow_redirects=5;
 
   console=stderr;
   long follow_redirects=5;
 
   console=stderr;
@@ -173,71 +211,28 @@ main(int argc,char *argv[])
   if(output==NULL)
     output=stdout;
 
   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)
     {
   /* Get the command and info block */
 
   while(fgets(line,MAX_LINE,input)!=NULL)
     {
-      int version;
-      char command[MAX_COMMAND+1];
+      int err;
       char option[MAX_OPTION+1];
       char option[MAX_OPTION+1];
-      char hash;
 
       if(line[0]=='\n')
        break;
 
 
       if(line[0]=='\n')
        break;
 
-      if(sscanf(line,"%c",&hash)==1 && hash=='#')
-       continue;
-
-      if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
-       {
-         command[MAX_COMMAND]='\0';
-
-         if(strcasecmp(command,"get")==0)
-           action=GET;
-
-         continue;
-       }
-
-      if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1)
+      err=parse_ks_options(line,opt);
+      if(err>0)
        {
        {
-         scheme[MAX_SCHEME]='\0';
-         continue;
-       }
-
-      if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1)
-       {
-         auth[MAX_AUTH]='\0';
-         continue;
-       }
-
-      if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
-       {
-         host[MAX_HOST]='\0';
-         continue;
-       }
-
-      if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
-       {
-         port[MAX_PORT]='\0';
-         continue;
-       }
-
-      if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1)
-       {
-         path[URLMAX_PATH]='\0';
-         continue;
-       }
-
-      if(sscanf(line,"VERSION %d\n",&version)==1)
-       {
-         if(version!=KEYSERVER_PROTO_VERSION)
-           {
-             ret=KEYSERVER_VERSION_ERROR;
-             goto fail;
-           }
-
-         continue;
+         ret=err;
+         goto fail;
        }
        }
+      else if(err==0)
+       continue;
 
       if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
        {
 
       if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
        {
@@ -252,14 +247,7 @@ main(int argc,char *argv[])
              start=&option[3];
            }
 
              start=&option[3];
            }
 
-         if(strcasecmp(start,"verbose")==0)
-           {
-             if(no)
-               verbose--;
-             else
-               verbose++;
-           }
-         else if(strncasecmp(start,"http-proxy",10)==0)
+         if(strncasecmp(start,"http-proxy",10)==0)
            {
              if(no)
                proxy[0]='\0';
            {
              if(no)
                proxy[0]='\0';
@@ -269,15 +257,6 @@ main(int argc,char *argv[])
                  proxy[MAX_PROXY]='\0';
                }
            }
                  proxy[MAX_PROXY]='\0';
                }
            }
-         else if(strncasecmp(start,"timeout",7)==0)
-           {
-             if(no)
-               timeout=0;
-             else if(start[7]=='=')
-               timeout=atoi(&start[8]);
-             else if(start[7]=='\0')
-               timeout=DEFAULT_KEYSERVER_TIMEOUT;
-           }
          else if(strncasecmp(start,"follow-redirects",16)==0)
            {
              if(no)
          else if(strncasecmp(start,"follow-redirects",16)==0)
            {
              if(no)
@@ -292,30 +271,41 @@ main(int argc,char *argv[])
        }
     }
 
        }
     }
 
-  if(scheme[0]=='\0')
+  if(!opt->scheme)
     {
       fprintf(console,"gpgkeys: no scheme supplied!\n");
     {
       fprintf(console,"gpgkeys: no scheme supplied!\n");
-      return KEYSERVER_SCHEME_NOT_FOUND;
+      ret=KEYSERVER_SCHEME_NOT_FOUND;
+      goto fail;
     }
 #ifdef HTTP_VIA_LIBCURL
     }
 #ifdef HTTP_VIA_LIBCURL
-  else if(strcasecmp(scheme,"http")==0)
+  else if(strcasecmp(opt->scheme,"http")==0)
     ;
 #endif /* HTTP_VIA_LIBCURL */
 #ifdef HTTPS_VIA_LIBCURL
     ;
 #endif /* HTTP_VIA_LIBCURL */
 #ifdef HTTPS_VIA_LIBCURL
-  else if(strcasecmp(scheme,"https")==0)
+  else if(strcasecmp(opt->scheme,"https")==0)
     ;
 #endif /* HTTP_VIA_LIBCURL */
 #ifdef FTP_VIA_LIBCURL
     ;
 #endif /* HTTP_VIA_LIBCURL */
 #ifdef FTP_VIA_LIBCURL
-  else if(strcasecmp(scheme,"ftp")==0)
+  else if(strcasecmp(opt->scheme,"ftp")==0)
     ;
 #endif /* FTP_VIA_LIBCURL */
     ;
 #endif /* FTP_VIA_LIBCURL */
+#ifdef FTPS_VIA_LIBCURL
+  else if(strcasecmp(opt->scheme,"ftps")==0)
+    ;
+#endif /* FTPS_VIA_LIBCURL */
   else
     {
   else
     {
-      fprintf(console,"gpgkeys: scheme `%s' not supported\n",scheme);
+      fprintf(console,"gpgkeys: scheme `%s' not supported\n",opt->scheme);
       return KEYSERVER_SCHEME_NOT_FOUND;
     }
 
       return KEYSERVER_SCHEME_NOT_FOUND;
     }
 
-  if(timeout && register_timeout()==-1)
+  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;
     {
       fprintf(console,"gpgkeys: unable to register timeout handler\n");
       return KEYSERVER_INTERNAL_ERROR;
@@ -337,13 +327,22 @@ main(int argc,char *argv[])
        curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects);
     }
 
        curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects);
     }
 
+  if(opt->debug)
+    {
+      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[0])
     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(proxy[0])
     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(action==GET)
+  if(opt->action==KS_GET)
     {
       /* Eat the rest of the file */
       for(;;)
     {
       /* Eat the rest of the file */
       for(;;)
@@ -379,7 +378,7 @@ main(int argc,char *argv[])
       goto fail;
     }
 
       goto fail;
     }
 
-  if(!thekey || !host[0])
+  if(!thekey)
     {
       fprintf(console,"gpgkeys: invalid keyserver instructions\n");
       goto fail;
     {
       fprintf(console,"gpgkeys: invalid keyserver instructions\n");
       goto fail;
@@ -390,23 +389,21 @@ main(int argc,char *argv[])
   fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
   fprintf(output,"PROGRAM %s\n\n",VERSION);
 
   fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
   fprintf(output,"PROGRAM %s\n\n",VERSION);
 
-  if(verbose)
+  if(opt->verbose)
     {
     {
-      fprintf(console,"Scheme:\t\t%s\n",scheme);
-      fprintf(console,"Host:\t\t%s\n",host);
-      if(port[0])
-       fprintf(console,"Port:\t\t%s\n",port);
-      if(path[0])
-       fprintf(console,"Path:\t\t%s\n",path);
+      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");
     }
 
       fprintf(console,"Command:\tGET\n");
     }
 
-  set_timeout(timeout);
+  set_timeout(opt->timeout);
 
   ret=get_key(thekey);
 
 
   ret=get_key(thekey);
 
-  curl_easy_cleanup(curl);
-
  fail:
 
   free(thekey);
  fail:
 
   free(thekey);
@@ -417,6 +414,11 @@ main(int argc,char *argv[])
   if(output!=stdout)
     fclose(output);
 
   if(output!=stdout)
     fclose(output);
 
+  free_ks_options(opt);
+
+  if(curl)
+    curl_easy_cleanup(curl);
+
   curl_global_cleanup();
 
   return ret;
   curl_global_cleanup();
 
   return ret;