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

Diff of /trunk/Src/wptGPGUtil.cpp

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

revision 33 by twoaday, Tue Oct 25 07:46:20 2005 UTC revision 121 by twoaday, Mon Dec 12 11:19:56 2005 UTC
# Line 1  Line 1 
1  /* wptGPGUtil.cpp - GPG helper functions  /* wptGPGUtil.cpp - GPG util functions
2   *      Copyright (C) 2005 g10 Code GmbH   *      Copyright (C) 2005 g10 Code GmbH
3   *   *      Copyright (C) 2005 Timo Schulz
4   * This file is part of WinPT.   *
5   *   * This file is part of WinPT.
6   * WinPT is free software; you can redistribute it and/or modify   *
7   * it under the terms of the GNU General Public License as published by   * WinPT is free software; you can redistribute it and/or modify
8   * the Free Software Foundation; either version 2 of the License, or   * it under the terms of the GNU General Public License as published by
9   * (at your option) any later version.   * the Free Software Foundation; either version 2 of the License, or
10   *   * (at your option) any later version.
11   * WinPT is distributed in the hope that it will be useful,   *
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * WinPT is distributed in the hope that it will be useful,
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * GNU General Public License for more details.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   *   * GNU General Public License for more details.
16   * You should have received a copy of the GNU General Public License   *
17   * along with WinPT; if not, write to the Free Software Foundation,   * You should have received a copy of the GNU General Public License
18   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * along with WinPT; if not, write to the Free Software Foundation,
19   */   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  #include <windows.h>   */
21  #include <sys/stat.h>  
22    #ifdef HAVE_CONFIG_H
23  #include "gpgme.h"  #include <config.h>
24    #endif
25    
26  #define NROFHEXDIGITS 2    #include <windows.h>
27  /* Convert two hexadecimal digits from STR to the value they  #include <sys/stat.h>
28     represent.  Returns -1 if one of the characters is not a  
29     hexadecimal digit.  */  #include "gpgme.h"
30  static int  #include "wptTypes.h"
31  hextobyte (const unsigned char *str)  #include "wptErrors.h"
32  {  
33      int val = 0;    #define NROFHEXDIGITS 2  
34      int i;  /* Convert two hexadecimal digits from STR to the value they
35       represent.  Returns -1 if one of the characters is not a
36      for (i = 0; i < NROFHEXDIGITS; i++) {     hexadecimal digit.  */
37          if (*str >= '0' && *str <= '9')  static int
38              val += *str - '0';  hextobyte (const unsigned char *str)
39          else if (*str >= 'A' && *str <= 'F')  {
40              val += 10 + *str - 'A';      int val = 0;  
41          else if (*str >= 'a' && *str <= 'f')      int i;
42              val += 10 + *str - 'a';  
43          else      for (i = 0; i < NROFHEXDIGITS; i++) {
44              return -1;          if (*str >= '0' && *str <= '9')
45          if (i < NROFHEXDIGITS - 1)              val += *str - '0';
46              val *= 16;          else if (*str >= 'A' && *str <= 'F')
47          str++;              val += 10 + *str - 'A';
48      }          else if (*str >= 'a' && *str <= 'f')
49      return val;              val += 10 + *str - 'a';
50  }          else
51                return -1;
52  /* Decode the C formatted string @src and store the result in the          if (i < NROFHEXDIGITS - 1)
53     buffer @destp which is @len bytes long.  If @len is zero, then a              val *= 16;
54     large enough buffer is allocated with malloc and @destp is set to          str++;
55     the result.  Currently, @len is only used to specify if allocation      }
56     is desired or not, the caller is expected to make sure that @destp      return val;
57     is large enough if @len is not zero.  */  }
58  gpgme_error_t  
59  gpg_decode_c_string (const char *src, char **destp, size_t len)  /* Decode the C formatted string @src and store the result in the
60  {     buffer @destp which is @len bytes long.  If @len is zero, then a
61    char *dest;     large enough buffer is allocated with malloc and @destp is set to
62       the result.  Currently, @len is only used to specify if allocation
63    /* Set up the destination buffer.  */     is desired or not, the caller is expected to make sure that @destp
64    if (len) {     is large enough if @len is not zero.  */
65        if (len < strlen (src) + 1)  gpgme_error_t
66            return gpg_error (GPG_ERR_TOO_SHORT);  gpg_decode_c_string (const char *src, char **destp, size_t len)
67        dest = *destp;  {
68    }    char *dest;
69    else {        
70    /* The converted string will never be larger than the original string.  */    /* Set up the destination buffer.  */
71        dest = (char*)malloc (strlen (src) + 1);    if (len) {
72        if (!dest)        if (len < strlen (src) + 1)
73            return gpg_error (GPG_ERR_ENOMEM);            return gpg_error (GPG_ERR_TOO_SHORT);
74        *destp = dest;        dest = *destp;
75    }    }
76      else {      
77    /* Convert the string.  */    /* The converted string will never be larger than the original string.  */
78    while (*src) {            dest = (char*)malloc (strlen (src) + 1);
79        if (*src != '\\') {        if (!dest)
80            *(dest++) = *(src++);            return gpg_error (GPG_ERR_ENOMEM);
81            continue;        *destp = dest;
82        }    }
83    
84        switch (src[1]) {    /* Convert the string.  */
85  #define DECODE_ONE(match,result)        \    while (*src) {    
86        case match:                       \        if (*src != '\\') {
87            src += 2;                     \            *(dest++) = *(src++);
88            *(dest++) = result;           \            continue;
89            break;        }
90    
91            DECODE_ONE ('\'', '\'');        switch (src[1]) {
92            DECODE_ONE ('\"', '\"');  #define DECODE_ONE(match,result)        \
93            DECODE_ONE ('\?', '\?');        case match:                       \
94            DECODE_ONE ('\\', '\\');            src += 2;                     \
95            DECODE_ONE ('a', '\a');            *(dest++) = result;           \
96            DECODE_ONE ('b', '\b');            break;
97            DECODE_ONE ('f', '\f');  
98            DECODE_ONE ('n', '\n');            DECODE_ONE ('\'', '\'');
99            DECODE_ONE ('r', '\r');            DECODE_ONE ('\"', '\"');
100            DECODE_ONE ('t', '\t');            DECODE_ONE ('\?', '\?');
101            DECODE_ONE ('v', '\v');            DECODE_ONE ('\\', '\\');
102              DECODE_ONE ('a', '\a');
103        case 'x': {            DECODE_ONE ('b', '\b');
104              int val = hextobyte ((unsigned char*)&src[2]);            DECODE_ONE ('f', '\f');
105              if (val == -1) { /* Should not happen.  */            DECODE_ONE ('n', '\n');
106                  *(dest++) = *(src++);            DECODE_ONE ('r', '\r');
107                  *(dest++) = *(src++);            DECODE_ONE ('t', '\t');
108                  if (*src)            DECODE_ONE ('v', '\v');
109                    *(dest++) = *(src++);  
110                  if (*src)        case 'x': {
111                    *(dest++) = *(src++);              int val = hextobyte ((unsigned char*)&src[2]);
112              }              if (val == -1) { /* Should not happen.  */
113              else {                  *(dest++) = *(src++);
114                  if (!val) {                  *(dest++) = *(src++);
115                      /* A binary zero is not representable in a C string.  */                  if (*src)
116                      *(dest++) = '\\';                    *(dest++) = *(src++);
117                      *(dest++) = '0';                  if (*src)
118                  }                    *(dest++) = *(src++);
119                  else              }
120                      *((unsigned char *) dest++) = val;              else {
121                  src += 4;                  if (!val) {
122              }                      /* A binary zero is not representable in a C string.  */
123          }                      *(dest++) = '\\';
124                        *(dest++) = '0';
125          default: /* Should not happen.  */                  }
126            {                  else
127              *(dest++) = *(src++);                      *((unsigned char *) dest++) = val;
128              *(dest++) = *(src++);                  src += 4;
129            }              }
130          }          }
131    }  
132    *(dest++) = 0;          default: /* Should not happen.  */
133    return 0;            {
134  }              *(dest++) = *(src++);
135                *(dest++) = *(src++);
136  /* Replace %foo% entries with its real values.            }
137     Return value: expanded path or NULL on error. */          }
138  static char *    }
139  expand_path (const char *path)    *(dest++) = 0;
140  {    return 0;
141      DWORD len;  }
142      char *p;  
143    /* Replace %foo% entries with its real values.
144      len = ExpandEnvironmentStrings (path, NULL, 0);     Return value: expanded path or NULL on error. */
145      if (!len)  static char *
146          return NULL;  expand_path (const char *path)
147      len += 1;  {
148      p = (char*)calloc (1, len+1);      DWORD len;
149      if (!p)      char *p;
150          abort ();  
151      len = ExpandEnvironmentStrings (path, p, len);      len = ExpandEnvironmentStrings (path, NULL, 0);
152      if (!len) {      if (!len)
153          free (p);          return NULL;
154          return NULL;      len += 1;
155      }      p = (char*)calloc (1, len+1);
156      return p;      if (!p)
157  }          BUG (NULL);
158        len = ExpandEnvironmentStrings (path, p, len);
159        if (!len) {
160  /* Read a string from the W32 registry. The directory is given          free (p);
161     in @dir and the name of the value in @name, */          return NULL;
162  static char *      }
163  read_w32_registry (HKEY root_key, const char *dir, const char *name)      return p;
164  {  }
165      HKEY key_handle;  
166      DWORD n1, nbytes;  
167      DWORD type;  /* Read a string from the W32 registry. The directory is given
168      char *result = NULL;     in @dir and the name of the value in @name, */
169        static char *
170      if (RegOpenKeyEx (root_key, dir, 0, KEY_READ, &key_handle))  read_w32_registry (HKEY root_key, const char *dir, const char *name)
171          return NULL; /* no need for a RegClose, so return direct */  {
172            HKEY key_handle;
173      nbytes = 1;      DWORD n1, nbytes;
174      if (RegQueryValueEx (key_handle, name, 0, NULL, NULL, &nbytes))      DWORD type;
175          goto leave;      char *result = NULL;
176      result = (char*)calloc (1, (n1=nbytes+1));      
177      if (!result)      if (RegOpenKeyEx (root_key, dir, 0, KEY_READ, &key_handle))
178          abort ();          return NULL; /* no need for a RegClose, so return direct */
179      if (RegQueryValueEx (key_handle, name, 0, &type, (BYTE*)result, &n1)) {      
180          free (result);      nbytes = 1;
181          result = NULL;      if (RegQueryValueEx (key_handle, name, 0, NULL, NULL, &nbytes))
182          goto leave;          goto leave;
183      }      result = (char*)calloc (1, (n1=nbytes+1));
184      if (type == REG_EXPAND_SZ && strchr (result, '%')) {      if (!result)
185          char *p = expand_path (result);          BUG (NULL);
186          free (result);      if (RegQueryValueEx (key_handle, name, 0, &type, (BYTE*)result, &n1)) {
187          result = p;          free (result);
188      }          result = NULL;
189                goto leave;
190  leave:      }
191      RegCloseKey (key_handle);      if (type == REG_EXPAND_SZ && strchr (result, '%')) {
192      return result;          char *p = expand_path (result);
193  }          free (result);
194            result = p;
195        }
196  /* Create a temp file based on the name of @name.      
197     Return value: handle to the file in case of success. */  leave:
198  static HANDLE      RegCloseKey (key_handle);
199  create_tmpfile (const char *name)      return result;
200  {      }
201      HANDLE out;  
202      SECURITY_ATTRIBUTES sattr;  
203      char tmp[300];  /* Create a temp file based on the name of @name.
204       Return value: handle to the file in case of success. */
205      memset (&sattr, 0, sizeof sattr);  static HANDLE
206      sattr.bInheritHandle = TRUE;  create_tmpfile (const char *name)
207      sattr.lpSecurityDescriptor = NULL;  {    
208      sattr.nLength = sizeof sattr;      HANDLE out;
209        SECURITY_ATTRIBUTES sec_attr;
210      GetTempPath (sizeof (tmp)-1 - strlen (name)-1, tmp);      char tmp[300];
211      strcat (tmp, name);  
212      out = CreateFile (tmp, GENERIC_READ|GENERIC_WRITE,      memset (&sec_attr, 0, sizeof sec_attr);
213                        FILE_SHARE_WRITE, &sattr,      sec_attr.bInheritHandle = TRUE;
214                        OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);      sec_attr.lpSecurityDescriptor = NULL;
215      return out;      sec_attr.nLength = sizeof sec_attr;
216  }  
217        GetTempPath (sizeof (tmp)-1 - strlen (name)-1, tmp);
218        strcat (tmp, name);
219  /* Create a pipe with a readable remote end and      out = CreateFile (tmp, GENERIC_READ|GENERIC_WRITE,
220     write the data from @dat to the local end.                        FILE_SHARE_WRITE, &sec_attr,
221     Return value: read handle on success. */                        OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
222  static HANDLE      if (out == INVALID_HANDLE_VALUE)
223  create_in_pipe (const char *dat)          log_debug ("create_tmpfile: CreateFile failed ec=%d\r\n",
224  {                     (int)GetLastError ());
225      HANDLE r, w;      return out;
226      SECURITY_ATTRIBUTES sec_attr;  }
227      DWORD n;  
228    
229      memset (&sec_attr, 0, sizeof sec_attr);  /* Create a pipe with a readable remote end and
230      sec_attr.bInheritHandle = TRUE;     write the data from @dat to the local end.
231      sec_attr.nLength = sizeof sec_attr;     Return value: read handle on success. */
232    static HANDLE
233      if (!CreatePipe (&r, &w, &sec_attr, 4096))  create_in_pipe (const char *dat)
234          return NULL;  {
235        HANDLE r, w;
236      WriteFile (w, dat, strlen (dat), &n, NULL);      SECURITY_ATTRIBUTES sec_attr;
237      CloseHandle (w);      DWORD n;
238    
239      return r;      memset (&sec_attr, 0, sizeof sec_attr);
240  }      sec_attr.bInheritHandle = TRUE;
241        sec_attr.nLength = sizeof sec_attr;
242    
243  /* Map the contents of the file handle @out to      if (!CreatePipe (&r, &w, &sec_attr, 4096)) {
244     a buffer and return it. */          log_debug ("create_in_pipe: CreatePipeFailed ec=%d\r\n",
245  static char*                     (int)GetLastError ());
246  map_tmpfile (HANDLE out)          return NULL;
247  {      }
248      DWORD n;  
249      char *p;      WriteFile (w, dat, strlen (dat), &n, NULL);
250        CloseHandle (w);
251      FlushFileBuffers (out);  
252      SetFilePointer (out, 0, NULL, FILE_BEGIN);      return r;
253      n = GetFileSize (out, NULL);  }
254      p = (char*)calloc (1, n+1);  
255      if (!p)  
256          abort ();  /* Map the contents of the file handle @out to
257      ReadFile (out, p, n, &n, NULL);     a buffer and return it. */
258      p[n] = 0;  static char*
259      return p;  map_tmpfile (HANDLE out)
260  }  {
261        DWORD n;
262        char *p;
263  /* Create a process from the command line in @cmd.  
264     If @out is != NULL, the output of the process will      FlushFileBuffers (out);
265     be redirected to @out. If @in is != NULL the input      SetFilePointer (out, 0, NULL, FILE_BEGIN);
266     will be read from @in.      n = GetFileSize (out, NULL);
267     Return value: 0 on success. */      p = (char*)calloc (1, n+1);
268  static int      if (!p)
269  create_process (const char *cmd, HANDLE in, HANDLE out)          BUG (NULL);
270  {      ReadFile (out, p, n, &n, NULL);
271      STARTUPINFO si;      p[n] = 0;
272      PROCESS_INFORMATION pi;      return p;
273    }
274      memset (&si, 0, sizeof (si));  
275      si.cb = sizeof si;  
276      if (in || out)  /* Create a process from the command line in @cmd.
277          si.dwFlags = STARTF_USESTDHANDLES;     If @out is != NULL, the output of the process will
278      if (out)     be redirected to @out. If @in is != NULL the input
279          si.hStdOutput = out;     will be read from @in.
280      if (in)     Return value: 0 on success. */
281          si.hStdInput = in;  static int
282      if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,  create_process (const char *cmd, HANDLE in, HANDLE out)
283                          NULL, NULL, &si, &pi))  {
284          return -1;      STARTUPINFO si;
285      WaitForSingleObject (pi.hProcess, INFINITE);      PROCESS_INFORMATION pi;
286      CloseHandle (pi.hProcess);  
287      return 0;      memset (&si, 0, sizeof (si));
288  }      si.cb = sizeof si;
289        if (in || out)
290            si.dwFlags = STARTF_USESTDHANDLES;
291  /* Export a GPG secret key given by @keyid into the file @outfile.      if (out)
292     Return value: 0 on success. */          si.hStdOutput = out;
293  gpgme_error_t      if (in)
294  gpg_export_seckey (const char *keyid, const char *outfile)          si.hStdInput = in;
295  {      si.dwFlags |= STARTF_USESHOWWINDOW;
296      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      si.wShowWindow = SW_HIDE;
297      struct stat st;      if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,
298      char *p;                          NULL, NULL, &si, &pi)) {
299      char *cmd;          log_debug ("create_process: CreateProcess failed ec=%d\r\n",
300                       (int)GetLastError ());
301      p = read_w32_registry (HKEY_CURRENT_USER,          return -1;
302                             "Software\\GNU\\GnuPG", "gpgProgram");      }
303      if (!p)      WaitForSingleObject (pi.hProcess, INFINITE);
304          return gpg_error (GPG_ERR_INV_ARG);      CloseHandle (pi.hProcess);
305      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)      return 0;
306                              + strlen (outfile) + 64 + 2);  }
307      if (!cmd)  
308          abort ();  
309      sprintf (cmd, "%s --yes --output \"%s\" --export-secret-key %s",  /* Export a GPG secret key given by @keyid into the file @outfile.
310               p, outfile, keyid);     Return value: 0 on success. */
311      if (create_process (cmd, NULL, NULL))  gpgme_error_t
312          err = gpg_error (GPG_ERR_INTERNAL);  gpg_export_seckey (const char *keyid, const char *outfile)
313    {
314      if (stat (outfile, &st) == -1 || st.st_size == 0)      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
315          err = gpg_error (GPG_ERR_NO_DATA);      struct stat st;
316        char *p;
317      free (p);      char *cmd;
318      free (cmd);  
319      return err;      p = read_w32_registry (HKEY_CURRENT_USER,
320  }                             "Software\\GNU\\GnuPG", "gpgProgram");
321        if (!p)
322            return gpg_error (GPG_ERR_INV_ARG);
323  /* If @export is 1, export the ownertrust data to the      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)
324     buffer @data. Otherwise import the ownertrust data from @data.                              + strlen (outfile) + 64 + 2);
325     Return value: 0 on success. */      if (!cmd)
326  gpgme_error_t          BUG (NULL);
327  gpg_manage_ownertrust (char **data, int export)      sprintf (cmd, "%s --yes --output \"%s\" --export-secret-key %s",
328  {               p, outfile, keyid);
329      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      if (create_process (cmd, NULL, NULL))
330      HANDLE out = NULL, in = NULL;          err = gpg_error (GPG_ERR_INTERNAL);
331      char *p;  
332      char *cmd;      if (stat (outfile, &st) == -1 || st.st_size == 0)
333            err = gpg_error (GPG_ERR_NO_DATA);
334      p = read_w32_registry (HKEY_CURRENT_USER,  
335                             "Software\\GNU\\GnuPG", "gpgProgram");      free (p);
336      if (!p)      free (cmd);
337          return gpg_error (GPG_ERR_INV_ARG);      return err;
338    }
339      cmd = (char*)calloc (1, strlen (p) + 64 + 1);  
340      if (!cmd)  
341          abort ();    /* If @export is 1, export the ownertrust data to the
342      sprintf (cmd, "%s %s", p,     buffer @data. Otherwise import the ownertrust data from @data.
343               export? "--export-ownertrust" : "--import-ownertrust");     Return value: 0 on success. */
344    gpgme_error_t
345      if (export)  gpg_manage_ownertrust (char **data, int do_export)
346          out = create_tmpfile ("gpg_ot_out");  {
347      else {      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
348          DWORD nw;      HANDLE out = NULL, in = NULL;
349          in = create_tmpfile ("gpg_ot_in");      char *p;
350          WriteFile (in, *data, strlen (*data), &nw, NULL);      char *cmd;
351          FlushFileBuffers (in);  
352          /* XXX: need a rewind? */      p = read_w32_registry (HKEY_CURRENT_USER,
353      }                             "Software\\GNU\\GnuPG", "gpgProgram");
354      if (create_process (cmd, in, out))      if (!p)
355          err = gpg_error (GPG_ERR_INTERNAL);          return gpg_error (GPG_ERR_INV_ARG);
356    
357      free (p);      cmd = (char*)calloc (1, strlen (p) + 64 + 1);
358      free (cmd);      if (!cmd)
359            BUG (NULL);
360      if (in)      sprintf (cmd, "%s %s", p,
361          CloseHandle (in);               do_export? "--export-ownertrust" : "--import-ownertrust");
362      if (out) {  
363          *data = map_tmpfile (out);      if (do_export)
364          CloseHandle (out);          out = create_tmpfile ("gpg_ot_out");
365      }      else {
366      return err;          DWORD nw;
367  }          in = create_tmpfile ("gpg_ot_in");
368            WriteFile (in, *data, strlen (*data), &nw, NULL);
369            FlushFileBuffers (in);
370  /* Call gpg --rebuild-keydb-caches to speed up signature listings. */          /* XXX: need a rewind? */
371  gpgme_error_t      }
372  gpg_rebuild_cache (char **r_inf)      if (create_process (cmd, in, out))
373  {          err = gpg_error (GPG_ERR_INTERNAL);
374      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);  
375      HANDLE out = NULL;      free (p);
376      char *p;      free (cmd);
377      char *cmd;  
378        if (in)
379      p = read_w32_registry (HKEY_CURRENT_USER,          CloseHandle (in);
380                             "Software\\GNU\\GnuPG", "gpgProgram");      if (out) {
381      if (!p)          *data = map_tmpfile (out);
382          return gpg_error (GPG_ERR_INV_ARG);          CloseHandle (out);
383      cmd = (char*)calloc (1, strlen (p) + 64);      }
384      if (!cmd)      return err;
385          abort ();  }
386      sprintf (cmd, "%s --logger-fd=1 --rebuild-keydb-caches", p);  
387    
388      if (r_inf)  /* Call gpg --rebuild-keydb-caches to speed up signature listings. */
389          out = create_tmpfile ("gpg_rebuild_cache");  gpgme_error_t
390    gpg_rebuild_cache (char **r_inf)
391      if (create_process (cmd, NULL, out))  {
392          err = gpg_error (GPG_ERR_INTERNAL);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
393        HANDLE out = NULL;
394      if (r_inf)      char *p;
395          *r_inf = map_tmpfile (out);      char *cmd;
396      if (out)  
397          CloseHandle (out);      p = read_w32_registry (HKEY_CURRENT_USER,
398      free (p);                             "Software\\GNU\\GnuPG", "gpgProgram");
399      free (cmd);      if (!p)
400      return 0;          return gpg_error (GPG_ERR_INV_ARG);
401  }      cmd = (char*)calloc (1, strlen (p) + 64);
402        if (!cmd)
403            BUG (NULL);
404  /* Call gpg --version to retrieve the 'about' information. */      sprintf (cmd, "%s --logger-fd=1 --rebuild-keydb-caches", p);
405  gpgme_error_t  
406  gpg_get_version (char **r_inf)      if (r_inf)
407  {          out = create_tmpfile ("gpg_rebuild_cache");
408      gpgme_error_t err= gpg_error (GPG_ERR_NO_ERROR);  
409      HANDLE out;          if (create_process (cmd, NULL, out))
410      char *p, *cmd;          err = gpg_error (GPG_ERR_INTERNAL);
411    
412      p =read_w32_registry (HKEY_CURRENT_USER,      if (r_inf)
413                            "Software\\GNU\\GnuPG", "gpgProgram");          *r_inf = map_tmpfile (out);
414      if (!p)      if (out)
415          return gpg_error (GPG_ERR_INV_ARG);          CloseHandle (out);
416      cmd = (char*)calloc (1, strlen (p) + 32);      free (p);
417      if (!cmd)      free (cmd);
418          abort ();      return 0;
419      sprintf (cmd, "%s --version", p);  }
420    
421      out = create_tmpfile ("gpg_out");  
422      if (create_process (cmd, NULL, out))  /* Call gpg --version to retrieve the 'about' information. */
423          err = gpg_error (GPG_ERR_INTERNAL);  gpgme_error_t
424    gpg_get_version (char **r_inf)
425      free (p);  {
426      free (cmd);      gpgme_error_t err= gpg_error (GPG_ERR_NO_ERROR);
427        HANDLE out;    
428      *r_inf = map_tmpfile (out);      char *p, *cmd;
429      CloseHandle (out);      
430      return err;      p =read_w32_registry (HKEY_CURRENT_USER,
431  }                            "Software\\GNU\\GnuPG", "gpgProgram");
432        if (!p)
433            return gpg_error (GPG_ERR_INV_ARG);
434  /* Return the colon file output of the given file @fname in @r_out.      cmd = (char*)calloc (1, strlen (p) + 32);
435     Return value: 0 on success. */      if (!cmd)
436  gpgme_error_t          BUG (NULL);
437  gpg_import_key_list (const char *fname, char **r_out)      sprintf (cmd, "%s --version", p);
438  {  
439      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      out = create_tmpfile ("gpg_out");
440      char *cmd, *p;      if (create_process (cmd, NULL, out))
441      HANDLE out;          err = gpg_error (GPG_ERR_INTERNAL);
442    
443      p = read_w32_registry (HKEY_CURRENT_USER,      free (p);
444                             "Software\\GNU\\GnuPG", "gpgProgram");      free (cmd);
445      if (!p)  
446          return gpg_error (GPG_ERR_INV_ARG);      *r_inf = map_tmpfile (out);
447        CloseHandle (out);    
448      cmd = (char*)calloc (1, strlen (p) + strlen (fname) + 2+2 + 64);      return err;
449      if (!cmd)  }
450          abort ();  
451      sprintf (cmd, "%s --fixed-list-mode --with-colons \"%s\"", p, fname);  
452    /* Return the colon file output of the given file @fname in @r_out.
453      out = create_tmpfile ("gpg_keys");     Return value: 0 on success. */
454      if (create_process (cmd, NULL, out))  gpgme_error_t
455          err = gpg_error (GPG_ERR_INTERNAL);  gpg_import_key_list (const char *fname, char **r_out)
456    {
457      free (p);      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
458      free (cmd);      char *cmd, *p;
459        HANDLE out;
460      *r_out = map_tmpfile (out);  
461      CloseHandle (out);      p = read_w32_registry (HKEY_CURRENT_USER,
462      return err;                             "Software\\GNU\\GnuPG", "gpgProgram");
463  }      if (!p)
464            return gpg_error (GPG_ERR_INV_ARG);
465  char*  
466  generate_revoc_input (int code, const char *cmt, const char *pass)      cmd = (char*)calloc (1, strlen (p) + strlen (fname) + 2+2 + 64);
467  {      if (!cmd)
468      const char *fmt;          BUG (NULL);
469      char *p;      sprintf (cmd, "%s --fixed-list-mode --with-colons \"%s\"", p, fname);
470      size_t n;  
471        out = create_tmpfile ("gpg_keys");
472      fmt = "Y\n"     /*  gen_revoke.okay */      if (create_process (cmd, NULL, out))
473            "%d\n"    /* ask_revocation_reason.code */          err = gpg_error (GPG_ERR_INTERNAL);
474            "%s\n"    /* ask_revocation_reason.text */  
475            "%s"      /* text != NULL '\n' otherwise '' */      free (p);
476            "Y\n"     /* ask_revocation_reason.okay */      free (cmd);
477            "%s\n";   /* passphrase.enter. */  
478      n = strlen (fmt) + 32;      *r_out = map_tmpfile (out);
479      if (pass)      CloseHandle (out);
480          n += strlen (pass) + 1;      return err;
481      if (cmt)  }
482          n += strlen (cmt) + 1;  
483      p = (char*)calloc (1, n+1);  char*
484      if (!p)  generate_revoc_input (int code, const char *cmt, const char *pass)
485          abort ();  {
486      sprintf (p, fmt, code, cmt? cmt : "", cmt? "\n" : "", pass? pass : "");      const char *fmt;
487      return p;      char *p;
488  }      size_t n;
489        
490        fmt = "Y\n"     /*  gen_revoke.okay */
491  /* Generate a revocation certificate for the key with the keyid @keyid.            "%d\n"    /* ask_revocation_reason.code */
492     @inp_data contains all needed data to answer the questions of the            "%s\n"    /* ask_revocation_reason.text */
493     command handler. Each separate with a '\n'.            "%s"      /* text != NULL '\n' otherwise '' */
494     @r_revcert contains the revocation cert on success.            "Y\n"     /* ask_revocation_reason.okay */
495     Return value: 0 on success. */            "%s\n";   /* passphrase.enter. */
496  gpgme_error_t      n = strlen (fmt) + 32;
497  gpg_revoke_key (const char *inp_data, const char *keyid, char **r_revcert)      if (pass)
498  {          n += strlen (pass) + 1;
499      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);      if (cmt)
500      char *rcrt;          n += strlen (cmt) + 1;
501      char *cmd, *p;      p = (char*)calloc (1, n+1);
502      HANDLE in, out;      if (!p)
503                BUG (NULL);
504      p = read_w32_registry (HKEY_CURRENT_USER,      sprintf (p, fmt, code, cmt? cmt : "", cmt? "\n" : "", pass? pass : "");
505                             "Software\\GNU\\GnuPG", "gpgProgram");      return p;
506      if (!p)  }
507          return gpg_error (GPG_ERR_INV_ARG);      
508    
509      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);  /* Generate a revocation certificate for the key with the keyid @keyid.
510      if (!cmd)     @inp_data contains all needed data to answer the questions of the
511          abort ();     command handler. Each separate with a '\n'.
512      sprintf (cmd, "%s --pgp7 --command-fd=0 --status-fd=2 --gen-revoke %s",     @r_revcert contains the revocation cert on success.
513               p, keyid);     Return value: 0 on success. */
514    gpgme_error_t
515      in = create_in_pipe (inp_data);  gpg_revoke_key (const char *inp_data, const char *keyid, char **r_revcert)
516      out = create_tmpfile ("gpg_revcert");  {
517      if (create_process (cmd, in, out)) {      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
518          *r_revcert = NULL;      char *rcrt;
519          err = gpg_error (GPG_ERR_INTERNAL);      char *cmd, *p;
520      }      HANDLE in, out;
521      else {      
522          rcrt = map_tmpfile (out);      p = read_w32_registry (HKEY_CURRENT_USER,
523          *r_revcert = rcrt;                             "Software\\GNU\\GnuPG", "gpgProgram");
524      }      if (!p)
525            return gpg_error (GPG_ERR_INV_ARG);
526      free (p);  
527      free (cmd);      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);
528        if (!cmd)
529      CloseHandle (in);          BUG (NULL);
530      CloseHandle (out);      sprintf (cmd, "%s --pgp7 --command-fd=0 --status-fd=2 --gen-revoke %s",
531      return err;               p, keyid);
532  }  
533        in = create_in_pipe (inp_data);
534        out = create_tmpfile ("gpg_revcert");
535  /* Return the validity of the user attribute, informerly known      if (create_process (cmd, in, out)) {
536     as photo-ID. If no uat was found, return 0 for unknown. */          *r_revcert = NULL;
537  gpgme_error_t          err = gpg_error (GPG_ERR_INTERNAL);
538  get_uat_validity (const char *keyid, gpgme_validity_t *r_valid)      }
539  {      else {
540      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);          rcrt = map_tmpfile (out);
541      HANDLE out;          *r_revcert = rcrt;
542      char *p, *cmd;      }
543      char *uat;  
544        free (p);
545      *r_valid = GPGME_VALIDITY_UNKNOWN;      free (cmd);
546      p = read_w32_registry (HKEY_CURRENT_USER,  
547                             "Software\\GNU\\GnuPG", "gpgProgram");      CloseHandle (in);
548      if (!p)      CloseHandle (out);
549          return gpg_error (GPG_ERR_INV_ARG);      return err;
550    }
551      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);  
552      if (!cmd)  
553          abort ();  /* Return the validity of the user attribute, informerly known
554      sprintf (cmd, "%s --with-colons --fixed-list-mode --list-keys \"%s\"",     as photo-ID. If no uat was found, return 0 for unknown. */
555               p, keyid);  gpgme_error_t
556    get_uat_validity (const char *keyid, gpgme_validity_t *r_valid)
557      out = create_tmpfile ("gpg_keys");  {
558      if (create_process (cmd, NULL, out))      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
559          err = gpg_error (GPG_ERR_INTERNAL);      HANDLE out;
560        char *p, *cmd;
561      free (p);      char *uat;
562      free (cmd);  
563            *r_valid = GPGME_VALIDITY_UNKNOWN;
564      p = map_tmpfile (out);      p = read_w32_registry (HKEY_CURRENT_USER,
565      if ((uat = strstr (p, "uat:"))) {                             "Software\\GNU\\GnuPG", "gpgProgram");
566          switch (*(uat+4)) {      if (!p)
567          case 'm': *r_valid = GPGME_VALIDITY_MARGINAL; break;          return gpg_error (GPG_ERR_INV_ARG);
568          case 'f':  
569          case 'u': *r_valid = GPGME_VALIDITY_FULL; break;      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);
570          default: *r_valid = GPGME_VALIDITY_UNDEFINED; break;      if (!cmd)
571          }          BUG (NULL);
572      }      sprintf (cmd, "%s --with-colons --fixed-list-mode --list-keys \"%s\"",
573                 p, keyid);
574      free (p);      
575      CloseHandle (out);      out = create_tmpfile ("gpg_keys");
576      return err;      if (create_process (cmd, NULL, out))
577  }          err = gpg_error (GPG_ERR_INTERNAL);
578    
579        free (p);
580  #if 0      free (cmd);
581  /* Extract all recipients from the file @file.      
582     Return value: 0 on success. */      p = map_tmpfile (out);
583  static int      if ((uat = strstr (p, "uat:"))) {
584  do_get_recipients (const char *file, gpgme_recipient_t *r_list)          switch (*(uat+4)) {
585  {          case 'm': *r_valid = GPGME_VALIDITY_MARGINAL; break;
586      gpgme_recipient_t l;          case 'f':
587      PACKET *pkt;          case 'u': *r_valid = GPGME_VALIDITY_FULL; break;
588      gpg_iobuf_t inp = NULL;          default: *r_valid = GPGME_VALIDITY_UNDEFINED; break;
589      armor_filter_context_t afx;          }
590      int rc = 0, quit=0;      }
591    
592      if (!file || !r_list) {      free (p);    
593          log_debug ("do_list_packets: !r_list || !file");      CloseHandle (out);
594          return -1;      return err;
595      }  }
596    
597      *r_list=NULL;  
598      inp = gpg_iobuf_open (file);  #if 0
599      if (!inp)  /* Extract all recipients from the file @file.
600          return WPTERR_FILE_OPEN;     Return value: 0 on success. */
601      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */  static int
602      if (gpg_use_armor_filter (inp)) {  do_get_recipients (const char *file, gpgme_recipient_t *r_list)
603          memset (&afx, 0, sizeof (afx));  {
604          gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);      gpgme_recipient_t l;
605      }      PACKET *pkt;
606      pkt = (PACKET *)calloc(1, sizeof *pkt);      gpg_iobuf_t inp = NULL;
607      gpg_init_packet (pkt);      armor_filter_context_t afx;
608      while (!quit && (rc = gpg_parse_packet (inp, pkt)) != -1) {      int rc = 0, quit=0;
609          switch (pkt->pkttype) {  
610          case PKT_PUBKEY_ENC:      if (!file || !r_list) {
611              {PKT_pubkey_enc *enc = pkt->pkt.pubkey_enc;          log_debug ("do_list_packets: !r_list || !file");
612              if (!enc)          return -1;
613                  break;      }
614              l = calloc (1, sizeof *l);  
615              l->keyid = calloc (1, 16+1);      *r_list=NULL;
616              _snprintf (l->keyid, 16, "%08lX%08lX", enc->keyid[0], enc->keyid[1]);      inp = gpg_iobuf_open (file);
617              l->pubkey_algo = enc->pubkey_algo;      if (!inp)
618              l->status = 0;          return WPTERR_FILE_OPEN;
619              l->next = (*r_list);      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
620              *r_list = l;      if (gpg_use_armor_filter (inp)) {
621              break;}          memset (&afx, 0, sizeof (afx));
622            gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);
623          case PKT_ENCRYPTED:          }
624          case PKT_ENCRYPTED_MDC:      pkt = (PACKET *)calloc(1, sizeof *pkt);
625          case PKT_COMPRESSED:      gpg_init_packet (pkt);
626          case PKT_PUBLIC_KEY:      while (!quit && (rc = gpg_parse_packet (inp, pkt)) != -1) {
627          case PKT_SECRET_KEY:          switch (pkt->pkttype) {
628              quit = 1;          case PKT_PUBKEY_ENC:
629              break;              {PKT_pubkey_enc *enc = pkt->pkt.pubkey_enc;
630          }              if (!enc)
631          gpg_free_packet (pkt);                  break;
632          gpg_init_packet (pkt);              l = calloc (1, sizeof *l);
633      }              l->keyid = calloc (1, 16+1);
634      gpg_iobuf_close (inp);              _snprintf (l->keyid, 16, "%08lX%08lX", enc->keyid[0], enc->keyid[1]);
635      safe_free (pkt);              l->pubkey_algo = enc->pubkey_algo;
636      return 0;              l->status = 0;
637  }              l->next = (*r_list);
638  #endif              *r_list = l;
639                break;}
640    
641            case PKT_ENCRYPTED:    
642            case PKT_ENCRYPTED_MDC:
643            case PKT_COMPRESSED:
644            case PKT_PUBLIC_KEY:
645            case PKT_SECRET_KEY:
646                quit = 1;
647                break;
648            }
649            gpg_free_packet (pkt);
650            gpg_init_packet (pkt);
651        }
652        gpg_iobuf_close (inp);
653        safe_free (pkt);
654        return 0;
655    }
656    #endif

Legend:
Removed from v.33  
changed lines
  Added in v.121

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26