Locate engine names only at runtime and prefer GnuPG-2.
[gpgme.git] / src / passphrase.c
1 /* passphrase.c - Passphrase callback.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
4
5    This file is part of GPGME.
6
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.
11
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.
16
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
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
30
31 #include "gpgme.h"
32 #include "context.h"
33 #include "ops.h"
34 #include "util.h"
35 #include "debug.h"
36
37 \f
38 typedef struct
39 {
40   int no_passphrase;
41   char *uid_hint;
42   char *passphrase_info;
43   int bad_passphrase;
44 } *op_data_t;
45
46
47 static void
48 release_op_data (void *hook)
49 {
50   op_data_t opd = (op_data_t) hook;
51
52   if (opd->passphrase_info)
53     free (opd->passphrase_info);
54   if (opd->uid_hint)
55     free (opd->uid_hint);
56 }
57
58 \f
59 gpgme_error_t
60 _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
61                                   char *args)
62 {
63   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
64   gpgme_error_t err;
65   void *hook;
66   op_data_t opd;
67
68   err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
69                                sizeof (*opd), release_op_data);
70   opd = hook;
71   if (err)
72     return err;
73
74   switch (code)
75     {
76     case GPGME_STATUS_USERID_HINT:
77       if (opd->uid_hint)
78         free (opd->uid_hint);
79       if (!(opd->uid_hint = strdup (args)))
80         return gpg_error_from_syserror ();
81       break;
82
83     case GPGME_STATUS_BAD_PASSPHRASE:
84       opd->bad_passphrase++;
85       opd->no_passphrase = 0;
86       break;
87
88     case GPGME_STATUS_GOOD_PASSPHRASE:
89       opd->bad_passphrase = 0;
90       opd->no_passphrase = 0;
91       break;
92
93     case GPGME_STATUS_NEED_PASSPHRASE:
94     case GPGME_STATUS_NEED_PASSPHRASE_SYM:
95     case GPGME_STATUS_NEED_PASSPHRASE_PIN:
96       if (opd->passphrase_info)
97         free (opd->passphrase_info);
98       opd->passphrase_info = strdup (args);
99       if (!opd->passphrase_info)
100         return gpg_error_from_syserror ();
101       break;
102
103     case GPGME_STATUS_MISSING_PASSPHRASE:
104       opd->no_passphrase = 1;
105       break;
106
107     case GPGME_STATUS_EOF:
108       if (opd->no_passphrase || opd->bad_passphrase)
109         return gpg_error (GPG_ERR_BAD_PASSPHRASE);
110       break;
111
112     default:
113       /* Ignore all other codes.  */
114       break;
115     }
116   return 0;
117 }
118
119
120 gpgme_error_t
121 _gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
122                                    const char *key, int fd, int *processed)
123 {
124   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
125   gpgme_error_t err;
126   void *hook;
127   op_data_t opd;
128
129   assert (ctx->passphrase_cb);
130
131   err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
132                                sizeof (*opd), release_op_data);
133   opd = hook;
134   if (err)
135     return err;
136
137   if (code == GPGME_STATUS_GET_HIDDEN
138       && (!strcmp (key, "passphrase.enter")
139           || !strcmp (key, "passphrase.pin.ask")))
140     {
141       if (processed)
142         *processed = 1;
143
144       err = ctx->passphrase_cb (ctx->passphrase_cb_value,
145                                 opd->uid_hint, opd->passphrase_info,
146                                 opd->bad_passphrase, fd);
147
148       /* Reset bad passphrase flag, in case it is correct now.  */
149       opd->bad_passphrase = 0;
150
151       return err;
152     }
153
154   return 0;
155 }