1 /* gpgkeys_finger.c - fetch a key via finger
2 * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
30 #ifdef HAVE_W32_SYSTEM
34 #include <sys/types.h>
35 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
43 #define INCLUDED_BY_MAIN_MODULE 1
45 #include "keyserver.h"
49 #ifdef HAVE_W32_SYSTEM
50 #define sock_close(a) closesocket(a)
52 #define sock_close(a) close(a)
58 static FILE *input
,*output
,*console
;
59 static struct ks_options
*opt
;
62 /* Connect to SERVER at PORT and return a file descriptor or -1 on
65 connect_server (const char *server
, unsigned short port
)
69 #ifdef HAVE_W32_SYSTEM
71 struct sockaddr_in addr
;
76 memset (&addr
, 0, sizeof addr
);
77 addr
.sin_family
= AF_INET
;
78 addr
.sin_port
= htons (port
);
80 /* Win32 gethostbyname doesn't handle IP addresses internally, so we
81 try inet_addr first on that platform only. */
82 if ((l
= inet_addr (server
)) != INADDR_NONE
)
83 memcpy (&addr
.sin_addr
, &l
, sizeof l
);
84 else if ((hp
= gethostbyname (server
)))
86 if (hp
->h_addrtype
!= AF_INET
)
88 fprintf (console
, "gpgkeys: unknown address family for `%s'\n",
92 if (hp
->h_length
!= 4)
94 fprintf (console
, "gpgkeys: illegal address length for `%s'\n",
98 memcpy (&addr
.sin_addr
, hp
->h_addr
, hp
->h_length
);
102 fprintf (console
, "gpgkeys: host `%s' not found: ec=%d\n",
103 server
, (int)WSAGetLastError ());
107 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
108 if (sock
== INVALID_SOCKET
)
110 fprintf (console
, "gpgkeys: error creating socket: ec=%d\n",
111 (int)WSAGetLastError ());
115 if (connect (sock
, (struct sockaddr
*)&addr
, sizeof addr
))
117 fprintf (console
, "gpgkeys: error connecting `%s': ec=%d\n",
118 server
, (int)WSAGetLastError ());
125 struct sockaddr_in addr
;
126 struct hostent
*host
;
128 addr
.sin_family
= AF_INET
;
129 addr
.sin_port
= htons (port
);
130 host
= gethostbyname ((char*)server
);
133 fprintf (console
, "gpgkeys: host `%s' not found: %s\n",
134 server
, strerror (errno
));
138 addr
.sin_addr
= *(struct in_addr
*)host
->h_addr
;
140 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
143 fprintf (console
, "gpgkeys: error creating socket: %s\n",
148 if (connect (sock
, (struct sockaddr
*)&addr
, sizeof addr
) == -1)
150 fprintf (console
, "gpgkeys: error connecting `%s': %s\n",
151 server
, strerror (errno
));
161 write_server (int sock
, const char *data
, size_t length
)
170 #ifdef HAVE_W32_SYSTEM
171 nwritten
= send (sock
, data
, nleft
, 0);
172 if ( nwritten
== SOCKET_ERROR
)
174 fprintf (console
, "gpgkeys: write failed: ec=%d\n",
175 (int)WSAGetLastError ());
179 nwritten
= write (sock
, data
, nleft
);
190 select(0, NULL
, NULL
, NULL
, &tv
);
193 fprintf (console
, "gpgkeys: write failed: %s\n", strerror(errno
));
205 /* Send the finger REQUEST to the server. Returns 0 and a file descriptor
206 in R_SOCK if the request was sucessful. */
208 send_request (const char *request
, int *r_sock
)
215 name
= strdup (request
);
218 fprintf(console
,"gpgkeys: out of memory\n");
219 return KEYSERVER_NO_MEMORY
;
222 server
= strchr (name
, '@');
225 fprintf (console
, "gpgkeys: no name included in request\n");
227 return KEYSERVER_GENERAL_ERROR
;
231 sock
= connect_server (server
, 79);
235 return KEYSERVER_UNREACHABLE
;
238 if (write_server (sock
, name
, strlen (name
))
239 || write_server (sock
, "\r\n", 2))
243 return KEYSERVER_GENERAL_ERROR
;
253 get_key (char *getkey
)
258 unsigned int maxlen
, buflen
, gotit
=0;
261 if (strncmp (getkey
,"0x",2)==0)
264 /* Frankly we don't know what keys the server will return; we
265 indicated the requested key anyway. */
266 fprintf(output
,"KEY 0x%s BEGIN\n",getkey
);
268 rc
=send_request(opt
->opaque
,&sock
);
271 fprintf(output
,"KEY 0x%s FAILED %d\n",getkey
, rc
);
276 /* Hmmm, we use iobuf here only to cope with Windows socket
277 peculiarities (we can't used fdopen). */
278 fp_read
= iobuf_sockopen (sock
, "r");
281 fprintf(output
,"KEY 0x%s FAILED %d\n",getkey
, KEYSERVER_INTERNAL_ERROR
);
286 while ( iobuf_read_line ( fp_read
, &line
, &buflen
, &maxlen
))
292 print_nocr(output
, (const char*)line
);
293 if (!strncmp((char*)line
,END
,strlen(END
)))
296 else if(!strncmp((char*)line
,BEGIN
,strlen(BEGIN
)))
298 print_nocr(output
, (const char*)line
);
304 fprintf (output
,"KEY 0x%s END\n", getkey
);
307 fprintf(console
,"gpgkeys: no key data found for finger:%s\n",
309 fprintf(output
,"KEY 0x%s FAILED %d\n",getkey
,KEYSERVER_KEY_NOT_FOUND
);
313 iobuf_close (fp_read
);
322 fprintf (fp
,"-h, --help\thelp\n");
323 fprintf (fp
,"-V\t\tmachine readable version\n");
324 fprintf (fp
,"--version\thuman readable version\n");
325 fprintf (fp
,"-o\t\toutput to this file\n");
329 main(int argc
,char *argv
[])
331 int arg
,ret
=KEYSERVER_INTERNAL_ERROR
;
337 /* Kludge to implement standard GNU options. */
338 if (argc
> 1 && !strcmp (argv
[1], "--version"))
340 fputs ("gpgkeys_finger (GnuPG) " VERSION
"\n", stdout
);
343 else if (argc
> 1 && !strcmp (argv
[1], "--help"))
349 while((arg
=getopt(argc
,argv
,"hVo:"))!=-1)
358 fprintf(stdout
,"%d\n%s\n",KEYSERVER_PROTO_VERSION
,VERSION
);
362 output
=fopen(optarg
,"w");
365 fprintf(console
,"gpgkeys: Cannot open output file `%s': %s\n",
366 optarg
,strerror(errno
));
367 return KEYSERVER_INTERNAL_ERROR
;
375 input
=fopen(argv
[optind
],"r");
378 fprintf(console
,"gpgkeys: Cannot open input file `%s': %s\n",
379 argv
[optind
],strerror(errno
));
380 return KEYSERVER_INTERNAL_ERROR
;
390 opt
=init_ks_options();
392 return KEYSERVER_NO_MEMORY
;
394 /* Get the command and info block */
396 while(fgets(line
,MAX_LINE
,input
)!=NULL
)
403 err
=parse_ks_options(line
,opt
);
415 fprintf(console
,"gpgkeys: finger://relay/user syntax is not"
416 " supported. Use finger:user instead.\n");
417 ret
=KEYSERVER_NOT_SUPPORTED
;
421 if(opt
->timeout
&& register_timeout()==-1)
423 fprintf(console
,"gpgkeys: unable to register timeout handler\n");
424 return KEYSERVER_INTERNAL_ERROR
;
427 /* If it's a GET or a SEARCH, the next thing to come in is the
428 keyids. If it's a SEND, then there are no keyids. */
430 if(opt
->action
==KS_GET
)
432 /* Eat the rest of the file */
435 if(fgets(line
,MAX_LINE
,input
)==NULL
)
439 if(line
[0]=='\n' || line
[0]=='\0')
447 fprintf(console
,"gpgkeys: out of memory while "
448 "building key list\n");
449 ret
=KEYSERVER_NO_MEMORY
;
453 /* Trim the trailing \n */
454 thekey
[strlen(line
)-1]='\0';
462 "gpgkeys: this keyserver type only supports key retrieval\n");
466 if(!thekey
|| !opt
->opaque
)
468 fprintf(console
,"gpgkeys: invalid keyserver instructions\n");
472 /* Send the response */
474 fprintf(output
,"VERSION %d\n",KEYSERVER_PROTO_VERSION
);
475 fprintf(output
,"PROGRAM %s\n\n",VERSION
);
479 fprintf(console
,"User:\t\t%s\n",opt
->opaque
);
480 fprintf(console
,"Command:\tGET\n");
483 set_timeout(opt
->timeout
);
497 free_ks_options(opt
);