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