* ksutil.h, ksutil.c (curl_armor_writer, curl_writer,
authorDavid Shaw <dshaw@jabberwocky.com>
Mon, 19 Dec 2005 19:39:32 +0000 (19:39 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Mon, 19 Dec 2005 19:39:32 +0000 (19:39 +0000)
curl_writer_finalize): New functionality to handle binary format keys by
armoring them for input to GPG.

* gpgkeys_curl.c (get_key), gpgkeys_hkp.c (get_key): Call it here.

keyserver/ChangeLog
keyserver/gpgkeys_curl.c
keyserver/gpgkeys_hkp.c
keyserver/ksutil.c
keyserver/ksutil.h

index f5c720c..6ce2c73 100644 (file)
@@ -1,3 +1,11 @@
+2005-12-19  David Shaw  <dshaw@jabberwocky.com>
+
+       * ksutil.h, ksutil.c (curl_armor_writer, curl_writer,
+       curl_writer_finalize): New functionality to handle binary format
+       keys by armoring them for input to GPG.
+
+       * gpgkeys_curl.c (get_key), gpgkeys_hkp.c (get_key): Call it here.
+
 2005-12-07  David Shaw  <dshaw@jabberwocky.com>
 
        * gpgkeys_finger.c (get_key), gpgkeys_curl.c (get_key): Better
index 10e44a1..bd26d78 100644 (file)
@@ -74,13 +74,18 @@ get_key(char *getkey)
              res,errorbuffer);
       fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
     }
-  else if(!ctx.done)
+  else
     {
-      fprintf(console,"gpgkeys: no key data found for %s\n",request);
-      fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND);
+      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);
     }
-  else
-    fprintf(output,"\nKEY 0x%s END\n",getkey);
 
   return curl_err_to_gpg_err(res);
 }
index 38e9cef..d51c659 100644 (file)
@@ -263,21 +263,22 @@ get_key(char *getkey)
   curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
 
   res=curl_easy_perform(curl);
-  if(res!=0)
+  if(res!=CURLE_OK)
     {
       fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
       fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
     }
   else
     {
-      if(ctx.done)
-       fprintf(output,"\nKEY 0x%s END\n",getkey);
-      else
+      curl_writer_finalize(&ctx);
+      if(!ctx.flags.done)
        {
          fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
-         fprintf(output,"KEY 0x%s FAILED %d\n",
+         fprintf(output,"\nKEY 0x%s FAILED %d\n",
                  getkey,KEYSERVER_KEY_NOT_FOUND);
        }
+      else
+       fprintf(output,"\nKEY 0x%s END\n",getkey);
     }
 
   return KEYSERVER_OK;
index e858bd4..8ea2a1a 100644 (file)
@@ -371,6 +371,47 @@ curl_err_to_gpg_err(CURLcode error)
     }
 }
 
+#define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+
+static void
+curl_armor_writer(const unsigned char *buf,size_t size,void *cw_ctx)
+{
+  struct curl_writer_ctx *ctx=cw_ctx;
+  size_t idx=0;
+
+  while(idx<size)
+    {
+      for(;ctx->armor_remaining<3 && idx<size;ctx->armor_remaining++,idx++)
+       ctx->armor_ctx[ctx->armor_remaining]=buf[idx];
+
+      if(ctx->armor_remaining==3)
+       {
+         /* Top 6 bytes of ctx->armor_ctx[0] */
+         fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
+         /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
+            ctx->armor_ctx[1] */
+         fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
+                    |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
+         /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of
+            ctx->armor_ctx[2] */
+         fputc(B64[(((ctx->armor_ctx[1]<<2)&0x3C)
+                    |((ctx->armor_ctx[2]>>6)&0x03))&0x3F],ctx->stream);
+         /* Bottom 6 bytes of ctx->armor_ctx[2] */
+         fputc(B64[(ctx->armor_ctx[2]&0x3F)],ctx->stream);
+
+         ctx->linelen+=4;
+         if(ctx->linelen>=70)
+           {
+             fputc('\n',ctx->stream);
+             ctx->linelen=0;
+           }
+
+         ctx->armor_remaining=0;
+       }
+    }
+
+}
+
 size_t
 curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx)
 {
@@ -378,52 +419,103 @@ curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx)
   const char *buf=ptr;
   size_t i;
 
-  if(!ctx->initialized)
+  if(!ctx->flags.initialized)
     {
-      ctx->marker=BEGIN;
-      ctx->initialized=1;
+      if(size*nmemb==0)
+       return 0;
+
+      /* The object we're fetching is in binary form */
+      if(*buf&0x80)
+       {
+         ctx->flags.armor=1;
+         fprintf(ctx->stream,BEGIN"\n\n");
+       }
+      else
+       ctx->marker=BEGIN;
+
+      ctx->flags.initialized=1;
     }
 
-  /* scan the incoming data for our marker */
-  for(i=0;!ctx->done && i<(size*nmemb);i++)
+  if(ctx->flags.armor)
+    curl_armor_writer(ptr,size*nmemb,cw_ctx);
+  else
     {
-      if(buf[i]==ctx->marker[ctx->markeridx])
+      /* scan the incoming data for our marker */
+      for(i=0;!ctx->flags.done && i<(size*nmemb);i++)
        {
-         ctx->markeridx++;
-         if(ctx->marker[ctx->markeridx]=='\0')
+         if(buf[i]==ctx->marker[ctx->markeridx])
            {
-             if(ctx->begun)
-               ctx->done=1;
-             else
+             ctx->markeridx++;
+             if(ctx->marker[ctx->markeridx]=='\0')
                {
-                 /* We've found the BEGIN marker, so now we're looking
-                    for the END marker. */
-                 ctx->begun=1;
-                 ctx->marker=END;
-                 ctx->markeridx=0;
-                 fprintf(ctx->stream,BEGIN);
-                 continue;
+                 if(ctx->flags.begun)
+                   ctx->flags.done=1;
+                 else
+                   {
+                     /* We've found the BEGIN marker, so now we're
+                        looking for the END marker. */
+                     ctx->flags.begun=1;
+                     ctx->marker=END;
+                     ctx->markeridx=0;
+                     fprintf(ctx->stream,BEGIN);
+                     continue;
+                   }
                }
            }
-       }
-      else
-       ctx->markeridx=0;
+         else
+           ctx->markeridx=0;
 
-      if(ctx->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],ctx->stream);
+         if(ctx->flags.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 this code is just
+                for handling armored keys, we don't have to worry
+                about odd cases like CRCRCR and the like. */
+
+             if(buf[i]!='\r')
+               fputc(buf[i],ctx->stream);
+           }
        }
     }
 
   return size*nmemb;
 }
+
+void
+curl_writer_finalize(struct curl_writer_ctx *ctx)
+{
+  if(ctx->flags.armor)
+    {
+      if(ctx->armor_remaining==2)
+       {
+         /* Top 6 bytes of ctx->armorctx[0] */
+         fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
+         /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
+            ctx->armor_ctx[1] */
+         fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
+                    |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
+         /* Bottom 4 bytes of ctx->armor_ctx[1] */
+         fputc(B64[((ctx->armor_ctx[1]<<2)&0x3C)],ctx->stream);
+         /* Pad */
+         fputc('=',ctx->stream);
+       }
+      else if(ctx->armor_remaining==1)
+       {
+         /* Top 6 bytes of ctx->armor_ctx[0] */
+         fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
+         /* Bottom 2 bytes of ctx->armor_ctx[0] */
+         fputc(B64[((ctx->armor_ctx[0]<<4)&0x30)],ctx->stream);
+         /* Pad */
+         fputc('=',ctx->stream);
+         /* Pad */
+         fputc('=',ctx->stream);
+       }
+
+      fprintf(ctx->stream,"\n"END);
+      ctx->flags.done=1;
+    }
+}
 #endif
index 8e00e79..4dd60a7 100644 (file)
@@ -111,12 +111,24 @@ int curl_err_to_gpg_err(CURLcode error);
 
 struct curl_writer_ctx
 {
-  int initialized,markeridx,begun,done;
+  struct
+  {
+    unsigned int initialized:1;
+    unsigned int begun:1;
+    unsigned int done:1;
+    unsigned int armor:1;
+  } flags;
+
+  int armor_remaining;
+  unsigned char armor_ctx[3];
+  int markeridx,linelen;
   const char *marker;
   FILE *stream;
 };
 
 size_t curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx);
+void curl_writer_finalize(struct curl_writer_ctx *ctx);
+
 #endif
 
 #endif /* !_KSUTIL_H_ */