1 /* import.c - Import a key.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
5 This file is part of GPGME.
7 GPGME is free software; you can redistribute it and/or modify it
8 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.
12 GPGME is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
38 struct _gpgme_op_import_result result;
40 /* A pointer to the next pointer of the last import status in the
41 list. This makes appending new imports painless while preserving
43 gpgme_import_status_t *lastp;
48 release_op_data (void *hook)
50 op_data_t opd = (op_data_t) hook;
51 gpgme_import_status_t import = opd->result.imports;
55 gpgme_import_status_t next = import->next;
64 gpgme_op_import_result (gpgme_ctx_t ctx)
70 TRACE_BEG (DEBUG_CTX, "gpgme_op_import_result", ctx);
72 err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL);
76 TRACE_SUC0 ("result=(null)");
81 if (_gpgme_debug_trace ())
83 gpgme_import_status_t impstat;
86 TRACE_LOG5 ("%i considered, %i no UID, %i imported, %i imported RSA, "
87 "%i unchanged", opd->result.considered,
88 opd->result.no_user_id, opd->result.imported,
89 opd->result.imported_rsa, opd->result.unchanged);
90 TRACE_LOG4 ("%i new UIDs, %i new sub keys, %i new signatures, "
91 "%i new revocations", opd->result.new_user_ids,
92 opd->result.new_sub_keys, opd->result.new_signatures,
93 opd->result.new_revocations);
94 TRACE_LOG3 ("%i secret keys, %i imported, %i unchanged",
95 opd->result.secret_read, opd->result.secret_imported,
96 opd->result.secret_unchanged);
97 TRACE_LOG2 ("%i skipped new keys, %i not imported",
98 opd->result.skipped_new_keys, opd->result.not_imported);
100 impstat = opd->result.imports;
104 TRACE_LOG4 ("import[%i] for %s = 0x%x (%s)",
105 i, impstat->fpr, impstat->status, impstat->result);
106 impstat = impstat->next;
111 TRACE_SUC1 ("result=%p", &opd->result);
117 parse_import (char *args, gpgme_import_status_t *import_status, int problem)
119 gpgme_import_status_t import;
123 import = malloc (sizeof (*import));
125 return gpg_error_from_syserror ();
128 gpg_err_set_errno (0);
129 nr = strtol (args, &tail, 0);
130 if (errno || args == tail || *tail != ' ')
132 /* The crypto backend does not behave. */
134 return gpg_error (GPG_ERR_INV_ENGINE);
145 import->result = gpg_error (GPG_ERR_GENERAL);
149 import->result = gpg_error (GPG_ERR_BAD_CERT);
153 import->result = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
157 import->result = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
164 import->result = gpg_error (GPG_ERR_NO_ERROR);
170 tail = strchr (args, ' ');
174 import->fpr = strdup (args);
177 int saved_errno = errno;
179 return gpg_error_from_errno (saved_errno);
182 *import_status = import;
189 parse_import_res (char *args, gpgme_import_result_t result)
193 gpg_err_set_errno (0);
195 #define PARSE_NEXT(x) \
196 (x) = strtol (args, &tail, 0); \
197 if (errno || args == tail || *tail != ' ') \
198 /* The crypto backend does not behave. */ \
199 return gpg_error (GPG_ERR_INV_ENGINE); \
202 PARSE_NEXT (result->considered);
203 PARSE_NEXT (result->no_user_id);
204 PARSE_NEXT (result->imported);
205 PARSE_NEXT (result->imported_rsa);
206 PARSE_NEXT (result->unchanged);
207 PARSE_NEXT (result->new_user_ids);
208 PARSE_NEXT (result->new_sub_keys);
209 PARSE_NEXT (result->new_signatures);
210 PARSE_NEXT (result->new_revocations);
211 PARSE_NEXT (result->secret_read);
212 PARSE_NEXT (result->secret_imported);
213 PARSE_NEXT (result->secret_unchanged);
214 PARSE_NEXT (result->skipped_new_keys);
215 PARSE_NEXT (result->not_imported);
222 import_status_handler (void *priv, gpgme_status_code_t code, char *args)
224 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
229 err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL);
236 case GPGME_STATUS_IMPORT_OK:
237 case GPGME_STATUS_IMPORT_PROBLEM:
238 err = parse_import (args, opd->lastp,
239 code == GPGME_STATUS_IMPORT_OK ? 0 : 1);
243 opd->lastp = &(*opd->lastp)->next;
246 case GPGME_STATUS_IMPORT_RES:
247 err = parse_import_res (args, &opd->result);
258 _gpgme_op_import_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t keydata)
264 err = _gpgme_op_reset (ctx, synchronous);
268 err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook,
269 sizeof (*opd), release_op_data);
273 opd->lastp = &opd->result.imports;
276 return gpg_error (GPG_ERR_NO_DATA);
278 _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);
280 return _gpgme_engine_op_import (ctx->engine, keydata, NULL);
285 gpgme_op_import_start (gpgme_ctx_t ctx, gpgme_data_t keydata)
289 TRACE_BEG1 (DEBUG_CTX, "gpgme_op_import_start", ctx,
290 "keydata=%p", keydata);
293 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
295 err = _gpgme_op_import_start (ctx, 0, keydata);
296 return TRACE_ERR (err);
300 /* Import the key in KEYDATA into the keyring. */
302 gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata)
306 TRACE_BEG1 (DEBUG_CTX, "gpgme_op_import", ctx,
307 "keydata=%p", keydata);
310 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
312 err = _gpgme_op_import_start (ctx, 1, keydata);
314 err = _gpgme_wait_one (ctx);
315 return TRACE_ERR (err);
321 _gpgme_op_import_keys_start (gpgme_ctx_t ctx, int synchronous,
327 int idx, firstidx, nkeys;
329 err = _gpgme_op_reset (ctx, synchronous);
333 err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook,
334 sizeof (*opd), release_op_data);
338 opd->lastp = &opd->result.imports;
341 return gpg_error (GPG_ERR_NO_DATA);
343 for (idx=nkeys=0, firstidx=-1; keys[idx]; idx++)
345 /* We only consider keys of the current protocol. */
346 if (keys[idx]->protocol != ctx->protocol)
350 /* If a key has been found using a different key listing mode,
351 we bail out. This makes the processing easier. Fixme: To
352 allow a mix of keys we would need to sort them by key listing
353 mode and start two import operations one after the other. */
354 if (keys[idx]->keylist_mode != keys[firstidx]->keylist_mode)
355 return gpg_error (GPG_ERR_CONFLICT);
359 return gpg_error (GPG_ERR_NO_DATA);
361 _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);
363 return _gpgme_engine_op_import (ctx->engine, NULL, keys);
367 /* Asynchronous version of gpgme_op_import_key. */
369 gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t *keys)
373 TRACE_BEG (DEBUG_CTX, "gpgme_op_import_keys_start", ctx);
376 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
378 if (_gpgme_debug_trace () && keys)
384 TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
385 (keys[i]->subkeys && keys[i]->subkeys->fpr) ?
386 keys[i]->subkeys->fpr : "invalid");
391 err = _gpgme_op_import_keys_start (ctx, 0, keys);
392 return TRACE_ERR (err);
396 /* Import the keys from the array KEYS into the keyring. This
397 function allows to move a key from one engine to another as long as
398 they are compatible. In particular it is used to actually import
399 keys retrieved from an external source (i.e. using
400 GPGME_KEYLIST_MODE_EXTERN). It replaces the old workaround of
401 exporting and then importing a key as used to make an X.509 key
402 permanent. This function automagically does the right thing.
404 KEYS is a NULL terminated array of gpgme key objects. The result
405 is the usual import result structure. Only keys matching the
406 current protocol are imported; other keys are ignored. */
408 gpgme_op_import_keys (gpgme_ctx_t ctx, gpgme_key_t *keys)
412 TRACE_BEG (DEBUG_CTX, "gpgme_op_import_keys", ctx);
415 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
417 if (_gpgme_debug_trace () && keys)
423 TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
424 (keys[i]->subkeys && keys[i]->subkeys->fpr) ?
425 keys[i]->subkeys->fpr : "invalid");
430 err = _gpgme_op_import_keys_start (ctx, 1, keys);
432 err = _gpgme_wait_one (ctx);
433 return TRACE_ERR (err);
437 /* Deprecated interface. */
439 gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, int *nr)
441 gpgme_error_t err = gpgme_op_import (ctx, keydata);
444 gpgme_import_result_t result = gpgme_op_import_result (ctx);
445 *nr = result->considered;