* gpgkeys_ldap.c (key_in_keylist, add_key_to_keylist, free_keylist,

get_key, search_key): The LDAP keyserver doesn't remove duplicates, so
remove them locally.  Do not include the key modification time in the
search response.
This commit is contained in:
David Shaw 2002-11-05 22:08:02 +00:00
parent 6920513cb4
commit ec0d9a416e
2 changed files with 309 additions and 215 deletions

View File

@ -1,3 +1,10 @@
2002-11-05 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_ldap.c (key_in_keylist, add_key_to_keylist,
free_keylist, get_key, search_key): The LDAP keyserver doesn't
remove duplicates, so remove them locally. Do not include the key
modification time in the search response.
2002-11-04 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_hkp.c (send_key), gpgkeys_ldap.c (send_key): Properly

View File

@ -106,6 +106,54 @@ ldap_to_gpg_err(LDAP *ld)
#endif
}
int
key_in_keylist(const char *key,struct keylist *list)
{
struct keylist *keyptr=list;
while(keyptr!=NULL)
{
if(strcasecmp(key,keyptr->str)==0)
return 1;
keyptr=keyptr->next;
}
return 0;
}
int
add_key_to_keylist(const char *key,struct keylist **list)
{
struct keylist *keyptr=malloc(sizeof(struct keylist));
if(keyptr==NULL)
{
fprintf(console,"gpgkeys: out of memory when deduping "
"key list\n");
return KEYSERVER_NO_MEMORY;
}
strncpy(keyptr->str,key,MAX_LINE);
keyptr->str[MAX_LINE-1]='\0';
keyptr->next=*list;
*list=keyptr;
return 0;
}
void
free_keylist(struct keylist *list)
{
while(list!=NULL)
{
struct keylist *keyptr=list;
list=keyptr->next;
free(keyptr);
}
}
int
send_key(int *eof)
{
@ -220,7 +268,6 @@ send_key(int *eof)
int
get_key(char *getkey)
{
char **vals;
LDAPMessage *res,*each;
int ret=KEYSERVER_INTERNAL_ERROR,err,count;
struct keylist *dupelist=NULL;
@ -316,149 +363,124 @@ get_key(char *getkey)
each=ldap_first_entry(ldap,res);
while(each!=NULL)
{
struct keylist *keyptr=dupelist;
char **vals,**certid;
/* 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. Note that this does NOT
mean that a keyid that exists multiple times on the
keyserver will not be fetched. It means that each KEY,
no matter how many user IDs share it's keyid, will be
no matter how many user IDs share its keyid, will be
fetched only once. If a keyid that belongs to more than
one key is fetched, the server quite properly responds
with all matching keys. -ds */
vals=ldap_get_values(ldap,each,"pgpcertid");
if(vals!=NULL)
certid=ldap_get_values(ldap,each,"pgpcertid");
if(certid!=NULL)
{
while(keyptr!=NULL)
{
if(strcasecmp(keyptr->str,vals[0])==0)
break;
keyptr=keyptr->next;
}
if(!keyptr)
if(!key_in_keylist(certid[0],dupelist))
{
/* it's not a duplicate, so add it */
keyptr=malloc(sizeof(struct keylist));
if(keyptr==NULL)
int rc=add_key_to_keylist(vals[0],&dupelist);
if(rc)
{
fprintf(console,"gpgkeys: out of memory when deduping "
"key list\n");
ret=KEYSERVER_NO_MEMORY;
ret=rc;
goto fail;
}
strncpy(keyptr->str,vals[0],MAX_LINE);
keyptr->str[MAX_LINE-1]='\0';
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)
if(verbose)
{
/* 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,"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);
}
fprintf(console,"Long key ID:\t%s\n",certid[0]);
/* YYYYMMDDHHmmssZ */
vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
if(vals!=NULL)
{
if(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)
{
if(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)
{
if(atoi(vals[0])>0)
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,"pgprevoked");
if(vals!=NULL)
vals=ldap_get_values(ldap,each,pgpkeystr);
if(vals==NULL)
{
if(atoi(vals[0])==1)
fprintf(console,"\t\t** KEY REVOKED **\n");
ldap_value_free(vals);
int errtag=ldap_to_gpg_err(ldap);
fprintf(console,"gpgkeys: unable to retrieve key %s "
"from keyserver\n",getkey);
fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag);
}
vals=ldap_get_values(ldap,each,"pgpdisabled");
if(vals!=NULL)
else
{
if(atoi(vals[0])==1)
fprintf(console,"\t\t** KEY DISABLED **\n");
ldap_value_free(vals);
}
fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey);
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)
{
if(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)
{
if(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)
{
if(atoi(vals[0])>0)
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,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,"KEY 0x%s FAILED %d\n",getkey,errtag);
}
else
{
fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey);
ldap_value_free(vals);
}
ldap_value_free(certid);
}
each=ldap_next_entry(ldap,each);
@ -469,15 +491,7 @@ get_key(char *getkey)
fail:
ldap_msgfree(res);
/* free up the dupe checker */
while(dupelist!=NULL)
{
struct keylist *keyptr=dupelist;
dupelist=keyptr->next;
free(keyptr);
}
free_keylist(dupelist);
return ret;
}
@ -527,7 +541,8 @@ search_key(char *searchkey)
{
char **vals;
LDAPMessage *res,*each;
int err,count;
int err,count=0;
struct keylist *dupelist=NULL;
/* The maxium size of the search, including the optional stuff and
the trailing \0 */
char search[2+12+MAX_LINE+2+15+14+1+1];
@ -563,7 +578,34 @@ search_key(char *searchkey)
return errtag;
}
count=ldap_count_entries(ldap,res);
/* The LDAP server doesn't return a real count of unique keys, so we
can't use ldap_count_entries here. */
each=ldap_first_entry(ldap,res);
while(each!=NULL)
{
char **certid=ldap_get_values(ldap,each,"pgpcertid");
if(certid!=NULL)
{
if(!key_in_keylist(certid[0],dupelist))
{
int rc=add_key_to_keylist(certid[0],&dupelist);
if(rc!=0)
{
fprintf(output,"SEARCH %s FAILED %d\n",searchkey,rc);
free_keylist(dupelist);
return rc;
}
count++;
}
}
each=ldap_next_entry(ldap,each);
}
free_keylist(dupelist);
dupelist=NULL;
if(count<1)
fprintf(output,"info:1:0\n");
@ -574,104 +616,149 @@ search_key(char *searchkey)
each=ldap_first_entry(ldap,res);
while(each!=NULL)
{
fprintf(output,"pub:");
char **certid;
vals=ldap_get_values(ldap,each,"pgpcertid");
if(vals!=NULL)
certid=ldap_get_values(ldap,each,"pgpcertid");
if(certid!=NULL)
{
fprintf(output,"%s",vals[0]);
ldap_value_free(vals);
LDAPMessage *uids;
/* Have we seen this certid before? */
if(!key_in_keylist(certid[0],dupelist))
{
int rc=add_key_to_keylist(certid[0],&dupelist);
if(rc)
{
fprintf(output,"SEARCH %s FAILED %d\n",searchkey,rc);
free_keylist(dupelist);
ldap_value_free(certid);
ldap_msgfree(res);
return rc;
}
fprintf(output,"pub:%s:",certid[0]);
vals=ldap_get_values(ldap,each,"pgpkeytype");
if(vals!=NULL)
{
/* The LDAP server doesn't exactly handle this
well. */
if(strcasecmp(vals[0],"RSA")==0)
fprintf(output,"1");
else if(strcasecmp(vals[0],"DSS/DH")==0)
fprintf(output,"17");
ldap_value_free(vals);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgpkeysize");
if(vals!=NULL)
{
/* Not sure why, but some keys are listed with a
key size of 0. Treat that like an
unknown. */
if(atoi(vals[0])>0)
fprintf(output,"%d",atoi(vals[0]));
ldap_value_free(vals);
}
fputc(':',output);
/* YYYYMMDDHHmmssZ */
vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
if(vals!=NULL && strlen(vals[0])==15)
{
fprintf(output,"%u",
(unsigned int)ldap2epochtime(vals[0]));
ldap_value_free(vals);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgpkeyexpiretime");
if(vals!=NULL && strlen(vals[0])==15)
{
fprintf(output,"%u",
(unsigned int)ldap2epochtime(vals[0]));
ldap_value_free(vals);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgprevoked");
if(vals!=NULL)
{
if(atoi(vals[0])==1)
fprintf(output,"r");
ldap_value_free(vals);
}
vals=ldap_get_values(ldap,each,"pgpdisabled");
if(vals!=NULL)
{
if(atoi(vals[0])==1)
fprintf(output,"d");
ldap_value_free(vals);
}
#if 0
/* This is not yet specified in the keyserver
protocol, but may be someday. */
fputc(':',output);
vals=ldap_get_values(ldap,each,"modifytimestamp");
if(vals!=NULL && strlen(vals[0])==15)
{
fprintf(output,"%u",
(unsigned int)ldap2epochtime(vals[0]));
ldap_value_free(vals);
}
#endif
fprintf(output,"\n");
/* Now print all the uids that have this certid */
uids=ldap_first_entry(ldap,res);
while(uids!=NULL)
{
vals=ldap_get_values(ldap,uids,"pgpcertid");
if(vals!=NULL)
{
if(strcasecmp(certid[0],vals[0])==0)
{
char **uidvals;
fprintf(output,"uid:");
uidvals=ldap_get_values(ldap,uids,"pgpuserid");
if(uidvals!=NULL)
{
/* Need to escape any colons */
printquoted(output,uidvals[0],':');
ldap_value_free(uidvals);
}
fprintf(output,"\n");
}
ldap_value_free(vals);
}
uids=ldap_next_entry(ldap,uids);
}
}
ldap_value_free(certid);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgpkeytype");
if(vals!=NULL)
{
/* The LDAP server doesn't exactly handle this well. */
if(strcasecmp(vals[0],"RSA")==0)
fprintf(output,"1");
else if(strcasecmp(vals[0],"DSS/DH")==0)
fprintf(output,"17");
ldap_value_free(vals);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgpkeysize");
if(vals!=NULL)
{
/* Not sure why, but some keys are listed with a key size of
0. Treat that like an unknown. */
if(atoi(vals[0])>0)
fprintf(output,"%d",atoi(vals[0]));
ldap_value_free(vals);
}
fputc(':',output);
/* YYYYMMDDHHmmssZ */
vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
if(vals!=NULL && strlen(vals[0])==15)
{
fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0]));
ldap_value_free(vals);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgpkeyexpiretime");
if(vals!=NULL && strlen(vals[0])==15)
{
fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0]));
ldap_value_free(vals);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgprevoked");
if(vals!=NULL)
{
if(atoi(vals[0])==1)
fprintf(output,"r");
ldap_value_free(vals);
}
vals=ldap_get_values(ldap,each,"pgpdisabled");
if(vals!=NULL)
{
if(atoi(vals[0])==1)
fprintf(output,"d");
ldap_value_free(vals);
}
fputc(':',output);
vals=ldap_get_values(ldap,each,"modifytimestamp");
if(vals!=NULL && strlen(vals[0])==15)
{
fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0]));
ldap_value_free(vals);
}
fprintf(output,"\nuid:");
vals=ldap_get_values(ldap,each,"pgpuserid");
if(vals!=NULL)
{
/* Need to escape any colons */
printquoted(output,vals[0],':');
ldap_value_free(vals);
}
fprintf(output,"\n");
each=ldap_next_entry(ldap,each);
}
}
ldap_msgfree(res);
free_keylist(dupelist);
fprintf(output,"SEARCH %s END\n",searchkey);