~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to keyserver/gpgkeys_hkp.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* gpgkeys_hkp.c - talk to an HKP keyserver
2
 
 * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
2
 * Copyright (C) 2001, 2002, 2003, 2004, 2005
 
3
 *               2006 Free Software Foundation, Inc.
3
4
 *
4
5
 * This file is part of GnuPG.
5
6
 *
6
7
 * GnuPG is free software; you can redistribute it and/or modify
7
8
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * the Free Software Foundation; either version 3 of the License, or
9
10
 * (at your option) any later version.
10
11
 *
11
12
 * GnuPG is distributed in the hope that it will be useful,
14
15
 * GNU General Public License for more details.
15
16
 *
16
17
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
18
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
19
 *
 
20
 * In addition, as a special exception, the Free Software Foundation
 
21
 * gives permission to link the code of the keyserver helper tools:
 
22
 * gpgkeys_ldap, gpgkeys_curl and gpgkeys_hkp with the OpenSSL
 
23
 * project's "OpenSSL" library (or with modified versions of it that
 
24
 * use the same license as the "OpenSSL" library), and distribute the
 
25
 * linked executables.  You must obey the GNU General Public License
 
26
 * in all respects for all of the code used other than "OpenSSL".  If
 
27
 * you modify this file, you may extend this exception to your version
 
28
 * of the file, but you are not obligated to do so.  If you do not
 
29
 * wish to do so, delete this exception statement from your version.
19
30
 */
20
31
 
21
32
#include <config.h>
22
33
#include <stdio.h>
23
34
#include <string.h>
24
 
#include <ctype.h>
25
35
#include <stdlib.h>
26
36
#include <errno.h>
27
37
#include <unistd.h>
28
38
#ifdef HAVE_GETOPT_H
29
39
#include <getopt.h>
30
40
#endif
31
 
#define INCLUDED_BY_MAIN_MODULE 1
32
 
#include "util.h"
33
 
#include "http.h"
 
41
#ifdef HAVE_LIBCURL
 
42
#include <curl/curl.h>
 
43
#else
 
44
#include "curl-shim.h"
 
45
#endif
34
46
#include "keyserver.h"
35
47
#include "ksutil.h"
36
48
 
37
49
extern char *optarg;
38
50
extern int optind;
39
51
 
40
 
#define GET    0
41
 
#define SEND   1
42
 
#define SEARCH 2
43
 
#define MAX_LINE 80
44
 
 
45
 
static int verbose=0,include_revoked=0,include_disabled=0;
46
 
static unsigned int http_flags=0;
47
 
static char host[80]={'\0'},proxy[80]={'\0'},port[10]={'\0'};
48
 
static FILE *input=NULL,*output=NULL,*console=NULL;
49
 
 
50
 
#define BEGIN "-----BEGIN PGP PUBLIC KEY BLOCK-----"
51
 
#define END   "-----END PGP PUBLIC KEY BLOCK-----"
52
 
 
53
 
struct keylist
54
 
{
55
 
  char str[MAX_LINE];
56
 
  struct keylist *next;
57
 
};
58
 
 
59
 
#ifdef __riscos__
60
 
#define HTTP_PROXY_ENV           "GnuPG$HttpProxy"
61
 
#else
62
 
#define HTTP_PROXY_ENV           "http_proxy"
63
 
#endif
64
 
 
65
 
int
66
 
urlencode_filter( void *opaque, int control,
67
 
                  IOBUF a, byte *buf, size_t *ret_len)
68
 
{
69
 
    size_t size = *ret_len;
70
 
    int rc=0;
71
 
 
72
 
    if( control == IOBUFCTRL_FLUSH ) {
73
 
        const byte *p;
74
 
        for(p=buf; size; p++, size-- ) {
75
 
            if( isalnum(*p) || *p == '-' )
76
 
                iobuf_put( a, *p );
77
 
            else if( *p == ' ' )
78
 
                iobuf_put( a, '+' );
79
 
            else {
80
 
                char numbuf[5];
81
 
                sprintf(numbuf, "%%%02X", *p );
82
 
                iobuf_writestr(a, numbuf );
83
 
            }
84
 
        }
 
52
static FILE *input,*output,*console;
 
53
static CURL *curl;
 
54
static struct ks_options *opt;
 
55
static char errorbuffer[CURL_ERROR_SIZE];
 
56
 
 
57
static size_t
 
58
curl_mrindex_writer(const void *ptr,size_t size,size_t nmemb,void *stream)
 
59
{
 
60
  static int checked=0,swallow=0;
 
61
 
 
62
  if(!checked)
 
63
    {
 
64
      /* If the document begins with a '<', assume it's a HTML
 
65
         response, which we don't support.  Discard the whole message
 
66
         body.  GPG can handle it, but this is an optimization to deal
 
67
         with it on this side of the pipe.  */
 
68
      const char *buf=ptr;
 
69
      if(buf[0]=='<')
 
70
        swallow=1;
 
71
 
 
72
      checked=1;
85
73
    }
86
 
    else if( control == IOBUFCTRL_DESC )
87
 
        *(char**)buf = "urlencode_filter";
88
 
    return rc;
 
74
 
 
75
  if(swallow || fwrite(ptr,size,nmemb,stream)==nmemb)
 
76
    return size*nmemb;
 
77
  else
 
78
    return 0;
 
79
}
 
80
 
 
81
/* Append but avoid creating a double slash // in the path. */
 
82
static char *
 
83
append_path(char *dest,const char *src)
 
84
{
 
85
  size_t n=strlen(dest);
 
86
 
 
87
  if(src[0]=='/' && n>0 && dest[n-1]=='/')
 
88
    dest[n-1]='\0';
 
89
 
 
90
  return strcat(dest,src);
89
91
}
90
92
 
91
93
int
92
 
send_key(int *eof)
 
94
send_key(int *r_eof)
93
95
{
94
 
  int rc,begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR;
95
 
  char keyid[17];
96
 
  char *request;
97
 
  struct http_context hd;
98
 
  unsigned int status;
99
 
  IOBUF temp = iobuf_temp();
 
96
  CURLcode res;
 
97
  char request[MAX_URL+15];
 
98
  int begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR;
 
99
  char keyid[17],state[6];
100
100
  char line[MAX_LINE];
101
 
 
102
 
  memset(&hd,0,sizeof(hd));
103
 
 
104
 
  request=malloc(strlen(host)+100);
105
 
  if(!request)
106
 
    {
107
 
      fprintf(console,"gpgkeys: out of memory\n");
108
 
      return KEYSERVER_NO_MEMORY;
109
 
    }
110
 
 
111
 
  iobuf_push_filter(temp,urlencode_filter,NULL);
 
101
  char *key=NULL,*encoded_key=NULL;
 
102
  size_t keylen=0,keymax=0;
112
103
 
113
104
  /* Read and throw away input until we see the BEGIN */
114
105
 
115
106
  while(fgets(line,MAX_LINE,input)!=NULL)
116
 
    if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1)
 
107
    if(sscanf(line,"KEY%*[ ]%16s%*[ ]%5s\n",keyid,state)==2
 
108
       && strcmp(state,"BEGIN")==0)
117
109
      {
118
110
        begin=1;
119
111
        break;
123
115
    {
124
116
      /* i.e. eof before the KEY BEGIN was found.  This isn't an
125
117
         error. */
126
 
      *eof=1;
 
118
      *r_eof=1;
127
119
      ret=KEYSERVER_OK;
128
120
      goto fail;
129
121
    }
131
123
  /* Now slurp up everything until we see the END */
132
124
 
133
125
  while(fgets(line,MAX_LINE,input))
134
 
    if(sscanf(line,"KEY %16s END\n",keyid)==1)
 
126
    if(sscanf(line,"KEY%*[ ]%16s%*[ ]%3s\n",keyid,state)==2
 
127
       && strcmp(state,"END")==0)
135
128
      {
136
129
        end=1;
137
130
        break;
138
131
      }
139
132
    else
140
 
      if(iobuf_writestr(temp,line))
141
 
        {
142
 
          fprintf(console,"gpgkeys: internal iobuf error\n");
143
 
          goto fail;
144
 
        }
 
133
      {
 
134
        if(strlen(line)+keylen>keymax)
 
135
          {
 
136
            char *tmp;
 
137
 
 
138
            keymax+=200;
 
139
            tmp=realloc(key,keymax+1);
 
140
            if(!tmp)
 
141
              {
 
142
                free(key);
 
143
                fprintf(console,"gpgkeys: out of memory\n");
 
144
                ret=KEYSERVER_NO_MEMORY;
 
145
                goto fail;
 
146
              }
 
147
 
 
148
            key=tmp;
 
149
          }
 
150
 
 
151
        strcpy(&key[keylen],line);
 
152
        keylen+=strlen(line);
 
153
      }
145
154
 
146
155
  if(!end)
147
156
    {
148
157
      fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
149
 
      *eof=1;
 
158
      *r_eof=1;
150
159
      ret=KEYSERVER_KEY_INCOMPLETE;
151
160
      goto fail;
152
161
    }
153
162
 
154
 
  iobuf_flush_temp(temp);
155
 
 
156
 
  sprintf(request,"hkp://%s%s%s/pks/add",host,port[0]?":":"",port[0]?port:"");
157
 
 
158
 
  if(verbose>2)
 
163
  encoded_key=curl_escape(key,keylen);
 
164
  if(!encoded_key)
 
165
    {
 
166
      fprintf(console,"gpgkeys: out of memory\n");
 
167
      ret=KEYSERVER_NO_MEMORY;
 
168
      goto fail;
 
169
    }
 
170
 
 
171
  free(key);
 
172
 
 
173
  key=malloc(8+strlen(encoded_key)+1);
 
174
  if(!key)
 
175
    {
 
176
      fprintf(console,"gpgkeys: out of memory\n");
 
177
      ret=KEYSERVER_NO_MEMORY;
 
178
      goto fail;
 
179
    }
 
180
 
 
181
  strcpy(key,"keytext=");
 
182
  strcat(key,encoded_key);
 
183
 
 
184
  strcpy(request,"http://");
 
185
  strcat(request,opt->host);
 
186
  strcat(request,":");
 
187
  if(opt->port)
 
188
    strcat(request,opt->port);
 
189
  else
 
190
    strcat(request,"11371");
 
191
  strcat(request,opt->path);
 
192
  /* request is MAX_URL+15 bytes long - MAX_URL covers the whole URL,
 
193
     including any supplied path.  The 15 covers /pks/add. */
 
194
  append_path(request,"/pks/add");
 
195
 
 
196
  if(opt->verbose>2)
159
197
    fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
160
198
 
161
 
  rc=http_open(&hd,HTTP_REQ_POST,request,http_flags,proxy[0]?proxy:NULL);
162
 
  if(rc)
163
 
    {
164
 
      fprintf(console,"gpgkeys: unable to connect to `%s'\n",host);
165
 
      goto fail;
166
 
    }
167
 
 
168
 
  /* Some keyservers require this Content-Type (e.g. CryptoEx). */
169
 
  iobuf_writestr(hd.fp_write,
170
 
                 "Content-Type: application/x-www-form-urlencoded\r\n");
171
 
 
172
 
  sprintf(request,"Content-Length: %u\r\n",
173
 
          (unsigned)iobuf_get_temp_length(temp)+9);
174
 
  iobuf_writestr(hd.fp_write,request);
175
 
 
176
 
  http_start_data(&hd);
177
 
 
178
 
  iobuf_writestr(hd.fp_write,"keytext=");
179
 
  iobuf_write(hd.fp_write,
180
 
              iobuf_get_temp_buffer(temp),iobuf_get_temp_length(temp));
181
 
  iobuf_put(hd.fp_write,'\n');
182
 
 
183
 
  rc=http_wait_response(&hd,&status);
184
 
  if(rc)
185
 
    {
186
 
      fprintf(console,"gpgkeys: error sending to `%s': %s\n",
187
 
              host,g10_errstr(rc));
188
 
      goto fail;
189
 
    }
190
 
 
191
 
  if((status/100)!=2)
192
 
    {
193
 
      fprintf(console,"gpgkeys: remote server returned error %d\n",status);
194
 
      goto fail;
195
 
    }
196
 
 
197
 
  fprintf(output,"KEY %s SENT\n",keyid);
 
199
  curl_easy_setopt(curl,CURLOPT_URL,request);
 
200
  curl_easy_setopt(curl,CURLOPT_POST,1L);
 
201
  curl_easy_setopt(curl,CURLOPT_POSTFIELDS,key);
 
202
  curl_easy_setopt(curl,CURLOPT_FAILONERROR,1L);
 
203
 
 
204
  res=curl_easy_perform(curl);
 
205
  if(res!=0)
 
206
    {
 
207
      fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer);
 
208
      ret=curl_err_to_gpg_err(res);
 
209
      goto fail;
 
210
    }
 
211
  else
 
212
    fprintf(output,"\nKEY %s SENT\n",keyid);
198
213
 
199
214
  ret=KEYSERVER_OK;
200
215
 
201
216
 fail:
202
 
  free(request);
203
 
  iobuf_close(temp);
204
 
  http_close(&hd);
 
217
  free(key);
 
218
  curl_free(encoded_key);
205
219
 
206
220
  if(ret!=0 && begin)
207
221
    fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
209
223
  return ret;
210
224
}
211
225
 
212
 
int
 
226
static int
213
227
get_key(char *getkey)
214
228
{
215
 
  int rc,gotit=0;
216
 
  char search[29];
217
 
  char *request;
218
 
  struct http_context hd;
 
229
  CURLcode res;
 
230
  char request[MAX_URL+60];
 
231
  char *offset;
 
232
  struct curl_writer_ctx ctx;
 
233
 
 
234
  memset(&ctx,0,sizeof(ctx));
219
235
 
220
236
  /* Build the search string.  HKP only uses the short key IDs. */
221
237
 
222
238
  if(strncmp(getkey,"0x",2)==0)
223
239
    getkey+=2;
224
240
 
 
241
  fprintf(output,"KEY 0x%s BEGIN\n",getkey);
 
242
 
225
243
  if(strlen(getkey)==32)
226
244
    {
227
245
      fprintf(console,
228
246
              "gpgkeys: HKP keyservers do not support v3 fingerprints\n");
229
 
      fprintf(output,"KEY 0x%s BEGIN\n",getkey);
230
247
      fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
231
248
      return KEYSERVER_NOT_SUPPORTED;
232
249
    }
233
250
 
234
 
 if(strlen(getkey)>8)
235
 
    {
236
 
      char *offset=&getkey[strlen(getkey)-8];
237
 
 
238
 
      /* fingerprint or long key id.  Take the last 8 characters and
239
 
         treat it like a short key id */
240
 
 
241
 
      sprintf(search,"0x%.8s",offset);
242
 
    }
243
 
 else
244
 
   {
245
 
      /* short key id */
246
 
 
247
 
      sprintf(search,"0x%.8s",getkey);
248
 
    }
249
 
 
250
 
  fprintf(output,"KEY 0x%s BEGIN\n",getkey);
251
 
 
252
 
  request=malloc(strlen(host)+100);
253
 
  if(!request)
254
 
    {
255
 
      fprintf(console,"gpgkeys: out of memory\n");
256
 
      return KEYSERVER_NO_MEMORY;
257
 
    }
258
 
 
259
 
  sprintf(request,"hkp://%s%s%s/pks/lookup?op=get&options=mr&search=%s",
260
 
          host,port[0]?":":"",port[0]?port:"", search);
261
 
 
262
 
  if(verbose>2)
 
251
  strcpy(request,"http://");
 
252
  strcat(request,opt->host);
 
253
  strcat(request,":");
 
254
  if(opt->port)
 
255
    strcat(request,opt->port);
 
256
  else
 
257
    strcat(request,"11371");
 
258
  strcat(request,opt->path);
 
259
  /* request is MAX_URL+55 bytes long - MAX_URL covers the whole URL,
 
260
     including any supplied path.  The 60 overcovers this /pks/... etc
 
261
     string plus the 8 bytes of key id */
 
262
  append_path(request,"/pks/lookup?op=get&options=mr&search=0x");
 
263
 
 
264
  /* fingerprint or long key id.  Take the last 8 characters and treat
 
265
     it like a short key id */
 
266
  if(strlen(getkey)>8)
 
267
    offset=&getkey[strlen(getkey)-8];
 
268
  else
 
269
    offset=getkey;
 
270
 
 
271
  strcat(request,offset);
 
272
 
 
273
  if(opt->verbose>2)
263
274
    fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
264
275
 
265
 
  rc=http_open_document(&hd,request,http_flags,proxy[0]?proxy:NULL);
266
 
  if(rc!=0)
 
276
  curl_easy_setopt(curl,CURLOPT_URL,request);
 
277
  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
 
278
  ctx.stream=output;
 
279
  curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
 
280
 
 
281
  res=curl_easy_perform(curl);
 
282
  if(res!=CURLE_OK)
267
283
    {
268
 
      fprintf(console,"gpgkeys: HKP fetch error: %s\n",
269
 
              rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
270
 
      fprintf(output,"KEY 0x%s FAILED %d\n",getkey,
271
 
            rc==G10ERR_NETWORK?KEYSERVER_UNREACHABLE:KEYSERVER_INTERNAL_ERROR);
 
284
      fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
 
285
      fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
272
286
    }
273
287
  else
274
288
    {
275
 
      unsigned int maxlen=1024,buflen;
276
 
      byte *line=NULL;
277
 
 
278
 
      while(iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen))
279
 
        {
280
 
          maxlen=1024;
281
 
 
282
 
          if(gotit)
283
 
            {
284
 
              fputs (line, output);
285
 
              if(strncmp(line,END,strlen(END))==0)
286
 
                break;
287
 
            }
288
 
          else
289
 
            if(strncmp(line,BEGIN,strlen(BEGIN))==0)
290
 
              {
291
 
                fputs (line,output);
292
 
                gotit=1;
293
 
              }
294
 
        }
295
 
 
296
 
      if(gotit)
297
 
        fprintf(output,"KEY 0x%s END\n",getkey);
298
 
      else
 
289
      curl_writer_finalize(&ctx);
 
290
      if(!ctx.flags.done)
299
291
        {
300
292
          fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
301
 
          fprintf(output,"KEY 0x%s FAILED %d\n",
 
293
          fprintf(output,"\nKEY 0x%s FAILED %d\n",
302
294
                  getkey,KEYSERVER_KEY_NOT_FOUND);
303
295
        }
304
 
 
305
 
      m_free(line);
 
296
      else
 
297
        fprintf(output,"\nKEY 0x%s END\n",getkey);
306
298
    }
307
299
 
308
 
  free(request);
309
 
 
310
300
  return KEYSERVER_OK;
311
301
}
312
302
 
313
 
/* Remove anything <between brackets> and de-urlencode in place.  Note
314
 
   that this requires all brackets to be closed on the same line.  It
315
 
   also means that the result is never larger than the input. */
316
 
void
317
 
dehtmlize(char *line)
318
 
{
319
 
  int parsedindex=0;
320
 
  char *parsed=line;
321
 
 
322
 
  while(*line!='\0')
323
 
    {
324
 
      switch(*line)
325
 
        {
326
 
        case '<':
327
 
          while(*line!='>' && *line!='\0')
328
 
            line++;
329
 
 
330
 
          if(*line!='\0')
331
 
            line++;
332
 
          break;
333
 
 
334
 
        case '&':
335
 
          if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='l') &&
336
 
             (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') &&
337
 
             (*(line+3)!='\0' && *(line+3)==';'))
338
 
            {
339
 
              parsed[parsedindex++]='<';
340
 
              line+=4;
341
 
              break;
342
 
            }
343
 
          else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='g') &&
344
 
                  (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') &&
345
 
                  (*(line+3)!='\0' && *(line+3)==';'))
346
 
            {
347
 
              parsed[parsedindex++]='>';
348
 
              line+=4;
349
 
              break;
350
 
            }
351
 
          else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='a') &&
352
 
                  (*(line+2)!='\0' && ascii_tolower(*(line+2))=='m') &&
353
 
                  (*(line+3)!='\0' && ascii_tolower(*(line+3))=='p') &&
354
 
                  (*(line+4)!='\0' && *(line+4)==';'))
355
 
            {
356
 
              parsed[parsedindex++]='&';
357
 
              line+=5;
358
 
              break;
359
 
            }
360
 
          else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='q') &&
361
 
                  (*(line+2)!='\0' && ascii_tolower(*(line+2))=='u') &&
362
 
                  (*(line+3)!='\0' && ascii_tolower(*(line+3))=='o') &&
363
 
                  (*(line+4)!='\0' && ascii_tolower(*(line+4))=='t') &&
364
 
                  (*(line+5)!='\0' && *(line+5)==';'))
365
 
            {
366
 
              parsed[parsedindex++]='"';
367
 
              line+=6;
368
 
              break;
369
 
            }
370
 
 
371
 
        default:
372
 
          parsed[parsedindex++]=*line;
373
 
          line++;
374
 
          break;
375
 
        }
376
 
    }
377
 
 
378
 
  parsed[parsedindex]='\0';
379
 
 
380
 
  /* Chop off any trailing whitespace.  Note that the HKP servers have
381
 
     \r\n as line endings, and the NAI HKP servers have just \n. */
382
 
 
383
 
  if(parsedindex>0)
384
 
    {
385
 
      parsedindex--;
386
 
      while(isspace(((unsigned char *)parsed)[parsedindex]))
387
 
        {
388
 
          parsed[parsedindex]='\0';
389
 
          if(parsedindex==0)
390
 
            break;
391
 
          parsedindex--;
392
 
        }
393
 
    }
394
 
}
395
 
 
396
 
int
397
 
write_quoted(IOBUF a, const char *buf, char delim)
398
 
{
399
 
  while(*buf)
400
 
    {
401
 
      if(*buf==delim)
402
 
        {
403
 
          char quoted[5];
404
 
          sprintf(quoted,"%%%02X",delim);
405
 
          if(iobuf_writestr(a,quoted))
406
 
            return -1;
407
 
        }
408
 
      else if(*buf=='%')
409
 
        {
410
 
          if(iobuf_writestr(a,"%25"))
411
 
            return -1;
 
303
static int
 
304
get_name(const char *getkey)
 
305
{
 
306
  CURLcode res;
 
307
  char *request=NULL;
 
308
  char *searchkey_encoded;
 
309
  int ret=KEYSERVER_INTERNAL_ERROR;
 
310
  struct curl_writer_ctx ctx;
 
311
 
 
312
  memset(&ctx,0,sizeof(ctx));
 
313
 
 
314
  searchkey_encoded=curl_escape((char *)getkey,0);
 
315
  if(!searchkey_encoded)
 
316
    {
 
317
      fprintf(console,"gpgkeys: out of memory\n");
 
318
      ret=KEYSERVER_NO_MEMORY;
 
319
      goto fail;
 
320
    }
 
321
 
 
322
  request=malloc(MAX_URL+60+strlen(searchkey_encoded));
 
323
  if(!request)
 
324
    {
 
325
      fprintf(console,"gpgkeys: out of memory\n");
 
326
      ret=KEYSERVER_NO_MEMORY;
 
327
      goto fail;
 
328
    }
 
329
 
 
330
  fprintf(output,"NAME %s BEGIN\n",getkey);
 
331
 
 
332
  strcpy(request,"http://");
 
333
  strcat(request,opt->host);
 
334
  strcat(request,":");
 
335
  if(opt->port)
 
336
    strcat(request,opt->port);
 
337
  else
 
338
    strcat(request,"11371");
 
339
  strcat(request,opt->path);
 
340
  append_path(request,"/pks/lookup?op=get&options=mr&search=");
 
341
  strcat(request,searchkey_encoded);
 
342
 
 
343
  if(opt->action==KS_GETNAME)
 
344
    strcat(request,"&exact=on");
 
345
 
 
346
  if(opt->verbose>2)
 
347
    fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
 
348
 
 
349
  curl_easy_setopt(curl,CURLOPT_URL,request);
 
350
  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
 
351
  ctx.stream=output;
 
352
  curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
 
353
 
 
354
  res=curl_easy_perform(curl);
 
355
  if(res!=CURLE_OK)
 
356
    {
 
357
      fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
 
358
      ret=curl_err_to_gpg_err(res);
 
359
    }
 
360
  else
 
361
    {
 
362
      curl_writer_finalize(&ctx);
 
363
      if(!ctx.flags.done)
 
364
        {
 
365
          fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
 
366
          ret=KEYSERVER_KEY_NOT_FOUND;
412
367
        }
413
368
      else
414
369
        {
415
 
          if(iobuf_writebyte(a,*buf))
416
 
            return -1;
417
 
        }
418
 
 
419
 
      buf++;
420
 
    }
421
 
 
422
 
  return 0;
423
 
}
424
 
 
425
 
/* 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; */
426
 
 
427
 
/* Luckily enough, both the HKP server and NAI HKP interface to their
428
 
   LDAP server are close enough in output so the same function can
429
 
   parse them both. */
430
 
 
431
 
int
432
 
parse_hkp_index(IOBUF buffer,char *line)
433
 
{
434
 
  int ret=0;
435
 
 
436
 
  /* printf("Open %d, LINE: `%s'\n",open,line); */
437
 
 
438
 
  dehtmlize(line);
439
 
 
440
 
  /* printf("Now open %d, LINE: `%s'\n",open,line); */
441
 
 
442
 
  if(line[0]=='\0')
443
 
    return 0;
444
 
  else if(ascii_strncasecmp(line,"pub",3)==0)
445
 
    {
446
 
      char *tok,*keyid,*uid=NULL,number[15];
447
 
      int bits=0,type=0,disabled=0,revoked=0;
448
 
      u32 createtime=0;
449
 
 
450
 
      line+=3;
451
 
 
452
 
      if(*line=='-')
453
 
        {
454
 
          disabled=1;
455
 
          if(!include_disabled)
456
 
            return 0;
457
 
        }
458
 
 
459
 
      line++;
460
 
 
461
 
      tok=strsep(&line,"/");
462
 
      if(tok==NULL || strlen(tok)==0)
463
 
        return ret;
464
 
 
465
 
      if(tok[strlen(tok)-1]=='R')
466
 
        type=1;
467
 
      else if(tok[strlen(tok)-1]=='D')
468
 
        type=17;
469
 
 
470
 
      bits=atoi(tok);
471
 
 
472
 
      keyid=strsep(&line," ");
473
 
 
474
 
      tok=strsep(&line," ");
475
 
      if(tok!=NULL)
476
 
        {
477
 
          char *temp=tok;
478
 
 
479
 
          /* The date parser wants '-' instead of '/', so... */
480
 
          while(*temp!='\0')
481
 
            {
482
 
              if(*temp=='/')
483
 
                *temp='-';
484
 
 
485
 
              temp++;
486
 
            }
487
 
 
488
 
          createtime=scan_isodatestr(tok);
489
 
        }
490
 
 
491
 
      if(line!=NULL)
492
 
        {
493
 
          while(*line==' ' && *line!='\0')
494
 
            line++;
495
 
 
496
 
          if(*line!='\0')
497
 
            {
498
 
              if(strncmp(line,"*** KEY REVOKED ***",19)==0)
499
 
                {
500
 
                  revoked=1;
501
 
                  if(!include_revoked)
502
 
                    return 0;
503
 
                }
504
 
              else
505
 
                uid=line;
506
 
            }
507
 
        }
508
 
 
509
 
      if(keyid)
510
 
        {
511
 
          iobuf_writestr(buffer,"pub:");
512
 
 
513
 
          write_quoted(buffer,keyid,':');
514
 
 
515
 
          iobuf_writestr(buffer,":");
516
 
 
517
 
          if(type)
518
 
            {
519
 
              sprintf(number,"%d",type);
520
 
              write_quoted(buffer,number,':');
521
 
            }
522
 
 
523
 
          iobuf_writestr(buffer,":");
524
 
 
525
 
          if(bits)
526
 
            {
527
 
              sprintf(number,"%d",bits);
528
 
              write_quoted(buffer,number,':');
529
 
            }
530
 
 
531
 
          iobuf_writestr(buffer,":");
532
 
 
533
 
          if(createtime)
534
 
            {
535
 
              sprintf(number,"%d",createtime);
536
 
              write_quoted(buffer,number,':');
537
 
            }
538
 
 
539
 
          iobuf_writestr(buffer,"::");
540
 
 
541
 
          if(revoked)
542
 
            write_quoted(buffer,"r",':');
543
 
 
544
 
          if(disabled)
545
 
            write_quoted(buffer,"d",':');
546
 
 
547
 
          if(uid)
548
 
            {
549
 
              iobuf_writestr(buffer,"\nuid:");
550
 
              write_quoted(buffer,uid,':');
551
 
            }
552
 
 
553
 
          iobuf_writestr(buffer,"\n");
554
 
 
555
 
          ret=1;
556
 
        }
557
 
    }
558
 
  else if(ascii_strncasecmp(line,"   ",3)==0)
559
 
    {
560
 
      while(*line==' ' && *line!='\0')
561
 
        line++;
562
 
 
563
 
      if(*line!='\0')
564
 
        {
565
 
          iobuf_writestr(buffer,"uid:");
566
 
          write_quoted(buffer,line,':');
567
 
          iobuf_writestr(buffer,"\n");
568
 
        }
569
 
    }
570
 
 
571
 
#if 0
572
 
  else if(open)
573
 
    {
574
 
      /* Try and catch some bastardization of HKP.  If we don't have
575
 
         certain unchanging landmarks, we can't reliably parse the
576
 
         response.  This only complains about problems within the key
577
 
         section itself.  Headers and footers should not matter. */
578
 
 
579
 
      fprintf(console,"gpgkeys: this keyserver does not support searching\n");
580
 
      ret=-1;
581
 
    }
582
 
#endif
 
370
          fprintf(output,"\nNAME %s END\n",getkey);
 
371
          ret=KEYSERVER_OK;
 
372
        }
 
373
    }
 
374
 
 
375
 fail:
 
376
  curl_free(searchkey_encoded);
 
377
  free(request);
 
378
 
 
379
  if(ret!=KEYSERVER_OK)
 
380
    fprintf(output,"\nNAME %s FAILED %d\n",getkey,ret);
583
381
 
584
382
  return ret;
585
383
}
586
384
 
587
 
void
588
 
handle_old_hkp_index(IOBUF inp)
589
 
{
590
 
  int ret,rc,count=0;
591
 
  unsigned int buflen;
592
 
  byte *line=NULL;
593
 
  IOBUF buffer=iobuf_temp();
594
 
 
595
 
  do
596
 
    {
597
 
      unsigned int maxlen=1024;
598
 
 
599
 
      /* This is a judgement call.  Is it better to slurp up all the
600
 
         results before prompting the user?  On the one hand, it
601
 
         probably makes the keyserver happier to not be blocked on
602
 
         sending for a long time while the user picks a key.  On the
603
 
         other hand, it might be nice for the server to be able to
604
 
         stop sending before a large search result page is
605
 
         complete. */
606
 
 
607
 
      rc=iobuf_read_line(inp,&line,&buflen,&maxlen);
608
 
 
609
 
      ret=parse_hkp_index(buffer,line);
610
 
      if(ret==-1)
611
 
        break;
612
 
 
613
 
      if(rc!=0)
614
 
        count+=ret;
615
 
    }
616
 
  while(rc!=0);
617
 
 
618
 
  m_free(line);
619
 
 
620
 
  if(ret>-1)
621
 
    fprintf(output,"info:1:%d\n%s",count,iobuf_get_temp_buffer(buffer));
622
 
 
623
 
  iobuf_close(buffer);
624
 
}
625
 
 
626
 
int
627
 
search_key(char *searchkey)
628
 
{
629
 
  int max=0,len=0,ret=KEYSERVER_INTERNAL_ERROR,rc;
630
 
  struct http_context hd;
631
 
  char *search=NULL,*request=NULL;
632
 
  unsigned char *skey=(unsigned char*) searchkey;
 
385
static int
 
386
search_key(const char *searchkey)
 
387
{
 
388
  CURLcode res;
 
389
  char *request=NULL;
 
390
  char *searchkey_encoded;
 
391
  int ret=KEYSERVER_INTERNAL_ERROR;
 
392
  enum ks_search_type search_type;
 
393
 
 
394
  search_type=classify_ks_search(&searchkey);
 
395
 
 
396
  if(opt->debug)
 
397
    fprintf(console,"gpgkeys: search type is %d, and key is \"%s\"\n",
 
398
            search_type,searchkey);
 
399
 
 
400
  searchkey_encoded=curl_escape((char *)searchkey,0);
 
401
  if(!searchkey_encoded)
 
402
    {
 
403
      fprintf(console,"gpgkeys: out of memory\n");
 
404
      ret=KEYSERVER_NO_MEMORY;
 
405
      goto fail;
 
406
    }
 
407
 
 
408
  request=malloc(MAX_URL+60+strlen(searchkey_encoded));
 
409
  if(!request)
 
410
    {
 
411
      fprintf(console,"gpgkeys: out of memory\n");
 
412
      ret=KEYSERVER_NO_MEMORY;
 
413
      goto fail;
 
414
    }
633
415
 
634
416
  fprintf(output,"SEARCH %s BEGIN\n",searchkey);
635
417
 
636
 
  /* Build the search string.  It's going to need url-encoding. */
637
 
 
638
 
  while(*skey!='\0')
639
 
    {
640
 
      if(max-len<3)
641
 
        {
642
 
          max+=100;
643
 
          search=realloc(search,max+1); /* Note +1 for \0 */
644
 
          if (!search)
645
 
            {
646
 
              fprintf(console,"gpgkeys: out of memory\n");
647
 
              ret=KEYSERVER_NO_MEMORY;
648
 
              goto fail;
649
 
            }
650
 
        }
651
 
 
652
 
      if(isalnum(*skey) || *skey=='-')
653
 
        search[len++]=*skey;
654
 
      else if(*skey==' ')
655
 
        search[len++]='+';
656
 
      else
657
 
        {
658
 
          sprintf(&search[len],"%%%02X",*skey);
659
 
          len+=3;
660
 
        }
661
 
 
662
 
      skey++;
663
 
    }
664
 
 
665
 
  if(!search)
666
 
    {
667
 
      fprintf(console,"gpgkeys: corrupt input?\n");
668
 
      return -1;
669
 
    }
670
 
 
671
 
  search[len]='\0';
672
 
 
673
 
  request=malloc(strlen(host)+100+strlen(search));
674
 
  if(!request)
675
 
    {
676
 
      fprintf(console,"gpgkeys: out of memory\n");
677
 
      ret=KEYSERVER_NO_MEMORY;
678
 
      goto fail;
679
 
    }
680
 
 
681
 
  sprintf(request,"hkp://%s%s%s/pks/lookup?op=index&options=mr&search=%s",
682
 
          host,port[0]?":":"",port[0]?port:"",search);
683
 
 
684
 
  if(verbose>2)
 
418
  strcpy(request,"http://");
 
419
  strcat(request,opt->host);
 
420
  strcat(request,":");
 
421
  if(opt->port)
 
422
    strcat(request,opt->port);
 
423
  else
 
424
    strcat(request,"11371");
 
425
  strcat(request,opt->path);
 
426
  append_path(request,"/pks/lookup?op=index&options=mr&search=");
 
427
 
 
428
  /* HKP keyservers like the 0x to be present when searching by
 
429
     keyid */
 
430
  if(search_type==KS_SEARCH_KEYID_SHORT || search_type==KS_SEARCH_KEYID_LONG)
 
431
    strcat(request,"0x");
 
432
 
 
433
  strcat(request,searchkey_encoded);
 
434
 
 
435
  if(search_type!=KS_SEARCH_SUBSTR)
 
436
    strcat(request,"&exact=on");
 
437
 
 
438
  if(opt->verbose>2)
685
439
    fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
686
440
 
687
 
  rc=http_open_document(&hd,request,http_flags,proxy[0]?proxy:NULL);
688
 
  if(rc)
 
441
  curl_easy_setopt(curl,CURLOPT_URL,request);
 
442
  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_mrindex_writer);
 
443
  curl_easy_setopt(curl,CURLOPT_FILE,output);
 
444
 
 
445
  res=curl_easy_perform(curl);
 
446
  if(res!=0)
689
447
    {
690
 
      fprintf(console,"gpgkeys: can't search keyserver `%s': %s\n",
691
 
              host,rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
 
448
      fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer);
 
449
      ret=curl_err_to_gpg_err(res);
692
450
    }
693
451
  else
694
452
    {
695
 
      unsigned int maxlen=1024,buflen;
696
 
      byte *line=NULL;
697
 
 
698
 
      /* Is it a pksd that knows how to handle machine-readable
699
 
         format? */
700
 
 
701
 
      rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
702
 
      if(line[0]=='<')
703
 
        handle_old_hkp_index(hd.fp_read);
704
 
      else
705
 
        do
706
 
          {
707
 
            fprintf(output,"%s",line);
708
 
            maxlen=1024;
709
 
            rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
710
 
          }
711
 
        while(rc!=0);
712
 
 
713
 
      m_free(line);
714
 
 
715
 
      http_close(&hd);
716
 
 
717
 
      fprintf(output,"SEARCH %s END\n",searchkey);
718
 
 
 
453
      fprintf(output,"\nSEARCH %s END\n",searchkey);
719
454
      ret=KEYSERVER_OK;
720
455
    }
721
456
 
722
457
 fail:
723
458
 
 
459
  curl_free(searchkey_encoded);
724
460
  free(request);
725
 
  free(search);
726
461
 
727
462
  if(ret!=KEYSERVER_OK)
728
 
    fprintf(output,"SEARCH %s FAILED %d\n",searchkey,ret);
 
463
    fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret);
729
464
 
730
465
  return ret;
731
466
}
732
467
 
733
468
void
734
 
fail_all(struct keylist *keylist,int action,int err)
 
469
fail_all(struct keylist *keylist,int err)
735
470
{
736
471
  if(!keylist)
737
472
    return;
738
473
 
739
 
  if(action==SEARCH)
 
474
  if(opt->action==KS_SEARCH)
740
475
    {
741
476
      fprintf(output,"SEARCH ");
742
477
      while(keylist)
765
500
int
766
501
main(int argc,char *argv[])
767
502
{
768
 
  int arg,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
 
503
  int arg,ret=KEYSERVER_INTERNAL_ERROR;
769
504
  char line[MAX_LINE];
770
505
  int failed=0;
771
506
  struct keylist *keylist=NULL,*keyptr=NULL;
772
 
  unsigned int timeout=DEFAULT_KEYSERVER_TIMEOUT;
 
507
  char *proxy=NULL;
773
508
 
774
509
  console=stderr;
775
510
 
776
511
  /* Kludge to implement standard GNU options.  */
777
512
  if (argc > 1 && !strcmp (argv[1], "--version"))
778
513
    {
779
 
      fputs ("gpgkeys_ldap (GnuPG) " VERSION"\n", stdout);
 
514
      fputs ("gpgkeys_hkp (GnuPG) " VERSION"\n", stdout);
780
515
      return 0;
781
516
    }
782
517
  else if (argc > 1 && !strcmp (argv[1], "--help"))
826
561
  if(output==NULL)
827
562
    output=stdout;
828
563
 
 
564
  opt=init_ks_options();
 
565
  if(!opt)
 
566
    return KEYSERVER_NO_MEMORY;
 
567
 
829
568
  /* Get the command and info block */
830
569
 
831
570
  while(fgets(line,MAX_LINE,input)!=NULL)
832
571
    {
833
 
      int version;
834
 
      char commandstr[7];
835
 
      char optionstr[110];
836
 
      char hash;
 
572
      int err;
 
573
      char option[MAX_OPTION+1];
837
574
 
838
575
      if(line[0]=='\n')
839
576
        break;
840
577
 
841
 
      if(sscanf(line,"%c",&hash)==1 && hash=='#')
 
578
      err=parse_ks_options(line,opt);
 
579
      if(err>0)
 
580
        {
 
581
          ret=err;
 
582
          goto fail;
 
583
        }
 
584
      else if(err==0)
842
585
        continue;
843
586
 
844
 
      if(sscanf(line,"COMMAND %6s\n",commandstr)==1)
845
 
        {
846
 
          commandstr[6]='\0';
847
 
 
848
 
          if(strcasecmp(commandstr,"get")==0)
849
 
            action=GET;
850
 
          else if(strcasecmp(commandstr,"send")==0)
851
 
            action=SEND;
852
 
          else if(strcasecmp(commandstr,"search")==0)
853
 
            action=SEARCH;
854
 
 
855
 
          continue;
856
 
        }
857
 
 
858
 
      if(sscanf(line,"HOST %79s\n",host)==1)
859
 
        {
860
 
          host[79]='\0';
861
 
          continue;
862
 
        }
863
 
 
864
 
      if(sscanf(line,"PORT %9s\n",port)==1)
865
 
        {
866
 
          port[9]='\0';
867
 
          continue;
868
 
        }
869
 
 
870
 
      if(sscanf(line,"VERSION %d\n",&version)==1)
871
 
        {
872
 
          if(version!=KEYSERVER_PROTO_VERSION)
873
 
            {
874
 
              ret=KEYSERVER_VERSION_ERROR;
875
 
              goto fail;
876
 
            }
877
 
 
878
 
          continue;
879
 
        }
880
 
 
881
 
      if(sscanf(line,"OPTION %109s\n",optionstr)==1)
 
587
      if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
882
588
        {
883
589
          int no=0;
884
 
          char *start=&optionstr[0];
885
 
 
886
 
          optionstr[109]='\0';
887
 
 
888
 
          if(strncasecmp(optionstr,"no-",3)==0)
 
590
          char *start=&option[0];
 
591
 
 
592
          option[MAX_OPTION]='\0';
 
593
 
 
594
          if(strncasecmp(option,"no-",3)==0)
889
595
            {
890
596
              no=1;
891
 
              start=&optionstr[3];
 
597
              start=&option[3];
892
598
            }
893
599
 
894
 
          if(strcasecmp(start,"verbose")==0)
895
 
            {
896
 
              if(no)
897
 
                verbose--;
898
 
              else
899
 
                verbose++;
900
 
            }
901
 
          else if(strcasecmp(start,"include-revoked")==0)
902
 
            {
903
 
              if(no)
904
 
                include_revoked=0;
905
 
              else
906
 
                include_revoked=1;
907
 
            }
908
 
          else if(strcasecmp(start,"include-disabled")==0)
909
 
            {
910
 
              if(no)
911
 
                include_disabled=0;
912
 
              else
913
 
                include_disabled=1;
914
 
            }
915
 
          else if(strncasecmp(start,"http-proxy",10)==0)
916
 
            {
917
 
              if(no)
918
 
                proxy[0]='\0';
 
600
          if(strncasecmp(start,"http-proxy",10)==0)
 
601
            {
 
602
              if(no)
 
603
                {
 
604
                  free(proxy);
 
605
                  proxy=strdup("");
 
606
                }
919
607
              else if(start[10]=='=')
920
608
                {
921
 
                  strncpy(proxy,&start[11],79);
922
 
                  proxy[79]='\0';
923
 
                }
924
 
              else if(start[10]=='\0')
925
 
                {
926
 
                  char *http_proxy=getenv(HTTP_PROXY_ENV);
927
 
                  if(http_proxy)
 
609
                  if(strlen(&start[11])<MAX_PROXY)
928
610
                    {
929
 
                      strncpy(proxy,http_proxy,79);
930
 
                      proxy[79]='\0';
 
611
                      free(proxy);
 
612
                      proxy=strdup(&start[11]);
931
613
                    }
932
614
                }
933
615
            }
934
 
          else if(strcasecmp(start,"broken-http-proxy")==0)
935
 
            {
936
 
              if(no)
937
 
                http_flags&=~HTTP_FLAG_NO_SHUTDOWN;
938
 
              else
939
 
                http_flags|=HTTP_FLAG_NO_SHUTDOWN;
940
 
            }
 
616
#if 0
941
617
          else if(strcasecmp(start,"try-dns-srv")==0)
942
618
            {
943
619
              if(no)
945
621
              else
946
622
                http_flags|=HTTP_FLAG_TRY_SRV;
947
623
            }
948
 
          else if(strncasecmp(start,"timeout",7)==0)
949
 
            {
950
 
              if(no)
951
 
                timeout=0;
952
 
              else if(start[7]=='=')
953
 
                timeout=atoi(&start[8]);
954
 
              else if(start[7]=='\0')
955
 
                timeout=DEFAULT_KEYSERVER_TIMEOUT;
956
 
            }
957
 
 
 
624
#endif
958
625
          continue;
959
626
        }
960
627
    }
961
628
 
962
 
  if(timeout && register_timeout()==-1)
 
629
  if(!opt->host)
 
630
    {
 
631
      fprintf(console,"gpgkeys: no keyserver host provided\n");
 
632
      goto fail;
 
633
    }
 
634
 
 
635
  if(opt->timeout && register_timeout()==-1)
963
636
    {
964
637
      fprintf(console,"gpgkeys: unable to register timeout handler\n");
965
638
      return KEYSERVER_INTERNAL_ERROR;
966
639
    }
967
640
 
 
641
  curl_global_init(CURL_GLOBAL_DEFAULT);
 
642
  curl=curl_easy_init();
 
643
  if(!curl)
 
644
    {
 
645
      fprintf(console,"gpgkeys: unable to initialize curl\n");
 
646
      ret=KEYSERVER_INTERNAL_ERROR;
 
647
      goto fail;
 
648
    }
 
649
 
 
650
  curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
 
651
 
 
652
  if(opt->auth)
 
653
    curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
 
654
 
 
655
  if(opt->debug)
 
656
    {
 
657
      fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
 
658
      curl_easy_setopt(curl,CURLOPT_STDERR,console);
 
659
      curl_easy_setopt(curl,CURLOPT_VERBOSE,1L);
 
660
    }
 
661
 
 
662
  if(proxy)
 
663
    curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
 
664
 
 
665
#if 0
968
666
  /* By suggested convention, if the user gives a :port, then disable
969
667
     SRV. */
970
 
  if(port[0])
 
668
  if(opt->port)
971
669
    http_flags&=~HTTP_FLAG_TRY_SRV;
 
670
#endif
972
671
 
973
672
  /* If it's a GET or a SEARCH, the next thing to come in is the
974
673
     keyids.  If it's a SEND, then there are no keyids. */
975
674
 
976
 
  if(action==SEND)
 
675
  if(opt->action==KS_SEND)
977
676
    while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
978
 
  else if(action==GET || action==SEARCH)
 
677
  else if(opt->action==KS_GET
 
678
          || opt->action==KS_GETNAME || opt->action==KS_SEARCH)
979
679
    {
980
680
      for(;;)
981
681
        {
1026
726
  fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
1027
727
  fprintf(output,"PROGRAM %s\n\n",VERSION);
1028
728
 
1029
 
  if(verbose>1)
1030
 
    {
1031
 
      fprintf(console,"Host:\t\t%s\n",host);
1032
 
      if(port[0])
1033
 
        fprintf(console,"Port:\t\t%s\n",port);
1034
 
      fprintf(console,"Command:\t%s\n",action==GET?"GET":
1035
 
              action==SEND?"SEND":"SEARCH");
1036
 
    }
1037
 
 
1038
 
#if 0
1039
 
  if(verbose>1)
1040
 
    {
1041
 
      vals=ldap_get_values(ldap,res,"software");
1042
 
      if(vals!=NULL)
1043
 
        {
1044
 
          fprintf(console,"Server: \t%s\n",vals[0]);
1045
 
          ldap_value_free(vals);
1046
 
        }
1047
 
 
1048
 
      vals=ldap_get_values(ldap,res,"version");
1049
 
      if(vals!=NULL)
1050
 
        {
1051
 
          fprintf(console,"Version:\t%s\n",vals[0]);
1052
 
          ldap_value_free(vals);
1053
 
        }
1054
 
    }
1055
 
#endif
1056
 
 
1057
 
  switch(action)
1058
 
    {
1059
 
    case GET:
 
729
  if(opt->verbose>1)
 
730
    {
 
731
      fprintf(console,"Host:\t\t%s\n",opt->host);
 
732
      if(opt->port)
 
733
        fprintf(console,"Port:\t\t%s\n",opt->port);
 
734
      if(strcmp(opt->path,"/")!=0)
 
735
        fprintf(console,"Path:\t\t%s\n",opt->path);
 
736
      fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action));
 
737
    }
 
738
 
 
739
  if(opt->action==KS_GET)
 
740
    {
1060
741
      keyptr=keylist;
1061
742
 
1062
743
      while(keyptr!=NULL)
1063
744
        {
1064
 
          set_timeout(timeout);
 
745
          set_timeout(opt->timeout);
1065
746
 
1066
747
          if(get_key(keyptr->str)!=KEYSERVER_OK)
1067
748
            failed++;
1068
749
 
1069
750
          keyptr=keyptr->next;
1070
751
        }
1071
 
      break;
1072
 
 
1073
 
    case SEND:
1074
 
      {
1075
 
        int eof=0;
1076
 
 
1077
 
        do
1078
 
          {
1079
 
            set_timeout(timeout);
1080
 
 
1081
 
            if(send_key(&eof)!=KEYSERVER_OK)
1082
 
              failed++;
1083
 
          }
1084
 
        while(!eof);
1085
 
      }
1086
 
      break;
1087
 
 
1088
 
    case SEARCH:
1089
 
      {
1090
 
        char *searchkey=NULL;
1091
 
        int len=0;
1092
 
 
1093
 
        set_timeout(timeout);
1094
 
 
1095
 
        /* To search, we stick a space in between each key to search
1096
 
           for. */
1097
 
 
1098
 
        keyptr=keylist;
1099
 
        while(keyptr!=NULL)
1100
 
          {
1101
 
            len+=strlen(keyptr->str)+1;
1102
 
            keyptr=keyptr->next;
1103
 
          }
1104
 
 
1105
 
        searchkey=malloc(len+1);
1106
 
        if(searchkey==NULL)
1107
 
          {
1108
 
            ret=KEYSERVER_NO_MEMORY;
1109
 
            fail_all(keylist,action,KEYSERVER_NO_MEMORY);
1110
 
            goto fail;
1111
 
          }
1112
 
 
1113
 
        searchkey[0]='\0';
1114
 
 
1115
 
        keyptr=keylist;
1116
 
        while(keyptr!=NULL)
1117
 
          {
1118
 
            strcat(searchkey,keyptr->str);
1119
 
            strcat(searchkey," ");
1120
 
            keyptr=keyptr->next;
1121
 
          }
1122
 
 
1123
 
        /* Nail that last space */
1124
 
        if(*searchkey)
1125
 
          searchkey[strlen(searchkey)-1]='\0';
1126
 
 
1127
 
        if(search_key(searchkey)!=KEYSERVER_OK)
1128
 
          failed++;
1129
 
 
1130
 
        free(searchkey);
1131
 
      }
1132
 
 
1133
 
      break;
1134
 
    }
 
752
    }
 
753
  else if(opt->action==KS_GETNAME)
 
754
    {
 
755
      keyptr=keylist;
 
756
 
 
757
      while(keyptr!=NULL)
 
758
        {
 
759
          set_timeout(opt->timeout);
 
760
 
 
761
          if(get_name(keyptr->str)!=KEYSERVER_OK)
 
762
            failed++;
 
763
 
 
764
          keyptr=keyptr->next;
 
765
        }
 
766
    }
 
767
  else if(opt->action==KS_SEND)
 
768
    {
 
769
      int myeof=0;
 
770
 
 
771
      do
 
772
        {
 
773
          set_timeout(opt->timeout);
 
774
 
 
775
          if(send_key(&myeof)!=KEYSERVER_OK)
 
776
            failed++;
 
777
        }
 
778
      while(!myeof);
 
779
    }
 
780
  else if(opt->action==KS_SEARCH)
 
781
    {
 
782
      char *searchkey=NULL;
 
783
      int len=0;
 
784
 
 
785
      set_timeout(opt->timeout);
 
786
 
 
787
      /* To search, we stick a space in between each key to search
 
788
         for. */
 
789
 
 
790
      keyptr=keylist;
 
791
      while(keyptr!=NULL)
 
792
        {
 
793
          len+=strlen(keyptr->str)+1;
 
794
          keyptr=keyptr->next;
 
795
        }
 
796
 
 
797
      searchkey=malloc(len+1);
 
798
      if(searchkey==NULL)
 
799
        {
 
800
          ret=KEYSERVER_NO_MEMORY;
 
801
          fail_all(keylist,KEYSERVER_NO_MEMORY);
 
802
          goto fail;
 
803
        }
 
804
 
 
805
      searchkey[0]='\0';
 
806
 
 
807
      keyptr=keylist;
 
808
      while(keyptr!=NULL)
 
809
        {
 
810
          strcat(searchkey,keyptr->str);
 
811
          strcat(searchkey," ");
 
812
          keyptr=keyptr->next;
 
813
        }
 
814
 
 
815
      /* Nail that last space */
 
816
      if(*searchkey)
 
817
        searchkey[strlen(searchkey)-1]='\0';
 
818
 
 
819
      if(search_key(searchkey)!=KEYSERVER_OK)
 
820
        failed++;
 
821
 
 
822
      free(searchkey);
 
823
    }
 
824
  else
 
825
    abort();
1135
826
 
1136
827
  if(!failed)
1137
828
    ret=KEYSERVER_OK;
1150
841
  if(output!=stdout)
1151
842
    fclose(output);
1152
843
 
 
844
  free_ks_options(opt);
 
845
 
 
846
  if(curl)
 
847
    curl_easy_cleanup(curl);
 
848
 
 
849
  free(proxy);
 
850
 
1153
851
  return ret;
1154
852
}