17f14436cd5e982cb133acae96ec557e83247ebd
[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
36 \f
37 typedef struct
38 {
39   int no_passphrase;
40   char *uid_hint;
41   char *passphrase_info;
42   int bad_passphrase;
43 } *op_data_t;
44
45
46 static void
47 release_op_data (void *hook)
48 {
49   op_data_t opd = (op_data_t) hook;
50
51   if (opd->passphrase_info)
52     free (opd->passphrase_info);
53   if (opd->uid_hint)
54     free (opd->uid_hint);
55 }
56
57 \f
58 gpgme_error_t
59 _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
60                                   char *args)
61 {
62   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
63   gpgme_error_t err;
64   void *hook;
65   op_data_t opd;
66
67   err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
68                                sizeof (*opd), release_op_data);
69   opd = hook;
70   if (err)
71     return err;
72
73   switch (code)
74     {
75     case GPGME_STATUS_USERID_HINT:
76       if (opd->uid_hint)
77         free (opd->uid_hint);
78       if (!(opd->uid_hint = strdup (args)))
79       return gpg_error_from_errno (errno);
80       break;
81
82     case GPGME_STATUS_BAD_PASSPHRASE:
83       opd->bad_passphrase++;
84       opd->no_passphrase = 0;
85       break;
86
87     case GPGME_STATUS_GOOD_PASSPHRASE:
88       opd->bad_passphrase = 0;
89       opd->no_passphrase = 0;
90       break;
91
92     case GPGME_STATUS_NEED_PASSPHRASE:
93     case GPGME_STATUS_NEED_PASSPHRASE_SYM:
94     case GPGME_STATUS_NEED_PASSPHRASE_PIN:
95       if (opd->passphrase_info)
96         free (opd->passphrase_info);
97       opd->passphrase_info = strdup (args);
98       if (!opd->passphrase_info)
99         return gpg_error_from_errno (errno);
100       break;
101
102     case GPGME_STATUS_MISSING_PASSPHRASE:
103       opd->no_passphrase = 1;
104       break;
105
106     case GPGME_STATUS_EOF:
107       if (opd->no_passphrase || opd->bad_passphrase)
108         return gpg_error (GPG_ERR_BAD_PASSPHRASE);
109       break;
110
111     default:
112       /* Ignore all other codes.  */
113       break;
114     }
115   return 0;
116 }
117
118
119 gpgme_error_t
120 _gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
121                                    const char *key, int fd, int *processed)
122 {
123   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
124   gpgme_error_t err;
125   void *hook;
126   op_data_t opd;
127
128   assert (ctx->passphrase_cb);
129
130   err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
131                                sizeof (*opd), release_op_data);
132   opd = hook;
133   if (err)
134     return err;
135
136   if (code == GPGME_STATUS_GET_HIDDEN
137       && (!strcmp (key, "passphrase.enter")
138           || !strcmp (key, "passphrase.pin.ask")))
139     {
140       if (processed)
141         *processed = 1;
142
143       err = ctx->passphrase_cb (ctx->passphrase_cb_value,
144                                 opd->uid_hint, opd->passphrase_info,
145                                 opd->bad_passphrase, fd);
146
147       /* Reset bad passphrase flag, in case it is correct now.  */
148       opd->bad_passphrase = 0;
149
150       return err;
151     }
152
153   return 0;
154 }