93 |
} /* base64_encode */ |
} /* base64_encode */ |
94 |
|
|
95 |
|
|
96 |
|
/* Skip the URL schema and return only the host part of it. */ |
97 |
static const char * |
static const char * |
98 |
skip_type_prefix (const char * hostname) |
skip_type_prefix (const char * hostname) |
99 |
{ |
{ |
109 |
} |
} |
110 |
|
|
111 |
|
|
112 |
|
/* Check that the keyserver response indicates an OK. |
113 |
|
Return 0 on success. */ |
114 |
static int |
static int |
115 |
check_hkp_response (const char *resp, int recv) |
check_hkp_response (const char *resp, int recv) |
116 |
{ |
{ |
134 |
return ec; |
return ec; |
135 |
} |
} |
136 |
return 0; |
return 0; |
137 |
} /* check_hkp_response */ |
} |
138 |
|
|
139 |
|
|
140 |
|
/* Read a single line (\r\n) from a socket. |
141 |
|
Return 0 on success. */ |
142 |
static int |
static int |
143 |
sock_getline (int fd, char *buf, int buflen, int *nbytes) |
sock_getline (int fd, char *buf, int buflen, int *nbytes) |
144 |
{ |
{ |
160 |
} |
} |
161 |
|
|
162 |
return -1; |
return -1; |
163 |
} /* sock_getline */ |
} |
164 |
|
|
165 |
|
|
166 |
|
/* Perform a select() on the given fd to find out |
167 |
|
is there is data for reading. Wait at least @nsecs seconds. */ |
168 |
static int |
static int |
169 |
sock_select (int fd) |
sock_select (int fd, int nsecs) |
170 |
{ |
{ |
171 |
FD_SET rfd; |
FD_SET rfd; |
172 |
timeval tv = {1, 0}; |
timeval tv = {nsecs, 0}; |
173 |
|
|
174 |
FD_ZERO (&rfd); |
FD_ZERO (&rfd); |
175 |
FD_SET (fd, &rfd); |
FD_SET (fd, &rfd); |
178 |
if (FD_ISSET (fd, &rfd)) |
if (FD_ISSET (fd, &rfd)) |
179 |
return 1; |
return 1; |
180 |
return 0; |
return 0; |
181 |
} /* sock_select */ |
} |
182 |
|
|
183 |
|
|
184 |
|
/* Read from a socket with a fixed timeout of 10 seconds. |
185 |
|
Return value: 0 on success. */ |
186 |
static int |
static int |
187 |
sock_read( int fd, char *buf, int buflen, int *nbytes ) |
sock_read (int fd, char *buf, int buflen, int *nbytes) |
188 |
{ |
{ |
189 |
DWORD nread; |
DWORD nread; |
190 |
int nleft = buflen; |
int nleft = buflen; |
193 |
while (nleft > 0) { |
while (nleft > 0) { |
194 |
if (n >= 10) |
if (n >= 10) |
195 |
return WPTERR_WINSOCK_TIMEOUT; |
return WPTERR_WINSOCK_TIMEOUT; |
196 |
if ( (rc = sock_select( fd )) == SOCKET_ERROR ) |
rc = sock_select (fd, 1); |
197 |
|
if (rc == SOCKET_ERROR) |
198 |
return SOCKET_ERROR; |
return SOCKET_ERROR; |
199 |
else if( !rc ) |
else if( !rc ) |
200 |
n++; |
n++; |
201 |
else { |
else { |
202 |
nread = recv(fd, buf, nleft, 0); |
nread = recv (fd, buf, nleft, 0); |
203 |
if (nread == SOCKET_ERROR) |
if (nread == SOCKET_ERROR) |
204 |
return SOCKET_ERROR; |
return SOCKET_ERROR; |
205 |
else if (!nread) |
else if (!nread) |
212 |
*nbytes = buflen - nleft; |
*nbytes = buflen - nleft; |
213 |
|
|
214 |
return 0; |
return 0; |
215 |
} /* sock_read */ |
} |
216 |
|
|
217 |
|
|
218 |
|
/* Write @buf to a socket. */ |
219 |
static int |
static int |
220 |
sock_write( int fd, const char *buf, int buflen ) |
sock_write (int fd, const char *buf, int buflen) |
221 |
{ |
{ |
222 |
DWORD nwritten; |
DWORD nwritten; |
223 |
int nleft = buflen; |
int nleft = buflen; |
247 |
} |
} |
248 |
else |
else |
249 |
default_keyserver_port = HKP_PORT; |
default_keyserver_port = HKP_PORT; |
250 |
} /* set_default_kserver */ |
} |
251 |
|
|
252 |
|
|
253 |
/* |
/* Initialize the Winsock2 interface.*/ |
|
* Initialize the Winsock2 interface. |
|
|
*/ |
|
254 |
int |
int |
255 |
wsock_init (void) |
wsock_init (void) |
256 |
{ |
{ |
260 |
return WPTERR_WINSOCK_INIT; |
return WPTERR_WINSOCK_INIT; |
261 |
set_default_kserver (); |
set_default_kserver (); |
262 |
return 0; |
return 0; |
263 |
} /* wsock_init */ |
} |
264 |
|
|
265 |
|
|
266 |
/* |
/* Cleanup the Winsock2 interface. */ |
|
* Should be called after the keyserver access. |
|
|
*/ |
|
267 |
void |
void |
268 |
wsock_end (void) |
wsock_end (void) |
269 |
{ |
{ |
276 |
free_if_alloc (server[i].name); |
free_if_alloc (server[i].name); |
277 |
} |
} |
278 |
WSACleanup (); |
WSACleanup (); |
279 |
} /* wsock_end */ |
} |
280 |
|
|
281 |
|
|
282 |
|
/* Return a string representation of a winsock error. */ |
283 |
const char* |
const char* |
284 |
wsock_strerror( void ) |
wsock_strerror (void) |
285 |
{ |
{ |
286 |
static char buf[384]; |
static char buf[384]; |
287 |
int ec = WSAGetLastError( ); |
int ec = WSAGetLastError (); |
288 |
|
|
289 |
switch ( ec ) { |
switch (ec) { |
290 |
case WSAENETDOWN: return _("The network subsystem has failed"); |
case WSAENETDOWN: |
291 |
case WSAHOST_NOT_FOUND: return _("Authoritative Answer Host not found"); |
return _("The network subsystem has failed"); |
292 |
case WSAETIMEDOUT: return _("The connection has been dropped because of a network failure"); |
case WSAHOST_NOT_FOUND: |
293 |
default: _snprintf( buf, sizeof (buf) -1, _("Unknown Winsock error ec=%d"),ec); return buf; |
return _("Authoritative Answer Host not found"); |
294 |
|
case WSAETIMEDOUT: |
295 |
|
return _("The connection has been dropped because of a network failure"); |
296 |
|
default: |
297 |
|
_snprintf (buf, sizeof (buf) -1, _("Unknown Winsock error ec=%d"),ec); |
298 |
|
return buf; |
299 |
} |
} |
300 |
return NULL; |
return NULL; |
301 |
} /* wsock_strerror */ |
} |
302 |
|
|
303 |
|
|
304 |
|
/* Return the last keyserver error as a string. */ |
305 |
const char* |
const char* |
306 |
kserver_strerror (void) |
kserver_strerror (void) |
307 |
{ |
{ |
308 |
if (hkp_err) |
if (hkp_err) |
309 |
return hkp_errmsg; |
return hkp_errmsg; |
310 |
return NULL; |
return NULL; |
311 |
} /* kserver_strerror */ |
} |
312 |
|
|
313 |
|
|
314 |
const char * |
/* Read a keyserver from the list at index @idx. |
315 |
|
Return value: keyserver name at the given position. */ |
316 |
|
const char* |
317 |
kserver_get_hostname (int idx, int type, u16 *port) |
kserver_get_hostname (int idx, int type, u16 *port) |
318 |
{ |
{ |
319 |
if (type == -1) { |
if (type == -1) { |
328 |
} |
} |
329 |
|
|
330 |
|
|
331 |
|
/* Check if the computer is connected to the internet. |
332 |
|
Return 0 on success -1 otherwise. */ |
333 |
int |
int |
334 |
kserver_check_inet_connection (void) |
kserver_check_inet_connection (void) |
335 |
{ |
{ |
385 |
} /* kserver_update_proxyuser */ |
} /* kserver_update_proxyuser */ |
386 |
|
|
387 |
|
|
388 |
|
/* Check that the given buffer contains a valid keyserver URL. */ |
389 |
static int |
static int |
390 |
check_URL (const char * buf) |
check_URL (const char * buf) |
391 |
{ |
{ |
397 |
&& !strstr (buf, "hkp://")) |
&& !strstr (buf, "hkp://")) |
398 |
return -1; |
return -1; |
399 |
return 0; |
return 0; |
400 |
} /* check_URL */ |
} |
401 |
|
|
402 |
|
|
403 |
|
/* Get the port number from the given protocol. */ |
404 |
static int |
static int |
405 |
port_from_proto (int proto) |
port_from_proto (int proto) |
406 |
{ |
{ |
413 |
} |
} |
414 |
|
|
415 |
|
|
416 |
|
/* Get the port number from the given URL. */ |
417 |
static int |
static int |
418 |
proto_from_URL (const char * buf) |
proto_from_URL (const char * buf) |
419 |
{ |
{ |
421 |
return KSPROTO_LDAP; |
return KSPROTO_LDAP; |
422 |
else if (strstr( buf, "finger")) |
else if (strstr( buf, "finger")) |
423 |
return KSPROTO_FINGER; |
return KSPROTO_FINGER; |
424 |
return KSPROTO_HTTP; |
return KSPROTO_HKP; |
425 |
} /* proto_from_URL */ |
} |
426 |
|
|
427 |
|
|
428 |
void |
void |
588 |
} /* kserver_get_proxy_info */ |
} /* kserver_get_proxy_info */ |
589 |
|
|
590 |
|
|
591 |
/* |
/* Connect to the keyserver @hostname. */ |
|
* Connect to the keyserver 'hostname'. |
|
|
* We always use the HKP port. |
|
|
*/ |
|
592 |
int |
int |
593 |
kserver_connect (const char *hostname, u16 port, int *conn_fd) |
kserver_connect (const char *hostname, u16 port, int *conn_fd) |
594 |
{ |
{ |
646 |
} /* kserver_connect */ |
} /* kserver_connect */ |
647 |
|
|
648 |
|
|
649 |
|
/* Perform URL-encoding on the given pubkey blob. */ |
650 |
static char* |
static char* |
651 |
kserver_urlencode (const char *pubkey, size_t octets, size_t *newlen) |
kserver_urlencode (const char *pubkey, size_t octets, size_t *newlen) |
652 |
{ |
{ |
678 |
p[size] = '\0'; |
p[size] = '\0'; |
679 |
*newlen = size; |
*newlen = size; |
680 |
return p; |
return p; |
681 |
} /* kserver_urlencode */ |
} |
682 |
|
|
683 |
|
|
684 |
/* |
/* Format a request for the given keyid (send). */ |
|
* Format a request for the given keyid (send). |
|
|
*/ |
|
685 |
static char* |
static char* |
686 |
kserver_send_request (const char *hostname, u16 port, const char *pubkey, int octets) |
kserver_send_request (const char *hostname, u16 port, const char *pubkey, int octets) |
687 |
{ |
{ |
738 |
} /* kserver_send_request */ |
} /* kserver_send_request */ |
739 |
|
|
740 |
|
|
741 |
/* |
/* Interface receiving a public key. */ |
|
* Interface receiving a public key. |
|
|
*/ |
|
742 |
int |
int |
743 |
kserver_recvkey (const char *hostname, u16 port, const char *keyid, char *key, int maxkeylen) |
kserver_recvkey (const char *hostname, u16 port, const char *keyid, char *key, int maxkeylen) |
744 |
{ |
{ |
802 |
} /* kserver_recvkey */ |
} /* kserver_recvkey */ |
803 |
|
|
804 |
|
|
805 |
/* |
/* Interface to send a public key. */ |
|
* Interface to send a public key. |
|
|
*/ |
|
806 |
int |
int |
807 |
kserver_sendkey (const char *hostname, u16 port, const char *pubkey, int len ) |
kserver_sendkey (const char *hostname, u16 port, const char *pubkey, int len ) |
808 |
{ |
{ |