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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
36 #include <sys/types.h>
37 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
45 #define INCLUDED_BY_MAIN_MODULE 1
47 #include "keyserver.h"
51 #define sock_close(a) closesocket(a)
53 #define sock_close(a) close(a)
59 static FILE *input
,*output
,*console
;
60 static struct ks_options
*opt
;
72 static int initialized
;
73 static WSADATA wsdata
;
78 if (WSAStartup (0x0101, &wsdata
) )
80 fprintf (console
, "error initializing socket library: ec=%d\n",
81 (int)WSAGetLastError () );
84 if (wsdata
.wVersion
< 0x0001)
86 fprintf (console
, "socket library version is %x.%x - but 1.1 needed\n",
87 LOBYTE(wsdata
.wVersion
), HIBYTE(wsdata
.wVersion
));
91 atexit (deinit_sockets
);
97 /* Connect to SERVER at PORT and return a file descriptor or -1 on
100 connect_server (const char *server
, unsigned short port
)
106 struct sockaddr_in addr
;
111 memset (&addr
, 0, sizeof addr
);
112 addr
.sin_family
= AF_INET
;
113 addr
.sin_port
= htons (port
);
115 /* Win32 gethostbyname doesn't handle IP addresses internally, so we
116 try inet_addr first on that platform only. */
117 if ((l
= inet_addr (server
)) != INADDR_NONE
)
118 memcpy (&addr
.sin_addr
, &l
, sizeof l
);
119 else if ((hp
= gethostbyname (server
)))
121 if (hp
->h_addrtype
!= AF_INET
)
123 fprintf (console
, "gpgkeys: unknown address family for `%s'\n",
127 if (hp
->h_length
!= 4)
129 fprintf (console
, "gpgkeys: illegal address length for `%s'\n",
133 memcpy (&addr
.sin_addr
, hp
->h_addr
, hp
->h_length
);
137 fprintf (console
, "gpgkeys: host `%s' not found: ec=%d\n",
138 server
, (int)WSAGetLastError ());
142 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
143 if (sock
== INVALID_SOCKET
)
145 fprintf (console
, "gpgkeys: error creating socket: ec=%d\n",
146 (int)WSAGetLastError ());
150 if (connect (sock
, (struct sockaddr
*)&addr
, sizeof addr
))
152 fprintf (console
, "gpgkeys: error connecting `%s': ec=%d\n",
153 server
, (int)WSAGetLastError ());
160 struct sockaddr_in addr
;
161 struct hostent
*host
;
163 addr
.sin_family
= AF_INET
;
164 addr
.sin_port
= htons (port
);
165 host
= gethostbyname ((char*)server
);
168 fprintf (console
, "gpgkeys: host `%s' not found: %s\n",
169 server
, strerror (errno
));
173 addr
.sin_addr
= *(struct in_addr
*)host
->h_addr
;
175 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
178 fprintf (console
, "gpgkeys: error creating socket: %s\n",
183 if (connect (sock
, (struct sockaddr
*)&addr
, sizeof addr
) == -1)
185 fprintf (console
, "gpgkeys: error connecting `%s': %s\n",
186 server
, strerror (errno
));
196 write_server (int sock
, const char *data
, size_t length
)
206 nwritten
= send (sock
, data
, nleft
, 0);
207 if ( nwritten
== SOCKET_ERROR
)
209 fprintf (console
, "gpgkeys: write failed: ec=%d\n",
210 (int)WSAGetLastError ());
214 nwritten
= write (sock
, data
, nleft
);
225 select(0, NULL
, NULL
, NULL
, &tv
);
228 fprintf (console
, "gpgkeys: write failed: %s\n", strerror(errno
));
240 /* Send the finger REQUEST to the server. Returns 0 and a file descriptor
241 in R_SOCK if the request was sucessful. */
243 send_request (const char *request
, int *r_sock
)
250 name
= strdup (request
);
253 fprintf(console
,"gpgkeys: out of memory\n");
254 return KEYSERVER_NO_MEMORY
;
257 server
= strchr (name
, '@');
260 fprintf (console
, "gpgkeys: no name included in request\n");
262 return KEYSERVER_GENERAL_ERROR
;
266 sock
= connect_server (server
, 79);
270 return KEYSERVER_UNREACHABLE
;
273 if (write_server (sock
, name
, strlen (name
))
274 || write_server (sock
, "\r\n", 2))
278 return KEYSERVER_GENERAL_ERROR
;
288 get_key (char *getkey
)
293 unsigned int maxlen
, buflen
, gotit
=0;
296 if (strncmp (getkey
,"0x",2)==0)
299 /* Frankly we don't know what keys the server will return; we
300 indicated the requested key anyway. */
301 fprintf(output
,"KEY 0x%s BEGIN\n",getkey
);
303 rc
=send_request(opt
->opaque
,&sock
);
306 fprintf(output
,"KEY 0x%s FAILED %d\n",getkey
, rc
);
311 /* Hmmm, we use iobuf here only to cope with Windows socket
312 peculiarities (we can't used fdopen). */
313 fp_read
= iobuf_sockopen (sock
, "r");
316 fprintf(output
,"KEY 0x%s FAILED %d\n",getkey
, KEYSERVER_INTERNAL_ERROR
);
321 while ( iobuf_read_line ( fp_read
, &line
, &buflen
, &maxlen
))
327 print_nocr(output
,line
);
328 if (!strncmp(line
,END
,strlen(END
)))
331 else if(!strncmp(line
,BEGIN
,strlen(BEGIN
)))
333 print_nocr(output
,line
);
339 fprintf (output
,"KEY 0x%s END\n", getkey
);
342 fprintf(console
,"gpgkeys: no key data found for finger:%s\n",
344 fprintf(output
,"KEY 0x%s FAILED %d\n",getkey
,KEYSERVER_KEY_NOT_FOUND
);
348 iobuf_close (fp_read
);
357 fprintf (fp
,"-h\thelp\n");
358 fprintf (fp
,"-V\tversion\n");
359 fprintf (fp
,"-o\toutput to this file\n");
363 main(int argc
,char *argv
[])
365 int arg
,ret
=KEYSERVER_INTERNAL_ERROR
;
371 /* Kludge to implement standard GNU options. */
372 if (argc
> 1 && !strcmp (argv
[1], "--version"))
374 fputs ("gpgkeys_finger (GnuPG) " VERSION
"\n", stdout
);
377 else if (argc
> 1 && !strcmp (argv
[1], "--help"))
383 while((arg
=getopt(argc
,argv
,"hVo:"))!=-1)
392 fprintf(stdout
,"%d\n%s\n",KEYSERVER_PROTO_VERSION
,VERSION
);
396 output
=fopen(optarg
,"w");
399 fprintf(console
,"gpgkeys: Cannot open output file `%s': %s\n",
400 optarg
,strerror(errno
));
401 return KEYSERVER_INTERNAL_ERROR
;
409 input
=fopen(argv
[optind
],"r");
412 fprintf(console
,"gpgkeys: Cannot open input file `%s': %s\n",
413 argv
[optind
],strerror(errno
));
414 return KEYSERVER_INTERNAL_ERROR
;
424 opt
=init_ks_options();
426 return KEYSERVER_NO_MEMORY
;
428 /* Get the command and info block */
430 while(fgets(line
,MAX_LINE
,input
)!=NULL
)
437 err
=parse_ks_options(line
,opt
);
449 fprintf(console
,"gpgkeys: finger://relay/user syntax is not"
450 " supported. Use finger:user instead.\n");
451 ret
=KEYSERVER_NOT_SUPPORTED
;
455 if(opt
->timeout
&& register_timeout()==-1)
457 fprintf(console
,"gpgkeys: unable to register timeout handler\n");
458 return KEYSERVER_INTERNAL_ERROR
;
461 /* If it's a GET or a SEARCH, the next thing to come in is the
462 keyids. If it's a SEND, then there are no keyids. */
464 if(opt
->action
==KS_GET
)
466 /* Eat the rest of the file */
469 if(fgets(line
,MAX_LINE
,input
)==NULL
)
473 if(line
[0]=='\n' || line
[0]=='\0')
481 fprintf(console
,"gpgkeys: out of memory while "
482 "building key list\n");
483 ret
=KEYSERVER_NO_MEMORY
;
487 /* Trim the trailing \n */
488 thekey
[strlen(line
)-1]='\0';
496 "gpgkeys: this keyserver type only supports key retrieval\n");
500 if(!thekey
|| !opt
->opaque
)
502 fprintf(console
,"gpgkeys: invalid keyserver instructions\n");
506 /* Send the response */
508 fprintf(output
,"VERSION %d\n",KEYSERVER_PROTO_VERSION
);
509 fprintf(output
,"PROGRAM %s\n\n",VERSION
);
513 fprintf(console
,"User:\t\t%s\n",opt
->opaque
);
514 fprintf(console
,"Command:\tGET\n");
517 set_timeout(opt
->timeout
);
531 free_ks_options(opt
);