~ubuntu-branches/ubuntu/hardy/gnupg/hardy-updates

« back to all changes in this revision

Viewing changes to keyserver/gpgkeys_curl.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-12-16 16:57:39 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20051216165739-v0m2d1you6hd8jho
Tags: upstream-1.4.2
ImportĀ upstreamĀ versionĀ 1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
16
16
 * You should have received a copy of the GNU General Public License
17
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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
19
 * USA.
19
20
 */
20
21
 
21
22
#include <config.h>
38
39
extern char *optarg;
39
40
extern int optind;
40
41
 
41
 
static int verbose=0;
42
 
static char scheme[MAX_SCHEME+1];
43
 
static char auth[MAX_AUTH+1];
44
 
static char host[MAX_HOST+1];
45
 
static char port[MAX_PORT+1];
46
 
static char path[URLMAX_PATH+1];
47
 
static char proxy[MAX_PROXY+1];
48
 
static FILE *input, *output, *console;
 
42
static FILE *input,*output,*console;
49
43
static CURL *curl;
50
 
static char request[MAX_URL];
51
 
 
52
 
static int
53
 
curl_err_to_gpg_err(CURLcode error)
54
 
{
55
 
  switch(error)
56
 
    {
57
 
    case CURLE_FTP_COULDNT_RETR_FILE: return KEYSERVER_KEY_NOT_FOUND;
58
 
    default: return KEYSERVER_INTERNAL_ERROR;
59
 
    }
60
 
}
61
 
 
62
 
static size_t
63
 
writer(const void *ptr,size_t size,size_t nmemb,void *stream)
64
 
{
65
 
  const char *buf=ptr;
66
 
  size_t i;
67
 
  static int markeridx=0,begun=0,done=0;
68
 
  static const char *marker=BEGIN;
69
 
 
70
 
  /* scan the incoming data for our marker */
71
 
  for(i=0;!done && i<(size*nmemb);i++)
72
 
    {
73
 
      if(buf[i]==marker[markeridx])
74
 
        {
75
 
          markeridx++;
76
 
          if(marker[markeridx]=='\0')
77
 
            {
78
 
              if(begun)
79
 
                done=1;
80
 
              else
81
 
                {
82
 
                  /* We've found the BEGIN marker, so now we're looking
83
 
                     for the END marker. */
84
 
                  begun=1;
85
 
                  marker=END;
86
 
                  markeridx=0;
87
 
                  fprintf(output,BEGIN);
88
 
                  continue;
89
 
                }
90
 
            }
91
 
        }
92
 
      else
93
 
        markeridx=0;
94
 
 
95
 
      if(begun)
96
 
        {
97
 
          /* Canonicalize CRLF to just LF by stripping CRs.  This
98
 
             actually makes sense, since on Unix-like machines LF is
99
 
             correct, and on win32-like machines, our output buffer is
100
 
             opened in textmode and will re-canonicalize line endings
101
 
             back to CRLF.  Since we only need to handle armored keys,
102
 
             we don't have to worry about odd cases like CRCRCR and
103
 
             the like. */
104
 
 
105
 
          if(buf[i]!='\r')
106
 
            fputc(buf[i],output);
107
 
        }
108
 
    }
109
 
 
110
 
  return size*nmemb;
111
 
}
 
44
static struct ks_options *opt;
112
45
 
113
46
static int
114
47
get_key(char *getkey)
115
48
{
116
49
  CURLcode res;
117
50
  char errorbuffer[CURL_ERROR_SIZE];
 
51
  char request[MAX_URL];
 
52
  struct curl_writer_ctx ctx;
 
53
 
 
54
  memset(&ctx,0,sizeof(ctx));
118
55
 
119
56
  if(strncmp(getkey,"0x",2)==0)
120
57
    getkey+=2;
121
58
 
122
59
  fprintf(output,"KEY 0x%s BEGIN\n",getkey);
123
60
 
124
 
  sprintf(request,"%s://%s%s%s%s%s%s%s",scheme,auth[0]?auth:"",auth[0]?"@":"",
125
 
          host,port[0]?":":"",port[0]?port:"",path[0]?"":"/",path);
 
61
  sprintf(request,"%s://%s%s%s%s",opt->scheme,opt->host,
 
62
          opt->port?":":"",opt->port?opt->port:"",opt->path?opt->path:"/");
126
63
 
127
64
  curl_easy_setopt(curl,CURLOPT_URL,request);
128
 
  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,writer);
129
 
  curl_easy_setopt(curl,CURLOPT_FILE,output);
 
65
  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
 
66
  ctx.stream=output;
 
67
  curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
130
68
  curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
131
69
 
132
70
  res=curl_easy_perform(curl);
133
 
  if(res!=0)
 
71
  if(res!=CURLE_OK)
134
72
    {
135
 
      fprintf(console,"gpgkeys: %s fetch error %d: %s\n",scheme,
 
73
      fprintf(console,"gpgkeys: %s fetch error %d: %s\n",opt->scheme,
136
74
              res,errorbuffer);
137
75
      fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
138
76
    }
139
77
  else
140
78
    fprintf(output,"\nKEY 0x%s END\n",getkey);
141
79
 
142
 
  return KEYSERVER_OK;
 
80
  return curl_err_to_gpg_err(res);
143
81
}
144
82
 
145
83
static void 
153
91
int
154
92
main(int argc,char *argv[])
155
93
{
156
 
  int arg,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
 
94
  int arg,ret=KEYSERVER_INTERNAL_ERROR;
157
95
  char line[MAX_LINE];
158
96
  char *thekey=NULL;
159
 
  unsigned int timeout=DEFAULT_KEYSERVER_TIMEOUT;
160
 
  long follow_redirects=5,debug=0,check_cert=1;
161
 
  char *ca_cert_file=NULL;
 
97
  long follow_redirects=5;
 
98
  char *proxy=NULL;
162
99
 
163
100
  console=stderr;
164
101
 
215
152
  if(output==NULL)
216
153
    output=stdout;
217
154
 
 
155
  opt=init_ks_options();
 
156
  if(!opt)
 
157
    return KEYSERVER_NO_MEMORY;
 
158
 
218
159
  /* Get the command and info block */
219
160
 
220
161
  while(fgets(line,MAX_LINE,input)!=NULL)
221
162
    {
222
 
      int version;
223
 
      char command[MAX_COMMAND+1];
 
163
      int err;
224
164
      char option[MAX_OPTION+1];
225
 
      char hash;
226
165
 
227
166
      if(line[0]=='\n')
228
167
        break;
229
168
 
230
 
      if(sscanf(line,"%c",&hash)==1 && hash=='#')
 
169
      err=parse_ks_options(line,opt);
 
170
      if(err>0)
 
171
        {
 
172
          ret=err;
 
173
          goto fail;
 
174
        }
 
175
      else if(err==0)
231
176
        continue;
232
177
 
233
 
      if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
234
 
        {
235
 
          command[MAX_COMMAND]='\0';
236
 
 
237
 
          if(strcasecmp(command,"get")==0)
238
 
            action=GET;
239
 
 
240
 
          continue;
241
 
        }
242
 
 
243
 
      if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1)
244
 
        {
245
 
          scheme[MAX_SCHEME]='\0';
246
 
          continue;
247
 
        }
248
 
 
249
 
      if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1)
250
 
        {
251
 
          auth[MAX_AUTH]='\0';
252
 
          continue;
253
 
        }
254
 
 
255
 
      if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
256
 
        {
257
 
          host[MAX_HOST]='\0';
258
 
          continue;
259
 
        }
260
 
 
261
 
      if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
262
 
        {
263
 
          port[MAX_PORT]='\0';
264
 
          continue;
265
 
        }
266
 
 
267
 
      if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1)
268
 
        {
269
 
          path[URLMAX_PATH]='\0';
270
 
          continue;
271
 
        }
272
 
 
273
 
      if(sscanf(line,"VERSION %d\n",&version)==1)
274
 
        {
275
 
          if(version!=KEYSERVER_PROTO_VERSION)
276
 
            {
277
 
              ret=KEYSERVER_VERSION_ERROR;
278
 
              goto fail;
279
 
            }
280
 
 
281
 
          continue;
282
 
        }
283
 
 
284
178
      if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
285
179
        {
286
180
          int no=0;
294
188
              start=&option[3];
295
189
            }
296
190
 
297
 
          if(strcasecmp(start,"verbose")==0)
298
 
            {
299
 
              if(no)
300
 
                verbose--;
301
 
              else
302
 
                verbose++;
303
 
            }
304
 
          else if(strncasecmp(start,"http-proxy",10)==0)
305
 
            {
306
 
              if(no)
307
 
                proxy[0]='\0';
 
191
          if(strncasecmp(start,"http-proxy",10)==0)
 
192
            {
 
193
              /* Safe to not check the return code of strdup() here.
 
194
                 If it fails, we simply won't use a proxy. */
 
195
              if(no)
 
196
                {
 
197
                  free(proxy);
 
198
                  proxy=strdup("");
 
199
                }
308
200
              else if(start[10]=='=')
309
201
                {
310
 
                  strncpy(proxy,&start[11],MAX_PROXY);
311
 
                  proxy[MAX_PROXY]='\0';
 
202
                  if(strlen(&start[11])<MAX_PROXY)
 
203
                    {
 
204
                      free(proxy);
 
205
                      proxy=strdup(&start[11]);
 
206
                    }
312
207
                }
313
208
            }
314
 
          else if(strncasecmp(start,"timeout",7)==0)
315
 
            {
316
 
              if(no)
317
 
                timeout=0;
318
 
              else if(start[7]=='=')
319
 
                timeout=atoi(&start[8]);
320
 
              else if(start[7]=='\0')
321
 
                timeout=DEFAULT_KEYSERVER_TIMEOUT;
322
 
            }
323
209
          else if(strncasecmp(start,"follow-redirects",16)==0)
324
210
            {
325
211
              if(no)
329
215
              else if(start[16]=='\0')
330
216
                follow_redirects=-1;
331
217
            }
332
 
          else if(strncasecmp(start,"debug",5)==0)
333
 
            {
334
 
              if(no)
335
 
                debug=0;
336
 
              else if(start[5]=='=')
337
 
                debug=atoi(&start[6]);
338
 
              else if(start[5]=='\0')
339
 
                debug=1;
340
 
            }
341
 
          else if(strcasecmp(start,"check-cert")==0)
342
 
            {
343
 
              if(no)
344
 
                check_cert=0;
345
 
              else
346
 
                check_cert=1;
347
 
            }
348
 
          else if(strncasecmp(start,"ca-cert-file",12)==0)
349
 
            {
350
 
              if(no)
351
 
                {
352
 
                  free(ca_cert_file);
353
 
                  ca_cert_file=NULL;
354
 
                }
355
 
              else if(start[12]=='=')
356
 
                {
357
 
                  free(ca_cert_file);
358
 
                  ca_cert_file=strdup(&start[13]);
359
 
                  if(!ca_cert_file)
360
 
                    {
361
 
                      fprintf(console,"gpgkeys: out of memory while creating "
362
 
                              "ca_cert_file\n");
363
 
                      ret=KEYSERVER_NO_MEMORY;
364
 
                      goto fail;
365
 
                    }
366
 
                }
367
 
            }
368
218
 
369
219
          continue;
370
220
        }
371
221
    }
372
222
 
373
 
  if(scheme[0]=='\0')
 
223
  if(!opt->scheme)
374
224
    {
375
225
      fprintf(console,"gpgkeys: no scheme supplied!\n");
376
 
      return KEYSERVER_SCHEME_NOT_FOUND;
 
226
      ret=KEYSERVER_SCHEME_NOT_FOUND;
 
227
      goto fail;
377
228
    }
378
 
#ifdef HTTP_VIA_LIBCURL
379
 
  else if(strcasecmp(scheme,"http")==0)
380
 
    ;
381
 
#endif /* HTTP_VIA_LIBCURL */
382
 
#ifdef HTTPS_VIA_LIBCURL
383
 
  else if(strcasecmp(scheme,"https")==0)
384
 
    ;
385
 
#endif /* HTTP_VIA_LIBCURL */
386
 
#ifdef FTP_VIA_LIBCURL
387
 
  else if(strcasecmp(scheme,"ftp")==0)
388
 
    ;
389
 
#endif /* FTP_VIA_LIBCURL */
390
 
#ifdef FTPS_VIA_LIBCURL
391
 
  else if(strcasecmp(scheme,"ftps")==0)
392
 
    ;
393
 
#endif /* FTPS_VIA_LIBCURL */
394
 
  else
 
229
 
 
230
  if(!opt->host)
395
231
    {
396
 
      fprintf(console,"gpgkeys: scheme `%s' not supported\n",scheme);
397
 
      return KEYSERVER_SCHEME_NOT_FOUND;
 
232
      fprintf(console,"gpgkeys: no keyserver host provided\n");
 
233
      goto fail;
398
234
    }
399
235
 
400
 
  if(timeout && register_timeout()==-1)
 
236
  if(opt->timeout && register_timeout()==-1)
401
237
    {
402
238
      fprintf(console,"gpgkeys: unable to register timeout handler\n");
403
239
      return KEYSERVER_INTERNAL_ERROR;
419
255
        curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects);
420
256
    }
421
257
 
422
 
  if(debug)
 
258
  if(opt->auth)
 
259
    curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
 
260
 
 
261
  if(opt->debug)
423
262
    {
424
263
      curl_easy_setopt(curl,CURLOPT_STDERR,console);
425
264
      curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
426
265
    }
427
266
 
428
 
  curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,check_cert);
429
 
 
430
 
  if(ca_cert_file)
431
 
    curl_easy_setopt(curl,CURLOPT_CAINFO,ca_cert_file);
432
 
 
433
 
  if(proxy[0])
 
267
  curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,opt->flags.check_cert);
 
268
  curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file);
 
269
 
 
270
  if(proxy)
434
271
    curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
435
272
 
436
273
  /* If it's a GET or a SEARCH, the next thing to come in is the
437
274
     keyids.  If it's a SEND, then there are no keyids. */
438
275
 
439
 
  if(action==GET)
 
276
  if(opt->action==KS_GET)
440
277
    {
441
278
      /* Eat the rest of the file */
442
279
      for(;;)
472
309
      goto fail;
473
310
    }
474
311
 
475
 
  if(!thekey || !host[0])
 
312
  if(!thekey)
476
313
    {
477
314
      fprintf(console,"gpgkeys: invalid keyserver instructions\n");
478
315
      goto fail;
483
320
  fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
484
321
  fprintf(output,"PROGRAM %s\n\n",VERSION);
485
322
 
486
 
  if(verbose)
 
323
  if(opt->verbose)
487
324
    {
488
 
      fprintf(console,"Scheme:\t\t%s\n",scheme);
489
 
      fprintf(console,"Host:\t\t%s\n",host);
490
 
      if(port[0])
491
 
        fprintf(console,"Port:\t\t%s\n",port);
492
 
      if(path[0])
493
 
        fprintf(console,"Path:\t\t%s\n",path);
 
325
      fprintf(console,"Scheme:\t\t%s\n",opt->scheme);
 
326
      fprintf(console,"Host:\t\t%s\n",opt->host);
 
327
      if(opt->port)
 
328
        fprintf(console,"Port:\t\t%s\n",opt->port);
 
329
      if(opt->path)
 
330
        fprintf(console,"Path:\t\t%s\n",opt->path);
494
331
      fprintf(console,"Command:\tGET\n");
495
332
    }
496
333
 
497
 
  set_timeout(timeout);
 
334
  set_timeout(opt->timeout);
498
335
 
499
336
  ret=get_key(thekey);
500
337
 
508
345
  if(output!=stdout)
509
346
    fclose(output);
510
347
 
 
348
  free_ks_options(opt);
 
349
 
511
350
  if(curl)
512
351
    curl_easy_cleanup(curl);
513
352
 
 
353
  free(proxy);
 
354
 
514
355
  curl_global_cleanup();
515
356
 
516
357
  return ret;