/[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 34 by twoaday, Wed Oct 26 11:20:09 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 - strlen (name)-1, 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|STARTF_USESHOWWINDOW;      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      si.wShowWindow = SW_HIDE;          si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
283      if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,      if (out)
284                          NULL, NULL, &si, &pi))          si.hStdOutput = out;
285          return -1;      if (in)
286      WaitForSingleObject (pi.hProcess, INFINITE);          si.hStdInput = in;
287      CloseHandle (pi.hProcess);      si.wShowWindow = SW_HIDE;
288      return 0;      if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,
289  }                          NULL, NULL, &si, &pi))
290            return -1;
291        WaitForSingleObject (pi.hProcess, INFINITE);
292  /* Export a GPG secret key given by @keyid into the file @outfile.      CloseHandle (pi.hProcess);
293     Return value: 0 on success. */      return 0;
294  gpgme_error_t  }
295  gpg_export_seckey (const char *keyid, const char *outfile)  
296  {  
297      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);  /* Export a GPG secret key given by @keyid into the file @outfile.
298      struct stat st;     Return value: 0 on success. */
299      char *p;  gpgme_error_t
300      char *cmd;  gpg_export_seckey (const char *keyid, const char *outfile)
301    {
302      p = read_w32_registry (HKEY_CURRENT_USER,      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
303                             "Software\\GNU\\GnuPG", "gpgProgram");      struct stat st;
304      if (!p)      char *p;
305          return gpg_error (GPG_ERR_INV_ARG);      char *cmd;
306      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)  
307                              + strlen (outfile) + 64 + 2);      p = read_w32_registry (HKEY_CURRENT_USER,
308      if (!cmd)                             "Software\\GNU\\GnuPG", "gpgProgram");
309          abort ();      if (!p)
310      sprintf (cmd, "%s --yes --output \"%s\" --export-secret-key %s",          return gpg_error (GPG_ERR_INV_ARG);
311               p, outfile, keyid);      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)
312      if (create_process (cmd, NULL, NULL))                              + strlen (outfile) + 64 + 2);
313          err = gpg_error (GPG_ERR_INTERNAL);      if (!cmd)
314            abort ();
315      if (stat (outfile, &st) == -1 || st.st_size == 0)      sprintf (cmd, "%s --yes --output \"%s\" --export-secret-key %s",
316          err = gpg_error (GPG_ERR_NO_DATA);               p, outfile, keyid);
317        if (create_process (cmd, NULL, NULL))
318      free (p);          err = gpg_error (GPG_ERR_INTERNAL);
319      free (cmd);  
320      return err;      if (stat (outfile, &st) == -1 || st.st_size == 0)
321  }          err = gpg_error (GPG_ERR_NO_DATA);
322    
323        free (p);
324  /* If @export is 1, export the ownertrust data to the      free (cmd);
325     buffer @data. Otherwise import the ownertrust data from @data.      return err;
326     Return value: 0 on success. */  }
327  gpgme_error_t  
328  gpg_manage_ownertrust (char **data, int export)  
329  {  /* If @export is 1, export the ownertrust data to the
330      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);     buffer @data. Otherwise import the ownertrust data from @data.
331      HANDLE out = NULL, in = NULL;     Return value: 0 on success. */
332      char *p;  gpgme_error_t
333      char *cmd;  gpg_manage_ownertrust (char **data, int export)
334    {
335      p = read_w32_registry (HKEY_CURRENT_USER,      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
336                             "Software\\GNU\\GnuPG", "gpgProgram");      HANDLE out = NULL, in = NULL;
337      if (!p)      char *p;
338          return gpg_error (GPG_ERR_INV_ARG);      char *cmd;
339    
340      cmd = (char*)calloc (1, strlen (p) + 64 + 1);      p = read_w32_registry (HKEY_CURRENT_USER,
341      if (!cmd)                             "Software\\GNU\\GnuPG", "gpgProgram");
342          abort ();        if (!p)
343      sprintf (cmd, "%s %s", p,          return gpg_error (GPG_ERR_INV_ARG);
344               export? "--export-ownertrust" : "--import-ownertrust");  
345        cmd = (char*)calloc (1, strlen (p) + 64 + 1);
346      if (export)      if (!cmd)
347          out = create_tmpfile ("gpg_ot_out");          abort ();  
348      else {      sprintf (cmd, "%s %s", p,
349          DWORD nw;               export? "--export-ownertrust" : "--import-ownertrust");
350          in = create_tmpfile ("gpg_ot_in");  
351          WriteFile (in, *data, strlen (*data), &nw, NULL);      if (export)
352          FlushFileBuffers (in);          out = create_tmpfile ("gpg_ot_out");
353          /* XXX: need a rewind? */      else {
354      }          DWORD nw;
355      if (create_process (cmd, in, out))          in = create_tmpfile ("gpg_ot_in");
356          err = gpg_error (GPG_ERR_INTERNAL);          WriteFile (in, *data, strlen (*data), &nw, NULL);
357            FlushFileBuffers (in);
358      free (p);          /* XXX: need a rewind? */
359      free (cmd);      }
360        if (create_process (cmd, in, out))
361      if (in)          err = gpg_error (GPG_ERR_INTERNAL);
362          CloseHandle (in);  
363      if (out) {      free (p);
364          *data = map_tmpfile (out);      free (cmd);
365          CloseHandle (out);  
366      }      if (in)
367      return err;          CloseHandle (in);
368  }      if (out) {
369            *data = map_tmpfile (out);
370            CloseHandle (out);
371  /* Call gpg --rebuild-keydb-caches to speed up signature listings. */      }
372  gpgme_error_t      return err;
373  gpg_rebuild_cache (char **r_inf)  }
374  {  
375      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);  
376      HANDLE out = NULL;  /* Call gpg --rebuild-keydb-caches to speed up signature listings. */
377      char *p;  gpgme_error_t
378      char *cmd;  gpg_rebuild_cache (char **r_inf)
379    {
380      p = read_w32_registry (HKEY_CURRENT_USER,      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
381                             "Software\\GNU\\GnuPG", "gpgProgram");      HANDLE out = NULL;
382      if (!p)      char *p;
383          return gpg_error (GPG_ERR_INV_ARG);      char *cmd;
384      cmd = (char*)calloc (1, strlen (p) + 64);  
385      if (!cmd)      p = read_w32_registry (HKEY_CURRENT_USER,
386          abort ();                             "Software\\GNU\\GnuPG", "gpgProgram");
387      sprintf (cmd, "%s --logger-fd=1 --rebuild-keydb-caches", p);      if (!p)
388            return gpg_error (GPG_ERR_INV_ARG);
389      if (r_inf)      cmd = (char*)calloc (1, strlen (p) + 64);
390          out = create_tmpfile ("gpg_rebuild_cache");      if (!cmd)
391            abort ();
392      if (create_process (cmd, NULL, out))      sprintf (cmd, "%s --logger-fd=1 --rebuild-keydb-caches", p);
393          err = gpg_error (GPG_ERR_INTERNAL);  
394        if (r_inf)
395      if (r_inf)          out = create_tmpfile ("gpg_rebuild_cache");
396          *r_inf = map_tmpfile (out);  
397      if (out)      if (create_process (cmd, NULL, out))
398          CloseHandle (out);          err = gpg_error (GPG_ERR_INTERNAL);
399      free (p);  
400      free (cmd);      if (r_inf)
401      return 0;          *r_inf = map_tmpfile (out);
402  }      if (out)
403            CloseHandle (out);
404        free (p);
405  /* Call gpg --version to retrieve the 'about' information. */      free (cmd);
406  gpgme_error_t      return 0;
407  gpg_get_version (char **r_inf)  }
408  {  
409      gpgme_error_t err= gpg_error (GPG_ERR_NO_ERROR);  
410      HANDLE out;      /* Call gpg --version to retrieve the 'about' information. */
411      char *p, *cmd;  gpgme_error_t
412    gpg_get_version (char **r_inf)
413      p =read_w32_registry (HKEY_CURRENT_USER,  {
414                            "Software\\GNU\\GnuPG", "gpgProgram");      gpgme_error_t err= gpg_error (GPG_ERR_NO_ERROR);
415      if (!p)      HANDLE out;    
416          return gpg_error (GPG_ERR_INV_ARG);      char *p, *cmd;
417      cmd = (char*)calloc (1, strlen (p) + 32);  
418      if (!cmd)      p =read_w32_registry (HKEY_CURRENT_USER,
419          abort ();                            "Software\\GNU\\GnuPG", "gpgProgram");
420      sprintf (cmd, "%s --version", p);      if (!p)
421            return gpg_error (GPG_ERR_INV_ARG);
422      out = create_tmpfile ("gpg_out");      cmd = (char*)calloc (1, strlen (p) + 32);
423      if (create_process (cmd, NULL, out))      if (!cmd)
424          err = gpg_error (GPG_ERR_INTERNAL);          abort ();
425        sprintf (cmd, "%s --version", p);
426      free (p);  
427      free (cmd);      out = create_tmpfile ("gpg_out");
428        if (create_process (cmd, NULL, out))
429      *r_inf = map_tmpfile (out);          err = gpg_error (GPG_ERR_INTERNAL);
430      CloseHandle (out);      
431      return err;      free (p);
432  }      free (cmd);
433    
434        *r_inf = map_tmpfile (out);
435  /* Return the colon file output of the given file @fname in @r_out.      CloseHandle (out);    
436     Return value: 0 on success. */      return err;
437  gpgme_error_t  }
438  gpg_import_key_list (const char *fname, char **r_out)  
439  {  
440      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);  /* Return the colon file output of the given file @fname in @r_out.
441      char *cmd, *p;     Return value: 0 on success. */
442      HANDLE out;  gpgme_error_t
443    gpg_import_key_list (const char *fname, char **r_out)
444      p = read_w32_registry (HKEY_CURRENT_USER,  {
445                             "Software\\GNU\\GnuPG", "gpgProgram");      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
446      if (!p)      char *cmd, *p;
447          return gpg_error (GPG_ERR_INV_ARG);      HANDLE out;
448    
449      cmd = (char*)calloc (1, strlen (p) + strlen (fname) + 2+2 + 64);      p = read_w32_registry (HKEY_CURRENT_USER,
450      if (!cmd)                             "Software\\GNU\\GnuPG", "gpgProgram");
451          abort ();      if (!p)
452      sprintf (cmd, "%s --fixed-list-mode --with-colons \"%s\"", p, fname);          return gpg_error (GPG_ERR_INV_ARG);
453    
454      out = create_tmpfile ("gpg_keys");      cmd = (char*)calloc (1, strlen (p) + strlen (fname) + 2+2 + 64);
455      if (create_process (cmd, NULL, out))      if (!cmd)
456          err = gpg_error (GPG_ERR_INTERNAL);          abort ();
457        sprintf (cmd, "%s --fixed-list-mode --with-colons \"%s\"", p, fname);
458      free (p);  
459      free (cmd);      out = create_tmpfile ("gpg_keys");
460        if (create_process (cmd, NULL, out))
461      *r_out = map_tmpfile (out);          err = gpg_error (GPG_ERR_INTERNAL);
462      CloseHandle (out);  
463      return err;      free (p);
464  }      free (cmd);
465    
466  char*      *r_out = map_tmpfile (out);
467  generate_revoc_input (int code, const char *cmt, const char *pass)      CloseHandle (out);
468  {      return err;
469      const char *fmt;  }
470      char *p;  
471      size_t n;  char*
472    generate_revoc_input (int code, const char *cmt, const char *pass)
473      fmt = "Y\n"     /*  gen_revoke.okay */  {
474            "%d\n"    /* ask_revocation_reason.code */      const char *fmt;
475            "%s\n"    /* ask_revocation_reason.text */      char *p;
476            "%s"      /* text != NULL '\n' otherwise '' */      size_t n;
477            "Y\n"     /* ask_revocation_reason.okay */  
478            "%s\n";   /* passphrase.enter. */      fmt = "Y\n"     /*  gen_revoke.okay */
479      n = strlen (fmt) + 32;            "%d\n"    /* ask_revocation_reason.code */
480      if (pass)            "%s\n"    /* ask_revocation_reason.text */
481          n += strlen (pass) + 1;            "%s"      /* text != NULL '\n' otherwise '' */
482      if (cmt)            "Y\n"     /* ask_revocation_reason.okay */
483          n += strlen (cmt) + 1;            "%s\n";   /* passphrase.enter. */
484      p = (char*)calloc (1, n+1);      n = strlen (fmt) + 32;
485      if (!p)      if (pass)
486          abort ();          n += strlen (pass) + 1;
487      sprintf (p, fmt, code, cmt? cmt : "", cmt? "\n" : "", pass? pass : "");      if (cmt)
488      return p;          n += strlen (cmt) + 1;
489  }      p = (char*)calloc (1, n+1);
490            if (!p)
491            abort ();
492  /* Generate a revocation certificate for the key with the keyid @keyid.      sprintf (p, fmt, code, cmt? cmt : "", cmt? "\n" : "", pass? pass : "");
493     @inp_data contains all needed data to answer the questions of the      return p;
494     command handler. Each separate with a '\n'.  }
495     @r_revcert contains the revocation cert on success.      
496     Return value: 0 on success. */  
497  gpgme_error_t  /* Generate a revocation certificate for the key with the keyid @keyid.
498  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
499  {     command handler. Each separate with a '\n'.
500      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);     @r_revcert contains the revocation cert on success.
501      char *rcrt;     Return value: 0 on success. */
502      char *cmd, *p;  gpgme_error_t
503      HANDLE in, out;  gpg_revoke_key (const char *inp_data, const char *keyid, char **r_revcert)
504        {
505      p = read_w32_registry (HKEY_CURRENT_USER,      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
506                             "Software\\GNU\\GnuPG", "gpgProgram");      char *rcrt;
507      if (!p)      char *cmd, *p;
508          return gpg_error (GPG_ERR_INV_ARG);      HANDLE in, out;
509        
510      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);      p = read_w32_registry (HKEY_CURRENT_USER,
511      if (!cmd)                             "Software\\GNU\\GnuPG", "gpgProgram");
512          abort ();      if (!p)
513      sprintf (cmd, "%s --pgp7 --command-fd=0 --status-fd=2 --gen-revoke %s",          return gpg_error (GPG_ERR_INV_ARG);
514               p, keyid);  
515        cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);
516      in = create_in_pipe (inp_data);      if (!cmd)
517      out = create_tmpfile ("gpg_revcert");          abort ();
518      if (create_process (cmd, in, out)) {      sprintf (cmd, "%s --pgp7 --command-fd=0 --status-fd=2 --gen-revoke %s",
519          *r_revcert = NULL;               p, keyid);
520          err = gpg_error (GPG_ERR_INTERNAL);  
521      }      in = create_in_pipe (inp_data);
522      else {      out = create_tmpfile ("gpg_revcert");
523          rcrt = map_tmpfile (out);      if (create_process (cmd, in, out)) {
524          *r_revcert = rcrt;          *r_revcert = NULL;
525      }          err = gpg_error (GPG_ERR_INTERNAL);
526        }
527      free (p);      else {
528      free (cmd);          rcrt = map_tmpfile (out);
529            *r_revcert = rcrt;
530      CloseHandle (in);      }
531      CloseHandle (out);  
532      return err;      free (p);
533  }      free (cmd);
534    
535        CloseHandle (in);
536  /* Return the validity of the user attribute, informerly known      CloseHandle (out);
537     as photo-ID. If no uat was found, return 0 for unknown. */      return err;
538  gpgme_error_t  }
539  get_uat_validity (const char *keyid, gpgme_validity_t *r_valid)  
540  {  
541      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);  /* Return the validity of the user attribute, informerly known
542      HANDLE out;     as photo-ID. If no uat was found, return 0 for unknown. */
543      char *p, *cmd;  gpgme_error_t
544      char *uat;  get_uat_validity (const char *keyid, gpgme_validity_t *r_valid)
545    {
546      *r_valid = GPGME_VALIDITY_UNKNOWN;      gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
547      p = read_w32_registry (HKEY_CURRENT_USER,      HANDLE out;
548                             "Software\\GNU\\GnuPG", "gpgProgram");      char *p, *cmd;
549      if (!p)      char *uat;
550          return gpg_error (GPG_ERR_INV_ARG);  
551        *r_valid = GPGME_VALIDITY_UNKNOWN;
552      cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);      p = read_w32_registry (HKEY_CURRENT_USER,
553      if (!cmd)                             "Software\\GNU\\GnuPG", "gpgProgram");
554          abort ();      if (!p)
555      sprintf (cmd, "%s --with-colons --fixed-list-mode --list-keys \"%s\"",          return gpg_error (GPG_ERR_INV_ARG);
556               p, keyid);  
557        cmd = (char*)calloc (1, strlen (p) + strlen (keyid)+1 + 128);
558      out = create_tmpfile ("gpg_keys");      if (!cmd)
559      if (create_process (cmd, NULL, out))          abort ();
560          err = gpg_error (GPG_ERR_INTERNAL);      sprintf (cmd, "%s --with-colons --fixed-list-mode --list-keys \"%s\"",
561                 p, keyid);
562      free (p);  
563      free (cmd);      out = create_tmpfile ("gpg_keys");
564            if (create_process (cmd, NULL, out))
565      p = map_tmpfile (out);          err = gpg_error (GPG_ERR_INTERNAL);
566      if ((uat = strstr (p, "uat:"))) {  
567          switch (*(uat+4)) {      free (p);
568          case 'm': *r_valid = GPGME_VALIDITY_MARGINAL; break;      free (cmd);
569          case 'f':      
570          case 'u': *r_valid = GPGME_VALIDITY_FULL; break;      p = map_tmpfile (out);
571          default: *r_valid = GPGME_VALIDITY_UNDEFINED; break;      if ((uat = strstr (p, "uat:"))) {
572          }          switch (*(uat+4)) {
573      }          case 'm': *r_valid = GPGME_VALIDITY_MARGINAL; break;
574            case 'f':
575      free (p);              case 'u': *r_valid = GPGME_VALIDITY_FULL; break;
576      CloseHandle (out);          default: *r_valid = GPGME_VALIDITY_UNDEFINED; break;
577      return err;          }
578  }      }
579    
580        free (p);    
581  #if 0      CloseHandle (out);
582  /* Extract all recipients from the file @file.      return err;
583     Return value: 0 on success. */  }
584  static int  
585  do_get_recipients (const char *file, gpgme_recipient_t *r_list)  
586  {  #if 0
587      gpgme_recipient_t l;  /* Extract all recipients from the file @file.
588      PACKET *pkt;     Return value: 0 on success. */
589      gpg_iobuf_t inp = NULL;  static int
590      armor_filter_context_t afx;  do_get_recipients (const char *file, gpgme_recipient_t *r_list)
591      int rc = 0, quit=0;  {
592        gpgme_recipient_t l;
593      if (!file || !r_list) {      PACKET *pkt;
594          log_debug ("do_list_packets: !r_list || !file");      gpg_iobuf_t inp = NULL;
595          return -1;      armor_filter_context_t afx;
596      }      int rc = 0, quit=0;
597    
598      *r_list=NULL;      if (!file || !r_list) {
599      inp = gpg_iobuf_open (file);          log_debug ("do_list_packets: !r_list || !file");
600      if (!inp)          return -1;
601          return WPTERR_FILE_OPEN;      }
602      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */  
603      if (gpg_use_armor_filter (inp)) {      *r_list=NULL;
604          memset (&afx, 0, sizeof (afx));      inp = gpg_iobuf_open (file);
605          gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);      if (!inp)
606      }          return WPTERR_FILE_OPEN;
607      pkt = (PACKET *)calloc(1, sizeof *pkt);      gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
608      gpg_init_packet (pkt);      if (gpg_use_armor_filter (inp)) {
609      while (!quit && (rc = gpg_parse_packet (inp, pkt)) != -1) {          memset (&afx, 0, sizeof (afx));
610          switch (pkt->pkttype) {          gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);
611          case PKT_PUBKEY_ENC:      }
612              {PKT_pubkey_enc *enc = pkt->pkt.pubkey_enc;      pkt = (PACKET *)calloc(1, sizeof *pkt);
613              if (!enc)      gpg_init_packet (pkt);
614                  break;      while (!quit && (rc = gpg_parse_packet (inp, pkt)) != -1) {
615              l = calloc (1, sizeof *l);          switch (pkt->pkttype) {
616              l->keyid = calloc (1, 16+1);          case PKT_PUBKEY_ENC:
617              _snprintf (l->keyid, 16, "%08lX%08lX", enc->keyid[0], enc->keyid[1]);              {PKT_pubkey_enc *enc = pkt->pkt.pubkey_enc;
618              l->pubkey_algo = enc->pubkey_algo;              if (!enc)
619              l->status = 0;                  break;
620              l->next = (*r_list);              l = calloc (1, sizeof *l);
621              *r_list = l;              l->keyid = calloc (1, 16+1);
622              break;}              _snprintf (l->keyid, 16, "%08lX%08lX", enc->keyid[0], enc->keyid[1]);
623                l->pubkey_algo = enc->pubkey_algo;
624          case PKT_ENCRYPTED:                  l->status = 0;
625          case PKT_ENCRYPTED_MDC:              l->next = (*r_list);
626          case PKT_COMPRESSED:              *r_list = l;
627          case PKT_PUBLIC_KEY:              break;}
628          case PKT_SECRET_KEY:  
629              quit = 1;          case PKT_ENCRYPTED:    
630              break;          case PKT_ENCRYPTED_MDC:
631          }          case PKT_COMPRESSED:
632          gpg_free_packet (pkt);          case PKT_PUBLIC_KEY:
633          gpg_init_packet (pkt);          case PKT_SECRET_KEY:
634      }              quit = 1;
635      gpg_iobuf_close (inp);              break;
636      safe_free (pkt);          }
637      return 0;          gpg_free_packet (pkt);
638  }          gpg_init_packet (pkt);
639  #endif      }
640        gpg_iobuf_close (inp);
641        safe_free (pkt);
642        return 0;
643    }
644    #endif

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26