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

Legend:
Removed from v.32  
changed lines
  Added in v.36

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26