Line data Source code
1 : /* vfs-create.c - vfs create support in GPGME
2 : Copyright (C) 2009 g10 Code GmbH
3 :
4 : This file is part of GPGME.
5 :
6 : GPGME is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU Lesser General Public License as
8 : published by the Free Software Foundation; either version 2.1 of
9 : the License, or (at your option) any later version.
10 :
11 : GPGME is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should have received a copy of the GNU Lesser General Public
17 : License along with this program; if not, write to the Free Software
18 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 : 02111-1307, USA. */
20 :
21 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 :
25 : #include <stdlib.h>
26 : #include <string.h>
27 :
28 : #include "gpgme.h"
29 : #include "debug.h"
30 : #include "context.h"
31 : #include "ops.h"
32 : #include "util.h"
33 :
34 : static gpgme_error_t
35 0 : vfs_start (gpgme_ctx_t ctx, int synchronous,
36 : const char *command,
37 : gpgme_assuan_data_cb_t data_cb,
38 : void *data_cb_value,
39 : gpgme_assuan_inquire_cb_t inq_cb,
40 : void *inq_cb_value,
41 : gpgme_assuan_status_cb_t status_cb,
42 : void *status_cb_value)
43 : {
44 : gpgme_error_t err;
45 :
46 0 : if (!command || !*command)
47 0 : return gpg_error (GPG_ERR_INV_VALUE);
48 :
49 : /* The flag value 256 is used to suppress an engine reset. This is
50 : required to keep the connection running. */
51 0 : err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256));
52 0 : if (err)
53 0 : return err;
54 :
55 0 : return _gpgme_engine_op_assuan_transact (ctx->engine, command,
56 : data_cb, data_cb_value,
57 : inq_cb, inq_cb_value,
58 : status_cb, status_cb_value);
59 : }
60 :
61 :
62 : #if 0
63 : /* XXXX. This is the asynchronous variant. */
64 : static gpgme_error_t
65 : gpgme_op_vfs_transact_start (gpgme_ctx_t ctx,
66 : const char *command,
67 : gpgme_assuan_data_cb_t data_cb,
68 : void *data_cb_value,
69 : gpgme_assuan_inquire_cb_t inq_cb,
70 : void *inq_cb_value,
71 : gpgme_assuan_status_cb_t status_cb,
72 : void *status_cb_value)
73 : {
74 : return vfs_start (ctx, 0, command, data_cb, data_cb_value,
75 : inq_cb, inq_cb_value, status_cb, status_cb_value);
76 : }
77 : #endif
78 :
79 :
80 : /* XXXX. This is the synchronous variant. */
81 : static gpgme_error_t
82 0 : gpgme_op_vfs_transact (gpgme_ctx_t ctx,
83 : const char *command,
84 : gpgme_assuan_data_cb_t data_cb,
85 : void *data_cb_value,
86 : gpgme_assuan_inquire_cb_t inq_cb,
87 : void *inq_cb_value,
88 : gpgme_assuan_status_cb_t status_cb,
89 : void *status_cb_value,
90 : gpgme_error_t *op_err)
91 : {
92 : gpgme_error_t err;
93 :
94 0 : if (!ctx)
95 0 : return gpg_error (GPG_ERR_INV_VALUE);
96 :
97 0 : err = vfs_start (ctx, 1, command, data_cb, data_cb_value,
98 : inq_cb, inq_cb_value, status_cb, status_cb_value);
99 0 : if (!err)
100 0 : err = _gpgme_wait_one_ext (ctx, op_err);
101 0 : return err;
102 : }
103 :
104 :
105 : /* The actual exported interface follows. */
106 :
107 : /* The container is automatically uncreateed when the context is reset
108 : or destroyed. This is a synchronous convenience interface, which
109 : automatically returns an operation error if there is no
110 : transmission error. */
111 : static gpgme_error_t
112 0 : _gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[],
113 : const char *container_file, unsigned int flags,
114 : gpgme_error_t *op_err)
115 : {
116 : gpg_error_t err;
117 : char *cmd;
118 0 : char *container_file_esc = NULL;
119 : int i;
120 :
121 : (void)flags;
122 :
123 : /* We want to encourage people to check error values, so not getting
124 : them is discouraged here. Also makes our code easier. */
125 0 : if (! op_err)
126 0 : return gpg_error (GPG_ERR_INV_VALUE);
127 :
128 0 : err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0);
129 0 : if (err)
130 0 : return err;
131 :
132 0 : i = 0;
133 0 : while (!err && recp[i])
134 : {
135 0 : if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
136 : {
137 0 : free (container_file_esc);
138 0 : return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
139 : }
140 :
141 0 : if (asprintf (&cmd, "RECIPIENT %s", recp[i]->subkeys->fpr) < 0)
142 : {
143 0 : err = gpg_error_from_syserror ();
144 0 : free (container_file_esc);
145 0 : return err;
146 : }
147 :
148 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
149 : NULL, NULL, op_err);
150 0 : free (cmd);
151 0 : if (err || *op_err)
152 : {
153 0 : free (container_file_esc);
154 0 : return err;
155 : }
156 0 : recp++;
157 : }
158 :
159 0 : if (asprintf (&cmd, "CREATE -- %s", container_file_esc) < 0)
160 : {
161 0 : err = gpg_error_from_syserror ();
162 0 : free (container_file_esc);
163 0 : return err;
164 : }
165 0 : free (container_file_esc);
166 :
167 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
168 : NULL, NULL, op_err);
169 0 : free (cmd);
170 :
171 0 : return err;
172 : }
173 :
174 :
175 : gpgme_error_t
176 0 : gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[],
177 : const char *container_file, unsigned int flags,
178 : gpgme_error_t *op_err)
179 : {
180 : gpg_error_t err;
181 :
182 0 : TRACE_BEG3 (DEBUG_CTX, "gpgme_op_vfs_create", ctx,
183 : "container_file=%s, flags=0x%x, op_err=%p",
184 : container_file, flags, op_err);
185 :
186 0 : if (!ctx)
187 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
188 :
189 0 : if (_gpgme_debug_trace () && recp)
190 : {
191 0 : int i = 0;
192 :
193 0 : while (recp[i])
194 : {
195 0 : TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
196 : (recp[i]->subkeys && recp[i]->subkeys->fpr) ?
197 : recp[i]->subkeys->fpr : "invalid");
198 0 : i++;
199 : }
200 : }
201 :
202 0 : err = _gpgme_op_vfs_create (ctx, recp, container_file, flags, op_err);
203 0 : return TRACE_ERR (err);
204 : }
205 :
|