3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it 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.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
27 #include <sys/types.h>
37 #include "pwmd-error.h"
38 #include "util-misc.h"
42 #include "util-string.h"
48 mem_realloc_cb (void *data
, const void *buffer
, size_t len
)
50 membuf_t
*mem
= (membuf_t
*) data
;
56 if ((p
= xrealloc (mem
->buf
, mem
->len
+ len
)) == NULL
)
60 memcpy ((char *) mem
->buf
+ mem
->len
, buffer
, len
);
66 status_cb (void *data
, const char *line
)
68 struct agent_s
*agent
= data
;
70 agent
->inquire_maxlen
= 0;
72 if (!strncmp (line
, "INQUIRE_MAXLEN ", 15))
73 agent
->inquire_maxlen
= atoi (line
+ 15);
79 inquire_cb (void *user
, const char *keyword
)
81 struct agent_s
*agent
= user
;
83 return assuan_send_data (agent
->ctx
, agent
->inquire
->line
,
88 assuan_command (struct agent_s
*a
, char **result
,
89 size_t * len
, const char *cmd
)
100 rc
= assuan_transact (a
->ctx
, cmd
, mem_realloc_cb
, &a
->data
,
101 inquire_cb
, a
, status_cb
, a
);
108 mem_realloc_cb (&a
->data
, "", 1);
110 *result
= (char *) a
->data
.buf
;
123 agent_connect (struct agent_s
*agent
)
126 assuan_context_t ctx
= NULL
;
127 static struct assuan_malloc_hooks mhooks
= { xmalloc
, xrealloc
, xfree
};
129 agent
->did_restart
= 0;
130 rc
= assuan_new_ext (&ctx
, GPG_ERR_SOURCE_DEFAULT
, &mhooks
, assuan_log_cb
,
135 rc
= assuan_socket_connect (ctx
, agent
->socket
, ASSUAN_INVALID_PID
, 0);
139 assuan_release (agent
->ctx
);
146 assuan_release (ctx
);
153 send_to_agent (struct agent_s
*agent
, char **result
, size_t *len
,
160 rc
= agent_connect (agent
);
165 rc
= assuan_command (agent
, result
, len
, cmd
);
166 if (!agent
->restart
&& gpg_err_source (rc
) == GPG_ERR_SOURCE_DEFAULT
167 && (gpg_err_code (rc
) == GPG_ERR_ASS_CONNECT_FAILED
168 || gpg_err_code (rc
) == GPG_ERR_EPIPE
))
170 log_write (_ ("gpg-agent connection died (rc=%u), reconnecting"), rc
);
172 rc
= agent_connect (agent
);
175 agent
->did_restart
= 1;
176 rc
= assuan_command (agent
, result
, len
, cmd
);
185 agent_command (struct agent_s
*agent
, char **result
, size_t * len
,
186 const char *fmt
, ...)
194 if (str_vasprintf (&cmd
, fmt
, ap
) > 0)
195 rc
= send_to_agent (agent
, result
, len
, cmd
);
205 agent_disconnect (struct agent_s
*agent
)
211 assuan_release (agent
->ctx
);
217 agent_free (struct agent_s
*agent
)
222 agent_disconnect (agent
);
223 xfree (agent
->socket
);
228 agent_init (struct agent_s
**agent
)
233 char line
[PATH_MAX
], *p
;
236 char *gpghome
= config_get_string ("global", "gpg_homedir");
239 buf
= str_asprintf ("gpgconf --homedir %s --list-dirs", gpghome
);
241 buf
= str_asprintf ("gpgconf --homedir %s/.gnupg --list-dirs", homedir
);
244 fp
= popen (buf
, "r");
247 rc
= gpg_error_from_syserror ();
254 while ((p
= fgets (line
, sizeof(line
), fp
)))
256 if (line
[strlen(line
)-1] == '\n')
257 line
[strlen(line
)-1] = 0;
259 if (!strncmp (line
, "agent-socket:", 13))
261 buf
= str_dup (line
+13);
270 return GPG_ERR_ASS_GENERAL
;
273 new = xcalloc (1, sizeof (struct agent_s
));
277 return GPG_ERR_ENOMEM
;
286 agent_set_option (struct agent_s
* agent
, const char *name
, const char *value
)
288 return agent_command (agent
, NULL
, NULL
, "OPTION %s=%s", name
, value
);
292 agent_kill_scd (struct agent_s
*agent
)
296 if (config_get_boolean (NULL
, "kill_scd"))
298 rc
= agent_command (agent
, NULL
, NULL
, "SCD KILLSCD");
299 if (rc
&& gpg_err_code (rc
) != GPG_ERR_NO_SCDAEMON
300 && gpg_err_code (rc
) != GPG_ERR_EPIPE
301 && gpg_err_code (rc
) != GPG_ERR_EOF
)
302 log_write ("%s: ERR %u: %s", __FUNCTION__
, rc
, pwmd_strerror (rc
));