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 : /* We want to encourage people to check error values, so not getting
122 : them is discouraged here. Also makes our code easier. */
123 0 : if (! op_err)
124 0 : return gpg_error (GPG_ERR_INV_VALUE);
125 :
126 0 : err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0);
127 0 : if (err)
128 0 : return err;
129 :
130 0 : i = 0;
131 0 : while (!err && recp[i])
132 : {
133 0 : if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
134 : {
135 0 : free (container_file_esc);
136 0 : return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
137 : }
138 :
139 0 : if (asprintf (&cmd, "RECIPIENT %s", recp[i]->subkeys->fpr) < 0)
140 : {
141 0 : err = gpg_error_from_syserror ();
142 0 : free (container_file_esc);
143 0 : return err;
144 : }
145 :
146 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
147 : NULL, NULL, op_err);
148 0 : free (cmd);
149 0 : if (err || *op_err)
150 : {
151 0 : free (container_file_esc);
152 0 : return err;
153 : }
154 0 : recp++;
155 : }
156 :
157 0 : if (asprintf (&cmd, "CREATE -- %s", container_file_esc) < 0)
158 : {
159 0 : err = gpg_error_from_syserror ();
160 0 : free (container_file_esc);
161 0 : return err;
162 : }
163 0 : free (container_file_esc);
164 :
165 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
166 : NULL, NULL, op_err);
167 0 : free (cmd);
168 :
169 0 : return err;
170 : }
171 :
172 :
173 : gpgme_error_t
174 0 : gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[],
175 : const char *container_file, unsigned int flags,
176 : gpgme_error_t *op_err)
177 : {
178 : gpg_error_t err;
179 :
180 0 : TRACE_BEG3 (DEBUG_CTX, "gpgme_op_vfs_create", ctx,
181 : "container_file=%s, flags=0x%x, op_err=%p",
182 : container_file, flags, op_err);
183 :
184 0 : if (!ctx)
185 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
186 :
187 0 : if (_gpgme_debug_trace () && recp)
188 : {
189 0 : int i = 0;
190 :
191 0 : while (recp[i])
192 : {
193 0 : TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
194 : (recp[i]->subkeys && recp[i]->subkeys->fpr) ?
195 : recp[i]->subkeys->fpr : "invalid");
196 0 : i++;
197 : }
198 : }
199 :
200 0 : err = _gpgme_op_vfs_create (ctx, recp, container_file, flags, op_err);
201 0 : return TRACE_ERR (err);
202 : }
203 :
|