1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Update head to match stable 1.0

This commit is contained in:
David Shaw 2002-06-29 13:31:13 +00:00
parent 98a05e4239
commit 151ee2f47b
154 changed files with 29296 additions and 1324 deletions

116
keyserver/ChangeLog Normal file
View file

@ -0,0 +1,116 @@
2002-06-11 David Shaw <dshaw@jabberwocky.com>
* Makefile.am: Don't hard-code the LDAP libraries - get them from
LDAPLIBS via configure. Also, gpgkeys_hkp is a program, not a
script.
2002-06-10 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_ldap.c (include_subkeys): Default "include-subkeys" to
off, since GnuPG now defaults it to on.
2002-06-06 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_hkp.c (parse_hkp_index): Type tweaks.
* gpgkeys_hkp.c (main): Add experimental code warning.
2002-06-05 David Shaw <dshaw@jabberwocky.com>
* Makefile.am, gpgkeys_hkp.c (new): Experimental HKP keyserver
interface.
2002-05-08 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_ldap.c: Include <lber.h> if we absolutely must. This
helps when compiling against a very old OpenLDAP.
2002-04-29 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_mailto.in: Properly handle key requests in full
fingerprint form.
2002-03-29 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_ldap.c (printquoted): Quote backslashes within keyserver
search responses.
2002-02-25 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_ldap (get_key): LDAP keyservers do not support v3
fingerprints, so error out if someone tries. Actually, they don't
support any fingerprints, but at least we can calculate a keyid
from a v4 fingerprint.
2002-02-23 David Shaw <dshaw@jabberwocky.com>
* 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 <dshaw@jabberwocky.com>
* gpgkeys_ldap.c: Fix compiler warning.
* gpgkeys_ldap.c: Be much more robust with mangled input files.
2001-12-28 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_mailto.in: Use the new OUTOFBAND indicator so gpg knows
not to try and import anything. Also turn on perl -w for
warnings.
* gpgkeys_ldap.c (main): If we're using temp files (rather than
stdin/stdout), make sure the file is closed when we're done.
2001-12-20 David Shaw <dshaw@jabberwocky.com>
* Properly free the LDAP response when we're done with it.
* Now that we handle multiple keys, we must remove duplicates as
the LDAP keyserver returns keys with multiple user IDs multiple
times.
* Properly handle multiple keys with the same key ID (it's really
rare, so fetch "0xDEADBEEF" to test this).
2001-12-17 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_ldap.c, gpgkeys_mailto.in: Fix GNU capitalization
issues. Prefix log messages with "gpgkeys" to clarify which
program is generating them.
2001-12-14 David Shaw <dshaw@jabberwocky.com>
* gpgkeys_ldap.c (search_key): Use unsigned int rather than uint
for portability.
2001-12-04 David Shaw <dshaw@jabberwocky.com>
* Initial version of gpgkeys_ldap (LDAP keyserver helper) and
gpgkeys_mailto (email keyserver helper)
Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

36
keyserver/Makefile.am Normal file
View file

@ -0,0 +1,36 @@
# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
# GnuPG is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# GnuPG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir)/include
EXTRA_PROGRAMS = gpgkeys_ldap gpgkeys_hkp
EXTRA_SCRIPTS = gpgkeys_mailto
# We don't need the libs the regular GPG binaries do
LIBS=
bin_PROGRAMS = @GPGKEYS_LDAP@ @GPGKEYS_HKP@
bin_SCRIPTS = @GPGKEYS_MAILTO@
noinst_SCRIPTS = gpgkeys_test
# don't distribute hkp for now
nodist_gpgkeys_hkp_SOURCES = gpgkeys_hkp.c
gpgkeys_ldap_LDADD = @LDAPLIBS@ @NETLIBS@
gpgkeys_hkp_LDADD = @NETLIBS@

981
keyserver/gpgkeys_hkp.c Normal file
View file

@ -0,0 +1,981 @@
/* gpgkeys_hkp.c - talk to an HKP keyserver
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#include "keyserver.h"
#define GET 0
#define SEND 1
#define SEARCH 2
#define MAX_LINE 80
int verbose=0,include_disabled=0,include_revoked=0;
char *basekeyspacedn=NULL;
char host[80];
FILE *input=NULL,*output=NULL,*console=NULL,*server=NULL;
struct keylist
{
char str[MAX_LINE];
struct keylist *next;
};
int http_connect(const char *host,unsigned short port)
{
int sock=-1;
struct hostent *ent;
struct sockaddr_in addr;
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock==-1)
{
fprintf(console,"gpgkeys: internal socket error: %s\n",strerror(errno));
goto fail;
}
ent=gethostbyname(host);
if(ent==NULL)
{
fprintf(console,"gpgkeys: DNS error: %s\n",hstrerror(h_errno));
goto fail;
}
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=*(int *)ent->h_addr_list[0];
addr.sin_port=htons(port?port:11371);
if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==-1)
{
fprintf(console,"gpgkeys: unable to contact keyserver: %s\n",
strerror(errno));
goto fail;
}
server=fdopen(sock,"r+");
if(server==NULL)
{
fprintf(console,"gpgkeys: unable to fdopen socket: %s\n",
strerror(errno));
goto fail;
}
if(verbose>3)
fprintf(console,"gpgkeys: HKP connect to %s:%d\n",host,port?port:11371);
return 0;
fail:
if(sock>-1)
close(sock);
return -1;
}
void http_disconnect(void)
{
if(verbose>3)
fprintf(console,"gpgkeys: HKP disconnect from %s\n",host);
fclose(server);
}
int http_get(const char *op,const char *search)
{
fprintf(server,"GET /pks/lookup?op=%s&search=%s HTTP/1.0\n\n",op,search);
if(verbose>2)
fprintf(console,"gpgkeys: HTTP GET /pks/lookup?op=%s&search=%s HTTP/1.0\n",
op,search);
return 0;
}
int http_post(const char *data)
{
char line[MAX_LINE];
int result;
fprintf(server,
"POST /pks/add HTTP/1.0\n"
"Content-type: application/x-www-form-urlencoded\n"
"Content-Length: %d\n\n%s",strlen(data),data);
if(verbose>2)
fprintf(console,
"gpgkeys: HTTP POST /pks/add HTTP/1.0\n"
"gpgkeys: Content-type: application/x-www-form-urlencoded\n"
"gpgkeys: Content-Length: %d\n\n",strlen(data));
/* Now wait for a response */
while(fgets(line,MAX_LINE,server)!=NULL)
if(sscanf(line,"HTTP/%*f %d OK",&result)==1)
return result;
return -1;
}
/* Returns 0 on success, -1 on failure, and 1 on eof */
int send_key(void)
{
int err,gotit=0,keylen,maxlen,ret=-1;
char keyid[17],line[MAX_LINE],*key;
key=strdup("keytext=");
if(key==NULL)
{
fprintf(console,"gpgkeys: unable to allocate for key\n");
goto fail;
}
maxlen=keylen=strlen(key);
/* Read and throw away stdin until we see the BEGIN */
while(fgets(line,MAX_LINE,input)!=NULL)
if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1)
{
gotit=1;
break;
}
if(!gotit)
{
/* i.e. eof before the KEY BEGIN was found */
ret=1;
goto fail;
}
gotit=0;
/* Now slurp up everything until we see the END */
while(fgets(line,MAX_LINE,input)!=NULL)
if(sscanf(line,"KEY %16s END\n",keyid)==1)
{
gotit=1;
break;
}
else
{
char *c=line;
while(*c!='\0')
{
if(maxlen-keylen<4)
{
maxlen+=1024;
key=realloc(key,maxlen);
if(key==NULL)
{
fprintf(console,"gpgkeys: unable to reallocate for key\n");
goto fail;
}
}
if(isalnum(*c) || *c=='-')
{
key[keylen++]=*c;
key[keylen]='\0';
}
else if(*c==' ')
{
key[keylen++]='+';
key[keylen]='\0';
}
else
{
sprintf(&key[keylen],"%%%02X",*c);
keylen+=3;
}
c++;
}
}
if(!gotit)
{
fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
goto fail;
}
err=http_post(key);
if(err!=200)
{
fprintf(console,"gpgkeys: remote server returned error %d\n",err);
goto fail;
}
ret=0;
fail:
free(key);
if(ret!=0)
fprintf(output,"KEY %s FAILED\n",keyid);
return ret;
}
int get_key(char *getkey)
{
int err,gotit=0;
char search[29],line[MAX_LINE];
/* Build the search string. HKP only uses the short key IDs. */
if(strncmp(getkey,"0x",2)==0)
getkey+=2;
if(strlen(getkey)==32)
{
fprintf(console,
"gpgkeys: HKP keyservers do not support v3 fingerprints\n");
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
fprintf(output,"KEY 0x%s FAILED\n",getkey);
return -1;
}
if(strlen(getkey)>8)
{
char *offset=&getkey[strlen(getkey)-8];
/* fingerprint or long key id. Take the last 8 characters and
treat it like a short key id */
sprintf(search,"0x%.8s",offset);
}
else
{
/* short key id */
sprintf(search,"0x%.8s",getkey);
}
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
if(verbose>2)
fprintf(console,"gpgkeys: HKP fetch for: %s\n",search);
fprintf(console,"gpgkeys: requesting key 0x%s from HKP keyserver %s\n",
getkey,host);
err=http_get("get",search);
if(err!=0)
{
fprintf(console,"gpgkeys: HKP fetch error: %s\n",strerror(errno));
fprintf(output,"KEY 0x%s FAILED\n",getkey);
return -1;
}
while(fgets(line,MAX_LINE,server))
{
if(gotit)
{
fprintf(output,line);
if(strcmp(line,"-----END PGP PUBLIC KEY BLOCK-----\n")==0)
{
gotit=0;
fprintf(output,"KEY 0x%s END\n",getkey);
break;
}
}
else
if(strcmp(line,"-----BEGIN PGP PUBLIC KEY BLOCK-----\n")==0)
{
fprintf(output,line);
gotit=1;
}
}
return 0;
}
void print_quoted(FILE *stream,char *string,char delim)
{
while(*string)
{
if(*string==delim)
fprintf(stream,"\\x%02X",*string);
else
fputc(*string,stream);
string++;
}
}
void append_quoted(char *buffer,char *string,char delim)
{
while(*buffer)
buffer++;
while(*string)
{
if(*string==delim)
{
sprintf(buffer,"\\x%02X",*string);
buffer+=4;
}
else
*buffer=*string;
buffer++;
string++;
}
*buffer='\0';
}
unsigned int scan_isodatestr( const char *string )
{
int year, month, day;
struct tm tmbuf;
time_t stamp;
int i;
if( strlen(string) != 10 || string[4] != '-' || string[7] != '-' )
return 0;
for( i=0; i < 4; i++ )
if( !isdigit(string[i]) )
return 0;
if( !isdigit(string[5]) || !isdigit(string[6]) )
return 0;
if( !isdigit(string[8]) || !isdigit(string[9]) )
return 0;
year = atoi(string);
month = atoi(string+5);
day = atoi(string+8);
/* some basic checks */
if( year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 )
return 0;
memset( &tmbuf, 0, sizeof tmbuf );
tmbuf.tm_mday = day;
tmbuf.tm_mon = month-1;
tmbuf.tm_year = year - 1900;
tmbuf.tm_isdst = -1;
stamp = mktime( &tmbuf );
if( stamp == (time_t)-1 )
return 0;
return stamp;
}
/* pub 2048/<a href="/pks/lookup?op=get&search=0x3CB3B415">3CB3B415</a> 1998/04/03 David M. Shaw &lt;<a href="/pks/lookup?op=get&search=0x3CB3B415">dshaw@jabberwocky.com</a>&gt; */
/* Luckily enough, both the HKP server and NAI HKP interface to their
LDAP server are close enough in output so the same function can
parse them both. */
int parse_hkp_index(char *line,char **buffer)
{
static int open=0,revoked=0;
static char *key,*uid;
static unsigned int bits,createtime;
int ret=0;
/* printf("Open %d, LINE: %s\n",open,line); */
/* For multiple UIDs */
if(open && uid!=NULL)
{
ret=0;
if(!(revoked && !include_revoked))
{
char intstr[11],*buf;
buf=realloc(*buffer,
(*buffer?strlen(*buffer):0)+
(strlen(key)*4)+
1+
(strlen(uid)*4)
+1
+2
+10
+4
+10
+1
+1);
if(buf)
*buffer=buf;
else
return -1;
append_quoted(*buffer,key,':');
append_quoted(*buffer,":",0);
append_quoted(*buffer,uid,':');
append_quoted(*buffer,":",0);
append_quoted(*buffer,revoked?"1:":":",0);
sprintf(intstr,"%u",createtime);
append_quoted(*buffer,intstr,':');
append_quoted(*buffer,"::::",0);
sprintf(intstr,"%u",bits);
append_quoted(*buffer,intstr,':');
append_quoted(*buffer,"\n",0);
ret=1;
}
if(strncmp(line," ",5)!=0)
{
revoked=0;
free(key);
free(uid);
uid=NULL;
open=0;
}
}
if(strncasecmp(line,"pub ",5)==0)
{
char *tok,*temp;
open=1;
line+=4;
tok=strsep(&line,"/");
if(tok==NULL)
return ret;
bits=atoi(tok);
tok=strsep(&line,">");
if(tok==NULL)
return ret;
tok=strsep(&line,"<");
if(tok==NULL)
{
key=strdup("00000000");
return ret;
}
key=strdup(tok);
tok=strsep(&line," ");
if(tok==NULL)
return ret;
tok=strsep(&line," ");
if(tok==NULL)
return ret;
/* The date parser wants '-' instead of '/', so... */
temp=tok;
while(*temp!='\0')
{
if(*temp=='/')
*temp='-';
temp++;
}
createtime=scan_isodatestr(tok);
}
if(open)
{
int uidindex=0;
if(line==NULL)
{
uid=strdup("Key index corrupted");
return ret;
}
/* All that's left is the user name. Strip off anything
<between brackets> and de-urlencode it. */
while(*line==' ' && *line!='\0')
line++;
if(strncmp(line,"*** KEY REVOKED ***",19)==0)
{
revoked=1;
return ret;
}
uid=malloc(strlen(line)+1);
while(*line!='\0')
{
switch(*line)
{
case '<':
while(*line!='>' && *line!='\0')
line++;
if(*line!='\0')
line++;
break;
case '&':
if((*(line+1)!='\0' && tolower(*(line+1))=='l') &&
(*(line+2)!='\0' && tolower(*(line+2))=='t') &&
(*(line+3)!='\0' && *(line+3)==';'))
{
uid[uidindex++]='<';
line+=4;
break;
}
if((*(line+1)!='\0' && tolower(*(line+1))=='g') &&
(*(line+2)!='\0' && tolower(*(line+2))=='t') &&
(*(line+3)!='\0' && *(line+3)==';'))
{
uid[uidindex++]='>';
line+=4;
break;
}
default:
uid[uidindex++]=*line;
line++;
break;
}
}
uid[uidindex]='\0';
/* Chop off the trailing \r, \n, or both. This is fussy as the
true HKP servers have \r\n, and the NAI HKP servers have just
\n. */
if(isspace(uid[uidindex-1]))
uid[uidindex-1]='\0';
if(isspace(uid[uidindex-2]))
uid[uidindex-2]='\0';
}
return ret;
}
int search_key(char *searchkey)
{
int ret=-1,err,count=0;
char *search,*request,*buffer=NULL;
char line[1024];
int max,len;
fprintf(output,"SEARCH %s BEGIN\n",searchkey);
/* Build the search string. It's going to need url-encoding. */
max=0;
len=0;
search=NULL;
request=searchkey;
while(*request!='\0')
{
if(max-len<3)
{
max+=100;
search=realloc(search,max+1); /* Note +1 for \0 */
}
if(isalnum(*request) || *request=='-')
search[len++]=*request;
else if(*request==' ')
search[len++]='+';
else
{
sprintf(&search[len],"%%%02X",*request);
len+=3;
}
request++;
}
search[len]='\0';
if(verbose>2)
fprintf(console,"gpgkeys: HKP search for: %s\n",search);
fprintf(console,("gpgkeys: searching for \"%s\" from HKP server %s\n"),
searchkey,host);
http_get("index",search);
free(search);
while(fgets(line,1024,server))
{
err=parse_hkp_index(line,&buffer);
if(err==-1)
goto fail;
count+=err;
}
fprintf(output,"COUNT %d\n%s",count,buffer);
// fprintf(output,"COUNT -1\n%s",buffer);
fprintf(output,"SEARCH %s END\n",searchkey);
ret=0;
fail:
free(buffer);
return ret;
}
int main(int argc,char *argv[])
{
int port=0,arg,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
char line[MAX_LINE];
int version,failed=0;
struct keylist *keylist=NULL,*keyptr=NULL;
console=stderr;
fprintf(console,
"gpgkeys: Warning: this is an *experimental* HKP interface!\n");
while((arg=getopt(argc,argv,"ho:"))!=-1)
switch(arg)
{
default:
case 'h':
fprintf(console,"-h\thelp\n");
fprintf(console,"-o\toutput to this file\n");
return KEYSERVER_OK;
case 'o':
output=fopen(optarg,"w");
if(output==NULL)
{
fprintf(console,"gpgkeys: Cannot open output file \"%s\": %s\n",
optarg,strerror(errno));
return KEYSERVER_INTERNAL_ERROR;
}
break;
}
if(argc>optind)
{
input=fopen(argv[optind],"r");
if(input==NULL)
{
fprintf(console,"gpgkeys: Cannot open input file \"%s\": %s\n",
argv[optind],strerror(errno));
return KEYSERVER_INTERNAL_ERROR;
}
}
if(input==NULL)
input=stdin;
if(output==NULL)
output=stdout;
/* Get the command and info block */
while(fgets(line,MAX_LINE,input)!=NULL)
{
char commandstr[7];
char portstr[10];
char optionstr[30];
char hash;
if(line[0]=='\n')
break;
if(sscanf(line,"%c",&hash)==1 && hash=='#')
continue;
if(sscanf(line,"COMMAND %6s\n",commandstr)==1)
{
commandstr[6]='\0';
if(strcasecmp(commandstr,"get")==0)
action=GET;
else if(strcasecmp(commandstr,"send")==0)
action=SEND;
else if(strcasecmp(commandstr,"search")==0)
action=SEARCH;
continue;
}
if(sscanf(line,"HOST %79s\n",host)==1)
{
host[79]='\0';
continue;
}
if(sscanf(line,"PORT %9s\n",portstr)==1)
{
portstr[9]='\0';
port=atoi(portstr);
continue;
}
if(sscanf(line,"VERSION %d\n",&version)==1)
{
if(version!=0)
{
ret=KEYSERVER_VERSION_ERROR;
goto fail;
}
continue;
}
if(sscanf(line,"OPTION %29s\n",optionstr)==1)
{
int no=0;
char *start=&optionstr[0];
optionstr[29]='\0';
if(strncasecmp(optionstr,"no-",3)==0)
{
no=1;
start=&optionstr[3];
}
if(strcasecmp(start,"verbose")==0)
{
if(no)
verbose--;
else
verbose++;
}
else if(strcasecmp(start,"include-disabled")==0)
{
if(no)
include_disabled=0;
else
include_disabled=1;
}
else if(strcasecmp(start,"include-revoked")==0)
{
if(no)
include_revoked=0;
else
include_revoked=1;
}
continue;
}
}
/* 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==SEND)
while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
else if(action==GET || action==SEARCH)
{
for(;;)
{
struct keylist *work;
if(fgets(line,MAX_LINE,input)==NULL)
break;
else
{
if(line[0]=='\n')
break;
work=malloc(sizeof(struct keylist));
if(work==NULL)
{
fprintf(console,"gpgkeys: out of memory while "
"building key list\n");
goto fail;
}
strcpy(work->str,line);
/* Trim the trailing \n */
work->str[strlen(line)-1]='\0';
work->next=NULL;
/* Always attach at the end to keep the list in proper
order for searching */
if(keylist==NULL)
keylist=work;
else
keyptr->next=work;
keyptr=work;
}
}
}
else
{
fprintf(console,"gpgkeys: no keyserver command specified\n");
goto fail;
}
/* Send the response */
fprintf(output,"VERSION 0\n");
fprintf(output,"PROGRAM %s\n\n",VERSION);
if(verbose>1)
{
fprintf(console,"Host:\t\t%s\n",host);
if(port)
fprintf(console,"Port:\t\t%d\n",port);
fprintf(console,"Command:\t%s\n",action==GET?"GET":
action==SEND?"SEND":"SEARCH");
}
#if 0
if(verbose>1)
{
vals=ldap_get_values(ldap,res,"software");
if(vals!=NULL)
{
fprintf(console,"Server: \t%s\n",vals[0]);
ldap_value_free(vals);
}
vals=ldap_get_values(ldap,res,"version");
if(vals!=NULL)
{
fprintf(console,"Version:\t%s\n",vals[0]);
ldap_value_free(vals);
}
}
#endif
switch(action)
{
case GET:
keyptr=keylist;
while(keyptr!=NULL)
{
http_connect(host,port);
if(get_key(keyptr->str)==-1)
failed++;
http_disconnect();
keyptr=keyptr->next;
}
break;
case SEND:
{
int ret;
do
{
http_connect(host,port);
ret=send_key();
if(ret==-1)
failed++;
http_disconnect();
}
while(ret!=1);
}
break;
case SEARCH:
{
char *searchkey=NULL;
int len=0;
/* To search, we stick a space in between each key to search
for. */
keyptr=keylist;
while(keyptr!=NULL)
{
len+=strlen(keyptr->str)+1;
keyptr=keyptr->next;
}
searchkey=malloc(len+1);
if(searchkey==NULL)
goto fail;
searchkey[0]='\0';
keyptr=keylist;
while(keyptr!=NULL)
{
strcat(searchkey,keyptr->str);
strcat(searchkey," ");
keyptr=keyptr->next;
}
/* Nail that last space */
searchkey[strlen(searchkey)-1]='\0';
http_connect(host,port);
if(search_key(searchkey)==-1)
{
fprintf(output,"SEARCH %s FAILED\n",searchkey);
failed++;
}
http_disconnect();
free(searchkey);
}
break;
}
if(!failed)
ret=KEYSERVER_OK;
fail:
while(keylist!=NULL)
{
struct keylist *current=keylist;
keylist=keylist->next;
free(current);
}
if(input!=stdin)
fclose(input);
if(output!=stdout)
fclose(output);
return ret;
}

986
keyserver/gpgkeys_ldap.c Normal file
View file

@ -0,0 +1,986 @@
/* gpgkeys_ldap.c - talk to a LDAP keyserver
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#ifdef NEED_LBER_H
#include <lber.h>
#endif
#include <ldap.h>
#include "keyserver.h"
#ifdef __riscos__
#include <unixlib/local.h>
#endif
#define GET 0
#define SEND 1
#define SEARCH 2
#define MAX_LINE 80
int verbose=0,include_disabled=0,include_revoked=0,include_subkeys=0;
char *basekeyspacedn=NULL;
char host[80];
FILE *input=NULL,*output=NULL,*console=NULL;
LDAP *ldap=NULL;
struct keylist
{
char str[MAX_LINE];
struct keylist *next;
};
/* Returns 0 on success, -1 on failure, and 1 on eof */
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
LDAPMod mod, *attrs[2];
mod.mod_op = LDAP_MOD_ADD;
mod.mod_type = "pgpKeyV2";
mod.mod_values = 0;
mod.mod_bvalues = 0;
attrs[0] = &mod;
attrs[1] = NULL;
#endif
dn=malloc(strlen("pgpCertid=virtual,")+strlen(basekeyspacedn)+1);
if(dn==NULL)
{
fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n");
goto fail;
}
strcpy(dn,"pgpCertid=virtual,");
strcat(dn,basekeyspacedn);
key[0]=malloc(1);
if(key[0]==NULL)
{
fprintf(console,"gpgkeys: unable to allocate memory for key\n");
goto fail;
}
key[0][0]='\0';
/* Read and throw away stdin until we see the BEGIN */
while(fgets(line,MAX_LINE,input)!=NULL)
if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1)
{
gotit=1;
break;
}
if(!gotit)
{
/* i.e. eof before the KEY BEGIN was found */
ret=1;
goto fail;
}
gotit=0;
/* Now slurp up everything until we see the END */
while(fgets(line,MAX_LINE,input)!=NULL)
if(sscanf(line,"KEY %16s END\n",keyid)==1)
{
gotit=1;
break;
}
else
{
keysize+=strlen(line);
key[0]=realloc(key[0],keysize);
if(key[0]==NULL)
{
fprintf(console,"gpgkeys: unable to reallocate for key\n");
goto fail;
}
strcat(key[0],line);
}
if(!gotit)
{
fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
goto fail;
}
err=ldap_add_s(ldap,dn,attrs);
if(err!=LDAP_SUCCESS)
{
fprintf(console,"gpgkeys: error adding key %s to keyserver: %s\n",
keyid,ldap_err2string(err));
goto fail;
}
ret=0;
fail:
free(key[0]);
free(dn);
if(ret!=0)
fprintf(output,"KEY %s FAILED\n",keyid);
return ret;
}
/* 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[62];
char *attrs[]={"pgpKeyV2","pgpuserid","pgpkeyid","pgpcertid","pgprevoked",
"pgpdisabled","pgpkeycreatetime","modifytimestamp",
"pgpkeysize","pgpkeytype",NULL};
/* Build the search string */
/* 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)==32)
{
fprintf(console,
"gpgkeys: LDAP keyservers do not support v3 fingerprints\n");
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
fprintf(output,"KEY 0x%s FAILED\n",getkey);
return -1;
}
if(strlen(getkey)>16)
{
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
{
/* short key id */
sprintf(search,"(pgpkeyid=%.8s)",getkey);
}
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
if(verbose>2)
fprintf(console,"gpgkeys: LDAP fetch for: %s\n",search);
if(!verbose)
attrs[1]=NULL;
fprintf(console,"gpgkeys: requesting key 0x%s from LDAP keyserver %s\n",
getkey,host);
err=ldap_search_s(ldap,basekeyspacedn,
LDAP_SCOPE_SUBTREE,search,attrs,0,&res);
if(err!=0)
{
fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err));
fprintf(output,"KEY 0x%s FAILED\n",getkey);
return -1;
}
count=ldap_count_entries(ldap,res);
if(count<1)
{
fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
fprintf(output,"KEY 0x%s FAILED\n",getkey);
}
else
{
/* 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)
{
struct keylist *keyptr=dupelist;
/* 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
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)
{
while(keyptr!=NULL)
{
if(strcasecmp(keyptr->str,vals[0])==0)
break;
keyptr=keyptr->next;
}
if(!keyptr)
{
/* 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;
}
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);
}
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,"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);
}
}
ret=0;
fail:
ldap_msgfree(res);
/* free up the dupe checker */
while(dupelist!=NULL)
{
struct keylist *keyptr=dupelist;
dupelist=keyptr->next;
free(keyptr);
}
return ret;
}
time_t ldap2epochtime(const char *timestr)
{
struct tm pgptime;
memset(&pgptime,0,sizeof(pgptime));
/* YYYYMMDDHHmmssZ */
sscanf(timestr,"%4d%2d%2d%2d%2d%2d",
&pgptime.tm_year,
&pgptime.tm_mon,
&pgptime.tm_mday,
&pgptime.tm_hour,
&pgptime.tm_min,
&pgptime.tm_sec);
pgptime.tm_year-=1900;
pgptime.tm_isdst=-1;
pgptime.tm_mon--;
return mktime(&pgptime);
}
void printquoted(FILE *stream,char *string,char delim)
{
while(*string)
{
if(*string==delim || *string=='\\')
fprintf(stream,"\\x%02x",*string);
else
fputc(*string,stream);
string++;
}
}
/* 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;
int err,count;
/* 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];
char *attrs[]={"pgpcertid","pgpuserid","pgprevoked","pgpdisabled",
"pgpkeycreatetime","pgpkeyexpiretime","modifytimestamp",
"pgpkeysize","pgpkeytype",NULL};
fprintf(output,"SEARCH %s BEGIN\n",searchkey);
/* Build the search string */
sprintf(search,"%s(pgpuserid=*%s*)%s%s%s",
(!(include_disabled&&include_revoked))?"(&":"",
searchkey,
include_disabled?"":"(pgpdisabled=0)",
include_revoked?"":"(pgprevoked=0)",
!(include_disabled&&include_revoked)?")":"");
if(verbose>2)
fprintf(console,"gpgkeys: LDAP search for: %s\n",search);
fprintf(console,("gpgkeys: searching for \"%s\" from LDAP server %s\n"),
searchkey,host);
err=ldap_search_s(ldap,basekeyspacedn,
LDAP_SCOPE_SUBTREE,search,attrs,0,&res);
if(err!=0)
{
fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err));
return -1;
}
count=ldap_count_entries(ldap,res);
if(count<1)
fprintf(output,"COUNT 0\n");
else
{
fprintf(output,"COUNT %d\n",count);
each=ldap_first_entry(ldap,res);
while(each!=NULL)
{
int flags=0;
vals=ldap_get_values(ldap,each,"pgpcertid");
if(vals!=NULL)
{
fprintf(output,"%s:",vals[0]);
ldap_value_free(vals);
}
else
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgpuserid");
if(vals!=NULL)
{
/* Need to escape any colons */
printquoted(output,vals[0],':');
fputc(':',output);
ldap_value_free(vals);
}
else
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgprevoked");
if(vals!=NULL)
{
if(atoi(vals[0])==1)
flags|=1;
ldap_value_free(vals);
}
vals=ldap_get_values(ldap,each,"pgpdisabled");
if(vals!=NULL)
{
if(atoi(vals[0])==1)
flags|=2;
ldap_value_free(vals);
}
fprintf(output,"%d:",flags);
/* 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);
}
else
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);
}
else
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);
}
else
fputc(':',output);
vals=ldap_get_values(ldap,each,"pgpkeytype");
if(vals!=NULL)
{
fprintf(output,"%s:",vals[0]);
ldap_value_free(vals);
}
else
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('\n',output);
each=ldap_next_entry(ldap,each);
}
}
ldap_msgfree(res);
fprintf(output,"SEARCH %s END\n",searchkey);
return 0;
}
int main(int argc,char *argv[])
{
int port=0,arg,err,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
char line[MAX_LINE],**vals;
int version,failed=0;
char *attrs[]={"basekeyspacedn","version","software",NULL};
LDAPMessage *res;
struct keylist *keylist=NULL,*keyptr=NULL;
#ifdef __riscos__
__riscosify_control = __RISCOSIFY_NO_PROCESS;
#endif
console=stderr;
while((arg=getopt(argc,argv,"ho:"))!=-1)
switch(arg)
{
default:
case 'h':
fprintf(console,"-h\thelp\n");
fprintf(console,"-o\toutput to this file\n");
return KEYSERVER_OK;
case 'o':
output=fopen(optarg,"w");
if(output==NULL)
{
fprintf(console,"gpgkeys: Cannot open output file \"%s\": %s\n",
optarg,strerror(errno));
return KEYSERVER_INTERNAL_ERROR;
}
break;
}
if(argc>optind)
{
input=fopen(argv[optind],"r");
if(input==NULL)
{
fprintf(console,"gpgkeys: Cannot open input file \"%s\": %s\n",
argv[optind],strerror(errno));
return KEYSERVER_INTERNAL_ERROR;
}
}
if(input==NULL)
input=stdin;
if(output==NULL)
output=stdout;
/* Get the command and info block */
while(fgets(line,MAX_LINE,input)!=NULL)
{
char commandstr[7];
char portstr[10];
char optionstr[30];
char hash;
if(line[0]=='\n')
break;
if(sscanf(line,"%c",&hash)==1 && hash=='#')
continue;
if(sscanf(line,"COMMAND %6s\n",commandstr)==1)
{
commandstr[6]='\0';
if(strcasecmp(commandstr,"get")==0)
action=GET;
else if(strcasecmp(commandstr,"send")==0)
action=SEND;
else if(strcasecmp(commandstr,"search")==0)
action=SEARCH;
continue;
}
if(sscanf(line,"HOST %79s\n",host)==1)
{
host[79]='\0';
continue;
}
if(sscanf(line,"PORT %9s\n",portstr)==1)
{
portstr[9]='\0';
port=atoi(portstr);
continue;
}
if(sscanf(line,"VERSION %d\n",&version)==1)
{
if(version!=0)
{
ret=KEYSERVER_VERSION_ERROR;
goto fail;
}
continue;
}
if(sscanf(line,"OPTION %29s\n",optionstr)==1)
{
int no=0;
char *start=&optionstr[0];
optionstr[29]='\0';
if(strncasecmp(optionstr,"no-",3)==0)
{
no=1;
start=&optionstr[3];
}
if(strcasecmp(start,"verbose")==0)
{
if(no)
verbose--;
else
verbose++;
}
else if(strcasecmp(start,"include-disabled")==0)
{
if(no)
include_disabled=0;
else
include_disabled=1;
}
else if(strcasecmp(start,"include-revoked")==0)
{
if(no)
include_revoked=0;
else
include_revoked=1;
}
else if(strcasecmp(start,"include-subkeys")==0)
{
if(no)
include_subkeys=0;
else
include_subkeys=1;
}
continue;
}
}
/* 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==SEND)
while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
else if(action==GET || action==SEARCH)
{
for(;;)
{
struct keylist *work;
if(fgets(line,MAX_LINE,input)==NULL)
break;
else
{
if(line[0]=='\n')
break;
work=malloc(sizeof(struct keylist));
if(work==NULL)
{
fprintf(console,"gpgkeys: out of memory while "
"building key list\n");
goto fail;
}
strcpy(work->str,line);
/* Trim the trailing \n */
work->str[strlen(line)-1]='\0';
work->next=NULL;
/* Always attach at the end to keep the list in proper
order for searching */
if(keylist==NULL)
keylist=work;
else
keyptr->next=work;
keyptr=work;
}
}
}
else
{
fprintf(console,"gpgkeys: no keyserver command specified\n");
goto fail;
}
/* Send the response */
fprintf(output,"VERSION 0\n");
fprintf(output,"PROGRAM %s\n\n",VERSION);
if(verbose>1)
{
fprintf(console,"Host:\t\t%s\n",host);
if(port)
fprintf(console,"Port:\t\t%d\n",port);
fprintf(console,"Command:\t%s\n",action==GET?"GET":
action==SEND?"SEND":"SEARCH");
}
ldap=ldap_init(host,port);
if(ldap==NULL)
{
fprintf(console,"gpgkeys: internal LDAP init error: %s\n",strerror(errno));
goto fail;
}
err=ldap_simple_bind_s(ldap,NULL,NULL);
if(err!=0)
{
fprintf(console,"gpgkeys: internal LDAP bind error: %s\n",
ldap_err2string(err));
goto fail;
}
/* Get the magic info record */
err=ldap_search_s(ldap,"cn=PGPServerInfo",LDAP_SCOPE_BASE,
"(objectclass=*)",attrs,0,&res);
if(err==-1)
{
fprintf(console,"gpgkeys: error retrieving LDAP server info: %s\n",
ldap_err2string(err));
goto fail;
}
if(ldap_count_entries(ldap,res)!=1)
{
fprintf(console,"gpgkeys: more than one serverinfo record\n");
goto fail;
}
if(verbose>1)
{
vals=ldap_get_values(ldap,res,"software");
if(vals!=NULL)
{
fprintf(console,"Server: \t%s\n",vals[0]);
ldap_value_free(vals);
}
vals=ldap_get_values(ldap,res,"version");
if(vals!=NULL)
{
fprintf(console,"Version:\t%s\n",vals[0]);
ldap_value_free(vals);
}
}
/* This is always "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not
be in the future. */
vals=ldap_get_values(ldap,res,"basekeyspacedn");
if(vals!=NULL)
{
basekeyspacedn=strdup(vals[0]);
if(basekeyspacedn==NULL)
{
fprintf(console,"gpgkeys: can't allocate string space "
"for LDAP base\n");
goto fail;
}
ldap_value_free(vals);
}
ldap_msgfree(res);
switch(action)
{
case GET:
keyptr=keylist;
while(keyptr!=NULL)
{
if(get_key(keyptr->str)==-1)
failed++;
keyptr=keyptr->next;
}
break;
case SEND:
{
int ret;
do
{
ret=send_key();
if(ret==-1)
failed++;
}
while(ret!=1);
}
break;
case SEARCH:
{
char *searchkey=NULL;
int len=0;
/* To search, we stick a * in between each key to search for.
This means that if the user enters words, they'll get
"enters*words". If the user "enters words", they'll get
"enters words" */
keyptr=keylist;
while(keyptr!=NULL)
{
len+=strlen(keyptr->str)+1;
keyptr=keyptr->next;
}
searchkey=malloc(len+1);
if(searchkey==NULL)
goto fail;
searchkey[0]='\0';
keyptr=keylist;
while(keyptr!=NULL)
{
strcat(searchkey,keyptr->str);
strcat(searchkey,"*");
keyptr=keyptr->next;
}
/* Nail that last "*" */
searchkey[strlen(searchkey)-1]='\0';
if(search_key(searchkey)==-1)
{
fprintf(output,"SEARCH %s FAILED\n",searchkey);
failed++;
}
free(searchkey);
}
break;
}
if(!failed)
ret=KEYSERVER_OK;
fail:
while(keylist!=NULL)
{
struct keylist *current=keylist;
keylist=keylist->next;
free(current);
}
if(input!=stdin)
fclose(input);
if(output!=stdout)
fclose(output);
if(ldap!=NULL)
ldap_unbind_s(ldap);
free(basekeyspacedn);
return ret;
}

164
keyserver/gpgkeys_mailto.in Executable file
View file

@ -0,0 +1,164 @@
#!@PERL@ -w
# gpgkeys_mailto - talk to a email keyserver
# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
# GnuPG is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# GnuPG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
use Getopt::Std;
$sendmail="@SENDMAIL@ -t";
###
getopts('o:');
if(defined($opt_o))
{
open(STDOUT,">$opt_o") || die "Can't open output file $opt_o\n";
}
if(@ARGV)
{
open(STDIN,$ARGV[0]) || die "Can't open input file $ARGV[0]\n";
}
($login,$name)=(getpwuid($<))[0,6];
while(<STDIN>)
{
last if($_ eq "\n");
if(/^COMMAND (\w+)/)
{
$command=$1;
}
if(/^HOST (\S+)/)
{
$host=$1;
}
if(/^OPTION (\w+)/)
{
if($1=~/^verbose$/i)
{
$verbose++;
}
elsif($1=~/^no-verbose$/i)
{
$verbose--;
}
}
}
while(<STDIN>)
{
last if($_ eq "\n");
chomp;
push(@keys,$_);
}
# Send response
print "VERSION 0\n";
print "OPTION OUTOFBAND\n\n";
# Email keyservers get and search the same way
if($command=~/get/i || $command=~/search/i)
{
if($command=~/search/i)
{
print "COUNT 0\n";
}
foreach $key (@keys)
{
open(MAIL,"|$sendmail") || die "ERROR: Can't open $sendmail\n";
print MAIL "From: $name <$login>\n";
print MAIL "To: $host\n";
if($command=~/get/i)
{
# mail keyservers don't like long-form keyids
if(substr($key,0,2) eq "0x")
{
$key=substr($key,2);
}
if(length($key)>8)
{
$key=substr($key,-8);
}
print MAIL "Subject: GET 0x$key\n\n";
}
else
{
print MAIL "Subject: GET $key\n\n";
}
print MAIL "GnuPG keyserver request\n";
close(MAIL);
# Tell GnuPG not to expect a key
print "KEY $key OUTOFBAND\n";
if($verbose)
{
print STDERR "gpgkeys: key $key requested from $host\n";
}
}
}
if($command=~/send/i)
{
while(!eof(STDIN))
{
open(MAIL,"|$sendmail") || die "ERROR: Can't open $sendmail\n";
print MAIL "From: $name <$login>\n";
print MAIL "To: $host\n";
print MAIL "Subject: ADD\n\n";
while(<STDIN>)
{
if(/^KEY (\w+) BEGIN$/)
{
$key=$1;
last;
}
}
while(<STDIN>)
{
if(/^KEY \w+ END$/)
{
last;
}
print MAIL;
}
close(MAIL);
if($verbose)
{
print STDERR "gpgkeys: key $key sent to $host\n";
}
}
}

79
keyserver/gpgkeys_test.in Executable file
View file

@ -0,0 +1,79 @@
#!@PERL@
# gpgkeys_test - keyserver code tester
# Copyright (C) 2001 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
# GnuPG is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# GnuPG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
use Getopt::Std;
$|=1;
print STDERR "gpgkeys_test starting\n";
getopts('o:');
if(defined($opt_o))
{
print STDERR "Using output file $opt_o\n";
open(STDOUT,">$opt_o") || die "Can't open output file $opt_o\n";
}
if(@ARGV)
{
print STDERR "Using input file $ARGV[0]\n";
open(STDIN,$ARGV[0]) || die "Can't open input file $ARGV[0]\n";
}
# Get the command block
print STDERR "Command block:\n";
while(<STDIN>)
{
last if($_ eq "\n");
print STDERR "--command-> $_";
if(/^COMMAND (\w+)/)
{
$command=$1;
}
}
# Get the keylist block
print STDERR "Keylist block:\n";
while(<STDIN>)
{
last if($_ eq "\n");
print STDERR "--keylist-> $_";
}
# If it's a SEND, then get the key material
if($command eq "SEND")
{
print STDERR "Key material to send:\n";
while(<STDIN>)
{
print STDERR "$_";
}
}
printf STDERR "gpgkeys_test finished\n";