/[winpt]/trunk/Src/wptKeyserver.cpp
ViewVC logotype

Diff of /trunk/Src/wptKeyserver.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 229 by twoaday, Mon Jun 19 14:04:31 2006 UTC revision 442 by twoaday, Sat Apr 14 14:23:34 2012 UTC
# Line 1  Line 1 
1  /* wptKeyserver.cpp - W32 Keyserver Access  /* wptKeyserver.cpp - W32 Keyserver Access
2   *      Copyright (C) 2000-2006 Timo Schulz   *      Copyright (C) 2000-2009 Timo Schulz
3   *      Copyright (C) 2001 Marco Cunha   *      Copyright (C) 2001 Marco Cunha
4   *   *
5   * This file is part of WinPT.   * This file is part of WinPT.
# Line 13  Line 13 
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * General Public License for more details.   * General Public License for more details.
  *  
  * You should have received a copy of the GNU General Public License  
  * along with WinPT; if not, write to the Free Software Foundation,  
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  
16   */   */
   
17  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
18  #include <config.h>  #include <config.h>
19  #endif  #endif
# Line 29  Line 24 
24  #include <sys/stat.h>  #include <sys/stat.h>
25  #include <ctype.h>  #include <ctype.h>
26    
27    #include "wptGPG.h"
28  #include "wptKeyserver.h"  #include "wptKeyserver.h"
29  #include "wptErrors.h"  #include "wptErrors.h"
30  #include "wptTypes.h"  #include "wptTypes.h"
31  #include "wptNLS.h"  #include "wptNLS.h"
32  #include "wptW32API.h"  #include "wptW32API.h"
 #include "wptGPG.h"  
33  #include "wptRegistry.h"  #include "wptRegistry.h"
34  #include "wptUTF8.h"  #include "wptUTF8.h"
35    #include "wptVersion.h"
36    #include "StringBuffer.h"
37    
38    
39  /* Map net_errno to a winsock error. */  /* Map net_errno to a winsock error. */
40  #define net_errno ((int)WSAGetLastError ())  #define net_errno ((int)WSAGetLastError ())
41    
42    keyserver server[MAX_KEYSERVERS] = {{0}};
 keyserver server[MAX_KEYSERVERS] = {0};  
43  keyserver_proxy_s proxy = {0};  keyserver_proxy_s proxy = {0};
44  static const char *server_list[] = {  static const char *server_list[] = {
45      "hkp://sks.keyserver.penguin.de",      "hkp://pool.sks-keyservers.net",
46      "hkp://subkeys.pgp.net",      "hkp://subkeys.pgp.net",
47      "ldap://keyserver.pgp.com",      "http://minsky.surfnet.nl",
48      NULL      NULL
49  };  };
50    #define NUM_DEF_KEYSERVERS 3
51    
52    static char  hkp_err_msg[384];  /* Holds the error message from the server */
53  static char  hkp_errmsg[1024];  /* Holds the error message from the server */  static int   hkp_has_err = 0;   /* != 0 indicates an error occurred. */
 static int   hkp_err = 0;       /* != 0 indicates an error occurred. */  
54    
55  /* Default keyserver and port. */  /* Default keyserver and port. */
56  char *default_keyserver = NULL;  char *default_keyserver = NULL;
57  WORD default_keyserver_port = 0;  WORD default_keyserver_port = 0;
58    
59  /* Default socket timeout. */  /* Default socket timeout (secs). */
60  static int default_socket_timeout = 6;  static size_t default_socket_timeout = 6;
61    
62    
63    /* Remove %AB sequences from the input buffer @in
64       and store the raw data in @out. */
65    void
66    unhexify_buffer (const char *in, char **r_out)
67    {
68        char temp[3], *out;
69        size_t len, pos, i=0;
70    
71        len = strlen (in);
72        out = new char[len+1];
73        if (!out)
74            BUG (0);
75        memset (out, 0, len+1);
76        for (pos = 0; pos < len; pos++) {
77            if (in[pos] == '%' && in[pos+1] == '%')
78                out[i++] = '%';
79            else if (in[pos] == '%') {
80                temp[0] = in[++pos];
81                temp[1] = in[++pos];
82                temp[2] = 0;
83                out[i++] = (char)strtoul (temp, NULL, 16);
84            }
85            else
86                out[i++] = in[pos];
87        }
88        out[i] = 0;
89        *r_out = out;
90    }
91    
92    
93  /* Wrapper for safe memory allocation. */  /* Wrapper for safe memory allocation. */
94  static char*  static char*
95  safe_alloc (DWORD n)  safe_alloc (DWORD n)
96  {  {
97      char *p;      char *p = new char[n+1];
   
     p = new char[n+1];  
98      if (!p)      if (!p)
99          BUG (0);          BUG (0);
100      memset (p, 0, n);      memset (p, 0, n);
101      return p;      return p;
102  }  }
103    
104    
105  /* Basic64 encode the input @inbuf to @outbuf. */  /* Basic64 encode the input @inbuf to @outbuf. */
106    #if 0
107  static void  static void
108  base64_encode (const char *inbuf, char *outbuf)  base64_encode (const char *inbuf, char *outbuf)
109  {  {
110      char base64code[] =      char base64code[] =
111          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
112      int index = 0, temp = 0, res = 0;      int index = 0, temp = 0, res = 0;
113      int i = 0, inputlen = 0, len = 0;      int inputlen, len = 0;
114            
115      inputlen = strlen (inbuf);      inputlen = strlen (inbuf);
116      for (i = 0; i < inputlen; i++) {      for (int i = 0; i < inputlen; i++) {
117          res = temp;          res = temp;
118          res = (res << 8) | (inbuf[i] & 0xFF);          res = (res << 8) | (inbuf[i] & 0xFF);
119          switch (index++) {          switch (index++) {
# Line 96  base64_encode (const char *inbuf, char * Line 123  base64_encode (const char *inbuf, char *
123              break;              break;
124          case 1:          case 1:
125              outbuf[len++] = base64code[res >> 4 & 0x3F];              outbuf[len++] = base64code[res >> 4 & 0x3F];
126              res &= 0xF;              res &= 0xF;
127              break;              break;
128          case 2:          case 2:
129              outbuf[len++] = base64code[res >> 6 & 0x3F];              outbuf[len++] = base64code[res >> 6 & 0x3F];
# Line 119  base64_encode (const char *inbuf, char * Line 146  base64_encode (const char *inbuf, char *
146    
147      outbuf[len] = '\0';      outbuf[len] = '\0';
148  }  }
149    #endif
150    
151  /* Check that the given buffer contains a valid keyserver URL  /* Check that the given buffer contains a valid keyserver URL
152     and return the prefix length, 0 in case of an error. */     and return the prefix length, 0 in case of an error. */
153  static int  static int
154  check_URL (const char *buf)  check_URL (const char *buf)
155  {  {
156      const char *proto[] = {      if (strstr (buf, "hkp://"))
157          "ldap://",          return 6;
158          "http://",      if (strstr (buf, "http://"))
159          "finger://",          return 7;
         "hkp://",  
         NULL};  
     int i;  
   
     if (strlen (buf) < 7)  
         return 0;  
   
     for (i=0; proto[i] != NULL; i++) {  
         if (strstr (buf, proto[i]))  
             return strlen (proto[i]);  
     }  
160      return 0;      return 0;
161  }  }
162    
# Line 160  skip_type_prefix (const char *hostname) Line 176  skip_type_prefix (const char *hostname)
176      return hostname;      return hostname;
177  }  }
178    
179    
180  /* Parse the keyserver response and extract the human  /* Parse the keyserver response and extract the human
181     readable text passages. */     readable text passages. */
182  static int  static int
# Line 167  parse_keyserver_error (const char *resp, Line 184  parse_keyserver_error (const char *resp,
184  {  {
185      char *p, *p2;      char *p, *p2;
186    
187      /* If we find no 'Error' substring, we assume a success. */      /* If we find no 'Error' substring we assume a success. */
188      if (!stristr (resp, "Error"))      if (!stristr (resp, "Error"))
189          return 0;          return -1;
190    
191      memset (txt, 0, txtlen);      memset (txt, 0, txtlen);
192      p = strstr (resp, "\r\n\r\n");      p = strstr (resp, "\r\n\r\n");
# Line 190  parse_keyserver_error (const char *resp, Line 207  parse_keyserver_error (const char *resp,
207      else {      else {
208          if (!strnicmp (resp, "<p>", 3))          if (!strnicmp (resp, "<p>", 3))
209              resp += 3;              resp += 3;
210          while (resp && *resp == '\r' || *resp == '\n')          while (resp && (*resp == '\r' || *resp == '\n'))
211              resp++;              resp++;
212          memcpy (txt, resp, strlen (resp));          memcpy (txt, resp, strlen (resp));
213      }      }
# Line 205  check_hkp_response (const char *resp, in Line 222  check_hkp_response (const char *resp, in
222  {  {
223      int ec;      int ec;
224    
     log_debug ("check_hkp_response: '%s'\r\n", resp);  
225      ec = recv ? WPTERR_WINSOCK_RECVKEY : WPTERR_WINSOCK_SENDKEY;      ec = recv ? WPTERR_WINSOCK_RECVKEY : WPTERR_WINSOCK_SENDKEY;
226        if (!resp)
227            return ec;
228        log_debug ("check_hkp_response: '%s'\r\n", resp);    
229      if (!strstr (resp, "HTTP/1.0 200 OK") &&      if (!strstr (resp, "HTTP/1.0 200 OK") &&
230          !strstr (resp, "HTTP/1.1 200 OK") &&          !strstr (resp, "HTTP/1.1 200 OK") &&
231          !strstr (resp, "HTTP/1.0 500 OK") &&          !strstr (resp, "HTTP/1.0 500 OK") &&
232          !strstr (resp, "HTTP/1.1 500 OK"))          !strstr (resp, "HTTP/1.1 500 OK"))
233          return ec; /* http error */          return ec; /* http error */
234    
235      if (parse_keyserver_error (resp, hkp_errmsg, sizeof (hkp_errmsg)-2)) {      if (!parse_keyserver_error (resp, hkp_err_msg, DIM (hkp_err_msg)-2)) {
236          if (!strlen (hkp_errmsg))          if (!strlen (hkp_err_msg))
237              _snprintf (hkp_errmsg, sizeof (hkp_errmsg)-1,              _snprintf (hkp_err_msg, DIM (hkp_err_msg)-1,
238                          "Unknown keyserver error");                          "Unknown keyserver error");
239          hkp_err = 1;          hkp_has_err = 1;
240          return ec;          return ec;
241      }      }
242      return 0;      return 0;
# Line 230  static int Line 249  static int
249  sock_getline (int fd, char *buf, int buflen, int *nbytes)  sock_getline (int fd, char *buf, int buflen, int *nbytes)
250  {  {
251      char ch;      char ch;
252      int nread = 0;            int nread;
253            
254      if (nbytes)      if (nbytes)
255          *nbytes = 0;          *nbytes = 0;
256      *buf = 0;      *buf = 0;
257        nread = 0;
258      while (recv (fd, &ch, 1, 0) > 0) {      while (recv (fd, &ch, 1, 0) > 0) {
259          *buf++ = ch;          *buf++ = ch;
260          nread++;          nread++;
# Line 253  sock_getline (int fd, char *buf, int buf Line 273  sock_getline (int fd, char *buf, int buf
273    
274    
275  /* Perform a select() on the given fd to find out  /* Perform a select() on the given fd to find out
276     is there is data for reading. Wait at least @nsecs seconds. */     is there is data for reading. Wait at least @nsecs milli seconds. */
277  static int  static int
278  sock_select (int fd, int nsecs)  sock_select (int fd, int nmsecs)
279  {  {
280      FD_SET rfd;      FD_SET rfd;
281      timeval tv = {nsecs, 0};      timeval tv = {0, nmsecs*1000};
282    
283      FD_ZERO (&rfd);      FD_ZERO (&rfd);
284      FD_SET (fd, &rfd);      FD_SET (fd, &rfd);
# Line 277  sock_select (int fd, int nsecs) Line 297  sock_select (int fd, int nsecs)
297     returned in @nbytes.     returned in @nbytes.
298     Return value: 0 on success. */     Return value: 0 on success. */
299  static int  static int
300  sock_read (int fd, char *buf, int buflen, int *nbytes)  sock_read (int fd, char *buf, size_t buflen, int *nbytes)
301  {  {    
302      DWORD nread;      size_t nleft = buflen;
303      int nleft = buflen;      size_t n;
304      int rc, n = 0;      int nread;
305        int rc;
306            
307      if (nbytes)      if (nbytes)
308          *nbytes = 0;          *nbytes = 0;
309        n = 0;
310      while (nleft > 0) {      while (nleft > 0) {
311          if (n >= default_socket_timeout)          if (n >= default_socket_timeout)
312              return WPTERR_WINSOCK_TIMEOUT;              return WPTERR_WINSOCK_TIMEOUT;
313          rc = sock_select (fd, 1);          rc = sock_select (fd, 400);
314          if (rc == SOCKET_ERROR)          if (rc == SOCKET_ERROR)
315              return rc;              return rc;
316          else if (!rc)          else if (!rc)
# Line 315  sock_read (int fd, char *buf, int buflen Line 337  sock_read (int fd, char *buf, int buflen
337  /* Helper to create a string from the gpgme data and  /* Helper to create a string from the gpgme data and
338     then release the gpgme data object. */     then release the gpgme data object. */
339  char*  char*
340  data_release_and_get_mem (gpgme_data_t in, int *r_bufferlen)  data_release_and_get_mem (gpgme_data_t in, size_t *r_bufferlen)
341  {  {    
     size_t n;  
342      char *buffer, *p;      char *buffer, *p;
343        size_t n;
344    
345      gpg_data_putc (in, '\0');      gpg_data_putc (in, '\0');
346      p = gpgme_data_release_and_get_mem (in, &n);      p = gpgme_data_release_and_get_mem (in, &n);
347      buffer = m_strdup (p);      buffer = m_strdup (p);
348      if (r_bufferlen)      if (r_bufferlen)
349          *r_bufferlen = (int)n;          *r_bufferlen = n;
350      gpgme_free (p);      gpgme_free (p);
351      return buffer;      return buffer;
352  }  }
# Line 334  data_release_and_get_mem (gpgme_data_t i Line 356  data_release_and_get_mem (gpgme_data_t i
356     return the data in @buffer. Caller must free data.     return the data in @buffer. Caller must free data.
357     Return value: 0 on success. */     Return value: 0 on success. */
358  int  int
359  sock_read_ext (int fd, char **buffer, int *r_bufferlen)  sock_read_ext (int fd, char **buffer, size_t *r_bufferlen)
360  {  {
361      gpgme_data_t dh;      gpgme_data_t dh;
362      char buf[1024];      char buf[1024];
363      size_t n=0;      size_t timeout=0;
364      int nread, rc;      int rc;
365    
366        *buffer = NULL;
367      if (gpgme_data_new (&dh))      if (gpgme_data_new (&dh))
368          BUG (0);          return SOCKET_ERROR;
369      while (n < 10) {      while (timeout < default_socket_timeout) {
370          rc = sock_select (fd, 1);          rc = sock_select (fd, 500);
371          if (rc == SOCKET_ERROR) {          if (rc == SOCKET_ERROR) {
372              gpgme_data_release (dh);              gpgme_data_release (dh);
373              return rc;              return rc;
374          }          }
375          else if (!rc)          else if (!rc)
376              n++;              timeout++; /* socket not ready yet. */
377          else {          else {
378              nread = recv (fd, buf, sizeof (buf), 0);              int nread = recv (fd, buf, DIM (buf), 0);
379                log_debug ("recv n=%d bytes\r\n", nread);
380              if (nread == SOCKET_ERROR)              if (nread == SOCKET_ERROR)
381                  return SOCKET_ERROR;                  return SOCKET_ERROR;
382              else if (!nread)              else if (!nread)
# Line 360  sock_read_ext (int fd, char **buffer, in Line 384  sock_read_ext (int fd, char **buffer, in
384              gpgme_data_write (dh, buf, nread);              gpgme_data_write (dh, buf, nread);
385          }          }
386      }      }
387        
388        if (timeout >= default_socket_timeout) {
389            gpgme_data_release (dh);
390            log_debug ("sock_read_ext: timeout\r\n");
391            return WPTERR_WINSOCK_TIMEOUT;
392        }
393        log_debug ("sock_read_ext: success\r\n");
394      *buffer = data_release_and_get_mem (dh, r_bufferlen);      *buffer = data_release_and_get_mem (dh, r_bufferlen);
395      return 0;      return 0;
396  }  }
# Line 368  sock_read_ext (int fd, char **buffer, in Line 398  sock_read_ext (int fd, char **buffer, in
398    
399  /* Write the buffer @buf with the length @buflen to a socket @fd. */  /* Write the buffer @buf with the length @buflen to a socket @fd. */
400  static int  static int
401  sock_write (int fd, const char *buf, int buflen)  sock_write (int fd, const char *buf, size_t buflen)
402  {  {
403      DWORD nwritten;      int nwritten;
404      int nleft = buflen;      int nleft = buflen;
405    
406      while (nleft > 0) {      while (nleft > 0) {
# Line 401  wsock_init (void) Line 431  wsock_init (void)
431  }  }
432    
433    
434  /* Cleanup the Winsock2 interface. */  /* Cleanup the Winsock2 interface and free all resources. */
435  void  void
436  wsock_end (void)  wsock_end (void)
437  {  {
438      char *p;      if (default_keyserver != NULL) {
439      int i;          char str_port[64];
440            set_reg_entry_keyserver ("Default", default_keyserver);
441      p = make_special_filename (CSIDL_APPDATA, "winpt\\keyserver.conf", NULL);          free_if_alloc (default_keyserver);
442      kserver_save_conf (p);          sprintf (str_port, "%d", default_keyserver_port);
443      free_if_alloc (p);          set_reg_entry_keyserver ("Default_Port", str_port);
444      free_if_alloc (default_keyserver);      }  
445      for (i=0; i < MAX_KEYSERVERS; i++) {      for (int i=0; i < MAX_KEYSERVERS; i++) {
446          if (server[i].used && server[i].name != NULL)          if (server[i].name != NULL)
447              free_if_alloc (server[i].name);              free_if_alloc (server[i].name);
448      }      }
449      kserver_proxy_release (&proxy);      kserver_proxy_release (&proxy);
# Line 431  wsock_strerror (void) Line 461  wsock_strerror (void)
461      if (!ec)      if (!ec)
462          return "";          return "";
463      switch (ec) {      switch (ec) {
464        case WSANOTINITIALISED:
465            return _("Winsock subsystem has not been initialized");
466            
467      case WSAENETDOWN:      case WSAENETDOWN:
468          return _("Network unreachable");          return _("Network subsystem has failed");
469    
     case WSAEHOSTUNREACH:  
         return _("Host unreachable");  
470    
471        case WSATRY_AGAIN:
472            return _("Nonauthoritative host not found, or server failure");
473            
474      case WSAHOST_NOT_FOUND:      case WSAHOST_NOT_FOUND:
475          return _("Could not resolve host name");          return _("Could not resolve host name");
476    
     case WSAECONNREFUSED:  
         return _("Connection refused");  
   
477      case WSAETIMEDOUT:      case WSAETIMEDOUT:
478      case WSAECONNABORTED:      case WSAECONNABORTED:
479          return _("Connection timeout");          return _("Connection timeout");
480    
481      case WSAENETRESET:      case WSAENETRESET:
482      case WSAECONNRESET:          case WSAECONNRESET:
483          return _("Connection resetted by peer");          return _("Connection resetted by peer");
484    
485        case WSAENETUNREACH:
486            return _("The network cannot be reached from this host at this time");
487            
488        case WSAEHOSTUNREACH:
489            return _("A socket operation was attempted to an unreachable host");
490            
491        case WSAECONNREFUSED:
492            return _("The attempt to connect was forcefully rejected");
493            
494      case WSAESHUTDOWN:      case WSAESHUTDOWN:
495          return _("Socket has been shutdown");          return _("Socket has been shutdown");
496    
# Line 458  wsock_strerror (void) Line 498  wsock_strerror (void)
498          break;          break;
499      }      }
500    
501      return "";      return _("Unknown network error");
502  }  }
503    
504    
505  /* Set default socket timeout for all reading operations. */  /* Set default socket timeout for all reading operations. */
506  void  void
507  kserver_set_socket_timeout (int nsec)  kserver_set_socket_timeout (size_t nsec)
508  {  {
509      if (nsec < 0 || nsec > 3600)      if (nsec < 0 || nsec > 3600)
510          nsec = 0;          nsec = 10;
511      default_socket_timeout = nsec;      default_socket_timeout = nsec;
512  }  }
513    
# Line 476  kserver_set_socket_timeout (int nsec) Line 516  kserver_set_socket_timeout (int nsec)
516  const char*  const char*
517  kserver_strerror (void)  kserver_strerror (void)
518  {        {      
519      if (hkp_err)      return hkp_has_err? hkp_err_msg : NULL;
         return hkp_errmsg;  
     return NULL;  
520  }  }
521    
522    
# Line 491  kserver_get_hostname (int idx, int type, Line 529  kserver_get_hostname (int idx, int type,
529          *port = default_keyserver_port;          *port = default_keyserver_port;
530          return default_keyserver;          return default_keyserver;
531      }      }
532      else if (!type && idx < DIM (server_list)) {      else if (!type && (size_t)idx < DIM (server_list)) {
         /* XXX: handle non HKP servers. */  
533          *port = HKP_PORT;          *port = HKP_PORT;
534          return server_list[idx];          return server_list[idx];
535      }      }
# Line 523  kserver_check_inet_connection (void) Line 560  kserver_check_inet_connection (void)
560  const char*  const char*
561  kserver_check_keyid (const char *keyid)  kserver_check_keyid (const char *keyid)
562  {        {      
563      static char id[22];      static char id[64];
564    
565      if (strstr (keyid, "@"))      if (strstr (keyid, "@"))
566          return keyid; /* email address */          return keyid; /* email address */
567      if (strncmp (keyid, "0x", 2)) {      if (strncmp (keyid, "0x", 2)) {
568          memset (&id, 0, sizeof (id));          memset (&id, 0, sizeof (id));
569          _snprintf (id, sizeof (id)-1, "0x%s", keyid);          _snprintf (id, DIM (id)-1, "0x%s", keyid);
570          return id;          return id;
571      }      }
572      return keyid;      return keyid;
# Line 537  kserver_check_keyid (const char *keyid) Line 574  kserver_check_keyid (const char *keyid)
574    
575    
576  /* Update the keyserver proxy user. */  /* Update the keyserver proxy user. */
577    #if 0
578  static void  static void
579  update_proxy_user (const char *proxy_user, const char *proxy_pass)  update_proxy_user (const char *proxy_user, const char *proxy_pass)
580  {  {
581      char t[257]; /* user:pass = 127+1+127+1 = 257 */      char t[257]; /* user:pass = 127+1+127+1 = 257 */
582      int n = 0;      size_t n;
583    
584      n = 4*strlen (proxy_user) / 3 + 32 + strlen (proxy_pass) + 2;      n = 4*(strlen (proxy_user) + strlen (proxy_pass))/3 + 32 + 2;
585      free_if_alloc (proxy.base64_user);      free_if_alloc (proxy.base64_user);
586      proxy.base64_user = safe_alloc (n+1);      proxy.base64_user = safe_alloc (n+1);
587      _snprintf (t, sizeof (t)-1, "%s:%s", proxy_user, proxy_pass);      _snprintf (t, DIM (t)-1, "%s:%s", proxy_user, proxy_pass);
588      base64_encode (t, proxy.base64_user);      base64_encode (t, proxy.base64_user);
589      free_if_alloc (proxy.user);      free_if_alloc (proxy.user);
590      free_if_alloc (proxy.pass);      free_if_alloc (proxy.pass);
591      proxy.user = m_strdup (proxy_user);      proxy.user = m_strdup (proxy_user);
592      proxy.pass = m_strdup (proxy_pass);      proxy.pass = m_strdup (proxy_pass);
593  }  }
594        #endif
   
 /* Get the port number from the given protocol. */  
 static int  
 port_from_proto (int proto)  
 {  
     switch (proto) {  
     case KSPROTO_LDAP:   return LDAP_PORT;  
     case KSPROTO_FINGER: return FINGER_PORT;  
     case KSPROTO_HTTP:   return HKP_PORT;  
     }  
     return 0;  
 }  
   
   
 /* Get the port number from the given URL. */  
 static int  
 proto_from_URL (const char *buf)  
 {  
     if (strstr (buf, "ldap"))  
         return KSPROTO_LDAP;  
     else if (strstr (buf, "finger"))  
         return KSPROTO_FINGER;  
     return KSPROTO_HKP;  
 }  
   
595    
596  /* Set the default keyserver.  /* Set the default keyserver. The position is always one. */
    If @hostname is NULL, use the predefined keyserver. */  
597  void  void
598  keyserver_set_default (const char *hostname, WORD port)  keyserver_set_default (const char *hostname, WORD port)
599  {  {
600      if (!port)      int pos=0;
601        
602        if (port == 0)
603          port = HKP_PORT;          port = HKP_PORT;
604      if (hostname != NULL) {      
605          free_if_alloc (default_keyserver);      free_if_alloc (default_keyserver);
606          default_keyserver = m_strdup (hostname);      default_keyserver = m_strdup (hostname);
607          default_keyserver_port = port;      default_keyserver_port = port;
608        
609        while (pos < MAX_KEYSERVERS) {
610            if (server[pos].is_default)
611                break;
612            if (server[pos].used) {
613                pos++;
614                continue;
615            }
616            break;
617      }      }
618      if (!default_keyserver) {      free_if_alloc (server[pos].name);
619          default_keyserver = m_strdup (DEF_HKP_KEYSERVER);      server[pos].name =  m_strdup (default_keyserver);
620          default_keyserver_port = HKP_PORT;      server[pos].used = 1;
621      }      server[pos].port = port;
622      server[0].name =  m_strdup (default_keyserver);      server[pos].is_default = 1;
     server[0].used = 1;  
     server[0].port = port;  
     server[0].proto = proto_from_URL (default_keyserver);  
623  }  }
624    
625    
626  /* Skip all kind of whitespace chars in @str. */  /* Skip all kind of whitespace chars in @str. */
627    #if 0
628  static const char*  static const char*
629  skip_whitespace (const char *str)  skip_whitespace (const char *str)
630  {  {
# Line 619  skip_whitespace (const char *str) Line 640  skip_whitespace (const char *str)
640      }      }
641      return str;      return str;
642  }  }
643    #endif
644    
645    
646  /* Save the keyserver config file in @conf. */  /* Return the specified keyserver config setting @key as an integer. */
647  int  #if 0
648  kserver_save_conf (const char *conf)  static int
649    get_conf_kserver_int (const char *key)
650  {  {
651      FILE *fp;      char *p;
652      int pos;      int val = 0;
653    
654      fp = fopen (conf, "wb");      p = get_reg_entry_keyserver (key);
655      if (!fp) {      if (p && *p)
656          msg_box (NULL, _("Could not save keyserver.conf file"),          val = atoi (p);
657                   _("Keyserver"), MB_ERR);      free_if_alloc (p);
658          return -1;      return val;
659      }  }
660    #endif
661    
662      fprintf (fp, "# do NOT manually modify this file, it will be "  /* Read the proxy configuration and store it into @prox. */
663                   "generated automatically!!\r\n");  #if 0
664      for (pos = 0; pos < MAX_KEYSERVERS; pos++) {  static void
665          if (!server[pos].used)  read_proxy_config (keyserver_proxy_t prox)
666              continue;  {
667          fprintf (fp, "%s:%d\r\n", server[pos].name, server[pos].port);      char *proto;
668    
669        if (!prox)
670            return;
671        
672        proto = get_reg_entry_keyserver("Proto");
673        if (proto != NULL && strlen (proto) > 0)
674            prox->proto = atoi (proto);
675        else
676            prox->proto = PROXY_PROTO_NONE;
677        free_if_alloc (proto);
678        
679        free_if_alloc (prox->host);
680        prox->host = get_reg_entry_keyserver ("Host");
681        
682        free_if_alloc (prox->user);
683        prox->user = get_reg_entry_keyserver ("User");
684        
685        free_if_alloc (prox->pass);
686        prox->pass = get_reg_entry_keyserver ("Pass");
687        
688        prox->port = get_conf_kserver_int ("Port");
689    }
690    #endif
691    
692    
693    static int
694    is_keyserver_present (const char *name)
695    {
696        for (int i=0; i < MAX_KEYSERVERS; i++) {
697            if (server[i].name != NULL &&
698                stricmp (server[i].name, name) == 0)
699                return 1;
700      }      }
     fclose (fp);  
701      return 0;      return 0;
702  }  }
703    
704    /* Load the keyserver configuration. */
 /* Load the keyserver config file @conf. */  
705  int  int
706  kserver_load_conf (const char *conf)  kserver_load_conf (void)
707  {      {
708      FILE *fp;      char *str_server, *str_port;
709      char buf[1024], *s, *p;      int port, list_pos;    
     char *user = NULL, *pass = NULL;      
     int no_config=0, chk_pos=0;  
     int pos;  
       
     for (pos = 0; pos < MAX_KEYSERVERS; pos++) {  
         server[pos].used = 0;  
         server[pos].port = HKP_PORT;  
     }  
710            
711      fp = fopen (conf, "rb");      /* If a preferred keyserver is available, load
712      if (!fp) {       * the values and store it at position 0.
713          for (pos = 0; server_list[pos]; pos++) {       */
714              server[pos].used = 1;      str_server = get_reg_entry_keyserver("Default");
715              server[pos].name = m_strdup (server_list[pos]);      if (str_server && *str_server) {
716              server[pos].proto = proto_from_URL (server_list[pos]);          port = HKP_PORT;
717          }          str_port = get_reg_entry_keyserver("Default_Port");
718          no_config=1;          if (str_port && *str_port)
719      }              port = atoi (str_port);        
720      get_reg_proxy_prefs (&proxy);          keyserver_set_default (str_server, port);
721      if (user && pass)          free_if_alloc (str_port);
722          update_proxy_user (user, pass);      }
723      else if (user && !pass || !user && pass) {      free_if_alloc (str_server);
724          msg_box (NULL, _("Invalid proxy configuration."      
725                           "You need to set a user and a password"      /* Now add the default pool servers after the
726                           "to use proxy authentication!"),       * preferred keyserver if present.
727                           _("Proxy Error"), MB_ERR);       */
728      }      list_pos = 1;
729      /* check if the host has a http:// prefix and skip it */      for (int i=0; server_list[i] != NULL; i++) {
730      if (proxy.host && !strncmp (proxy.host, "http://", 7)) {          if (is_keyserver_present (server_list[i]))
         char *host = m_strdup (proxy.host+7);  
         free_if_alloc (proxy.host);  
         proxy.host = host;  
     }  
     free_if_alloc (user);  
     free_if_alloc (pass);  
       
     pos = 0;  
     while (fp && !feof (fp)) {  
         s = fgets (buf, sizeof (buf)-1, fp);  
         if (!s)  
             break;  
         if (strstr (buf, "\r\n"))  
             buf[strlen (buf)-2] = '\0';  
         if (strstr (buf, "\n"))  
             buf[strlen (buf)-1] = '\0';  
         s = (char *)skip_whitespace (buf);  
         if (*s == '#' || strlen (s) < 7)  
             continue;  
         chk_pos = check_URL (s);  
         if (!chk_pos) {  
             msg_box (NULL, _("All entries of this file must have a valid prefix.\n"  
                              "Currently HKP/HTTP, LDAP and FINGER are supported.\n"),  
                              _("Keyserver Error"), MB_ERR);  
731              continue;              continue;
732          }          server[list_pos].used = 1;
733          p = strchr (s+chk_pos, ':');          server[list_pos].port = HKP_PORT;
734          server[pos].used = 1;          server[list_pos].name = m_strdup (server_list[i]);
735          server[pos].proto = proto_from_URL (s);          server[list_pos].is_default = 0;
736          server[pos].port = port_from_proto (server[pos].proto);          list_pos++;
737          if (!p)          if (list_pos > MAX_KEYSERVERS)
             server[pos].name = m_strdup (s);  
         else {        
             server[pos].port = atol (p+1);  
             if (server[pos].port < 0 || server[pos].port > 65536)  
                 server[pos].port = HKP_PORT;  
             server[pos].name = safe_alloc ((p-s)+2);  
             memset (server[pos].name, 0, (p-s)+2);  
             memcpy (server[pos].name, s, (p-s));  
         }  
         pos++;  
         if (pos > MAX_KEYSERVERS) {  
             msg_box (NULL, _("The keyserver limit is exceeded"),  
                      _("Keyserver Warning"), MB_INFO);  
738              break;              break;
         }  
     }  
     if (fp)  
         fclose (fp);  
     if (!pos) {  
         /* only issue an error if the config file exist but  
            it has no valid entries. */  
         keyserver_set_default (NULL, HKP_PORT);  
         if (!no_config)  
             return WPTERR_CONFIG_FILE;  
739      }      }
   
740      return 0;      return 0;
741  }  }
742    
# Line 752  kserver_connect (const char *hostname, W Line 750  kserver_connect (const char *hostname, W
750      struct sockaddr_in sock;      struct sockaddr_in sock;
751      char host[128] = {0};      char host[128] = {0};
752      DWORD iaddr;      DWORD iaddr;
753        bool use_proxy = proxy.host != NULL;
754      int rc, fd;      int rc, fd;
755    
     log_debug ("kserver_connect: %s:%d\r\n", hostname, port);  
   
756      if (!port)      if (!port)
757          port = HKP_PORT;          port = HKP_PORT;
758      if (conn_fd)      if (conn_fd)
759          *conn_fd = 0;          *conn_fd = 0;
760      hostname = skip_type_prefix (hostname);      hostname = skip_type_prefix (hostname);
761        log_debug ("kserver_connect: %s:%d\r\n", hostname, port);
762            
763      if (proxy.host && proxy.proto == PROXY_PROTO_HTTP)      if (use_proxy && proxy.proto == PROXY_PROTO_HTTP)
764          port = proxy.port;          port = proxy.port;
765      memset (&sock, 0, sizeof (sock));      memset (&sock, 0, sizeof (sock));
766      sock.sin_family = AF_INET;      sock.sin_family = AF_INET;
767      sock.sin_port = htons (port);      sock.sin_port = htons (port);
768      if (proxy.host)      strncpy (host, use_proxy? proxy.host : hostname, DIM (host)-1);
         strncpy (host, proxy.host, 127);  
     else  
         strncpy (host, hostname, 127);  
769    
770      if ((iaddr = inet_addr (host)) != INADDR_NONE)      if ((iaddr = inet_addr (host)) != INADDR_NONE)
771          memcpy (&sock.sin_addr, &iaddr, sizeof (iaddr));          memcpy (&sock.sin_addr, &iaddr, sizeof (iaddr));
# Line 782  kserver_connect (const char *hostname, W Line 777  kserver_connect (const char *hostname, W
777          memcpy (&sock.sin_addr, hp->h_addr, hp->h_length);          memcpy (&sock.sin_addr, hp->h_addr, hp->h_length);
778      }      }
779      else {      else {
780          log_debug ("gethostbyname: failed ec=%d.\r\n", net_errno);          log_debug ("gethostbyname(%s): failed ec=%d.\r\n", host, net_errno);
781          return WPTERR_WINSOCK_RESOLVE;          return use_proxy? WPTERR_WINSOCK_PROXY : WPTERR_WINSOCK_RESOLVE;
782      }      }
783      fd = socket (AF_INET, SOCK_STREAM, 0);      fd = socket (AF_INET, SOCK_STREAM, 0);
784      if (fd == INVALID_SOCKET)        if (fd == (int)INVALID_SOCKET)      
785          return WPTERR_WINSOCK_SOCKET;          return WPTERR_WINSOCK_SOCKET;
786      rc = connect (fd, (struct sockaddr *) &sock, sizeof (sock));      rc = connect (fd, (struct sockaddr *) &sock, sizeof (sock));
787      if (rc == SOCKET_ERROR) {      if (rc == SOCKET_ERROR) {
788          log_debug ("connect: failed ec=%d.\r\n", net_errno);          log_debug ("connect: failed ec=%d.\r\n", net_errno);
789          closesocket (fd);          closesocket (fd);
790          return WPTERR_WINSOCK_CONNECT;          return use_proxy? WPTERR_WINSOCK_PROXY : WPTERR_WINSOCK_CONNECT;
791      }      }
792        
     if (proxy.proto == PROXY_PROTO_SOCKS5) {  
         rc = socks_handshake (&proxy, fd, hostname, port);  
         if (rc) {  
             closesocket (fd);  
             return WPTERR_GENERAL; /* XXX: use better code. */  
         }  
     }  
   
793      if (conn_fd)      if (conn_fd)
794          *conn_fd = fd;          *conn_fd = fd;
795      WSASetLastError (0);      WSASetLastError (0);
# Line 810  kserver_connect (const char *hostname, W Line 797  kserver_connect (const char *hostname, W
797  }  }
798    
799    
800  /* Check if the URL needs to be encoded or not. */  /* Check if the URL needs to be encoded or not.
801  static bool  static bool
802  URL_must_encoded (const char *url)  URL_must_encoded (const char *url)
803  {  {
804      if (strchr (url, '.') || strchr (url, '@') || strchr (url, ' '))      if (strchr (url, '.') || strchr (url, '@') || strchr (url, ' '))
805          return true;          return true;
806      return false;      return false;
807  }  }*/
808    
809    
810  /* Perform URL encoding of the given data. */  /* Perform URL encoding of the given data. */
# Line 825  static char* Line 812  static char*
812  URL_encode (const char *url, DWORD ulen, DWORD *ret_nlen)  URL_encode (const char *url, DWORD ulen, DWORD *ret_nlen)
813  {  {
814      gpgme_data_t hd;      gpgme_data_t hd;
815      char numbuf[5], *p;      char numbuf[8], *p;
816      size_t i;      size_t i, nlen;
     int nlen;  
817    
818      if (gpgme_data_new (&hd))      if (gpgme_data_new (&hd))
819          BUG (0);          BUG (0);
# Line 875  kserver_send_request (const char *hostna Line 861  kserver_send_request (const char *hostna
861                "Proxy-Authorization: Basic %s\r\n"                "Proxy-Authorization: Basic %s\r\n"
862                "Content-type: application/x-www-form-urlencoded\r\n"                "Content-type: application/x-www-form-urlencoded\r\n"
863                "Content-length: %d\r\n"                "Content-length: %d\r\n"
864                  "Connection: close\r\n"
865                "\r\n"                "\r\n"
866                "keytext=%s"                "keytext=%s"
867                "\r\n";                "\r\n";
# Line 891  kserver_send_request (const char *hostna Line 878  kserver_send_request (const char *hostna
878                "Host: %s:%d\r\n"                "Host: %s:%d\r\n"
879                "Content-type: application/x-www-form-urlencoded\r\n"                "Content-type: application/x-www-form-urlencoded\r\n"
880                "Content-length: %d\r\n"                "Content-length: %d\r\n"
881                  "Connection: close\r\n"
882                "\r\n"                "\r\n"
883                "keytext=%s"                "keytext=%s"
884                "\r\n";                "\r\n";
# Line 910  kserver_send_request (const char *hostna Line 898  kserver_send_request (const char *hostna
898  /* Interface for receiving a public key. */  /* Interface for receiving a public key. */
899  int  int
900  kserver_recvkey (const char *hostname, WORD port, const char *keyid,  kserver_recvkey (const char *hostname, WORD port, const char *keyid,
901                   char **r_key, int *r_keylen)                   char **r_key, size_t *r_keylen)
902  {  {
903      const char *fmt;      StringBuffer req;
904      char *request = NULL;      const char *reqbuf;
905      int conn_fd;      int conn_fd;
906      int rc, reqlen;      int rc;
907    
908      if (!port)      if (!port)
909          port = HKP_PORT;          port = HKP_PORT;
910      hkp_err = 0; /* reset */      hkp_has_err = 0; /* reset */
911      rc = kserver_connect (hostname, port, &conn_fd);      rc = kserver_connect (hostname, port, &conn_fd);
912      if (rc)      if (rc)
913          goto leave;          goto leave;
914    
     reqlen = strlen (hostname)+32+strlen (keyid)+1;  
915      if (proxy.host && proxy.user && proxy.proto == PROXY_PROTO_HTTP) {      if (proxy.host && proxy.user && proxy.proto == PROXY_PROTO_HTTP) {
916          fmt = "GET http://%s:%d/pks/lookup?op=get&search=%s HTTP/1.0\r\n"          req = req + "GET http://" + skip_type_prefix (hostname) +
917                "Proxy-Authorization: Basic %s\r\n\r\n";              ":" + port +
918          reqlen =+ strlen (fmt) + strlen (proxy.base64_user)+1;              "/pks/lookup?op=get&search=" + keyid + " HTTP/1.0\r\n" +
919          request = safe_alloc (reqlen+1);              "Proxy-Authorization: Basic " + proxy.base64_user + "\r\n" +
920          _snprintf (request, reqlen, fmt, skip_type_prefix (hostname), port,              "Host: " + skip_type_prefix (hostname) + ":" + port + "\r\n"+
921                     keyid, proxy.base64_user);              "Connection: close\r\n"+
922                "\r\n";
923      }      }
924      else if (proxy.host && proxy.proto == PROXY_PROTO_HTTP) {      else if (proxy.host && proxy.proto == PROXY_PROTO_HTTP) {
925          fmt = "GET http://%s:%d/pks/lookup?op=get&search=%s HTTP/1.0\r\n\r\n";          req = req + "GET http://" + skip_type_prefix (hostname) +
926          reqlen += strlen (fmt)+1;              ":" + port + "/pks/lookup?op=get&search=" + keyid +
927          request = safe_alloc (reqlen+1);              " HTTP/1.0\r\n" +
928          _snprintf (request, reqlen, fmt, skip_type_prefix (hostname),              "Host: " + skip_type_prefix (hostname) + ":" + port + "\r\n"+
929                                           port, keyid);              "Connection: close\r\n"+
930                "\r\n";
931      }      }
932      else {      else
933          fmt = "GET /pks/lookup?op=get&search=%s HTTP/1.0\r\n\r\n";          req = req + "GET /pks/lookup?op=get&search=" + keyid +    
934          reqlen += strlen (fmt)+1;              " HTTP/1.0\r\n"+ // FIXME
935          request = safe_alloc (reqlen+1);              "Host: " + skip_type_prefix (hostname) + ":" + port + "\r\n"+
936          _snprintf (request, reqlen, fmt, keyid);              "Connection: close\r\n"+
937      }              "\r\n";
   
     log_debug ("request:\r\n%s\r\n", request);  
938            
939      rc = sock_write (conn_fd, request, strlen (request));      log_debug ("req:\r\n%s\r\n", req.getBuffer ());  
940    
941        reqbuf = req.getBuffer ();
942        rc = sock_write (conn_fd, reqbuf, strlen (reqbuf));
943      if (rc == SOCKET_ERROR) {      if (rc == SOCKET_ERROR) {
944          rc = WPTERR_WINSOCK_RECVKEY;          rc = WPTERR_WINSOCK_RECVKEY;
945          goto leave;          goto leave;
# Line 970  kserver_recvkey (const char *hostname, W Line 960  kserver_recvkey (const char *hostname, W
960            
961  leave:  leave:
962      closesocket (conn_fd);      closesocket (conn_fd);
     free_if_alloc (request);  
963      return rc;      return rc;
964  }  }
965    
966    
967  /* Interface to send a public key. */  /* Interface to send a public key. */
968  int  int
969  kserver_sendkey (const char *hostname, WORD port, const char *pubkey, int len )  kserver_sendkey (const char *hostname, WORD port,
970                     const char *pubkey, size_t len)
971  {  {
972      char *request = NULL;      char *request = NULL;
973      char log[2048] = {0};      char log[2048] = {0};
974      int conn_fd, n;      int conn_fd, n;
975      int rc;      int rc;
976            
977      hkp_err = 0; /* reset */      hkp_has_err = 0; /* reset */
978      rc = kserver_connect (hostname, port, &conn_fd);      rc = kserver_connect (hostname, port, &conn_fd);
979      if (rc)      if (rc)
980          goto leave;          goto leave;
981            
982      request = kserver_send_request (hostname, port, pubkey, len);      request = kserver_send_request (hostname, port, pubkey, len);
     if (request == NULL) {  
         rc = WPTERR_GENERAL;  
         goto leave;      
     }  
       
983      rc = sock_write (conn_fd, request, strlen (request));      rc = sock_write (conn_fd, request, strlen (request));
984      if (rc == SOCKET_ERROR) {      if (rc == SOCKET_ERROR) {
985          rc = WPTERR_WINSOCK_SENDKEY;          rc = WPTERR_WINSOCK_SENDKEY;
986          goto leave;              goto leave;    
987      }      }
988            
989      rc = sock_read (conn_fd, log, sizeof (log)-1, &n);      rc = sock_read (conn_fd, log, DIM (log)-1, &n);
990      if (rc == SOCKET_ERROR) {      if (rc == SOCKET_ERROR) {
991          rc = WPTERR_WINSOCK_SENDKEY;          rc = WPTERR_WINSOCK_SENDKEY;
992          goto leave;          goto leave;
# Line 1013  kserver_sendkey (const char *hostname, W Line 998  kserver_sendkey (const char *hostname, W
998          goto leave;          goto leave;
999            
1000      WSASetLastError (0);      WSASetLastError (0);
1001        
1002  leave:  leave:
1003      closesocket (conn_fd);      closesocket (conn_fd);
1004      free_if_alloc (request);      free_if_alloc (request);
# Line 1029  kserver_search_chkresp (int fd) Line 1014  kserver_search_chkresp (int fd)
1014      int n=0;      int n=0;
1015            
1016      /* parse response 'HTTP/1.0 500 OK' */      /* parse response 'HTTP/1.0 500 OK' */
1017      if (sock_getline (fd, buf, sizeof (buf)-1, &n))      if (sock_getline (fd, buf, DIM (buf)-1, &n))
1018          return WPTERR_KEYSERVER_NOTFOUND;          return WPTERR_KEYSERVER_NOTFOUND;
1019    
1020      log_debug ("kserver_search_chkpresp: %s\r\n", buf);      log_debug ("kserver_search_chkpresp: %s\r\n", buf);
# Line 1051  kserver_search_end (int conn_fd) Line 1036  kserver_search_end (int conn_fd)
1036    
1037    
1038  /* Extract the amount of keys from the info record. */  /* Extract the amount of keys from the info record. */
1039  static int  static size_t
1040  count_keys_in_response (char *buf)  count_keys_in_response (char *buf)
1041  {  {
1042      char *p;      char *p;
1043      int recno = 0;      int recno = 0;
1044      int n = 0;      size_t n = 0;
1045    
1046      /* info:1:4 */      /* info:1:4 */
1047      if (strncmp (buf, "info", 4))      if (strncmp (buf, "info", 4))
# Line 1079  count_keys_in_response (char *buf) Line 1064  count_keys_in_response (char *buf)
1064     the amount of keys which were found. */     the amount of keys which were found. */
1065  int  int
1066  kserver_search_begin (const char *hostname, WORD port,  kserver_search_begin (const char *hostname, WORD port,
1067                        const char *pattern, int *conn_fd, int *nkeys)                        const char *pattern, int *conn_fd, size_t *nkeys)
1068  {  {
1069      const char *fmt;  
1070      char *request = NULL;      StringBuffer req;
1071        const char *reqbuf;
1072      char *enc_patt = NULL;      char *enc_patt = NULL;
1073      char status[128];      char status[128];
1074      int rc, sock_fd;      int rc, sock_fd;
1075      int reqlen;      int nread;
1076            
1077      *conn_fd = 0;      *conn_fd = 0;
1078    
# Line 1095  kserver_search_begin (const char *hostna Line 1081  kserver_search_begin (const char *hostna
1081          goto leave;          goto leave;
1082    
1083      enc_patt = URL_encode (pattern, strlen (pattern), NULL);      enc_patt = URL_encode (pattern, strlen (pattern), NULL);
     reqlen = strlen (enc_patt) + strlen (hostname) + 32 + 1;  
   
1084      if (proxy.host && proxy.user && proxy.proto == PROXY_PROTO_HTTP) {      if (proxy.host && proxy.user && proxy.proto == PROXY_PROTO_HTTP) {
1085          fmt = "GET http://%s:%d/pks/lookup?options=mr&op=index&search=%s HTTP/1.0\r\n"          req = req + "GET http://" + skip_type_prefix (hostname) + ":" + port +
1086                "Proxy-Authorization: Basic %s\r\n\r\n";              "/pks/lookup?options=mr&op=index&search=" + enc_patt +
1087          reqlen += strlen (proxy.base64_user) + strlen (fmt) + 1;              " HTTP/1.0\r\n" +
1088          request = safe_alloc (reqlen+1);              "Host: " + skip_type_prefix (hostname)  + ":" + port+ "\r\n"+
1089          _snprintf (request, reqlen, fmt, skip_type_prefix (hostname), port,              "Connection: close\r\n" +
1090                     enc_patt, proxy.base64_user);              "Proxy-Authorization: Basic " + proxy.base64_user + "\r\n\r\n";
1091      }          }    
1092      else if (proxy.host && proxy.proto == PROXY_PROTO_HTTP) {      else if (proxy.host && proxy.proto == PROXY_PROTO_HTTP) {
1093          fmt = "GET http://%s:%d/pks/lookup?options=mr&op=index&search=%s HTTP/1.0\r\n\r\n";          req = req + "GET http://" + skip_type_prefix (hostname) + ":" + port +
1094          reqlen += strlen (fmt)+1;              "/pks/lookup?options=mr&op=index&search=" + enc_patt +
1095          request = safe_alloc (reqlen+1);              " HTTP/1.0\r\n"+
1096          _snprintf (request, reqlen, skip_type_prefix (hostname), port,              "Host: " + skip_type_prefix (hostname)  + ":" + port+ "\r\n"+
1097                              enc_patt);              "Connection: close\r\n"+
1098                "\r\n";
1099      }      }
1100      else {      else {
1101          fmt = "GET /pks/lookup?options=mr&op=index&search=%s HTTP/1.0\r\n\r\n";          req = req + "GET /pks/lookup?options=mr&op=index&search=" +
1102          reqlen += strlen (fmt)+1;           enc_patt + " HTTP/1.0\r\n" +
1103          request = safe_alloc (reqlen+1);           "Host: " + skip_type_prefix (hostname)  + ":" + port+ "\r\n"+
1104          _snprintf (request, reqlen, fmt, enc_patt);           "Connection: close\r\n"+
1105             "\r\n";
1106      }      }
1107        
1108      log_debug ("kserver_search_begin:\r\n%s\r\n", request);      log_debug ("kserver_search_begin:\r\n%s\r\n", req.getBuffer ());
1109      if (sock_write (sock_fd, request, strlen (request)) == SOCKET_ERROR) {      reqbuf = req.getBuffer ();
1110        if (sock_write (sock_fd, reqbuf, strlen (reqbuf)) == SOCKET_ERROR) {
1111          rc = WPTERR_GENERAL;          rc = WPTERR_GENERAL;
1112          goto leave;          goto leave;
1113      }      }
# Line 1134  kserver_search_begin (const char *hostna Line 1121  kserver_search_begin (const char *hostna
1121    
1122      /* Skip all lines until we reach the "info:" record. */      /* Skip all lines until we reach the "info:" record. */
1123      for (;;) {      for (;;) {
1124          if (sock_getline (sock_fd, status, sizeof (status)-1, &reqlen)) {                if (sock_getline (sock_fd, status, DIM (status)-1, &nread)) {  
1125              log_debug ("kserver_search_begin: retrieving status line failed.\r\n");              log_debug ("kserver_search_begin: retrieving status line failed.\r\n");
1126              closesocket (sock_fd);              closesocket (sock_fd);
1127              sock_fd = 0;              sock_fd = 0;
# Line 1150  kserver_search_begin (const char *hostna Line 1137  kserver_search_begin (const char *hostna
1137      *conn_fd = sock_fd;      *conn_fd = sock_fd;
1138            
1139  leave:  leave:
     free_if_alloc (request);  
1140      free_if_alloc (enc_patt);      free_if_alloc (enc_patt);
1141      return rc;      return rc;
1142  }  }
# Line 1163  parse_pub_record (keyserver_key_s *key, Line 1149  parse_pub_record (keyserver_key_s *key,
1149      enum pub_rec_t {ID=1, KEYID, ALGO, SIZE, CREATE, EXPIRE};      enum pub_rec_t {ID=1, KEYID, ALGO, SIZE, CREATE, EXPIRE};
1150      char *p;      char *p;
1151      int recno = 0;      int recno = 0;
1152        int off = 0;
1153    
1154      /* pub:BF3DF9B4:17:1024:925411133:: */      /* pub:{BF3DF9B4, ED4681C9BF3DF9B4, FPR}:17:1024:925411133:: */
1155      p = strtok (buf, ":");      p = strtok (buf, ":");
1156      while (p != NULL) {      while (p != NULL) {
1157          recno++;          recno++;
# Line 1172  parse_pub_record (keyserver_key_s *key, Line 1159  parse_pub_record (keyserver_key_s *key,
1159          case ID:          case ID:
1160              break;              break;
1161    
1162          case KEYID:          case KEYID:
1163                /* If for any reason the returned record actually contains
1164                   a fingerprint instead of a key ID, we truncate the fpr. */
1165                off = strlen (p) == 40? 32 : 0;
1166              free_if_alloc (key->keyid);              free_if_alloc (key->keyid);
1167              key->keyid = m_strdup (p);              key->keyid = m_strdup (p+off);
1168              break;              break;
1169    
1170          case ALGO:          case ALGO:
# Line 1195  parse_pub_record (keyserver_key_s *key, Line 1185  parse_pub_record (keyserver_key_s *key,
1185          }          }
1186          p = strtok (NULL, ":");          p = strtok (NULL, ":");
1187      }      }
       
1188  }  }
1189    
1190    
# Line 1279  kserver_search_next (int fd, keyserver_k Line 1268  kserver_search_next (int fd, keyserver_k
1268      key = new keyserver_key_s;      key = new keyserver_key_s;
1269      memset (key, 0, sizeof *key);      memset (key, 0, sizeof *key);
1270      for (;;) {      for (;;) {
1271          if (sock_getline (fd, buf, sizeof (buf)-1, &n))          if (sock_getline (fd, buf, DIM (buf)-1, &n))
1272              break;              break;
1273          /*log_debug ("record: '%s'\r\n", buf); */          /*log_debug ("record: '%s'\r\n", buf); */
1274          if (!strncmp (buf, "pub", 3))          if (!strncmp (buf, "pub", 3))
# Line 1333  kserver_proxy_release (keyserver_proxy_t Line 1322  kserver_proxy_release (keyserver_proxy_t
1322  }  }
1323    
1324    
1325  /* Spawn a process given by @cmdl. */  /* Check if the given name @name is a valid inernet address
1326  static int     which means an dotted IP or a valid DNS name.
1327  spawn_application (char *cmdl)     Return value: 0 on success. */
 {  
     STARTUPINFO si;  
     PROCESS_INFORMATION pi;  
     int rc = 0;  
   
     memset (&si, 0, sizeof (si));  
     si.cb = sizeof (si);  
     si.dwFlags = STARTF_USESHOWWINDOW;  
     si.wShowWindow = SW_HIDE;  
     memset (&pi, 0, sizeof (pi));  
   
     if (!CreateProcess (NULL, cmdl, NULL, NULL, FALSE, 0,  
                         NULL, NULL, &si, &pi)) {  
         log_box ("Keyserver Plugin", MB_ERR, "Could not spawn helper process");  
         rc = -1;  
     }  
   
     CloseHandle (pi.hThread);  
     WaitForSingleObject (pi.hProcess, INFINITE);  
     CloseHandle (pi.hProcess);  
     return rc;  
 }  
   
   
 static FILE*  
 do_spawn_ldap_helper (const char *host, const char *keyid)  
 {  
     FILE *fp = NULL;  
     char *p, *sep;  
     char *ksprg;  
     char outf[256], inf[256];  
     size_t n;  
   
     p = get_gnupg_prog ();  
     n = strlen (p) + 1 + 128;  
     ksprg = safe_alloc (n+1);  
     if (!ksprg)  
         BUG (0);  
     sep = strrchr (p, '\\');  
     if (sep != NULL)  
         p[(sep-p)] = 0;  
   
     _snprintf (ksprg, n, "%s\\gpgkeys_ldap.exe", p);  
     free_if_alloc (p);  
     if (file_exist_check (ksprg)) {  
         log_box ("LDAP Keyserver Plugin", MB_ERR,  
                  "%s: could not find LDAP keyserver module!", ksprg);  
         fp = NULL;  
         goto leave;  
     }  
     get_temp_name (outf, sizeof (outf)-1, keyid);  
     get_temp_name (inf, sizeof (inf)-1, NULL);  
     fp = fopen (inf, "w+b");  
     if (!fp) {  
         log_box ("LDAP Keyserver Plugin", MB_ERR, "%s: %s", inf,  
                  winpt_strerror (WPTERR_FILE_OPEN));  
         goto leave;  
     }  
     fprintf (fp,  
         "VERSION 1\n"  
         "PROGRAM 1.4.3-cvs\n"  
         "SCHEME ldap\n"  
         "HOST %s\n"  
         "COMMAND GET\n"  
         "\n"  
         "%s\n",  
         host? skip_type_prefix (host): "64.94.85.200", keyid);  
     fclose (fp);  
   
     p = safe_alloc (strlen (ksprg) + strlen (inf) + strlen (outf) + 32);  
     sprintf (p, "%s -o %s %s", ksprg, outf, inf);  
     if (spawn_application (p)) {  
         fp = NULL;  
         goto leave;  
     }  
     fp = fopen (outf, "rb");  
     if (!fp)  
         log_box ("LDAP Keyserver Plugin", MB_ERR, "%s: %s", outf,  
                  winpt_strerror (WPTERR_FILE_OPEN));  
   
 leave:  
     DeleteFile (inf);  
     DeleteFile (outf);  
     free_if_alloc (p);  
     free_if_alloc (ksprg);  
     return fp;  
 }  
   
 /* Receive an key via LDAP from host @host with the keyid @keyid.  
    @key contains the key on success. */  
 int  
 ldap_recvkey (const char *host, const char *keyid,  
               char **r_key, int *r_keylen)  
 {    
     gpgme_data_t raw;  
     FILE *fp;  
     const char *s;  
     char buf[512];  
     int start_key = 0, failed = 0;  
     int rc = 0;  
   
     fp = do_spawn_ldap_helper (host, keyid);  
     if (!fp)  
         return WPTERR_GENERAL;  
   
     if (gpgme_data_new (&raw))  
         BUG (0);  
     while (!feof (fp)) {  
         s = fgets (buf, sizeof (buf)-1, fp);  
         if (!s)  
             break;  
         if (strstr (s, "KEY") && strstr (s, "FAILED")) {  
             failed = 1;  
             break;  
         }  
         if (!start_key && strstr (s, "KEY") && strstr (s, "BEGIN")) {  
             start_key = 1;  
             continue;  
         }  
         if (!start_key)  
             continue;  
         gpgme_data_write (raw, buf, strlen (buf));  
         if (strstr (s, "KEY") && strstr (s, "END"))  
             break;  
     }  
     fclose (fp);  
   
     if (failed)  
         rc = WPTERR_WINSOCK_RECVKEY;  
     *r_key = data_release_and_get_mem (raw, r_keylen);  
     return rc;  
 }  
   
   
 /* Receive an key via FINGER from host @host with the user @user.  
    On success @key contains the key. */  
 int  
 finger_recvkey (const char *host, const char *user,  
                 char **r_key, int *r_keylen)  
 {  
     gpgme_data_t raw;  
     char buf[256];  
     int fd, nread;  
     int start_key = 0;  
     int rc=0;  
   
     rc = kserver_connect (host, FINGER_PORT, &fd);  
     if (rc)  
         return rc;  
   
     sock_write (fd, user, strlen (user));  
     sock_write (fd, "\r\n", 2);  
   
     if (gpgme_data_new (&raw))  
         BUG (0);  
   
     for (;;) {  
         if (sock_getline (fd, buf, sizeof (buf), &nread))  
             break;  
         strcat (buf, "\n");  
         if (strstr (buf, "BEGIN PGP PUBLIC KEY BLOCK")) {  
             gpgme_data_write (raw, buf, nread);  
             start_key = 1;  
         }  
         else if (strstr (buf, "END PGP PUBLIC KEY BLOCK" ) && start_key) {  
             gpgme_data_write (raw, buf, nread);  
             start_key--;  
             break;  
         }  
         else if (start_key)  
             gpgme_data_write (raw, buf, nread);  
     }  
   
     closesocket (fd);  
     if (start_key != 0)  
         rc = WPTERR_WINSOCK_RECVKEY;  
     *r_key = data_release_and_get_mem (raw, r_keylen);  
     return rc;  
 }  
   
   
 /* Check if the given name @name is a valid hostname. */  
1328  int  int
1329  check_IP_or_hostname (const char *name)  check_inet_address (const char *addr)
1330  {  {
1331      const char *not_allowed = "=!�$%&@#*~\\/}][{<>|,;:'";      const char *not_allowed = "=!�$%&@#*~\\/}][{<>|,;:'";
     size_t i, j;  
1332    
1333      for (i=0; i < strlen (name); i++) {      for (size_t i=0; i < strlen (addr); i++) {
1334          for (j =0; j < strlen (not_allowed); j++) {          if (strchr (not_allowed, addr[i]))
1335              if (name[i] == not_allowed[j])              return -1;
                 return -1;  
         }  
1336      }      }
1337      return 0;      return 0;
1338  }  }
# Line 1541  parse_keyserver_url (char **r_keyserver, Line 1345  parse_keyserver_url (char **r_keyserver,
1345  {  {
1346      char *p;      char *p;
1347      char *url = *r_keyserver;      char *url = *r_keyserver;
1348      int off = 0;      int off;
1349    
1350      /* no port is given so use the default port. */      /* no port is given so use the default port. */
1351      p = strrchr (url, ':');      p = strrchr (url, ':');
1352      if (p == strchr (url, ':')) {      if (p == strchr (url, ':')) {
1353          int port = port_from_proto (proto_from_URL (url));          *r_port = HKP_PORT;
         if (!port)  
             port = HKP_PORT;  
         *r_port = port;  
1354          return 0;          return 0;
1355      }      }
1356    
1357      if (url[(p-url)-1] == '/') /* remove / in .de/:11371 */      if (url[(p-url)-1] == '/') /* remove / in .de/:11371 */
1358          off = 1;          off = 1;
1359        else
1360            off = 0;
1361    
1362      *r_keyserver = substr (url, 0, (p-url)-off);      *r_keyserver = substr (url, 0, (p-url)-off);
1363      *r_port = atoi (url+(p-url)+1);      *r_port = atoi (url+(p-url)+1);

Legend:
Removed from v.229  
changed lines
  Added in v.442

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26