mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Added keyserver directory from trunk
This commit is contained in:
parent
6c208fea32
commit
640d5a8c53
@ -1,3 +1,10 @@
|
||||
2006-06-30 Werner Koch <wk@g10code.com>
|
||||
|
||||
* keyserver/: New. Taken from 1.4.4
|
||||
* Makefile.am (SUBDIRS): Include keyserver/.
|
||||
* configure.ac: Include keyserver/.
|
||||
(FAKE_CURL, GPGKEYS_CURL): New.
|
||||
|
||||
2006-06-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
Released 1.9.21.
|
||||
|
@ -35,8 +35,11 @@ endif
|
||||
|
||||
if BUILD_GPG
|
||||
gpg = g10
|
||||
# fixme: Noy yet ready for a build
|
||||
keyserver =
|
||||
else
|
||||
gpg =
|
||||
keyserver =
|
||||
endif
|
||||
if BUILD_GPGSM
|
||||
sm = sm
|
||||
@ -61,7 +64,7 @@ tests = tests
|
||||
endif
|
||||
|
||||
SUBDIRS = m4 intl gl jnlib common ${kbx} \
|
||||
${gpg} ${sm} ${agent} ${scd} tools po doc ${tests}
|
||||
${gpg} ${keyserver} ${sm} ${agent} ${scd} tools po doc ${tests}
|
||||
|
||||
dist-hook:
|
||||
@set -e; \
|
||||
|
15
configure.ac
15
configure.ac
@ -716,6 +716,20 @@ fi
|
||||
AC_SUBST(GPGKEYS_LDAP)
|
||||
AC_SUBST(LDAPLIBS)
|
||||
|
||||
|
||||
# Check for curl. We fake the curl API if libcurl isn't installed.
|
||||
|
||||
# fixme: need to add this
|
||||
#LIBCURL_CHECK_CONFIG([yes],,,[fake_curl=yes])
|
||||
#AM_CONDITIONAL(FAKE_CURL,test x"$fake_curl" = xyes)
|
||||
AM_CONDITIONAL(FAKE_CURL,1)
|
||||
|
||||
# Generic, for us, means curl
|
||||
|
||||
if test x"$try_generic" = xyes ; then
|
||||
AC_SUBST(GPGKEYS_CURL,"gpgkeys_curl$EXEEXT")
|
||||
fi
|
||||
|
||||
dnl This isn't necessarily sendmail itself, but anything that gives a
|
||||
dnl sendmail-ish interface to the outside world. That includes qmail,
|
||||
dnl postfix, etc. Basically, anything that can handle "sendmail -t".
|
||||
@ -1231,6 +1245,7 @@ jnlib/Makefile
|
||||
common/Makefile
|
||||
kbx/Makefile
|
||||
g10/Makefile
|
||||
keyserver/Makefile
|
||||
sm/Makefile
|
||||
agent/Makefile
|
||||
scd/Makefile
|
||||
|
1067
keyserver/ChangeLog
Normal file
1067
keyserver/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
53
keyserver/Makefile.am
Normal file
53
keyserver/Makefile.am
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright (C) 2001, 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
|
||||
EXTRA_PROGRAMS = gpgkeys_ldap gpgkeys_hkp gpgkeys_finger gpgkeys_curl
|
||||
EXTRA_SCRIPTS = gpgkeys_mailto
|
||||
|
||||
gpglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
|
||||
gpglibexec_PROGRAMS = @GPGKEYS_LDAP@ @GPGKEYS_HKP@ @GPGKEYS_FINGER@ @GPGKEYS_CURL@
|
||||
gpglibexec_SCRIPTS = @GPGKEYS_MAILTO@
|
||||
noinst_SCRIPTS = gpgkeys_test
|
||||
|
||||
gpgkeys_ldap_SOURCES = gpgkeys_ldap.c ksutil.c ksutil.h
|
||||
gpgkeys_hkp_SOURCES = gpgkeys_hkp.c ksutil.c ksutil.h
|
||||
gpgkeys_finger_SOURCES = gpgkeys_finger.c ksutil.c ksutil.h
|
||||
gpgkeys_curl_SOURCES = gpgkeys_curl.c ksutil.c ksutil.h
|
||||
|
||||
other_libs = $(LIBICONV) $(LIBINTL) $(CAPLIBS)
|
||||
|
||||
gpgkeys_ldap_CPPFLAGS = @LDAP_CPPFLAGS@
|
||||
gpgkeys_ldap_LDADD = ../util/libutil.a @LDAPLIBS@ @NETLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
|
||||
|
||||
gpgkeys_finger_LDADD = ../util/libutil.a @NETLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
|
||||
|
||||
if FAKE_CURL
|
||||
gpgkeys_curl_SOURCES += curl-shim.c curl-shim.h
|
||||
gpgkeys_curl_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
|
||||
gpgkeys_hkp_SOURCES += curl-shim.c curl-shim.h
|
||||
gpgkeys_hkp_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
|
||||
else
|
||||
gpgkeys_curl_CPPFLAGS = @LIBCURL_CPPFLAGS@
|
||||
gpgkeys_curl_LDADD = @LIBCURL@ @GETOPT@
|
||||
gpgkeys_hkp_CPPFLAGS = @LIBCURL_CPPFLAGS@
|
||||
gpgkeys_hkp_LDADD = @LIBCURL@ @GETOPT@
|
||||
endif
|
324
keyserver/curl-shim.c
Normal file
324
keyserver/curl-shim.c
Normal file
@ -0,0 +1,324 @@
|
||||
/* curl-shim.c - Implement a small subset of the curl API in terms of
|
||||
* the iobuf HTTP API
|
||||
*
|
||||
* Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "http.h"
|
||||
#include "util.h"
|
||||
#include "ksutil.h"
|
||||
#include "curl-shim.h"
|
||||
|
||||
static CURLcode
|
||||
handle_error(CURL *curl,CURLcode err,const char *str)
|
||||
{
|
||||
if(curl->errorbuffer)
|
||||
{
|
||||
/* Make sure you never exceed CURL_ERROR_SIZE, currently set to
|
||||
256 in curl-shim.h */
|
||||
switch(err)
|
||||
{
|
||||
case CURLE_OK:
|
||||
strcpy(curl->errorbuffer,"okay");
|
||||
break;
|
||||
|
||||
case CURLE_UNSUPPORTED_PROTOCOL:
|
||||
strcpy(curl->errorbuffer,"unsupported protocol");
|
||||
break;
|
||||
|
||||
case CURLE_COULDNT_CONNECT:
|
||||
strcpy(curl->errorbuffer,"couldn't connect");
|
||||
break;
|
||||
|
||||
case CURLE_WRITE_ERROR:
|
||||
strcpy(curl->errorbuffer,"write error");
|
||||
break;
|
||||
|
||||
case CURLE_HTTP_RETURNED_ERROR:
|
||||
sprintf(curl->errorbuffer,"url returned error %u",curl->status);
|
||||
break;
|
||||
|
||||
default:
|
||||
strcpy(curl->errorbuffer,"generic error");
|
||||
break;
|
||||
}
|
||||
|
||||
if(str && (strlen(curl->errorbuffer)+2+strlen(str)+1)<=CURL_ERROR_SIZE)
|
||||
{
|
||||
strcat(curl->errorbuffer,": ");
|
||||
strcat(curl->errorbuffer,str);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
CURLcode
|
||||
curl_global_init(long flags)
|
||||
{
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void
|
||||
curl_global_cleanup(void) {}
|
||||
|
||||
CURL *
|
||||
curl_easy_init(void)
|
||||
{
|
||||
CURL *handle;
|
||||
|
||||
handle=calloc(1,sizeof(CURL));
|
||||
if(handle)
|
||||
handle->errors=stderr;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void
|
||||
curl_easy_cleanup(CURL *curl)
|
||||
{
|
||||
free(curl);
|
||||
}
|
||||
|
||||
CURLcode
|
||||
curl_easy_setopt(CURL *curl,CURLoption option,...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap,option);
|
||||
|
||||
switch(option)
|
||||
{
|
||||
case CURLOPT_URL:
|
||||
curl->url=va_arg(ap,char *);
|
||||
break;
|
||||
case CURLOPT_USERPWD:
|
||||
curl->auth=va_arg(ap,char *);
|
||||
break;
|
||||
case CURLOPT_WRITEFUNCTION:
|
||||
curl->writer=va_arg(ap,write_func);
|
||||
break;
|
||||
case CURLOPT_FILE:
|
||||
curl->file=va_arg(ap,void *);
|
||||
break;
|
||||
case CURLOPT_ERRORBUFFER:
|
||||
curl->errorbuffer=va_arg(ap,char *);
|
||||
break;
|
||||
case CURLOPT_PROXY:
|
||||
curl->proxy=va_arg(ap,char *);
|
||||
break;
|
||||
case CURLOPT_POST:
|
||||
curl->flags.post=va_arg(ap,unsigned int);
|
||||
break;
|
||||
case CURLOPT_POSTFIELDS:
|
||||
curl->postfields=va_arg(ap,char *);
|
||||
break;
|
||||
case CURLOPT_FAILONERROR:
|
||||
curl->flags.failonerror=va_arg(ap,unsigned int);
|
||||
break;
|
||||
case CURLOPT_VERBOSE:
|
||||
curl->flags.verbose=va_arg(ap,unsigned int);
|
||||
break;
|
||||
case CURLOPT_STDERR:
|
||||
curl->errors=va_arg(ap,FILE *);
|
||||
break;
|
||||
default:
|
||||
/* We ignore the huge majority of curl options */
|
||||
break;
|
||||
}
|
||||
|
||||
return handle_error(curl,CURLE_OK,NULL);
|
||||
}
|
||||
|
||||
CURLcode
|
||||
curl_easy_perform(CURL *curl)
|
||||
{
|
||||
int rc;
|
||||
CURLcode err=CURLE_OK;
|
||||
const char *errstr=NULL;
|
||||
char *proxy=NULL;
|
||||
|
||||
/* Emulate the libcurl proxy behavior. If the calling program set a
|
||||
proxy, use it. If it didn't set a proxy or set it to NULL, check
|
||||
for one in the environment. If the calling program explicitly
|
||||
set a null-string proxy, don't set a proxy at all. */
|
||||
|
||||
if(curl->proxy)
|
||||
{
|
||||
if(*curl->proxy)
|
||||
proxy=curl->proxy;
|
||||
}
|
||||
else
|
||||
proxy=getenv(HTTP_PROXY_ENV);
|
||||
|
||||
if(curl->flags.verbose)
|
||||
fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null");
|
||||
|
||||
if(curl->flags.post)
|
||||
{
|
||||
rc=http_open(&curl->hd,HTTP_REQ_POST,curl->url,curl->auth,0,proxy);
|
||||
if(rc==0)
|
||||
{
|
||||
char content_len[50];
|
||||
unsigned int post_len=strlen(curl->postfields);
|
||||
|
||||
iobuf_writestr(curl->hd.fp_write,
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n");
|
||||
sprintf(content_len,"Content-Length: %u\r\n",post_len);
|
||||
|
||||
iobuf_writestr(curl->hd.fp_write,content_len);
|
||||
|
||||
http_start_data(&curl->hd);
|
||||
iobuf_write(curl->hd.fp_write,curl->postfields,post_len);
|
||||
rc=http_wait_response(&curl->hd,&curl->status);
|
||||
if(rc==0 && curl->flags.failonerror && curl->status>=300)
|
||||
err=CURLE_HTTP_RETURNED_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc=http_open(&curl->hd,HTTP_REQ_GET,curl->url,curl->auth,0,proxy);
|
||||
if(rc==0)
|
||||
{
|
||||
rc=http_wait_response(&curl->hd,&curl->status);
|
||||
if(rc==0)
|
||||
{
|
||||
if(curl->flags.failonerror && curl->status>=300)
|
||||
err=CURLE_HTTP_RETURNED_ERROR;
|
||||
else
|
||||
{
|
||||
unsigned int maxlen=1024,buflen,len;
|
||||
byte *line=NULL;
|
||||
|
||||
while((len=iobuf_read_line(curl->hd.fp_read,
|
||||
&line,&buflen,&maxlen)))
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
maxlen=1024;
|
||||
|
||||
ret=(curl->writer)(line,len,1,curl->file);
|
||||
if(ret!=len)
|
||||
{
|
||||
err=CURLE_WRITE_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xfree(line);
|
||||
http_close(&curl->hd);
|
||||
}
|
||||
}
|
||||
else
|
||||
http_close(&curl->hd);
|
||||
}
|
||||
}
|
||||
|
||||
switch(rc)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case G10ERR_INVALID_URI:
|
||||
err=CURLE_UNSUPPORTED_PROTOCOL;
|
||||
break;
|
||||
|
||||
case G10ERR_NETWORK:
|
||||
errstr=strerror(errno);
|
||||
err=CURLE_COULDNT_CONNECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
errstr=g10_errstr(rc);
|
||||
err=CURLE_COULDNT_CONNECT;
|
||||
break;
|
||||
}
|
||||
|
||||
return handle_error(curl,err,errstr);
|
||||
}
|
||||
|
||||
/* This is not the same exact set that is allowed according to
|
||||
RFC-2396, but it is what the real curl uses. */
|
||||
#define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
||||
"0123456789"
|
||||
|
||||
char *
|
||||
curl_escape(char *str,int length)
|
||||
{
|
||||
int len,max,idx,enc_idx=0;
|
||||
char *enc;
|
||||
|
||||
if(length)
|
||||
len=length;
|
||||
else
|
||||
len=strlen(str);
|
||||
|
||||
enc=malloc(len+1);
|
||||
if(!enc)
|
||||
return enc;
|
||||
|
||||
max=len;
|
||||
|
||||
for(idx=0;idx<len;idx++)
|
||||
{
|
||||
if(enc_idx+3>max)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
max+=100;
|
||||
|
||||
tmp=realloc(enc,max+1);
|
||||
if(!tmp)
|
||||
{
|
||||
free(enc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enc=tmp;
|
||||
}
|
||||
|
||||
if(strchr(VALID_URI_CHARS,str[idx]))
|
||||
enc[enc_idx++]=str[idx];
|
||||
else
|
||||
{
|
||||
char numbuf[5];
|
||||
sprintf(numbuf,"%%%02X",str[idx]);
|
||||
strcpy(&enc[enc_idx],numbuf);
|
||||
enc_idx+=3;
|
||||
}
|
||||
}
|
||||
|
||||
enc[enc_idx]='\0';
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
void
|
||||
curl_free(char *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
92
keyserver/curl-shim.h
Normal file
92
keyserver/curl-shim.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* curl-shim.h
|
||||
* Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef _CURL_SHIM_H_
|
||||
#define _CURL_SHIM_H_
|
||||
|
||||
#include "http.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CURLE_OK=0,
|
||||
CURLE_UNSUPPORTED_PROTOCOL=1,
|
||||
CURLE_COULDNT_CONNECT=7,
|
||||
CURLE_FTP_COULDNT_RETR_FILE=19,
|
||||
CURLE_HTTP_RETURNED_ERROR=22,
|
||||
CURLE_WRITE_ERROR=23
|
||||
} CURLcode;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CURLOPT_URL,
|
||||
CURLOPT_USERPWD,
|
||||
CURLOPT_WRITEFUNCTION,
|
||||
CURLOPT_FILE,
|
||||
CURLOPT_ERRORBUFFER,
|
||||
CURLOPT_FOLLOWLOCATION,
|
||||
CURLOPT_MAXREDIRS,
|
||||
CURLOPT_STDERR,
|
||||
CURLOPT_VERBOSE,
|
||||
CURLOPT_SSL_VERIFYPEER,
|
||||
CURLOPT_PROXY,
|
||||
CURLOPT_CAINFO,
|
||||
CURLOPT_POST,
|
||||
CURLOPT_POSTFIELDS,
|
||||
CURLOPT_FAILONERROR
|
||||
} CURLoption;
|
||||
|
||||
typedef size_t (*write_func)(char *buffer,size_t size,
|
||||
size_t nitems,void *outstream);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *url;
|
||||
char *auth;
|
||||
char *errorbuffer;
|
||||
char *proxy;
|
||||
write_func writer;
|
||||
void *file;
|
||||
char *postfields;
|
||||
unsigned int status;
|
||||
FILE *errors;
|
||||
struct
|
||||
{
|
||||
unsigned int post:1;
|
||||
unsigned int failonerror:1;
|
||||
unsigned int verbose:1;
|
||||
} flags;
|
||||
struct http_context hd;
|
||||
} CURL;
|
||||
|
||||
#define CURL_ERROR_SIZE 256
|
||||
#define CURL_GLOBAL_DEFAULT 0
|
||||
|
||||
CURLcode curl_global_init(long flags);
|
||||
void curl_global_cleanup(void);
|
||||
CURL *curl_easy_init(void);
|
||||
CURLcode curl_easy_setopt(CURL *curl,CURLoption option,...);
|
||||
CURLcode curl_easy_perform(CURL *curl);
|
||||
void curl_easy_cleanup(CURL *curl);
|
||||
char *curl_escape(char *str,int len);
|
||||
void curl_free(char *ptr);
|
||||
#define curl_version() "GnuPG curl-shim "VERSION
|
||||
|
||||
#endif /* !_CURL_SHIM_H_ */
|
369
keyserver/gpgkeys_curl.c
Normal file
369
keyserver/gpgkeys_curl.c
Normal file
@ -0,0 +1,369 @@
|
||||
/* gpgkeys_curl.c - fetch a key via libcurl
|
||||
* Copyright (C) 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBCURL
|
||||
#include <curl/curl.h>
|
||||
#else
|
||||
#include "curl-shim.h"
|
||||
#endif
|
||||
#include "keyserver.h"
|
||||
#include "ksutil.h"
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
static FILE *input,*output,*console;
|
||||
static CURL *curl;
|
||||
static struct ks_options *opt;
|
||||
|
||||
static int
|
||||
get_key(char *getkey)
|
||||
{
|
||||
CURLcode res;
|
||||
char errorbuffer[CURL_ERROR_SIZE];
|
||||
char request[MAX_URL];
|
||||
struct curl_writer_ctx ctx;
|
||||
|
||||
memset(&ctx,0,sizeof(ctx));
|
||||
|
||||
if(strncmp(getkey,"0x",2)==0)
|
||||
getkey+=2;
|
||||
|
||||
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
|
||||
|
||||
sprintf(request,"%s://%s%s%s%s",opt->scheme,opt->host,
|
||||
opt->port?":":"",opt->port?opt->port:"",opt->path?opt->path:"/");
|
||||
|
||||
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);
|
||||
curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
|
||||
|
||||
res=curl_easy_perform(curl);
|
||||
if(res!=CURLE_OK)
|
||||
{
|
||||
fprintf(console,"gpgkeys: %s fetch error %d: %s\n",opt->scheme,
|
||||
res,errorbuffer);
|
||||
fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return curl_err_to_gpg_err(res);
|
||||
}
|
||||
|
||||
static void
|
||||
show_help (FILE *fp)
|
||||
{
|
||||
fprintf (fp,"-h\thelp\n");
|
||||
fprintf (fp,"-V\tversion\n");
|
||||
fprintf (fp,"-o\toutput to this file\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc,char *argv[])
|
||||
{
|
||||
int arg,ret=KEYSERVER_INTERNAL_ERROR;
|
||||
char line[MAX_LINE];
|
||||
char *thekey=NULL;
|
||||
long follow_redirects=5;
|
||||
char *proxy=NULL;
|
||||
|
||||
console=stderr;
|
||||
|
||||
/* Kludge to implement standard GNU options. */
|
||||
if (argc > 1 && !strcmp (argv[1], "--version"))
|
||||
{
|
||||
fputs ("gpgkeys_curl (GnuPG) " VERSION"\n", stdout);
|
||||
return 0;
|
||||
}
|
||||
else if (argc > 1 && !strcmp (argv[1], "--help"))
|
||||
{
|
||||
show_help (stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while((arg=getopt(argc,argv,"hVo:"))!=-1)
|
||||
switch(arg)
|
||||
{
|
||||
default:
|
||||
case 'h':
|
||||
show_help (console);
|
||||
return KEYSERVER_OK;
|
||||
|
||||
case 'V':
|
||||
fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION);
|
||||
return KEYSERVER_OK;
|
||||
|
||||
case 'o':
|
||||
output=fopen(optarg,"wb");
|
||||
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;
|
||||
|
||||
opt=init_ks_options();
|
||||
if(!opt)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
|
||||
/* Get the command and info block */
|
||||
|
||||
while(fgets(line,MAX_LINE,input)!=NULL)
|
||||
{
|
||||
int err;
|
||||
char option[MAX_OPTION+1];
|
||||
|
||||
if(line[0]=='\n')
|
||||
break;
|
||||
|
||||
err=parse_ks_options(line,opt);
|
||||
if(err>0)
|
||||
{
|
||||
ret=err;
|
||||
goto fail;
|
||||
}
|
||||
else if(err==0)
|
||||
continue;
|
||||
|
||||
if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
|
||||
{
|
||||
int no=0;
|
||||
char *start=&option[0];
|
||||
|
||||
option[MAX_OPTION]='\0';
|
||||
|
||||
if(strncasecmp(option,"no-",3)==0)
|
||||
{
|
||||
no=1;
|
||||
start=&option[3];
|
||||
}
|
||||
|
||||
if(strncasecmp(start,"http-proxy",10)==0)
|
||||
{
|
||||
/* Safe to not check the return code of strdup() here.
|
||||
If it fails, we simply won't use a proxy. */
|
||||
if(no)
|
||||
{
|
||||
free(proxy);
|
||||
proxy=strdup("");
|
||||
}
|
||||
else if(start[10]=='=')
|
||||
{
|
||||
if(strlen(&start[11])<MAX_PROXY)
|
||||
{
|
||||
free(proxy);
|
||||
proxy=strdup(&start[11]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strncasecmp(start,"follow-redirects",16)==0)
|
||||
{
|
||||
if(no)
|
||||
follow_redirects=0;
|
||||
else if(start[16]=='=')
|
||||
follow_redirects=atoi(&start[17]);
|
||||
else if(start[16]=='\0')
|
||||
follow_redirects=-1;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!opt->scheme)
|
||||
{
|
||||
fprintf(console,"gpgkeys: no scheme supplied!\n");
|
||||
ret=KEYSERVER_SCHEME_NOT_FOUND;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(!opt->host)
|
||||
{
|
||||
fprintf(console,"gpgkeys: no keyserver host provided\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(opt->timeout && register_timeout()==-1)
|
||||
{
|
||||
fprintf(console,"gpgkeys: unable to register timeout handler\n");
|
||||
return KEYSERVER_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
curl=curl_easy_init();
|
||||
if(!curl)
|
||||
{
|
||||
fprintf(console,"gpgkeys: unable to initialize curl\n");
|
||||
ret=KEYSERVER_INTERNAL_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(follow_redirects)
|
||||
{
|
||||
curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);
|
||||
if(follow_redirects>0)
|
||||
curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects);
|
||||
}
|
||||
|
||||
if(opt->auth)
|
||||
curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
|
||||
|
||||
if(opt->debug)
|
||||
{
|
||||
fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
|
||||
curl_easy_setopt(curl,CURLOPT_STDERR,console);
|
||||
curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,opt->flags.check_cert);
|
||||
curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file);
|
||||
|
||||
if(proxy)
|
||||
curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
|
||||
|
||||
/* 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(opt->action==KS_GET)
|
||||
{
|
||||
/* Eat the rest of the file */
|
||||
for(;;)
|
||||
{
|
||||
if(fgets(line,MAX_LINE,input)==NULL)
|
||||
break;
|
||||
else
|
||||
{
|
||||
if(line[0]=='\n' || line[0]=='\0')
|
||||
break;
|
||||
|
||||
if(!thekey)
|
||||
{
|
||||
thekey=strdup(line);
|
||||
if(!thekey)
|
||||
{
|
||||
fprintf(console,"gpgkeys: out of memory while "
|
||||
"building key list\n");
|
||||
ret=KEYSERVER_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Trim the trailing \n */
|
||||
thekey[strlen(line)-1]='\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(console,
|
||||
"gpgkeys: this keyserver type only supports key retrieval\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(!thekey)
|
||||
{
|
||||
fprintf(console,"gpgkeys: invalid keyserver instructions\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Send the response */
|
||||
|
||||
fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
|
||||
fprintf(output,"PROGRAM %s\n\n",VERSION);
|
||||
|
||||
if(opt->verbose)
|
||||
{
|
||||
fprintf(console,"Scheme:\t\t%s\n",opt->scheme);
|
||||
fprintf(console,"Host:\t\t%s\n",opt->host);
|
||||
if(opt->port)
|
||||
fprintf(console,"Port:\t\t%s\n",opt->port);
|
||||
if(opt->path)
|
||||
fprintf(console,"Path:\t\t%s\n",opt->path);
|
||||
fprintf(console,"Command:\tGET\n");
|
||||
}
|
||||
|
||||
set_timeout(opt->timeout);
|
||||
|
||||
ret=get_key(thekey);
|
||||
|
||||
fail:
|
||||
|
||||
free(thekey);
|
||||
|
||||
if(input!=stdin)
|
||||
fclose(input);
|
||||
|
||||
if(output!=stdout)
|
||||
fclose(output);
|
||||
|
||||
free_ks_options(opt);
|
||||
|
||||
if(curl)
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
free(proxy);
|
||||
|
||||
curl_global_cleanup();
|
||||
|
||||
return ret;
|
||||
}
|
534
keyserver/gpgkeys_finger.c
Normal file
534
keyserver/gpgkeys_finger.c
Normal file
@ -0,0 +1,534 @@
|
||||
/* gpgkeys_finger.c - fetch a key via finger
|
||||
* Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#define INCLUDED_BY_MAIN_MODULE 1
|
||||
#include "util.h"
|
||||
#include "keyserver.h"
|
||||
#include "ksutil.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define sock_close(a) closesocket(a)
|
||||
#else
|
||||
#define sock_close(a) close(a)
|
||||
#endif
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
static FILE *input,*output,*console;
|
||||
static struct ks_options *opt;
|
||||
|
||||
#ifdef _WIN32
|
||||
static void
|
||||
deinit_sockets (void)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
static void
|
||||
init_sockets (void)
|
||||
{
|
||||
static int initialized;
|
||||
static WSADATA wsdata;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
if (WSAStartup (0x0101, &wsdata) )
|
||||
{
|
||||
fprintf (console, "error initializing socket library: ec=%d\n",
|
||||
(int)WSAGetLastError () );
|
||||
return;
|
||||
}
|
||||
if (wsdata.wVersion < 0x0001)
|
||||
{
|
||||
fprintf (console, "socket library version is %x.%x - but 1.1 needed\n",
|
||||
LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion));
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
atexit (deinit_sockets);
|
||||
initialized = 1;
|
||||
}
|
||||
#endif /*_WIN32*/
|
||||
|
||||
|
||||
/* Connect to SERVER at PORT and return a file descriptor or -1 on
|
||||
error. */
|
||||
static int
|
||||
connect_server (const char *server, unsigned short port)
|
||||
{
|
||||
int sock = -1;
|
||||
|
||||
#ifdef _WIN32
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in addr;
|
||||
unsigned long l;
|
||||
|
||||
init_sockets ();
|
||||
|
||||
memset (&addr, 0, sizeof addr);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons (port);
|
||||
|
||||
/* Win32 gethostbyname doesn't handle IP addresses internally, so we
|
||||
try inet_addr first on that platform only. */
|
||||
if ((l = inet_addr (server)) != INADDR_NONE)
|
||||
memcpy (&addr.sin_addr, &l, sizeof l);
|
||||
else if ((hp = gethostbyname (server)))
|
||||
{
|
||||
if (hp->h_addrtype != AF_INET)
|
||||
{
|
||||
fprintf (console, "gpgkeys: unknown address family for `%s'\n",
|
||||
server);
|
||||
return -1;
|
||||
}
|
||||
if (hp->h_length != 4)
|
||||
{
|
||||
fprintf (console, "gpgkeys: illegal address length for `%s'\n",
|
||||
server);
|
||||
return -1;
|
||||
}
|
||||
memcpy (&addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (console, "gpgkeys: host `%s' not found: ec=%d\n",
|
||||
server, (int)WSAGetLastError ());
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == INVALID_SOCKET)
|
||||
{
|
||||
fprintf (console, "gpgkeys: error creating socket: ec=%d\n",
|
||||
(int)WSAGetLastError ());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect (sock, (struct sockaddr *)&addr, sizeof addr))
|
||||
{
|
||||
fprintf (console, "gpgkeys: error connecting `%s': ec=%d\n",
|
||||
server, (int)WSAGetLastError ());
|
||||
sock_close (sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *host;
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons (port);
|
||||
host = gethostbyname ((char*)server);
|
||||
if (!host)
|
||||
{
|
||||
fprintf (console, "gpgkeys: host `%s' not found: %s\n",
|
||||
server, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sin_addr = *(struct in_addr*)host->h_addr;
|
||||
|
||||
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == -1)
|
||||
{
|
||||
fprintf (console, "gpgkeys: error creating socket: %s\n",
|
||||
strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect (sock, (struct sockaddr *)&addr, sizeof addr) == -1)
|
||||
{
|
||||
fprintf (console, "gpgkeys: error connecting `%s': %s\n",
|
||||
server, strerror (errno));
|
||||
close (sock);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
static int
|
||||
write_server (int sock, const char *data, size_t length)
|
||||
{
|
||||
int nleft;
|
||||
|
||||
nleft = length;
|
||||
while (nleft > 0)
|
||||
{
|
||||
int nwritten;
|
||||
|
||||
#ifdef _WIN32
|
||||
nwritten = send (sock, data, nleft, 0);
|
||||
if ( nwritten == SOCKET_ERROR )
|
||||
{
|
||||
fprintf (console, "gpgkeys: write failed: ec=%d\n",
|
||||
(int)WSAGetLastError ());
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
nwritten = write (sock, data, nleft);
|
||||
if (nwritten == -1)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 50000;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
continue;
|
||||
}
|
||||
fprintf (console, "gpgkeys: write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
nleft -=nwritten;
|
||||
data += nwritten;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Send the finger REQUEST to the server. Returns 0 and a file descriptor
|
||||
in R_SOCK if the request was sucessful. */
|
||||
static int
|
||||
send_request (const char *request, int *r_sock)
|
||||
{
|
||||
char *server;
|
||||
char *name;
|
||||
int sock;
|
||||
|
||||
*r_sock = -1;
|
||||
name = strdup (request);
|
||||
if (!name)
|
||||
{
|
||||
fprintf(console,"gpgkeys: out of memory\n");
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
}
|
||||
|
||||
server = strchr (name, '@');
|
||||
if (!server)
|
||||
{
|
||||
fprintf (console, "gpgkeys: no name included in request\n");
|
||||
free (name);
|
||||
return KEYSERVER_GENERAL_ERROR;
|
||||
}
|
||||
*server++ = 0;
|
||||
|
||||
sock = connect_server (server, 79);
|
||||
if (sock == -1)
|
||||
{
|
||||
free (name);
|
||||
return KEYSERVER_UNREACHABLE;
|
||||
}
|
||||
|
||||
if (write_server (sock, name, strlen (name))
|
||||
|| write_server (sock, "\r\n", 2))
|
||||
{
|
||||
free (name);
|
||||
sock_close (sock);
|
||||
return KEYSERVER_GENERAL_ERROR;
|
||||
}
|
||||
free (name);
|
||||
*r_sock = sock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
get_key (char *getkey)
|
||||
{
|
||||
int rc;
|
||||
int sock;
|
||||
IOBUF fp_read;
|
||||
unsigned int maxlen, buflen, gotit=0;
|
||||
byte *line = NULL;
|
||||
|
||||
if (strncmp (getkey,"0x",2)==0)
|
||||
getkey+=2;
|
||||
|
||||
/* Frankly we don't know what keys the server will return; we
|
||||
indicated the requested key anyway. */
|
||||
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
|
||||
|
||||
rc=send_request(opt->opaque,&sock);
|
||||
if(rc)
|
||||
{
|
||||
fprintf(output,"KEY 0x%s FAILED %d\n",getkey, rc);
|
||||
sock_close (sock);
|
||||
return KEYSERVER_OK;
|
||||
}
|
||||
|
||||
/* Hmmm, we use iobuf here only to cope with Windows socket
|
||||
peculiarities (we can't used fdopen). */
|
||||
fp_read = iobuf_sockopen (sock , "r");
|
||||
if (!fp_read)
|
||||
{
|
||||
fprintf(output,"KEY 0x%s FAILED %d\n",getkey, KEYSERVER_INTERNAL_ERROR);
|
||||
sock_close (sock);
|
||||
return KEYSERVER_OK;
|
||||
}
|
||||
|
||||
while ( iobuf_read_line ( fp_read, &line, &buflen, &maxlen))
|
||||
{
|
||||
maxlen=1024;
|
||||
|
||||
if(gotit)
|
||||
{
|
||||
print_nocr(output,line);
|
||||
if (!strncmp(line,END,strlen(END)))
|
||||
break;
|
||||
}
|
||||
else if(!strncmp(line,BEGIN,strlen(BEGIN)))
|
||||
{
|
||||
print_nocr(output,line);
|
||||
gotit=1;
|
||||
}
|
||||
}
|
||||
|
||||
if(gotit)
|
||||
fprintf (output,"KEY 0x%s END\n", getkey);
|
||||
else
|
||||
{
|
||||
fprintf(console,"gpgkeys: no key data found for finger:%s\n",
|
||||
opt->opaque);
|
||||
fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND);
|
||||
}
|
||||
|
||||
xfree(line);
|
||||
iobuf_close (fp_read);
|
||||
|
||||
return KEYSERVER_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
show_help (FILE *fp)
|
||||
{
|
||||
fprintf (fp,"-h\thelp\n");
|
||||
fprintf (fp,"-V\tversion\n");
|
||||
fprintf (fp,"-o\toutput to this file\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc,char *argv[])
|
||||
{
|
||||
int arg,ret=KEYSERVER_INTERNAL_ERROR;
|
||||
char line[MAX_LINE];
|
||||
char *thekey=NULL;
|
||||
|
||||
console=stderr;
|
||||
|
||||
/* Kludge to implement standard GNU options. */
|
||||
if (argc > 1 && !strcmp (argv[1], "--version"))
|
||||
{
|
||||
fputs ("gpgkeys_finger (GnuPG) " VERSION"\n", stdout);
|
||||
return 0;
|
||||
}
|
||||
else if (argc > 1 && !strcmp (argv[1], "--help"))
|
||||
{
|
||||
show_help (stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while((arg=getopt(argc,argv,"hVo:"))!=-1)
|
||||
switch(arg)
|
||||
{
|
||||
default:
|
||||
case 'h':
|
||||
show_help (console);
|
||||
return KEYSERVER_OK;
|
||||
|
||||
case 'V':
|
||||
fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION);
|
||||
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;
|
||||
|
||||
opt=init_ks_options();
|
||||
if(!opt)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
|
||||
/* Get the command and info block */
|
||||
|
||||
while(fgets(line,MAX_LINE,input)!=NULL)
|
||||
{
|
||||
int err;
|
||||
|
||||
if(line[0]=='\n')
|
||||
break;
|
||||
|
||||
err=parse_ks_options(line,opt);
|
||||
if(err>0)
|
||||
{
|
||||
ret=err;
|
||||
goto fail;
|
||||
}
|
||||
else if(err==0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(opt->host)
|
||||
{
|
||||
fprintf(console,"gpgkeys: finger://relay/user syntax is not"
|
||||
" supported. Use finger:user instead.\n");
|
||||
ret=KEYSERVER_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(opt->timeout && register_timeout()==-1)
|
||||
{
|
||||
fprintf(console,"gpgkeys: unable to register timeout handler\n");
|
||||
return KEYSERVER_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/* 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(opt->action==KS_GET)
|
||||
{
|
||||
/* Eat the rest of the file */
|
||||
for(;;)
|
||||
{
|
||||
if(fgets(line,MAX_LINE,input)==NULL)
|
||||
break;
|
||||
else
|
||||
{
|
||||
if(line[0]=='\n' || line[0]=='\0')
|
||||
break;
|
||||
|
||||
if(!thekey)
|
||||
{
|
||||
thekey=strdup(line);
|
||||
if(!thekey)
|
||||
{
|
||||
fprintf(console,"gpgkeys: out of memory while "
|
||||
"building key list\n");
|
||||
ret=KEYSERVER_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Trim the trailing \n */
|
||||
thekey[strlen(line)-1]='\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(console,
|
||||
"gpgkeys: this keyserver type only supports key retrieval\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(!thekey || !opt->opaque)
|
||||
{
|
||||
fprintf(console,"gpgkeys: invalid keyserver instructions\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Send the response */
|
||||
|
||||
fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
|
||||
fprintf(output,"PROGRAM %s\n\n",VERSION);
|
||||
|
||||
if(opt->verbose>1)
|
||||
{
|
||||
fprintf(console,"User:\t\t%s\n",opt->opaque);
|
||||
fprintf(console,"Command:\tGET\n");
|
||||
}
|
||||
|
||||
set_timeout(opt->timeout);
|
||||
|
||||
ret=get_key(thekey);
|
||||
|
||||
fail:
|
||||
|
||||
free(thekey);
|
||||
|
||||
if(input!=stdin)
|
||||
fclose(input);
|
||||
|
||||
if(output!=stdout)
|
||||
fclose(output);
|
||||
|
||||
free_ks_options(opt);
|
||||
|
||||
return ret;
|
||||
}
|
833
keyserver/gpgkeys_hkp.c
Normal file
833
keyserver/gpgkeys_hkp.c
Normal file
@ -0,0 +1,833 @@
|
||||
/* gpgkeys_hkp.c - talk to an HKP keyserver
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBCURL
|
||||
#include <curl/curl.h>
|
||||
#else
|
||||
#include "curl-shim.h"
|
||||
#endif
|
||||
#include "keyserver.h"
|
||||
#include "ksutil.h"
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
static FILE *input,*output,*console;
|
||||
static CURL *curl;
|
||||
static struct ks_options *opt;
|
||||
static char errorbuffer[CURL_ERROR_SIZE];
|
||||
|
||||
static size_t
|
||||
curl_mrindex_writer(const void *ptr,size_t size,size_t nmemb,void *stream)
|
||||
{
|
||||
static int checked=0,swallow=0;
|
||||
|
||||
if(!checked)
|
||||
{
|
||||
/* If the document begins with a '<', assume it's a HTML
|
||||
response, which we don't support. Discard the whole message
|
||||
body. GPG can handle it, but this is an optimization to deal
|
||||
with it on this side of the pipe. */
|
||||
const char *buf=ptr;
|
||||
if(buf[0]=='<')
|
||||
swallow=1;
|
||||
|
||||
checked=1;
|
||||
}
|
||||
|
||||
if(swallow || fwrite(ptr,size,nmemb,stream)==nmemb)
|
||||
return size*nmemb;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Append but avoid creating a double slash // in the path. */
|
||||
static char *
|
||||
append_path(char *dest,const char *src)
|
||||
{
|
||||
size_t n=strlen(dest);
|
||||
|
||||
if(src[0]=='/' && n>0 && dest[n-1]=='/')
|
||||
dest[n-1]='\0';
|
||||
|
||||
return strcat(dest,src);
|
||||
}
|
||||
|
||||
int
|
||||
send_key(int *eof)
|
||||
{
|
||||
CURLcode res;
|
||||
char request[MAX_URL+15];
|
||||
int begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR;
|
||||
char keyid[17];
|
||||
char line[MAX_LINE];
|
||||
char *key=NULL,*encoded_key=NULL;
|
||||
size_t keylen=0,keymax=0;
|
||||
|
||||
/* Read and throw away input until we see the BEGIN */
|
||||
|
||||
while(fgets(line,MAX_LINE,input)!=NULL)
|
||||
if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1)
|
||||
{
|
||||
begin=1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!begin)
|
||||
{
|
||||
/* i.e. eof before the KEY BEGIN was found. This isn't an
|
||||
error. */
|
||||
*eof=1;
|
||||
ret=KEYSERVER_OK;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Now slurp up everything until we see the END */
|
||||
|
||||
while(fgets(line,MAX_LINE,input))
|
||||
if(sscanf(line,"KEY %16s END\n",keyid)==1)
|
||||
{
|
||||
end=1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(strlen(line)+keylen>keymax)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
keymax+=200;
|
||||
tmp=realloc(key,keymax+1);
|
||||
if(!tmp)
|
||||
{
|
||||
free(key);
|
||||
fprintf(console,"gpgkeys: out of memory\n");
|
||||
ret=KEYSERVER_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
key=tmp;
|
||||
}
|
||||
|
||||
strcpy(&key[keylen],line);
|
||||
keylen+=strlen(line);
|
||||
}
|
||||
|
||||
if(!end)
|
||||
{
|
||||
fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
|
||||
*eof=1;
|
||||
ret=KEYSERVER_KEY_INCOMPLETE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
encoded_key=curl_escape(key,keylen);
|
||||
if(!encoded_key)
|
||||
{
|
||||
fprintf(console,"gpgkeys: out of memory\n");
|
||||
ret=KEYSERVER_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
free(key);
|
||||
|
||||
key=malloc(8+strlen(encoded_key)+1);
|
||||
if(!key)
|
||||
{
|
||||
fprintf(console,"gpgkeys: out of memory\n");
|
||||
ret=KEYSERVER_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
strcpy(key,"keytext=");
|
||||
strcat(key,encoded_key);
|
||||
|
||||
strcpy(request,"http://");
|
||||
strcat(request,opt->host);
|
||||
strcat(request,":");
|
||||
if(opt->port)
|
||||
strcat(request,opt->port);
|
||||
else
|
||||
strcat(request,"11371");
|
||||
strcat(request,opt->path);
|
||||
/* request is MAX_URL+15 bytes long - MAX_URL covers the whole URL,
|
||||
including any supplied path. The 15 covers /pks/add. */
|
||||
append_path(request,"/pks/add");
|
||||
|
||||
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_POST,1);
|
||||
curl_easy_setopt(curl,CURLOPT_POSTFIELDS,key);
|
||||
curl_easy_setopt(curl,CURLOPT_FAILONERROR,1);
|
||||
|
||||
res=curl_easy_perform(curl);
|
||||
if(res!=0)
|
||||
{
|
||||
fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer);
|
||||
ret=curl_err_to_gpg_err(res);
|
||||
}
|
||||
else
|
||||
fprintf(output,"\nKEY %s SENT\n",keyid);
|
||||
|
||||
ret=KEYSERVER_OK;
|
||||
|
||||
fail:
|
||||
free(key);
|
||||
curl_free(encoded_key);
|
||||
|
||||
if(ret!=0 && begin)
|
||||
fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
get_key(char *getkey)
|
||||
{
|
||||
CURLcode res;
|
||||
char request[MAX_URL+60];
|
||||
char *offset;
|
||||
struct curl_writer_ctx ctx;
|
||||
|
||||
memset(&ctx,0,sizeof(ctx));
|
||||
|
||||
/* Build the search string. HKP only uses the short key IDs. */
|
||||
|
||||
if(strncmp(getkey,"0x",2)==0)
|
||||
getkey+=2;
|
||||
|
||||
fprintf(output,"KEY 0x%s BEGIN\n",getkey);
|
||||
|
||||
if(strlen(getkey)==32)
|
||||
{
|
||||
fprintf(console,
|
||||
"gpgkeys: HKP keyservers do not support v3 fingerprints\n");
|
||||
fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
|
||||
return KEYSERVER_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
strcpy(request,"http://");
|
||||
strcat(request,opt->host);
|
||||
strcat(request,":");
|
||||
if(opt->port)
|
||||
strcat(request,opt->port);
|
||||
else
|
||||
strcat(request,"11371");
|
||||
strcat(request,opt->path);
|
||||
/* request is MAX_URL+55 bytes long - MAX_URL covers the whole URL,
|
||||
including any supplied path. The 60 overcovers this /pks/... etc
|
||||
string plus the 8 bytes of key id */
|
||||
append_path(request,"/pks/lookup?op=get&options=mr&search=0x");
|
||||
|
||||
/* fingerprint or long key id. Take the last 8 characters and treat
|
||||
it like a short key id */
|
||||
if(strlen(getkey)>8)
|
||||
offset=&getkey[strlen(getkey)-8];
|
||||
else
|
||||
offset=getkey;
|
||||
|
||||
strcat(request,offset);
|
||||
|
||||
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);
|
||||
fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,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);
|
||||
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;
|
||||
}
|
||||
|
||||
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->action==KS_GETNAME)
|
||||
strcat(request,"&exact=on");
|
||||
|
||||
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;
|
||||
int ret=KEYSERVER_INTERNAL_ERROR;
|
||||
enum ks_search_type search_type;
|
||||
|
||||
search_type=classify_ks_search(&searchkey);
|
||||
|
||||
if(opt->debug)
|
||||
fprintf(console,"gpgkeys: search type is %d, and key is \"%s\"\n",
|
||||
search_type,searchkey);
|
||||
|
||||
searchkey_encoded=curl_escape((char *)searchkey,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,"SEARCH %s BEGIN\n",searchkey);
|
||||
|
||||
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=index&options=mr&search=");
|
||||
strcat(request,searchkey_encoded);
|
||||
|
||||
if(search_type!=KS_SEARCH_SUBSTR)
|
||||
strcat(request,"&exact=on");
|
||||
|
||||
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_mrindex_writer);
|
||||
curl_easy_setopt(curl,CURLOPT_FILE,output);
|
||||
|
||||
res=curl_easy_perform(curl);
|
||||
if(res!=0)
|
||||
{
|
||||
fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer);
|
||||
ret=curl_err_to_gpg_err(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(output,"\nSEARCH %s END\n",searchkey);
|
||||
ret=KEYSERVER_OK;
|
||||
}
|
||||
|
||||
fail:
|
||||
|
||||
curl_free(searchkey_encoded);
|
||||
free(request);
|
||||
|
||||
if(ret!=KEYSERVER_OK)
|
||||
fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
fail_all(struct keylist *keylist,int err)
|
||||
{
|
||||
if(!keylist)
|
||||
return;
|
||||
|
||||
if(opt->action==KS_SEARCH)
|
||||
{
|
||||
fprintf(output,"SEARCH ");
|
||||
while(keylist)
|
||||
{
|
||||
fprintf(output,"%s ",keylist->str);
|
||||
keylist=keylist->next;
|
||||
}
|
||||
fprintf(output,"FAILED %d\n",err);
|
||||
}
|
||||
else
|
||||
while(keylist)
|
||||
{
|
||||
fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
|
||||
keylist=keylist->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_help (FILE *fp)
|
||||
{
|
||||
fprintf (fp,"-h\thelp\n");
|
||||
fprintf (fp,"-V\tversion\n");
|
||||
fprintf (fp,"-o\toutput to this file\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc,char *argv[])
|
||||
{
|
||||
int arg,ret=KEYSERVER_INTERNAL_ERROR;
|
||||
char line[MAX_LINE];
|
||||
int failed=0;
|
||||
struct keylist *keylist=NULL,*keyptr=NULL;
|
||||
char *proxy=NULL;
|
||||
|
||||
console=stderr;
|
||||
|
||||
/* Kludge to implement standard GNU options. */
|
||||
if (argc > 1 && !strcmp (argv[1], "--version"))
|
||||
{
|
||||
fputs ("gpgkeys_hkp (GnuPG) " VERSION"\n", stdout);
|
||||
return 0;
|
||||
}
|
||||
else if (argc > 1 && !strcmp (argv[1], "--help"))
|
||||
{
|
||||
show_help (stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while((arg=getopt(argc,argv,"hVo:"))!=-1)
|
||||
switch(arg)
|
||||
{
|
||||
default:
|
||||
case 'h':
|
||||
show_help (console);
|
||||
return KEYSERVER_OK;
|
||||
|
||||
case 'V':
|
||||
fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION);
|
||||
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;
|
||||
|
||||
opt=init_ks_options();
|
||||
if(!opt)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
|
||||
/* Get the command and info block */
|
||||
|
||||
while(fgets(line,MAX_LINE,input)!=NULL)
|
||||
{
|
||||
int err;
|
||||
char option[MAX_OPTION+1];
|
||||
|
||||
if(line[0]=='\n')
|
||||
break;
|
||||
|
||||
err=parse_ks_options(line,opt);
|
||||
if(err>0)
|
||||
{
|
||||
ret=err;
|
||||
goto fail;
|
||||
}
|
||||
else if(err==0)
|
||||
continue;
|
||||
|
||||
if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
|
||||
{
|
||||
int no=0;
|
||||
char *start=&option[0];
|
||||
|
||||
option[MAX_OPTION]='\0';
|
||||
|
||||
if(strncasecmp(option,"no-",3)==0)
|
||||
{
|
||||
no=1;
|
||||
start=&option[3];
|
||||
}
|
||||
|
||||
if(strncasecmp(start,"http-proxy",10)==0)
|
||||
{
|
||||
if(no)
|
||||
{
|
||||
free(proxy);
|
||||
proxy=strdup("");
|
||||
}
|
||||
else if(start[10]=='=')
|
||||
{
|
||||
if(strlen(&start[11])<MAX_PROXY)
|
||||
{
|
||||
free(proxy);
|
||||
proxy=strdup(&start[11]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else if(strcasecmp(start,"try-dns-srv")==0)
|
||||
{
|
||||
if(no)
|
||||
http_flags&=~HTTP_FLAG_TRY_SRV;
|
||||
else
|
||||
http_flags|=HTTP_FLAG_TRY_SRV;
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!opt->host)
|
||||
{
|
||||
fprintf(console,"gpgkeys: no keyserver host provided\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(opt->timeout && register_timeout()==-1)
|
||||
{
|
||||
fprintf(console,"gpgkeys: unable to register timeout handler\n");
|
||||
return KEYSERVER_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
curl=curl_easy_init();
|
||||
if(!curl)
|
||||
{
|
||||
fprintf(console,"gpgkeys: unable to initialize curl\n");
|
||||
ret=KEYSERVER_INTERNAL_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
|
||||
|
||||
if(opt->auth)
|
||||
curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
|
||||
|
||||
if(opt->debug)
|
||||
{
|
||||
fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
|
||||
curl_easy_setopt(curl,CURLOPT_STDERR,console);
|
||||
curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
|
||||
}
|
||||
|
||||
if(proxy)
|
||||
curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
|
||||
|
||||
#if 0
|
||||
/* By suggested convention, if the user gives a :port, then disable
|
||||
SRV. */
|
||||
if(opt->port)
|
||||
http_flags&=~HTTP_FLAG_TRY_SRV;
|
||||
#endif
|
||||
|
||||
/* 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(opt->action==KS_SEND)
|
||||
while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
|
||||
else if(opt->action==KS_GET
|
||||
|| opt->action==KS_GETNAME || opt->action==KS_SEARCH)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
struct keylist *work;
|
||||
|
||||
if(fgets(line,MAX_LINE,input)==NULL)
|
||||
break;
|
||||
else
|
||||
{
|
||||
if(line[0]=='\n' || line[0]=='\0')
|
||||
break;
|
||||
|
||||
work=malloc(sizeof(struct keylist));
|
||||
if(work==NULL)
|
||||
{
|
||||
fprintf(console,"gpgkeys: out of memory while "
|
||||
"building key list\n");
|
||||
ret=KEYSERVER_NO_MEMORY;
|
||||
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 %d\n",KEYSERVER_PROTO_VERSION);
|
||||
fprintf(output,"PROGRAM %s\n\n",VERSION);
|
||||
|
||||
if(opt->verbose>1)
|
||||
{
|
||||
fprintf(console,"Host:\t\t%s\n",opt->host);
|
||||
if(opt->port)
|
||||
fprintf(console,"Port:\t\t%s\n",opt->port);
|
||||
if(strcmp(opt->path,"/")!=0)
|
||||
fprintf(console,"Path:\t\t%s\n",opt->path);
|
||||
fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action));
|
||||
}
|
||||
|
||||
if(opt->action==KS_GET)
|
||||
{
|
||||
keyptr=keylist;
|
||||
|
||||
while(keyptr!=NULL)
|
||||
{
|
||||
set_timeout(opt->timeout);
|
||||
|
||||
if(get_key(keyptr->str)!=KEYSERVER_OK)
|
||||
failed++;
|
||||
|
||||
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;
|
||||
|
||||
do
|
||||
{
|
||||
set_timeout(opt->timeout);
|
||||
|
||||
if(send_key(&eof)!=KEYSERVER_OK)
|
||||
failed++;
|
||||
}
|
||||
while(!eof);
|
||||
}
|
||||
else if(opt->action==KS_SEARCH)
|
||||
{
|
||||
char *searchkey=NULL;
|
||||
int len=0;
|
||||
|
||||
set_timeout(opt->timeout);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
ret=KEYSERVER_NO_MEMORY;
|
||||
fail_all(keylist,KEYSERVER_NO_MEMORY);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
searchkey[0]='\0';
|
||||
|
||||
keyptr=keylist;
|
||||
while(keyptr!=NULL)
|
||||
{
|
||||
strcat(searchkey,keyptr->str);
|
||||
strcat(searchkey," ");
|
||||
keyptr=keyptr->next;
|
||||
}
|
||||
|
||||
/* Nail that last space */
|
||||
if(*searchkey)
|
||||
searchkey[strlen(searchkey)-1]='\0';
|
||||
|
||||
if(search_key(searchkey)!=KEYSERVER_OK)
|
||||
failed++;
|
||||
|
||||
free(searchkey);
|
||||
}
|
||||
else
|
||||
abort();
|
||||
|
||||
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);
|
||||
|
||||
free_ks_options(opt);
|
||||
|
||||
if(curl)
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
free(proxy);
|
||||
|
||||
return ret;
|
||||
}
|
2350
keyserver/gpgkeys_ldap.c
Normal file
2350
keyserver/gpgkeys_ldap.c
Normal file
File diff suppressed because it is too large
Load Diff
225
keyserver/gpgkeys_mailto.in
Executable file
225
keyserver/gpgkeys_mailto.in
Executable file
@ -0,0 +1,225 @@
|
||||
#!@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
use Getopt::Std;
|
||||
$Getopt::Std::STANDARD_HELP_VERSION=1;
|
||||
$sendmail="@SENDMAIL@ -t";
|
||||
|
||||
###
|
||||
|
||||
sub VERSION_MESSAGE ()
|
||||
{
|
||||
print STDOUT "gpgkeys_mailto (GnuPG) @VERSION@\n";
|
||||
}
|
||||
|
||||
sub HELP_MESSAGE ()
|
||||
{
|
||||
print STDOUT <<EOT
|
||||
|
||||
--help Print this help
|
||||
--version Print the version
|
||||
-o FILE Write output to FILE
|
||||
EOT
|
||||
}
|
||||
|
||||
|
||||
|
||||
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];
|
||||
|
||||
$from="$name <$login>";
|
||||
|
||||
while(<STDIN>)
|
||||
{
|
||||
last if($_ eq "\n");
|
||||
|
||||
if(/^COMMAND (\S+)/)
|
||||
{
|
||||
$command=$1;
|
||||
}
|
||||
|
||||
if(/^OPAQUE (\S+)/)
|
||||
{
|
||||
$address=$1;
|
||||
}
|
||||
|
||||
if(/^PROGRAM (\S+)/)
|
||||
{
|
||||
$program=$1;
|
||||
}
|
||||
|
||||
if(/^OPTION (\S+)/)
|
||||
{
|
||||
if($1=~/^verbose$/i)
|
||||
{
|
||||
$verbose++;
|
||||
}
|
||||
elsif($1=~/^no-verbose$/i)
|
||||
{
|
||||
$verbose--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$program="(unknown)" if(!defined($program));
|
||||
|
||||
if(!defined($address))
|
||||
{
|
||||
print STDERR "gpgkeys: no address provided\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
# decode $address
|
||||
|
||||
($address,$args)=split(/\?/,$address);
|
||||
|
||||
if(defined($args))
|
||||
{
|
||||
@pairs = split(/&/, $args);
|
||||
foreach $pair (@pairs)
|
||||
{
|
||||
($hdr, $val) = split(/=/, $pair);
|
||||
$hdr =~ tr/+/ /;
|
||||
$hdr =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$val =~ tr/+/ /;
|
||||
$val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
# we only handle "from" right now
|
||||
if($hdr=~/^from$/i)
|
||||
{
|
||||
$from=$val;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(<STDIN>)
|
||||
{
|
||||
last if($_ eq "\n");
|
||||
|
||||
chomp;
|
||||
|
||||
push(@keys,$_);
|
||||
}
|
||||
|
||||
# Send response
|
||||
|
||||
print "VERSION 1\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: $from\n";
|
||||
print MAIL "To: $address\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 $program email 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 $address\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: $address\n";
|
||||
print MAIL "Subject: ADD\n\n";
|
||||
|
||||
while(<STDIN>)
|
||||
{
|
||||
if(/^KEY (\S+) BEGIN$/)
|
||||
{
|
||||
$key=$1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
while(<STDIN>)
|
||||
{
|
||||
if(/^KEY \S+ END$/)
|
||||
{
|
||||
last;
|
||||
}
|
||||
|
||||
print MAIL;
|
||||
}
|
||||
|
||||
close(MAIL);
|
||||
|
||||
if($verbose)
|
||||
{
|
||||
print STDERR "gpgkeys: key $key sent to $address\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Local Variables:
|
||||
# mode:perl
|
||||
# End:
|
99
keyserver/gpgkeys_test.in
Executable file
99
keyserver/gpgkeys_test.in
Executable file
@ -0,0 +1,99 @@
|
||||
#!@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
use Getopt::Std;
|
||||
$Getopt::Std::STANDARD_HELP_VERSION=1;
|
||||
|
||||
$|=1;
|
||||
|
||||
sub VERSION_MESSAGE ()
|
||||
{
|
||||
print STDOUT "gpgkeys_test (GnuPG) @VERSION@\n";
|
||||
}
|
||||
|
||||
sub HELP_MESSAGE ()
|
||||
{
|
||||
print STDOUT <<EOT
|
||||
|
||||
--help Print this help
|
||||
--version Print the version
|
||||
EOT
|
||||
}
|
||||
|
||||
|
||||
getopts('o:');
|
||||
|
||||
print STDERR "gpgkeys_test starting\n";
|
||||
|
||||
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";
|
||||
|
||||
# Local Variables:
|
||||
# mode:perl
|
||||
# End:
|
540
keyserver/ksutil.c
Normal file
540
keyserver/ksutil.c
Normal file
@ -0,0 +1,540 @@
|
||||
/* ksutil.c - general keyserver utility functions
|
||||
* Copyright (C) 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_LIBCURL
|
||||
#include <curl/curl.h>
|
||||
#else
|
||||
#include "curl-shim.h"
|
||||
#endif
|
||||
#include "keyserver.h"
|
||||
#include "ksutil.h"
|
||||
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
|
||||
unsigned int set_timeout(unsigned int seconds) {return 0;}
|
||||
int register_timeout(void) {return 0;}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
catch_alarm(int foo)
|
||||
{
|
||||
(void)foo;
|
||||
_exit(KEYSERVER_TIMEOUT);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
set_timeout(unsigned int seconds)
|
||||
{
|
||||
return alarm(seconds);
|
||||
}
|
||||
|
||||
int
|
||||
register_timeout(void)
|
||||
{
|
||||
#if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler=catch_alarm;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags=0;
|
||||
return sigaction(SIGALRM,&act,NULL);
|
||||
#else
|
||||
if(signal(SIGALRM,catch_alarm)==SIG_ERR)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* !HAVE_DOSISH_SYSTEM */
|
||||
|
||||
struct ks_options *
|
||||
init_ks_options(void)
|
||||
{
|
||||
struct ks_options *opt;
|
||||
|
||||
opt=calloc(1,sizeof(struct ks_options));
|
||||
|
||||
if(opt)
|
||||
{
|
||||
opt->action=KS_UNKNOWN;
|
||||
opt->flags.include_revoked=1;
|
||||
opt->flags.include_subkeys=1;
|
||||
opt->flags.check_cert=1;
|
||||
opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
|
||||
opt->path=strdup("/");
|
||||
if(!opt->path)
|
||||
{
|
||||
free(opt);
|
||||
opt=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return opt;
|
||||
}
|
||||
|
||||
void
|
||||
free_ks_options(struct ks_options *opt)
|
||||
{
|
||||
if(opt)
|
||||
{
|
||||
free(opt->host);
|
||||
free(opt->port);
|
||||
free(opt->scheme);
|
||||
free(opt->auth);
|
||||
free(opt->path);
|
||||
free(opt->opaque);
|
||||
free(opt->ca_cert_file);
|
||||
free(opt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns 0 if we "ate" the line. Returns >0, a KEYSERVER_ error
|
||||
code if that error applies. Returns -1 if we did not match the
|
||||
line at all. */
|
||||
int
|
||||
parse_ks_options(char *line,struct ks_options *opt)
|
||||
{
|
||||
int version;
|
||||
char command[MAX_COMMAND+1];
|
||||
char host[MAX_HOST+1];
|
||||
char port[MAX_PORT+1];
|
||||
char scheme[MAX_SCHEME+1];
|
||||
char auth[MAX_AUTH+1];
|
||||
char path[URLMAX_PATH+1];
|
||||
char opaque[MAX_OPAQUE+1];
|
||||
char option[MAX_OPTION+1];
|
||||
|
||||
if(line[0]=='#')
|
||||
return 0;
|
||||
|
||||
if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
|
||||
{
|
||||
command[MAX_COMMAND]='\0';
|
||||
|
||||
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)
|
||||
opt->action=KS_SEARCH;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
|
||||
{
|
||||
host[MAX_HOST]='\0';
|
||||
free(opt->host);
|
||||
opt->host=strdup(host);
|
||||
if(!opt->host)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
|
||||
{
|
||||
port[MAX_PORT]='\0';
|
||||
free(opt->port);
|
||||
opt->port=strdup(port);
|
||||
if(!opt->port)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1)
|
||||
{
|
||||
scheme[MAX_SCHEME]='\0';
|
||||
free(opt->scheme);
|
||||
opt->scheme=strdup(scheme);
|
||||
if(!opt->scheme)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1)
|
||||
{
|
||||
auth[MAX_AUTH]='\0';
|
||||
free(opt->auth);
|
||||
opt->auth=strdup(auth);
|
||||
if(!opt->auth)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1)
|
||||
{
|
||||
path[URLMAX_PATH]='\0';
|
||||
free(opt->path);
|
||||
opt->path=strdup(path);
|
||||
if(!opt->path)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"OPAQUE %" MKSTRING(MAX_OPAQUE) "s\n",opaque)==1)
|
||||
{
|
||||
opaque[MAX_OPAQUE]='\0';
|
||||
free(opt->opaque);
|
||||
opt->opaque=strdup(opaque);
|
||||
if(!opt->opaque)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"VERSION %d\n",&version)==1)
|
||||
{
|
||||
if(version!=KEYSERVER_PROTO_VERSION)
|
||||
return KEYSERVER_VERSION_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "[^\n]\n",option)==1)
|
||||
{
|
||||
int no=0;
|
||||
char *start=&option[0];
|
||||
|
||||
option[MAX_OPTION]='\0';
|
||||
|
||||
if(strncasecmp(option,"no-",3)==0)
|
||||
{
|
||||
no=1;
|
||||
start=&option[3];
|
||||
}
|
||||
|
||||
if(strncasecmp(start,"verbose",7)==0)
|
||||
{
|
||||
if(no)
|
||||
opt->verbose=0;
|
||||
else if(start[7]=='=')
|
||||
opt->verbose=atoi(&start[8]);
|
||||
else
|
||||
opt->verbose++;
|
||||
}
|
||||
else if(strcasecmp(start,"include-disabled")==0)
|
||||
{
|
||||
if(no)
|
||||
opt->flags.include_disabled=0;
|
||||
else
|
||||
opt->flags.include_disabled=1;
|
||||
}
|
||||
else if(strcasecmp(start,"include-revoked")==0)
|
||||
{
|
||||
if(no)
|
||||
opt->flags.include_revoked=0;
|
||||
else
|
||||
opt->flags.include_revoked=1;
|
||||
}
|
||||
else if(strcasecmp(start,"include-subkeys")==0)
|
||||
{
|
||||
if(no)
|
||||
opt->flags.include_subkeys=0;
|
||||
else
|
||||
opt->flags.include_subkeys=1;
|
||||
}
|
||||
else if(strcasecmp(start,"check-cert")==0)
|
||||
{
|
||||
if(no)
|
||||
opt->flags.check_cert=0;
|
||||
else
|
||||
opt->flags.check_cert=1;
|
||||
}
|
||||
else if(strncasecmp(start,"debug",5)==0)
|
||||
{
|
||||
if(no)
|
||||
opt->debug=0;
|
||||
else if(start[5]=='=')
|
||||
opt->debug=atoi(&start[6]);
|
||||
else if(start[5]=='\0')
|
||||
opt->debug=1;
|
||||
}
|
||||
else if(strncasecmp(start,"timeout",7)==0)
|
||||
{
|
||||
if(no)
|
||||
opt->timeout=0;
|
||||
else if(start[7]=='=')
|
||||
opt->timeout=atoi(&start[8]);
|
||||
else if(start[7]=='\0')
|
||||
opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
|
||||
}
|
||||
else if(strncasecmp(start,"ca-cert-file",12)==0)
|
||||
{
|
||||
if(no)
|
||||
{
|
||||
free(opt->ca_cert_file);
|
||||
opt->ca_cert_file=NULL;
|
||||
}
|
||||
else if(start[12]=='=')
|
||||
{
|
||||
free(opt->ca_cert_file);
|
||||
opt->ca_cert_file=strdup(&start[13]);
|
||||
if(!opt->ca_cert_file)
|
||||
return KEYSERVER_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *
|
||||
ks_action_to_string(enum ks_action action)
|
||||
{
|
||||
switch(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";
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
void
|
||||
print_nocr(FILE *stream,const char *str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
if(*str!='\r')
|
||||
fputc(*str,stream);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
enum ks_search_type
|
||||
classify_ks_search(const char **search)
|
||||
{
|
||||
switch(**search)
|
||||
{
|
||||
case '*':
|
||||
(*search)++;
|
||||
return KS_SEARCH_SUBSTR;
|
||||
case '=':
|
||||
(*search)++;
|
||||
return KS_SEARCH_EXACT;
|
||||
case '<':
|
||||
(*search)++;
|
||||
return KS_SEARCH_MAIL;
|
||||
case '@':
|
||||
(*search)++;
|
||||
return KS_SEARCH_MAILSUB;
|
||||
case '0':
|
||||
if((*search)[1]=='x')
|
||||
{
|
||||
if(strlen(*search)==10
|
||||
&& strspn(*search,"abcdefABCDEF1234567890x")==10)
|
||||
{
|
||||
(*search)+=2;
|
||||
return KS_SEARCH_KEYID_SHORT;
|
||||
}
|
||||
else if(strlen(*search)==18
|
||||
&& strspn(*search,"abcdefABCDEF1234567890x")==18)
|
||||
{
|
||||
(*search)+=2;
|
||||
return KS_SEARCH_KEYID_LONG;
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
return KS_SEARCH_SUBSTR;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
curl_err_to_gpg_err(CURLcode error)
|
||||
{
|
||||
switch(error)
|
||||
{
|
||||
case CURLE_OK: return KEYSERVER_OK;
|
||||
case CURLE_UNSUPPORTED_PROTOCOL: return KEYSERVER_SCHEME_NOT_FOUND;
|
||||
case CURLE_COULDNT_CONNECT: return KEYSERVER_UNREACHABLE;
|
||||
case CURLE_FTP_COULDNT_RETR_FILE: return KEYSERVER_KEY_NOT_FOUND;
|
||||
default: return KEYSERVER_INTERNAL_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)
|
||||
{
|
||||
struct curl_writer_ctx *ctx=cw_ctx;
|
||||
const char *buf=ptr;
|
||||
size_t i;
|
||||
|
||||
if(!ctx->flags.initialized)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if(ctx->flags.armor)
|
||||
curl_armor_writer(ptr,size*nmemb,cw_ctx);
|
||||
else
|
||||
{
|
||||
/* scan the incoming data for our marker */
|
||||
for(i=0;!ctx->flags.done && i<(size*nmemb);i++)
|
||||
{
|
||||
if(buf[i]==ctx->marker[ctx->markeridx])
|
||||
{
|
||||
ctx->markeridx++;
|
||||
if(ctx->marker[ctx->markeridx]=='\0')
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
130
keyserver/ksutil.h
Normal file
130
keyserver/ksutil.h
Normal file
@ -0,0 +1,130 @@
|
||||
/* ksutil.h
|
||||
* Copyright (C) 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef _KSUTIL_H_
|
||||
#define _KSUTIL_H_
|
||||
|
||||
#ifdef HAVE_LIBCURL
|
||||
#include <curl/curl.h>
|
||||
#else
|
||||
#include "curl-shim.h"
|
||||
#endif
|
||||
|
||||
/* MAX_LINE must be at least 1 larger than the largest item we expect
|
||||
to receive, including the name tag ("COMMAND", "PORT", etc) and
|
||||
space between. In practice, that means it should be
|
||||
strlen("OPAQUE")+1+sizeof_opaque+1 */
|
||||
#define MAX_LINE (6+1+1024+1)
|
||||
|
||||
#define MAX_COMMAND 7
|
||||
#define MAX_OPTION 256
|
||||
#define MAX_SCHEME 20
|
||||
#define MAX_OPAQUE 1024
|
||||
#define MAX_AUTH 128
|
||||
#define MAX_HOST 80
|
||||
#define MAX_PORT 10
|
||||
#define URLMAX_PATH 1024
|
||||
#define MAX_PROXY 128
|
||||
#define MAX_URL (MAX_SCHEME+1+3+MAX_AUTH+1+1+MAX_HOST+1+1 \
|
||||
+MAX_PORT+1+1+URLMAX_PATH+1+50)
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define MKSTRING(x) STRINGIFY(x)
|
||||
|
||||
#define BEGIN "-----BEGIN PGP PUBLIC KEY BLOCK-----"
|
||||
#define END "-----END PGP PUBLIC KEY BLOCK-----"
|
||||
|
||||
#ifdef __riscos__
|
||||
#define HTTP_PROXY_ENV "GnuPG$HttpProxy"
|
||||
#else
|
||||
#define HTTP_PROXY_ENV "http_proxy"
|
||||
#endif
|
||||
|
||||
struct keylist
|
||||
{
|
||||
char str[MAX_LINE];
|
||||
struct keylist *next;
|
||||
};
|
||||
|
||||
/* 2 minutes seems reasonable */
|
||||
#define DEFAULT_KEYSERVER_TIMEOUT 120
|
||||
|
||||
unsigned int set_timeout(unsigned int seconds);
|
||||
int register_timeout(void);
|
||||
|
||||
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,
|
||||
KS_SEARCH_KEYID_LONG,KS_SEARCH_KEYID_SHORT};
|
||||
|
||||
struct ks_options
|
||||
{
|
||||
enum ks_action action;
|
||||
char *host;
|
||||
char *port;
|
||||
char *scheme;
|
||||
char *auth;
|
||||
char *path;
|
||||
char *opaque;
|
||||
struct
|
||||
{
|
||||
unsigned int include_disabled:1;
|
||||
unsigned int include_revoked:1;
|
||||
unsigned int include_subkeys:1;
|
||||
unsigned int check_cert:1;
|
||||
} flags;
|
||||
unsigned int verbose;
|
||||
unsigned int debug;
|
||||
unsigned int timeout;
|
||||
char *ca_cert_file;
|
||||
};
|
||||
|
||||
struct ks_options *init_ks_options(void);
|
||||
void free_ks_options(struct ks_options *opt);
|
||||
int parse_ks_options(char *line,struct ks_options *opt);
|
||||
const char *ks_action_to_string(enum ks_action action);
|
||||
void print_nocr(FILE *stream,const char *str);
|
||||
enum ks_search_type classify_ks_search(const char **search);
|
||||
|
||||
int curl_err_to_gpg_err(CURLcode error);
|
||||
|
||||
struct curl_writer_ctx
|
||||
{
|
||||
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 /* !_KSUTIL_H_ */
|
@ -1,3 +1,8 @@
|
||||
2006-06-30 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ldap.m4: New. Taken from gnupg 1.4.4
|
||||
* Makefile.am (EXTRA_DIST): Add ldap.me
|
||||
|
||||
2004-09-30 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpg-error.m4, libassuan.m4, libgcrypt.m4: Updated.
|
||||
|
@ -1,3 +1,5 @@
|
||||
EXTRA_DIST = intmax.m4 longdouble.m4 longlong.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4
|
||||
|
||||
EXTRA_DIST += ldap.m4
|
||||
|
||||
EXTRA_DIST += gpg-error.m4 libgcrypt.m4 libassuan.m4 ksba.m4
|
||||
|
97
m4/ldap.m4
Normal file
97
m4/ldap.m4
Normal file
@ -0,0 +1,97 @@
|
||||
dnl Check for LDAP
|
||||
dnl Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
dnl
|
||||
dnl Defines @GPGKEYS_LDAP@ to a executable name if a working ldap
|
||||
dnl setup is found, and sets @LDAPLIBS@ to the necessary libraries.
|
||||
|
||||
AC_DEFUN([GNUPG_CHECK_LDAP],
|
||||
[
|
||||
# Try and link a LDAP test program to weed out unusable LDAP
|
||||
# libraries. -lldap [-llber [-lresolv]] is for older OpenLDAPs.
|
||||
# OpenLDAP, circa 1999, was terrible with creating weird dependencies.
|
||||
# If all else fails, the user can play guess-the-dependency by using
|
||||
# something like ./configure LDAPLIBS="-Lfoo -lbar"
|
||||
|
||||
AC_ARG_WITH(ldap,
|
||||
AC_HELP_STRING([--with-ldap=DIR],[look for the LDAP library in DIR]),
|
||||
[_ldap_with=$withval])
|
||||
|
||||
if test x$_ldap_with != xno ; then
|
||||
|
||||
if test -d "$withval" ; then
|
||||
LDAP_CPPFLAGS="-I$withval/include"
|
||||
LDAP_LDFLAGS="-L$withval/lib"
|
||||
fi
|
||||
|
||||
_ldap_save_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="${LDAP_CPPFLAGS} ${CPPFLAGS}"
|
||||
_ldap_save_ldflags=$LDFLAGS
|
||||
LDFLAGS="${LDAP_LDFLAGS} ${LDFLAGS}"
|
||||
|
||||
for MY_LDAPLIBS in ${LDAPLIBS+"$LDAPLIBS"} "-lldap" "-lldap -llber" "-lldap -llber -lresolv" "-lwldap32"; do
|
||||
_ldap_save_libs=$LIBS
|
||||
LIBS="$MY_LDAPLIBS $1 $LIBS"
|
||||
|
||||
AC_MSG_CHECKING([whether LDAP via \"$MY_LDAPLIBS\" is present and sane])
|
||||
AC_TRY_LINK([
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <winldap.h>
|
||||
#else
|
||||
#include <ldap.h>
|
||||
#endif
|
||||
],[ldap_open("foobar",1234);],
|
||||
[gnupg_cv_func_ldap_init=yes],[gnupg_cv_func_ldap_init=no])
|
||||
AC_MSG_RESULT([$gnupg_cv_func_ldap_init])
|
||||
|
||||
if test $gnupg_cv_func_ldap_init = no; then
|
||||
AC_MSG_CHECKING([whether I can make LDAP be sane with lber.h])
|
||||
AC_TRY_LINK([#include <lber.h>
|
||||
#include <ldap.h>],[ldap_open("foobar",1234);],
|
||||
[gnupg_cv_func_ldaplber_init=yes],[gnupg_cv_func_ldaplber_init=no])
|
||||
AC_MSG_RESULT([$gnupg_cv_func_ldaplber_init])
|
||||
fi
|
||||
|
||||
if test "$gnupg_cv_func_ldaplber_init" = yes ; then
|
||||
AC_DEFINE(NEED_LBER_H,1,[Define if the LDAP library requires including lber.h before ldap.h])
|
||||
fi
|
||||
|
||||
if test "$gnupg_cv_func_ldap_init" = yes || \
|
||||
test "$gnupg_cv_func_ldaplber_init" = yes ; then
|
||||
LDAPLIBS="$LDAP_LDFLAGS $MY_LDAPLIBS"
|
||||
GPGKEYS_LDAP="gpgkeys_ldap$EXEEXT"
|
||||
|
||||
AC_CHECK_FUNCS(ldap_get_option ldap_set_option ldap_start_tls_s)
|
||||
|
||||
if test "$ac_cv_func_ldap_get_option" != yes ; then
|
||||
AC_MSG_CHECKING([whether LDAP supports ld_errno])
|
||||
AC_TRY_LINK([#include <ldap.h>],[LDAP *ldap; ldap->ld_errno;],
|
||||
[gnupg_cv_func_ldap_ld_errno=yes],
|
||||
[gnupg_cv_func_ldap_ld_errno=no])
|
||||
AC_MSG_RESULT([$gnupg_cv_func_ldap_ld_errno])
|
||||
|
||||
if test "$gnupg_cv_func_ldap_ld_errno" = yes ; then
|
||||
AC_DEFINE(HAVE_LDAP_LD_ERRNO,1,[Define if the LDAP library supports ld_errno])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
LIBS=$_ldap_save_libs
|
||||
|
||||
if test "$GPGKEYS_LDAP" != "" ; then break; fi
|
||||
done
|
||||
|
||||
AC_SUBST(GPGKEYS_LDAP)
|
||||
AC_SUBST(LDAPLIBS)
|
||||
AC_SUBST(LDAP_CPPFLAGS)
|
||||
|
||||
CPPFLAGS=$_ldap_save_cppflags
|
||||
LDFLAGS=$_ldap_save_ldflags
|
||||
fi
|
||||
])dnl
|
Loading…
x
Reference in New Issue
Block a user