29 |
#include <sys/stat.h> |
#include <sys/stat.h> |
30 |
#include <ctype.h> |
#include <ctype.h> |
31 |
|
|
32 |
|
#include "wptGPG.h" |
33 |
#include "wptKeyserver.h" |
#include "wptKeyserver.h" |
34 |
#include "wptErrors.h" |
#include "wptErrors.h" |
35 |
#include "wptTypes.h" |
#include "wptTypes.h" |
36 |
#include "wptNLS.h" |
#include "wptNLS.h" |
37 |
#include "wptW32API.h" |
#include "wptW32API.h" |
|
#include "wptGPG.h" |
|
38 |
#include "wptRegistry.h" |
#include "wptRegistry.h" |
39 |
#include "wptUTF8.h" |
#include "wptUTF8.h" |
40 |
|
|
83 |
char base64code[] = |
char base64code[] = |
84 |
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
85 |
int index = 0, temp = 0, res = 0; |
int index = 0, temp = 0, res = 0; |
86 |
int i = 0, inputlen = 0, len = 0; |
int i, inputlen, len = 0; |
87 |
|
|
88 |
inputlen = strlen (inbuf); |
inputlen = strlen (inbuf); |
89 |
for (i = 0; i < inputlen; i++) { |
for (i = 0; i < inputlen; i++) { |
160 |
return hostname; |
return hostname; |
161 |
} |
} |
162 |
|
|
163 |
|
/* Parse the keyserver response and extract the human |
164 |
|
readable text passages. */ |
165 |
|
static int |
166 |
|
parse_keyserver_error (const char *resp, char *txt, size_t txtlen) |
167 |
|
{ |
168 |
|
char *p, *p2; |
169 |
|
|
170 |
|
/* If we find no 'Error' substring, we assume a success. */ |
171 |
|
if (!stristr (resp, "Error")) |
172 |
|
return -1; |
173 |
|
|
174 |
|
memset (txt, 0, txtlen); |
175 |
|
p = strstr (resp, "\r\n\r\n"); |
176 |
|
if (!p) |
177 |
|
return -1; |
178 |
|
resp += (p-resp); |
179 |
|
p = strstr (resp, "<h1>"); |
180 |
|
if (!p) |
181 |
|
return -1; |
182 |
|
resp += (p-resp)+strlen ("<h1>"); |
183 |
|
p = strstr (resp, "</h1>"); |
184 |
|
if (!p) |
185 |
|
return -1; |
186 |
|
resp += (p-resp)+strlen ("</h1>"); |
187 |
|
p2 = strstr (resp, "</body>"); |
188 |
|
if (p2 != NULL) |
189 |
|
memcpy (txt, resp, (p2-resp)); |
190 |
|
else { |
191 |
|
if (!strnicmp (resp, "<p>", 3)) |
192 |
|
resp += 3; |
193 |
|
while (resp && *resp == '\r' || *resp == '\n') |
194 |
|
resp++; |
195 |
|
memcpy (txt, resp, strlen (resp)); |
196 |
|
} |
197 |
|
return 0; |
198 |
|
} |
199 |
|
|
200 |
|
|
201 |
/* Check that the keyserver response indicates an OK. |
/* Check that the keyserver response indicates an OK. |
202 |
Return 0 on success. */ |
Return 0 on success. */ |
203 |
static int |
static int |
204 |
check_hkp_response (const char *resp, int recv) |
check_hkp_response (const char *resp, int recv) |
205 |
{ |
{ |
206 |
char *p, *end; |
int ec; |
|
int ec, len; |
|
207 |
|
|
208 |
log_debug ("check_hkp_response: '%s'\r\n", resp); |
log_debug ("check_hkp_response: '%s'\r\n", resp); |
209 |
ec = recv ? WPTERR_WINSOCK_RECVKEY : WPTERR_WINSOCK_SENDKEY; |
ec = recv ? WPTERR_WINSOCK_RECVKEY : WPTERR_WINSOCK_SENDKEY; |
210 |
if (!strstr (resp, "HTTP/1.0 200 OK") && |
if (!strstr (resp, "HTTP/1.0 200 OK") && |
211 |
!strstr (resp, "HTTP/1.1 200 OK")) /* http error */ |
!strstr (resp, "HTTP/1.1 200 OK") && |
212 |
return ec; |
!strstr (resp, "HTTP/1.0 500 OK") && |
213 |
if (strstr (resp, "Public Key Server -- Error") |
!strstr (resp, "HTTP/1.1 500 OK")) |
214 |
|| strstr (resp, "Public Key Server -- Error") |
return ec; /* http error */ |
215 |
|| strstr (resp, "No matching keys in database")) { |
|
216 |
p = strstr (resp, "<p>"); |
if (!parse_keyserver_error (resp, hkp_errmsg, DIM (hkp_errmsg)-2)) { |
217 |
if (p && strlen (p) < sizeof (hkp_errmsg)-1) { |
if (!strlen (hkp_errmsg)) |
218 |
end = strstr (p, "</p>"); |
_snprintf (hkp_errmsg, DIM (hkp_errmsg)-1, |
219 |
len = end? (end - p + 1) : strlen (p); |
"Unknown keyserver error"); |
220 |
memset (hkp_errmsg, 0, sizeof (hkp_errmsg)); |
hkp_err = 1; |
|
strncpy (hkp_errmsg, p, len); |
|
|
hkp_err = 1; |
|
|
} |
|
221 |
return ec; |
return ec; |
222 |
} |
} |
223 |
return 0; |
return 0; |
352 |
else if (!rc) |
else if (!rc) |
353 |
n++; |
n++; |
354 |
else { |
else { |
355 |
nread = recv (fd, buf, sizeof (buf), 0); |
nread = recv (fd, buf, DIM (buf), 0); |
356 |
if (nread == SOCKET_ERROR) |
if (nread == SOCKET_ERROR) |
357 |
return SOCKET_ERROR; |
return SOCKET_ERROR; |
358 |
else if (!nread) |
else if (!nread) |
408 |
char *p; |
char *p; |
409 |
int i; |
int i; |
410 |
|
|
411 |
|
#ifdef WINPT_MOBILE |
412 |
|
p = m_strdup ("keyserver.conf"); |
413 |
|
#else |
414 |
p = make_special_filename (CSIDL_APPDATA, "winpt\\keyserver.conf", NULL); |
p = make_special_filename (CSIDL_APPDATA, "winpt\\keyserver.conf", NULL); |
415 |
|
#endif |
416 |
kserver_save_conf (p); |
kserver_save_conf (p); |
417 |
free_if_alloc (p); |
free_if_alloc (p); |
418 |
free_if_alloc (default_keyserver); |
free_if_alloc (default_keyserver); |
533 |
return keyid; /* email address */ |
return keyid; /* email address */ |
534 |
if (strncmp (keyid, "0x", 2)) { |
if (strncmp (keyid, "0x", 2)) { |
535 |
memset (&id, 0, sizeof (id)); |
memset (&id, 0, sizeof (id)); |
536 |
_snprintf (id, sizeof (id)-1, "0x%s", keyid); |
_snprintf (id, DIM (id)-1, "0x%s", keyid); |
537 |
return id; |
return id; |
538 |
} |
} |
539 |
return keyid; |
return keyid; |
550 |
n = 4*strlen (proxy_user) / 3 + 32 + strlen (proxy_pass) + 2; |
n = 4*strlen (proxy_user) / 3 + 32 + strlen (proxy_pass) + 2; |
551 |
free_if_alloc (proxy.base64_user); |
free_if_alloc (proxy.base64_user); |
552 |
proxy.base64_user = safe_alloc (n+1); |
proxy.base64_user = safe_alloc (n+1); |
553 |
_snprintf (t, sizeof (t)-1, "%s:%s", proxy_user, proxy_pass); |
_snprintf (t, DIM (t)-1, "%s:%s", proxy_user, proxy_pass); |
554 |
base64_encode (t, proxy.base64_user); |
base64_encode (t, proxy.base64_user); |
555 |
free_if_alloc (proxy.user); |
free_if_alloc (proxy.user); |
556 |
free_if_alloc (proxy.pass); |
free_if_alloc (proxy.pass); |
651 |
} |
} |
652 |
|
|
653 |
|
|
654 |
|
/* Return the specified keyserver config setting @key as an integer. */ |
655 |
|
static int |
656 |
|
get_conf_kserver_int (const char *key) |
657 |
|
{ |
658 |
|
char *p; |
659 |
|
int val = 0; |
660 |
|
|
661 |
|
p = get_reg_entry_keyserver (key); |
662 |
|
if (p && *p) |
663 |
|
val = atoi (p); |
664 |
|
free_if_alloc (p); |
665 |
|
return val; |
666 |
|
} |
667 |
|
|
668 |
|
|
669 |
|
/* Read the proxy configuration and store it into @prox. */ |
670 |
|
static void |
671 |
|
read_proxy_config (keyserver_proxy_t prox) |
672 |
|
{ |
673 |
|
char *proto; |
674 |
|
|
675 |
|
if (!prox) |
676 |
|
return; |
677 |
|
|
678 |
|
proto = get_reg_entry_keyserver("Proto"); |
679 |
|
if (proto != NULL && strlen (proto) > 0) |
680 |
|
prox->proto = atoi (proto); |
681 |
|
else |
682 |
|
prox->proto = PROXY_PROTO_NONE; |
683 |
|
free_if_alloc (proto); |
684 |
|
free_if_alloc (prox->host); |
685 |
|
prox->host = get_reg_entry_keyserver ("Host"); |
686 |
|
free_if_alloc (prox->user); |
687 |
|
prox->user = get_reg_entry_keyserver ("User"); |
688 |
|
free_if_alloc (prox->pass); |
689 |
|
prox->pass = get_reg_entry_keyserver ("Pass"); |
690 |
|
prox->port = get_conf_kserver_int ("Port"); |
691 |
|
} |
692 |
|
|
693 |
|
|
694 |
/* Load the keyserver config file @conf. */ |
/* Load the keyserver config file @conf. */ |
695 |
int |
int |
696 |
kserver_load_conf (const char *conf) |
kserver_load_conf (const char *conf) |
715 |
} |
} |
716 |
no_config=1; |
no_config=1; |
717 |
} |
} |
718 |
get_reg_proxy_prefs (&proxy); |
read_proxy_config (&proxy); |
719 |
if (user && pass) |
if (user && pass) |
720 |
update_proxy_user (user, pass); |
update_proxy_user (user, pass); |
721 |
else if (user && !pass || !user && pass) { |
else if (user && !pass || !user && pass) { |
722 |
msg_box (NULL, _("Invalid proxy configuration." |
msg_box (NULL, _("Invalid proxy configuration. " |
723 |
"You need to set a user and a password" |
"You need to set a user and a password " |
724 |
"to use proxy authentication!"), |
"to use proxy authentication!"), |
725 |
_("Proxy Error"), MB_ERR); |
_("Proxy Error"), MB_ERR); |
726 |
} |
} |
735 |
|
|
736 |
pos = 0; |
pos = 0; |
737 |
while (fp && !feof (fp)) { |
while (fp && !feof (fp)) { |
738 |
s = fgets (buf, sizeof (buf)-1, fp); |
s = fgets (buf, DIM (buf)-1, fp); |
739 |
if (!s) |
if (!s) |
740 |
break; |
break; |
741 |
if (strstr (buf, "\r\n")) |
if (strstr (buf, "\r\n")) |
796 |
struct sockaddr_in sock; |
struct sockaddr_in sock; |
797 |
char host[128] = {0}; |
char host[128] = {0}; |
798 |
DWORD iaddr; |
DWORD iaddr; |
799 |
|
bool use_proxy = proxy.host != NULL; |
800 |
int rc, fd; |
int rc, fd; |
801 |
|
|
|
log_debug ("kserver_connect: %s:%d\r\n", hostname, port); |
|
|
|
|
802 |
if (!port) |
if (!port) |
803 |
port = HKP_PORT; |
port = HKP_PORT; |
804 |
if (conn_fd) |
if (conn_fd) |
805 |
*conn_fd = 0; |
*conn_fd = 0; |
806 |
hostname = skip_type_prefix (hostname); |
hostname = skip_type_prefix (hostname); |
807 |
|
log_debug ("kserver_connect: %s:%d\r\n", hostname, port); |
808 |
|
|
809 |
if (proxy.host && proxy.proto == PROXY_PROTO_HTTP) |
if (use_proxy && proxy.proto == PROXY_PROTO_HTTP) |
810 |
port = proxy.port; |
port = proxy.port; |
811 |
memset (&sock, 0, sizeof (sock)); |
memset (&sock, 0, sizeof (sock)); |
812 |
sock.sin_family = AF_INET; |
sock.sin_family = AF_INET; |
813 |
sock.sin_port = htons (port); |
sock.sin_port = htons (port); |
814 |
if (proxy.host) |
if (use_proxy) |
815 |
strncpy (host, proxy.host, 127); |
strncpy (host, proxy.host, DIM (host)-1); |
816 |
else |
else |
817 |
strncpy (host, hostname, 127); |
strncpy (host, hostname, DIM (host)-1); |
818 |
|
|
819 |
if ((iaddr = inet_addr (host)) != INADDR_NONE) |
if ((iaddr = inet_addr (host)) != INADDR_NONE) |
820 |
memcpy (&sock.sin_addr, &iaddr, sizeof (iaddr)); |
memcpy (&sock.sin_addr, &iaddr, sizeof (iaddr)); |
827 |
} |
} |
828 |
else { |
else { |
829 |
log_debug ("gethostbyname: failed ec=%d.\r\n", net_errno); |
log_debug ("gethostbyname: failed ec=%d.\r\n", net_errno); |
830 |
return WPTERR_WINSOCK_RESOLVE; |
return use_proxy? WPTERR_WINSOCK_PROXY : WPTERR_WINSOCK_RESOLVE; |
831 |
} |
} |
832 |
fd = socket (AF_INET, SOCK_STREAM, 0); |
fd = socket (AF_INET, SOCK_STREAM, 0); |
833 |
if (fd == INVALID_SOCKET) |
if (fd == INVALID_SOCKET) |
836 |
if (rc == SOCKET_ERROR) { |
if (rc == SOCKET_ERROR) { |
837 |
log_debug ("connect: failed ec=%d.\r\n", net_errno); |
log_debug ("connect: failed ec=%d.\r\n", net_errno); |
838 |
closesocket (fd); |
closesocket (fd); |
839 |
return WPTERR_WINSOCK_CONNECT; |
return use_proxy? WPTERR_WINSOCK_PROXY : WPTERR_WINSOCK_CONNECT; |
840 |
} |
} |
841 |
|
|
842 |
if (proxy.proto == PROXY_PROTO_SOCKS5) { |
if (proxy.proto == PROXY_PROTO_SOCKS5) { |
843 |
|
/* XXX: finish code and provide errors constants. */ |
844 |
rc = socks_handshake (&proxy, fd, hostname, port); |
rc = socks_handshake (&proxy, fd, hostname, port); |
845 |
if (rc) { |
if (rc) { |
846 |
closesocket (fd); |
closesocket (fd); |
847 |
return WPTERR_GENERAL; /* XXX: use better code. */ |
return WPTERR_GENERAL; |
848 |
} |
} |
849 |
} |
} |
850 |
|
|
1046 |
goto leave; |
goto leave; |
1047 |
} |
} |
1048 |
|
|
1049 |
rc = sock_read (conn_fd, log, sizeof (log)-1, &n); |
rc = sock_read (conn_fd, log, DIM (log)-1, &n); |
1050 |
if (rc == SOCKET_ERROR) { |
if (rc == SOCKET_ERROR) { |
1051 |
rc = WPTERR_WINSOCK_SENDKEY; |
rc = WPTERR_WINSOCK_SENDKEY; |
1052 |
goto leave; |
goto leave; |
1074 |
int n=0; |
int n=0; |
1075 |
|
|
1076 |
/* parse response 'HTTP/1.0 500 OK' */ |
/* parse response 'HTTP/1.0 500 OK' */ |
1077 |
if (sock_getline (fd, buf, sizeof (buf)-1, &n)) |
if (sock_getline (fd, buf, DIM (buf)-1, &n)) |
1078 |
return WPTERR_KEYSERVER_NOTFOUND; |
return WPTERR_KEYSERVER_NOTFOUND; |
1079 |
|
|
1080 |
log_debug ("kserver_search_chkpresp: %s\r\n", buf); |
log_debug ("kserver_search_chkpresp: %s\r\n", buf); |
1179 |
|
|
1180 |
/* Skip all lines until we reach the "info:" record. */ |
/* Skip all lines until we reach the "info:" record. */ |
1181 |
for (;;) { |
for (;;) { |
1182 |
if (sock_getline (sock_fd, status, sizeof (status)-1, &reqlen)) { |
if (sock_getline (sock_fd, status, DIM (status)-1, &reqlen)) { |
1183 |
log_debug ("kserver_search_begin: retrieving status line failed.\r\n"); |
log_debug ("kserver_search_begin: retrieving status line failed.\r\n"); |
1184 |
closesocket (sock_fd); |
closesocket (sock_fd); |
1185 |
sock_fd = 0; |
sock_fd = 0; |
1208 |
enum pub_rec_t {ID=1, KEYID, ALGO, SIZE, CREATE, EXPIRE}; |
enum pub_rec_t {ID=1, KEYID, ALGO, SIZE, CREATE, EXPIRE}; |
1209 |
char *p; |
char *p; |
1210 |
int recno = 0; |
int recno = 0; |
1211 |
|
int off = 0; |
1212 |
|
|
1213 |
/* pub:BF3DF9B4:17:1024:925411133:: */ |
/* pub:BF3DF9B4:17:1024:925411133:: */ |
1214 |
p = strtok (buf, ":"); |
p = strtok (buf, ":"); |
1218 |
case ID: |
case ID: |
1219 |
break; |
break; |
1220 |
|
|
1221 |
case KEYID: |
case KEYID: |
1222 |
|
/* If for any reason the returned record actually contains |
1223 |
|
a fingerprint instead of a key ID, we truncate the fpr. */ |
1224 |
|
off = strlen (p) == 40? 32 : 0; |
1225 |
free_if_alloc (key->keyid); |
free_if_alloc (key->keyid); |
1226 |
key->keyid = m_strdup (p); |
key->keyid = m_strdup (p+off); |
1227 |
break; |
break; |
1228 |
|
|
1229 |
case ALGO: |
case ALGO: |
1244 |
} |
} |
1245 |
p = strtok (NULL, ":"); |
p = strtok (NULL, ":"); |
1246 |
} |
} |
|
|
|
1247 |
} |
} |
1248 |
|
|
1249 |
|
|
1327 |
key = new keyserver_key_s; |
key = new keyserver_key_s; |
1328 |
memset (key, 0, sizeof *key); |
memset (key, 0, sizeof *key); |
1329 |
for (;;) { |
for (;;) { |
1330 |
if (sock_getline (fd, buf, sizeof (buf)-1, &n)) |
if (sock_getline (fd, buf, DIM (buf)-1, &n)) |
1331 |
break; |
break; |
1332 |
/*log_debug ("record: '%s'\r\n", buf); */ |
/*log_debug ("record: '%s'\r\n", buf); */ |
1333 |
if (!strncmp (buf, "pub", 3)) |
if (!strncmp (buf, "pub", 3)) |
1434 |
fp = NULL; |
fp = NULL; |
1435 |
goto leave; |
goto leave; |
1436 |
} |
} |
1437 |
get_temp_name (outf, sizeof (outf)-1, keyid); |
get_temp_name (outf, DIM (outf)-1, keyid); |
1438 |
get_temp_name (inf, sizeof (inf)-1, NULL); |
get_temp_name (inf, DIM (inf)-1, NULL); |
1439 |
fp = fopen (inf, "w+b"); |
fp = fopen (inf, "w+b"); |
1440 |
if (!fp) { |
if (!fp) { |
1441 |
log_box ("LDAP Keyserver Plugin", MB_ERR, "%s: %s", inf, |
log_box ("LDAP Keyserver Plugin", MB_ERR, "%s: %s", inf, |
1492 |
if (gpgme_data_new (&raw)) |
if (gpgme_data_new (&raw)) |
1493 |
BUG (0); |
BUG (0); |
1494 |
while (!feof (fp)) { |
while (!feof (fp)) { |
1495 |
s = fgets (buf, sizeof (buf)-1, fp); |
s = fgets (buf, DIM (buf)-1, fp); |
1496 |
if (!s) |
if (!s) |
1497 |
break; |
break; |
1498 |
if (strstr (s, "KEY") && strstr (s, "FAILED")) { |
if (strstr (s, "KEY") && strstr (s, "FAILED")) { |
1525 |
char **r_key, int *r_keylen) |
char **r_key, int *r_keylen) |
1526 |
{ |
{ |
1527 |
gpgme_data_t raw; |
gpgme_data_t raw; |
1528 |
char buf[256]; |
char buf[256+1]; |
1529 |
int fd, nread; |
int fd, nread; |
1530 |
int start_key = 0; |
int start_key = 0; |
1531 |
int rc=0; |
int rc=0; |
1541 |
BUG (0); |
BUG (0); |
1542 |
|
|
1543 |
for (;;) { |
for (;;) { |
1544 |
if (sock_getline (fd, buf, sizeof (buf), &nread)) |
if (sock_getline (fd, buf, DIM (buf)-1, &nread)) |
1545 |
break; |
break; |
1546 |
strcat (buf, "\n"); |
strcat (buf, "\n"); |
1547 |
if (strstr (buf, "BEGIN PGP PUBLIC KEY BLOCK")) { |
if (strstr (buf, "BEGIN PGP PUBLIC KEY BLOCK")) { |