* ksutil.h, ksutil.c (parse_ks_options): New keyserver command "getname".
authorDavid Shaw <dshaw@jabberwocky.com>
Fri, 23 Dec 2005 20:51:48 +0000 (20:51 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Fri, 23 Dec 2005 20:51:48 +0000 (20:51 +0000)
* gpgkeys_hkp.c (main, get_name), gpgkeys_ldap.c (main, get_name): Use it
here to do direct name (rather than key ID) fetches.

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

index 6ce2c73..beade08 100644 (file)
@@ -1,3 +1,11 @@
+2005-12-23  David Shaw  <dshaw@jabberwocky.com>
+
+       * ksutil.h, ksutil.c (parse_ks_options): New keyserver command
+       "getname".
+
+       * gpgkeys_hkp.c (main, get_name), gpgkeys_ldap.c (main, get_name):
+       Use it here to do direct name (rather than key ID) fetches.
+
 2005-12-19  David Shaw  <dshaw@jabberwocky.com>
 
        * ksutil.h, ksutil.c (curl_armor_writer, curl_writer,
index d51c659..6d6ca51 100644 (file)
@@ -285,11 +285,90 @@ get_key(char *getkey)
 }
 
 static int
+get_name(const char *getkey)
+{
+  CURLcode res;
+  char *request=NULL;
+  char *searchkey_encoded;
+  int ret=KEYSERVER_INTERNAL_ERROR;
+  struct curl_writer_ctx ctx;
+
+  memset(&ctx,0,sizeof(ctx));
+
+  searchkey_encoded=curl_escape((char *)getkey,0);
+  if(!searchkey_encoded)
+    {
+      fprintf(console,"gpgkeys: out of memory\n");
+      ret=KEYSERVER_NO_MEMORY;
+      goto fail;
+    }
+
+  request=malloc(MAX_URL+60+strlen(searchkey_encoded));
+  if(!request)
+    {
+      fprintf(console,"gpgkeys: out of memory\n");
+      ret=KEYSERVER_NO_MEMORY;
+      goto fail;
+    }
+
+  fprintf(output,"NAME %s BEGIN\n",getkey);
+
+  strcpy(request,"http://");
+  strcat(request,opt->host);
+  strcat(request,":");
+  if(opt->port)
+    strcat(request,opt->port);
+  else
+    strcat(request,"11371");
+  strcat(request,opt->path);
+  append_path(request,"/pks/lookup?op=get&options=mr&search=");
+  strcat(request,searchkey_encoded);
+
+  if(opt->verbose>2)
+    fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
+
+  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);
+
+  res=curl_easy_perform(curl);
+  if(res!=CURLE_OK)
+    {
+      fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
+      ret=curl_err_to_gpg_err(res);
+    }
+  else
+    {
+      curl_writer_finalize(&ctx);
+      if(!ctx.flags.done)
+       {
+         fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
+         ret=KEYSERVER_KEY_NOT_FOUND;
+       }
+      else
+       {
+         fprintf(output,"\nNAME %s END\n",getkey);
+         ret=KEYSERVER_OK;
+       }
+    }
+
+ fail:
+  curl_free(searchkey_encoded);
+  free(request);
+
+  if(ret!=KEYSERVER_OK)
+    fprintf(output,"\nNAME %s FAILED %d\n",getkey,ret);
+
+  return ret;
+}
+
+static int
 search_key(const char *searchkey)
 {
   CURLcode res;
   char *request=NULL;
-  char *searchkey_encoded=NULL;
+  char *searchkey_encoded;
   int ret=KEYSERVER_INTERNAL_ERROR;
   enum ks_search_type search_type;
 
@@ -570,7 +649,8 @@ main(int argc,char *argv[])
 
   if(opt->action==KS_SEND)
     while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
-  else if(opt->action==KS_GET || opt->action==KS_SEARCH)
+  else if(opt->action==KS_GET
+         || opt->action==KS_GETNAME || opt->action==KS_SEARCH)
     {
       for(;;)
        {
@@ -645,6 +725,20 @@ main(int argc,char *argv[])
          keyptr=keyptr->next;
        }
     }
+  else if(opt->action==KS_GETNAME)
+    {
+      keyptr=keylist;
+
+      while(keyptr!=NULL)
+       {
+         set_timeout(opt->timeout);
+
+         if(get_name(keyptr->str)!=KEYSERVER_OK)
+           failed++;
+
+         keyptr=keyptr->next;
+       }
+    }
   else if(opt->action==KS_SEND)
     {
       int eof=0;
index a483e27..74555b8 100644 (file)
@@ -1116,20 +1116,6 @@ get_key(char *getkey)
   return ret;
 }
 
-static void
-printquoted(FILE *stream,char *string,char delim)
-{
-  while(*string)
-    {
-      if(*string==delim || *string=='%')
-       fprintf(stream,"%%%02x",*string);
-      else
-       fputc(*string,stream);
-
-      string++;
-    }
-}
-
 #define LDAP_ESCAPE_CHARS "*()\\"
 
 static int
@@ -1164,6 +1150,132 @@ ldap_quote(char *buffer,const char *string)
   return count;
 }
 
+/* Note that key-not-found is not a fatal error */
+static int
+get_name(char *getkey)
+{
+  LDAPMessage *res,*each;
+  int ret=KEYSERVER_INTERNAL_ERROR,err,count;
+  char *expanded_search;
+  /* The maximum size of the search, including the optional stuff and
+     the trailing \0 */
+  char search[2+11+3+MAX_LINE+2+15+14+1+1+20];
+  /* This ordering is significant - specifically, "pgpcertid" needs to
+     be the second item in the list, since everything after it may be
+     discarded if the user isn't in verbose mode. */
+  char *attrs[]={"replaceme","pgpcertid","pgpuserid","pgpkeyid","pgprevoked",
+                "pgpdisabled","pgpkeycreatetime","modifytimestamp",
+                "pgpkeysize","pgpkeytype",NULL};
+  attrs[0]=pgpkeystr; /* Some compilers don't like using variables as
+                         array initializers. */
+
+  expanded_search=malloc(ldap_quote(NULL,getkey)+1);
+  if(!expanded_search)
+    {
+      fprintf(output,"NAME %s FAILED %d\n",getkey,KEYSERVER_NO_MEMORY);
+      fprintf(console,"Out of memory when quoting LDAP search string\n");
+      return KEYSERVER_NO_MEMORY;
+    }
+
+  ldap_quote(expanded_search,getkey);
+
+  /* Build the search string */
+
+  sprintf(search,"%s(pgpuserid=*%s*)%s%s%s",
+         (!(opt->flags.include_disabled&&opt->flags.include_revoked))?"(&":"",
+         expanded_search,
+         opt->flags.include_disabled?"":"(pgpdisabled=0)",
+         opt->flags.include_revoked?"":"(pgprevoked=0)",
+         !(opt->flags.include_disabled&&opt->flags.include_revoked)?")":"");
+
+  free(expanded_search);
+
+  if(opt->verbose>2)
+    fprintf(console,"gpgkeys: LDAP fetch for: %s\n",search);
+
+  if(!opt->verbose)
+    attrs[2]=NULL; /* keep only pgpkey(v2) and pgpcertid */
+
+  err=ldap_search_s(ldap,basekeyspacedn,
+                   LDAP_SCOPE_SUBTREE,search,attrs,0,&res);
+  if(err!=0)
+    {
+      int errtag=ldap_err_to_gpg_err(err);
+
+      fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err));
+      fprintf(output,"NAME %s BEGIN\n",getkey);
+      fprintf(output,"NAME %s FAILED %d\n",getkey,errtag);
+      return errtag;
+    }
+
+  count=ldap_count_entries(ldap,res);
+  if(count<1)
+    {
+      fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
+      fprintf(output,"NAME %s BEGIN\n",getkey);
+      fprintf(output,"NAME %s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND);
+    }
+  else
+    {
+      /* There may be more than one result, but we return them all. */
+
+      each=ldap_first_entry(ldap,res);
+      while(each!=NULL)
+       {
+         char **vals,**certid;
+
+         certid=ldap_get_values(ldap,each,"pgpcertid");
+         if(certid!=NULL)
+           {
+             build_info(certid[0],each);
+
+             fprintf(output,"NAME %s BEGIN\n",getkey);
+
+             vals=ldap_get_values(ldap,each,pgpkeystr);
+             if(vals==NULL)
+               {
+                 int errtag=ldap_to_gpg_err(ldap);
+
+                 fprintf(console,"gpgkeys: unable to retrieve key %s "
+                         "from keyserver\n",getkey);
+                 fprintf(output,"NAME %s FAILED %d\n",getkey,errtag);
+               }
+             else
+               {
+                 print_nocr(output,vals[0]);
+                 fprintf(output,"\nNAME %s END\n",getkey);
+
+                 ldap_value_free(vals);
+               }
+
+             ldap_value_free(certid);
+           }
+
+         each=ldap_next_entry(ldap,each);
+       }
+    }
+
+  ret=KEYSERVER_OK;
+
+  ldap_msgfree(res);
+
+  return ret;
+}
+
+static void
+printquoted(FILE *stream,char *string,char delim)
+{
+  while(*string)
+    {
+      if(*string==delim || *string=='%')
+       fprintf(stream,"%%%02x",*string);
+      else
+       fputc(*string,stream);
+
+      string++;
+    }
+}
+
 /* Returns 0 on success and -1 on error.  Note that key-not-found is
    not an error! */
 static int
@@ -1173,9 +1285,9 @@ search_key(const char *searchkey)
   LDAPMessage *res,*each;
   int err,count=0;
   struct keylist *dupelist=NULL;
+  char *expanded_search;
   /* The maximum size of the search, including the optional stuff and
      the trailing \0 */
-  char *expanded_search;
   char search[2+11+3+MAX_LINE+2+15+14+1+1+20];
   char *attrs[]={"pgpcertid","pgpuserid","pgprevoked","pgpdisabled",
                 "pgpkeycreatetime","pgpkeyexpiretime","modifytimestamp",
@@ -1794,7 +1906,8 @@ main(int argc,char *argv[])
 
   if(opt->action==KS_SEND)
     while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
-  else if(opt->action==KS_GET || opt->action==KS_SEARCH)
+  else if(opt->action==KS_GET
+         || opt->action==KS_GETNAME || opt->action==KS_SEARCH)
     {
       for(;;)
        {
@@ -2018,6 +2131,20 @@ main(int argc,char *argv[])
          keyptr=keyptr->next;
        }
     }
+  else if(opt->action==KS_GETNAME)
+    {
+      keyptr=keylist;
+
+      while(keyptr!=NULL)
+       {
+         set_timeout(opt->timeout);
+
+         if(get_name(keyptr->str)!=KEYSERVER_OK)
+           failed++;
+
+         keyptr=keyptr->next;
+       }
+    }
   else if(opt->action==KS_SEND)
     {
       int eof=0;
index 8ea2a1a..8df684e 100644 (file)
@@ -140,6 +140,8 @@ parse_ks_options(char *line,struct ks_options *opt)
 
       if(strcasecmp(command,"get")==0)
        opt->action=KS_GET;
+      else if(strcasecmp(command,"getname")==0)
+       opt->action=KS_GETNAME;
       else if(strcasecmp(command,"send")==0)
        opt->action=KS_SEND;
       else if(strcasecmp(command,"search")==0)
@@ -311,6 +313,7 @@ ks_action_to_string(enum ks_action action)
     {
     case KS_UNKNOWN: return "UNKNOWN";
     case KS_GET:     return "GET";
+    case KS_GETNAME: return "GETNAME";
     case KS_SEND:    return "SEND";
     case KS_SEARCH:  return "SEARCH";
     }
index 4dd60a7..b5e67bb 100644 (file)
@@ -36,7 +36,7 @@
    strlen("OPAQUE")+1+sizeof_opaque+1 */
 #define MAX_LINE       (6+1+1024+1)
 
-#define MAX_COMMAND    6
+#define MAX_COMMAND    7
 #define MAX_OPTION   256
 #define MAX_SCHEME    20
 #define MAX_OPAQUE  1024
@@ -72,7 +72,7 @@ struct keylist
 unsigned int set_timeout(unsigned int seconds);
 int register_timeout(void);
 
-enum ks_action {KS_UNKNOWN=0,KS_GET,KS_SEND,KS_SEARCH};
+enum ks_action {KS_UNKNOWN=0,KS_GET,KS_GETNAME,KS_SEND,KS_SEARCH};
 
 enum ks_search_type {KS_SEARCH_SUBSTR,KS_SEARCH_EXACT,
                     KS_SEARCH_MAIL,KS_SEARCH_MAILSUB};