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