e852e5cb30e69548a10321ab30b656e2b7d45a92
[gpgme.git] / gpgme / passphrase.c
1 /* passphrase.c - Passphrase callback.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 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 General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (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    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include "gpgme.h"
30 #include "context.h"
31 #include "ops.h"
32
33 \f
34 typedef struct
35 {
36   int no_passphrase;
37   char *uid_hint;
38   char *passphrase_info;
39   int bad_passphrase;
40 } *op_data_t;
41
42
43 static void
44 release_op_data (void *hook)
45 {
46   op_data_t opd = (op_data_t) hook;
47
48   if (opd->passphrase_info)
49     free (opd->passphrase_info);
50   if (opd->uid_hint)
51     free (opd->uid_hint);
52 }
53
54 \f
55 gpgme_error_t
56 _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
57                                   char *args)
58 {
59   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
60   gpgme_error_t err;
61   void *hook;
62   op_data_t opd;
63
64   if (!ctx->passphrase_cb)
65     return 0;
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 GPGME_Out_Of_Core;
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       if (opd->passphrase_info)
95         free (opd->passphrase_info);
96       opd->passphrase_info = strdup (args);
97       if (!opd->passphrase_info)
98         return GPGME_Out_Of_Core;
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 GPGME_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_internal (void *priv,
120                                             gpgme_status_code_t code,
121                                             const char *key, int fd,
122                                             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 && !strcmp (key, "passphrase.enter"))
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 }
154
155
156 gpgme_error_t
157 _gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
158                                    const char *key, int fd)
159 {
160   return _gpgme_passphrase_command_handler_internal (priv, code, key, fd,
161                                                      NULL);
162 }