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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26