aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--keyserver/ChangeLog19
-rw-r--r--keyserver/gpgkeys_ldap.c345
2 files changed, 214 insertions, 150 deletions
diff --git a/keyserver/ChangeLog b/keyserver/ChangeLog
index fb3c3345b..47a711ef6 100644
--- a/keyserver/ChangeLog
+++ b/keyserver/ChangeLog
@@ -1,3 +1,22 @@
+2002-02-23 David Shaw <[email protected]>
+
+ * gpgkeys_ldap: Clarify the notion of a partial failure. This is
+ possible if more than one key is being handled in a batch, and one
+ fails while the other succeeds. Note that a search that comes up
+ with no results is not a failure - that is a valid response of "no
+ answer".
+
+ * gpgkeys_ldap.c (get_key): Allow GnuPG to send us full v4
+ fingerprints, long key ids, or short key ids while fetching.
+ Since the LDAP server doesn't actually handle fingerprints, chop
+ them down to long key ids for actual use.
+
+ * gpgkeys_ldap.c (main, get_key): When searching for a keyid,
+ search for subkeys as well as primary keys. This is mostly
+ significant when automatically fetching the key based on the id in
+ a header (i.e. "signature made by...."). "no-include-subkeys"
+ disables.
+
2002-02-14 David Shaw <[email protected]>
* gpgkeys_ldap.c: Fix compiler warning.
diff --git a/keyserver/gpgkeys_ldap.c b/keyserver/gpgkeys_ldap.c
index 048af8948..e28b18fb3 100644
--- a/keyserver/gpgkeys_ldap.c
+++ b/keyserver/gpgkeys_ldap.c
@@ -37,10 +37,11 @@
#define SEARCH 2
#define MAX_LINE 80
-int verbose=0,include_disabled=0,include_revoked=0;
+int verbose=0,include_disabled=0,include_revoked=0,include_subkeys=1;
char *basekeyspacedn=NULL;
char host[80];
FILE *input=NULL,*output=NULL,*console=NULL;
+LDAP *ldap=NULL;
struct keylist
{
@@ -49,12 +50,13 @@ struct keylist
};
/* Returns 0 on success, -1 on failure, and 1 on eof */
-int send_key(LDAP *ldap,char *keyid)
+int send_key(void)
{
int err,gotit=0,keysize=1,ret=-1;
char *dn=NULL;
char line[MAX_LINE];
char *key[2]={0,0};
+ char keyid[17];
#ifndef __riscos__
LDAPMod mod={LDAP_MOD_ADD,"pgpKeyV2",{key}},*attrs[2]={&mod,NULL};
#else
@@ -148,31 +150,61 @@ int send_key(LDAP *ldap,char *keyid)
free(key[0]);
free(dn);
+ if(ret!=0)
+ fprintf(output,"KEY %s FAILED\n",keyid);
+
return ret;
}
-int get_key(LDAP *ldap,char *getkey)
+/* Returns 0 on success and -1 on failure. Note that key-not-found is
+ not an error! */
+int get_key(char *getkey)
{
char **vals;
LDAPMessage *res,*each;
int ret=-1,err,count;
struct keylist *dupelist=NULL;
- char search[29];
+ char search[62];
char *attrs[]={"pgpKeyV2","pgpuserid","pgpkeyid","pgpcertid","pgprevoked",
"pgpdisabled","pgpkeycreatetime","modifytimestamp",
"pgpkeysize","pgpkeytype",NULL};
/* Build the search string */
- if(strncmp(getkey,"0x00000000",10)==0)
+ /* GPG can send us a v4 fingerprint, a v3 or v4 long key id, or a v3
+ or v4 short key id */
+
+ if(strncmp(getkey,"0x",2)==0)
+ getkey+=2;
+
+ if(strlen(getkey)>16)
{
- getkey+=10;
- sprintf(search,"(pgpkeyid=%.8s)",getkey);
+ char *offset=&getkey[strlen(getkey)-16];
+
+ /* fingerprint. Take the last 16 characters and treat it like a
+ long key id */
+
+ if(include_subkeys)
+ sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))",
+ offset,offset);
+ else
+ sprintf(search,"(pgpcertid=%.16s)",offset);
+ }
+ else if(strlen(getkey)>8)
+ {
+ /* long key id */
+
+ if(include_subkeys)
+ sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))",
+ getkey,getkey);
+ else
+ sprintf(search,"(pgpcertid=%.16s)",getkey);
}
else
{
- getkey+=2;
- sprintf(search,"(pgpcertid=%.16s)",getkey);
+ /* short key id */
+
+ sprintf(search,"(pgpkeyid=%.8s)",getkey);
}
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
@@ -183,7 +215,7 @@ int get_key(LDAP *ldap,char *getkey)
if(!verbose)
attrs[1]=NULL;
- fprintf(console,"gpgkeys: requesting key %s from LDAP keyserver %s\n",
+ fprintf(console,"gpgkeys: requesting key 0x%s from LDAP keyserver %s\n",
getkey,host);
err=ldap_search_s(ldap,basekeyspacedn,
@@ -200,149 +232,151 @@ int get_key(LDAP *ldap,char *getkey)
{
fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
fprintf(output,"KEY 0x%s FAILED\n",getkey);
- goto fail;
}
-
- /* There may be more than one unique result for a given keyID, so we
- should fetch them all (test this by fetching short key id
- 0xDEADBEEF). */
-
- each=ldap_first_entry(ldap,res);
- while(each!=NULL)
+ else
{
- struct keylist *keyptr=dupelist;
+ /* There may be more than one unique result for a given keyID,
+ so we should fetch them all (test this by fetching short key
+ id 0xDEADBEEF). */
- /* Use the long keyid to remove duplicates. The LDAP server
- returns the same keyid more than once if there are multiple
- user IDs on the key. */
-
- vals=ldap_get_values(ldap,each,"pgpcertid");
- if(vals!=NULL)
+ each=ldap_first_entry(ldap,res);
+ while(each!=NULL)
{
- while(keyptr!=NULL)
- {
- if(strcasecmp(keyptr->str,vals[0])==0)
- break;
+ struct keylist *keyptr=dupelist;
- keyptr=keyptr->next;
- }
+ /* Use the long keyid to remove duplicates. The LDAP server
+ returns the same keyid more than once if there are
+ multiple user IDs on the key. */
- if(!keyptr)
+ vals=ldap_get_values(ldap,each,"pgpcertid");
+ if(vals!=NULL)
{
- /* it's not a duplicate, so add it */
-
- keyptr=malloc(sizeof(struct keylist));
- if(keyptr==NULL)
+ while(keyptr!=NULL)
{
- fprintf(console,"gpgkeys: out of memory when deduping "
- "key list\n");
- goto fail;
- }
-
- strncpy(keyptr->str,vals[0],MAX_LINE);
- keyptr->str[MAX_LINE-1]='\0';
+ if(strcasecmp(keyptr->str,vals[0])==0)
+ break;
- keyptr->next=dupelist;
- dupelist=keyptr;
- keyptr=NULL;
- }
-
- ldap_value_free(vals);
- }
-
- if(!keyptr) /* it's not a duplicate */
- {
- if(verbose)
- {
- vals=ldap_get_values(ldap,each,"pgpuserid");
- if(vals!=NULL)
- {
- /* This is wrong, as the user ID is UTF8. A better way to
- handle this would be to send it over to gpg and display
- it on that side of the pipe. */
- fprintf(console,"\nUser ID:\t%s\n",vals[0]);
- ldap_value_free(vals);
+ keyptr=keyptr->next;
}
- vals=ldap_get_values(ldap,each,"pgprevoked");
- if(vals!=NULL)
+ if(!keyptr)
{
- if(atoi(vals[0])==1)
- fprintf(console,"\t\t** KEY REVOKED **\n");
- ldap_value_free(vals);
+ /* it's not a duplicate, so add it */
+
+ keyptr=malloc(sizeof(struct keylist));
+ if(keyptr==NULL)
+ {
+ fprintf(console,"gpgkeys: out of memory when deduping "
+ "key list\n");
+ goto fail;
+ }
+
+ strncpy(keyptr->str,vals[0],MAX_LINE);
+ keyptr->str[MAX_LINE-1]='\0';
+
+ keyptr->next=dupelist;
+ dupelist=keyptr;
+ keyptr=NULL;
}
- vals=ldap_get_values(ldap,each,"pgpdisabled");
- if(vals!=NULL)
- {
- if(atoi(vals[0])==1)
- fprintf(console,"\t\t** KEY DISABLED **\n");
- ldap_value_free(vals);
- }
-
- vals=ldap_get_values(ldap,each,"pgpkeyid");
- if(vals!=NULL)
- {
- fprintf(console,"Short key ID:\t%s\n",vals[0]);
- ldap_value_free(vals);
- }
-
- vals=ldap_get_values(ldap,each,"pgpcertid");
- if(vals!=NULL)
- {
- fprintf(console,"Long key ID:\t%s\n",vals[0]);
- ldap_value_free(vals);
- }
-
- /* YYYYMMDDHHmmssZ */
+ ldap_value_free(vals);
+ }
- vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
- if(vals!=NULL && strlen(vals[0])==15)
+ if(!keyptr) /* it's not a duplicate */
+ {
+ if(verbose)
{
- fprintf(console,"Key created:\t%.2s/%.2s/%.4s\n",
- &vals[0][4],&vals[0][6],vals[0]);
- ldap_value_free(vals);
+ vals=ldap_get_values(ldap,each,"pgpuserid");
+ if(vals!=NULL)
+ {
+ /* This is wrong, as the user ID is UTF8. A
+ better way to handle this would be to send it
+ over to gpg and display it on that side of
+ the pipe. */
+ fprintf(console,"\nUser ID:\t%s\n",vals[0]);
+ ldap_value_free(vals);
+ }
+
+ vals=ldap_get_values(ldap,each,"pgprevoked");
+ if(vals!=NULL)
+ {
+ if(atoi(vals[0])==1)
+ fprintf(console,"\t\t** KEY REVOKED **\n");
+ ldap_value_free(vals);
+ }
+
+ vals=ldap_get_values(ldap,each,"pgpdisabled");
+ if(vals!=NULL)
+ {
+ if(atoi(vals[0])==1)
+ fprintf(console,"\t\t** KEY DISABLED **\n");
+ ldap_value_free(vals);
+ }
+
+ vals=ldap_get_values(ldap,each,"pgpkeyid");
+ if(vals!=NULL)
+ {
+ fprintf(console,"Short key ID:\t%s\n",vals[0]);
+ ldap_value_free(vals);
+ }
+
+ vals=ldap_get_values(ldap,each,"pgpcertid");
+ if(vals!=NULL)
+ {
+ fprintf(console,"Long key ID:\t%s\n",vals[0]);
+ ldap_value_free(vals);
+ }
+
+ /* YYYYMMDDHHmmssZ */
+
+ vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
+ if(vals!=NULL && strlen(vals[0])==15)
+ {
+ fprintf(console,"Key created:\t%.2s/%.2s/%.4s\n",
+ &vals[0][4],&vals[0][6],vals[0]);
+ ldap_value_free(vals);
+ }
+
+ vals=ldap_get_values(ldap,each,"modifytimestamp");
+ if(vals!=NULL && strlen(vals[0])==15)
+ {
+ fprintf(console,"Key modified:\t%.2s/%.2s/%.4s\n",
+ &vals[0][4],&vals[0][6],vals[0]);
+ ldap_value_free(vals);
+ }
+
+ vals=ldap_get_values(ldap,each,"pgpkeysize");
+ if(vals!=NULL)
+ {
+ fprintf(console,"Key size:\t%d\n",atoi(vals[0]));
+ ldap_value_free(vals);
+ }
+
+ vals=ldap_get_values(ldap,each,"pgpkeytype");
+ if(vals!=NULL)
+ {
+ fprintf(console,"Key type:\t%s\n",vals[0]);
+ ldap_value_free(vals);
+ }
}
- vals=ldap_get_values(ldap,each,"modifytimestamp");
- if(vals!=NULL && strlen(vals[0])==15)
+ vals=ldap_get_values(ldap,each,"pgpKeyV2");
+ if(vals==NULL)
{
- fprintf(console,"Key modified:\t%.2s/%.2s/%.4s\n",
- &vals[0][4],&vals[0][6],vals[0]);
- ldap_value_free(vals);
+ fprintf(console,"gpgkeys: unable to retrieve key %s "
+ "from keyserver\n",getkey);
+ fprintf(output,"KEY 0x%s FAILED\n",getkey);
}
-
- vals=ldap_get_values(ldap,each,"pgpkeysize");
- if(vals!=NULL)
+ else
{
- fprintf(console,"Key size:\t%d\n",atoi(vals[0]));
- ldap_value_free(vals);
- }
+ fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey);
- vals=ldap_get_values(ldap,each,"pgpkeytype");
- if(vals!=NULL)
- {
- fprintf(console,"Key type:\t%s\n",vals[0]);
ldap_value_free(vals);
}
}
- vals=ldap_get_values(ldap,each,"pgpKeyV2");
- if(vals==NULL)
- {
- fprintf(console,"gpgkeys: unable to retrieve key %s "
- "from keyserver\n",getkey);
- fprintf(output,"KEY 0x%s FAILED\n",getkey);
- }
- else
- {
- fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey);
-
- ldap_value_free(vals);
- }
+ each=ldap_next_entry(ldap,each);
}
-
- each=ldap_next_entry(ldap,each);
}
ret=0;
@@ -398,7 +432,9 @@ void printquoted(FILE *stream,char *string,char delim)
}
}
-int search_key(LDAP *ldap,char *searchkey)
+/* Returns 0 on success and -1 on error. Note that key-not-found is
+ not an error! */
+int search_key(char *searchkey)
{
char **vals;
LDAPMessage *res,*each;
@@ -549,10 +585,9 @@ int search_key(LDAP *ldap,char *searchkey)
int main(int argc,char *argv[])
{
- LDAP *ldap=NULL;
int port=0,arg,err,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
char line[MAX_LINE],**vals;
- int version;
+ int version,failed=0;
char *attrs[]={"basekeyspacedn","version","software",NULL};
LDAPMessage *res;
struct keylist *keylist=NULL,*keyptr=NULL;
@@ -688,6 +723,13 @@ int main(int argc,char *argv[])
else
include_revoked=1;
}
+ else if(strcasecmp(start,"include-subkeys")==0)
+ {
+ if(no)
+ include_subkeys=0;
+ else
+ include_subkeys=1;
+ }
continue;
}
@@ -832,27 +874,24 @@ int main(int argc,char *argv[])
while(keyptr!=NULL)
{
- struct keylist *current=keyptr;
+ if(get_key(keyptr->str)==-1)
+ failed++;
- get_key(ldap,current->str);
-
- keyptr=current->next;
-
- /* Free it as we go */
- free(current);
+ keyptr=keyptr->next;
}
break;
case SEND:
{
- char keyid[17]="????";
int ret;
- while((ret=send_key(ldap,keyid))!=1)
+ do
{
- if(ret!=0)
- fprintf(output,"KEY %s FAILED\n",keyid);
+ ret=send_key();
+ if(ret==-1)
+ failed++;
}
+ while(ret!=1);
}
break;
@@ -882,21 +921,19 @@ int main(int argc,char *argv[])
keyptr=keylist;
while(keyptr!=NULL)
{
- struct keylist *current=keyptr;
-
- strcat(searchkey,current->str);
+ strcat(searchkey,keyptr->str);
strcat(searchkey,"*");
- keyptr=current->next;
-
- /* Free it as we go */
- free(current);
+ keyptr=keyptr->next;
}
/* Nail that last "*" */
searchkey[strlen(searchkey)-1]='\0';
- if(search_key(ldap,searchkey)==-1)
- fprintf(output,"SEARCH %s FAILED\n",searchkey);
+ if(search_key(searchkey)==-1)
+ {
+ fprintf(output,"SEARCH %s FAILED\n",searchkey);
+ failed++;
+ }
free(searchkey);
}
@@ -904,10 +941,18 @@ int main(int argc,char *argv[])
break;
}
- ret=KEYSERVER_OK;
+ if(!failed)
+ ret=KEYSERVER_OK;
fail:
+ while(keylist!=NULL)
+ {
+ struct keylist *current=keylist;
+ keylist=keylist->next;
+ free(current);
+ }
+
if(input!=stdin)
fclose(input);