g10: Unattended key generation "Key-Grip" and "Subkey-Grip".
[gnupg.git] / tools / call-dirmngr.c
1 /* call-dirmngr.c - Interact with the Dirmngr.
2  * Copyright (C) 2016 g10 Code GmbH
3  * Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <time.h>
28 #ifdef HAVE_LOCALE_H
29 # include <locale.h>
30 #endif
31
32 #include <assuan.h>
33 #include "../common/util.h"
34 #include "../common/i18n.h"
35 #include "../common/asshelp.h"
36 #include "../common/mbox-util.h"
37 #include "./call-dirmngr.h"
38
39 static struct
40 {
41   int verbose;
42   int debug_ipc;
43   int autostart;
44 } opt;
45
46
47
48 void
49 set_dirmngr_options (int verbose, int debug_ipc, int autostart)
50 {
51   opt.verbose = verbose;
52   opt.debug_ipc = debug_ipc;
53   opt.autostart = autostart;
54 }
55
56
57 /* Connect to the Dirmngr and return an assuan context.  */
58 static gpg_error_t
59 connect_dirmngr (assuan_context_t *r_ctx)
60 {
61   gpg_error_t err;
62   assuan_context_t ctx;
63
64   *r_ctx = NULL;
65   err = start_new_dirmngr (&ctx,
66                            GPG_ERR_SOURCE_DEFAULT,
67                            NULL,
68                            opt.autostart, opt.verbose, opt.debug_ipc,
69                            NULL, NULL);
70   if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_DIRMNGR)
71     {
72       static int shown;
73
74       if (!shown)
75         {
76           shown = 1;
77           log_info (_("no dirmngr running in this session\n"));
78         }
79     }
80
81   if (err)
82     assuan_release (ctx);
83   else
84     {
85       *r_ctx = ctx;
86     }
87
88   return err;
89 }
90
91
92
93 \f
94 /* Parameter structure used with the WKD_GET command.  */
95 struct wkd_get_parm_s
96 {
97   estream_t memfp;
98 };
99
100
101 /* Data callback for the WKD_GET command. */
102 static gpg_error_t
103 wkd_get_data_cb (void *opaque, const void *data, size_t datalen)
104 {
105   struct wkd_get_parm_s *parm = opaque;
106   gpg_error_t err = 0;
107   size_t nwritten;
108
109   if (!data)
110     return 0;  /* Ignore END commands.  */
111   if (!parm->memfp)
112     return 0;  /* Data is not required.  */
113
114   if (es_write (parm->memfp, data, datalen, &nwritten))
115     err = gpg_error_from_syserror ();
116
117   return err;
118 }
119
120
121 /* Status callback for the WKD_GET command.  */
122 static gpg_error_t
123 wkd_get_status_cb (void *opaque, const char *line)
124 {
125   struct wkd_get_parm_s *parm = opaque;
126   gpg_error_t err = 0;
127
128   (void)line;
129   (void)parm;
130
131   return err;
132 }
133
134
135 /* Ask the dirmngr for the submission address of a WKD server for the
136  * mail address ADDRSPEC.  On success the submission address is stored
137  * at R_ADDRSPEC.  */
138 gpg_error_t
139 wkd_get_submission_address (const char *addrspec, char **r_addrspec)
140 {
141   gpg_error_t err;
142   assuan_context_t ctx;
143   struct wkd_get_parm_s parm;
144   char *line = NULL;
145   void *vp;
146   char *buffer = NULL;
147   char *p;
148
149   memset (&parm, 0, sizeof parm);
150   *r_addrspec = NULL;
151
152   err = connect_dirmngr (&ctx);
153   if (err)
154     return err;
155
156   line = es_bsprintf ("WKD_GET --submission-address -- %s", addrspec);
157   if (!line)
158     {
159       err = gpg_error_from_syserror ();
160       goto leave;
161     }
162   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
163     {
164       err = gpg_error (GPG_ERR_TOO_LARGE);
165       goto leave;
166     }
167
168   parm.memfp = es_fopenmem (0, "rwb");
169   if (!parm.memfp)
170     {
171       err = gpg_error_from_syserror ();
172       goto leave;
173     }
174   err = assuan_transact (ctx, line, wkd_get_data_cb, &parm,
175                          NULL, NULL, wkd_get_status_cb, &parm);
176   if (err)
177     goto leave;
178
179   es_fputc (0, parm.memfp);
180   if (es_fclose_snatch (parm.memfp, &vp, NULL))
181     {
182       err = gpg_error_from_syserror ();
183       goto leave;
184     }
185   buffer = vp;
186   parm.memfp = NULL;
187   p = strchr (buffer, '\n');
188   if (p)
189     *p = 0;
190   trim_spaces (buffer);
191   if (!is_valid_mailbox (buffer))
192     {
193       err = gpg_error (GPG_ERR_INV_USER_ID);
194       goto leave;
195     }
196   *r_addrspec = xtrystrdup (buffer);
197   if (!*r_addrspec)
198     err = gpg_error_from_syserror ();
199
200  leave:
201   es_free (buffer);
202   es_fclose (parm.memfp);
203   xfree (line);
204   assuan_release (ctx);
205   return err;
206 }
207
208
209 /* Ask the dirmngr for the policy flags and return them as an estream
210  * memory stream.  If no policy flags are set, NULL is stored at
211  * R_BUFFER.  */
212 gpg_error_t
213 wkd_get_policy_flags (const char *addrspec, estream_t *r_buffer)
214 {
215   gpg_error_t err;
216   assuan_context_t ctx;
217   struct wkd_get_parm_s parm;
218   char *line = NULL;
219   char *buffer = NULL;
220
221   memset (&parm, 0, sizeof parm);
222   *r_buffer = NULL;
223
224   err = connect_dirmngr (&ctx);
225   if (err)
226     return err;
227
228   line = es_bsprintf ("WKD_GET --policy-flags -- %s", addrspec);
229   if (!line)
230     {
231       err = gpg_error_from_syserror ();
232       goto leave;
233     }
234   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
235     {
236       err = gpg_error (GPG_ERR_TOO_LARGE);
237       goto leave;
238     }
239
240   parm.memfp = es_fopenmem (0, "rwb");
241   if (!parm.memfp)
242     {
243       err = gpg_error_from_syserror ();
244       goto leave;
245     }
246   err = assuan_transact (ctx, line, wkd_get_data_cb, &parm,
247                          NULL, NULL, wkd_get_status_cb, &parm);
248   if (err)
249     goto leave;
250
251   es_rewind (parm.memfp);
252   *r_buffer = parm.memfp;
253   parm.memfp = 0;
254
255  leave:
256   es_free (buffer);
257   es_fclose (parm.memfp);
258   xfree (line);
259   assuan_release (ctx);
260   return err;
261 }
262
263
264 /* Ask the dirmngr for the key for ADDRSPEC.  On success a stream with
265  * the key is stored at R_KEY.  */
266 gpg_error_t
267 wkd_get_key (const char *addrspec, estream_t *r_key)
268 {
269   gpg_error_t err;
270   assuan_context_t ctx;
271   struct wkd_get_parm_s parm;
272   char *line = NULL;
273
274   memset (&parm, 0, sizeof parm);
275   *r_key = NULL;
276
277   err = connect_dirmngr (&ctx);
278   if (err)
279     return err;
280
281   line = es_bsprintf ("WKD_GET -- %s", addrspec);
282   if (!line)
283     {
284       err = gpg_error_from_syserror ();
285       goto leave;
286     }
287   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
288     {
289       err = gpg_error (GPG_ERR_TOO_LARGE);
290       goto leave;
291     }
292
293   parm.memfp = es_fopenmem (0, "rwb");
294   if (!parm.memfp)
295     {
296       err = gpg_error_from_syserror ();
297       goto leave;
298     }
299   err = assuan_transact (ctx, line, wkd_get_data_cb, &parm,
300                          NULL, NULL, wkd_get_status_cb, &parm);
301   if (err)
302     goto leave;
303
304   es_rewind (parm.memfp);
305   *r_key = parm.memfp;
306   parm.memfp = NULL;
307
308  leave:
309   es_fclose (parm.memfp);
310   xfree (line);
311   assuan_release (ctx);
312   return err;
313 }