Line data Source code
1 : /* gpg-connect-agent.c - Tool to connect to the agent.
2 : * Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
3 : * Copyright (C) 2014 Werner Koch
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG 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 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG 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.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include <errno.h>
27 : #include <ctype.h>
28 : #include <assuan.h>
29 : #include <unistd.h>
30 : #include <assert.h>
31 :
32 : #include "i18n.h"
33 : #include "../common/util.h"
34 : #include "../common/asshelp.h"
35 : #include "../common/sysutils.h"
36 : #include "../common/membuf.h"
37 : #include "../common/ttyio.h"
38 : #ifdef HAVE_W32_SYSTEM
39 : # include "../common/exechelp.h"
40 : #endif
41 : #include "../common/init.h"
42 :
43 :
44 : #define CONTROL_D ('D' - 'A' + 1)
45 : #define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
46 :
47 : /* Constants to identify the commands and options. */
48 : enum cmd_and_opt_values
49 : {
50 : aNull = 0,
51 : oQuiet = 'q',
52 : oVerbose = 'v',
53 : oRawSocket = 'S',
54 : oTcpSocket = 'T',
55 : oExec = 'E',
56 : oRun = 'r',
57 : oSubst = 's',
58 :
59 : oNoVerbose = 500,
60 : oHomedir,
61 : oAgentProgram,
62 : oDirmngrProgram,
63 : oHex,
64 : oDecode,
65 : oNoExtConnect,
66 : oDirmngr,
67 : oUIServer,
68 : oNoAutostart,
69 :
70 : };
71 :
72 :
73 : /* The list of commands and options. */
74 : static ARGPARSE_OPTS opts[] = {
75 : ARGPARSE_group (301, N_("@\nOptions:\n ")),
76 :
77 : ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
78 : ARGPARSE_s_n (oQuiet, "quiet", N_("quiet")),
79 : ARGPARSE_s_n (oHex, "hex", N_("print data out hex encoded")),
80 : ARGPARSE_s_n (oDecode,"decode", N_("decode received data lines")),
81 : ARGPARSE_s_n (oDirmngr,"dirmngr", N_("connect to the dirmngr")),
82 : ARGPARSE_s_n (oUIServer, "uiserver", "@"),
83 : ARGPARSE_s_s (oRawSocket, "raw-socket",
84 : N_("|NAME|connect to Assuan socket NAME")),
85 : ARGPARSE_s_s (oTcpSocket, "tcp-socket",
86 : N_("|ADDR|connect to Assuan server at ADDR")),
87 : ARGPARSE_s_n (oExec, "exec",
88 : N_("run the Assuan server given on the command line")),
89 : ARGPARSE_s_n (oNoExtConnect, "no-ext-connect",
90 : N_("do not use extended connect mode")),
91 : ARGPARSE_s_s (oRun, "run",
92 : N_("|FILE|run commands from FILE on startup")),
93 : ARGPARSE_s_n (oSubst, "subst", N_("run /subst on startup")),
94 :
95 : ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
96 : ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
97 : ARGPARSE_s_s (oHomedir, "homedir", "@" ),
98 : ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
99 : ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
100 :
101 : ARGPARSE_end ()
102 : };
103 :
104 :
105 : /* We keep all global options in the structure OPT. */
106 : struct
107 : {
108 : int verbose; /* Verbosity level. */
109 : int quiet; /* Be extra quiet. */
110 : int autostart; /* Start the server if not running. */
111 : const char *homedir; /* Configuration directory name */
112 : const char *agent_program; /* Value of --agent-program. */
113 : const char *dirmngr_program; /* Value of --dirmngr-program. */
114 : int hex; /* Print data lines in hex format. */
115 : int decode; /* Decode received data lines. */
116 : int use_dirmngr; /* Use the dirmngr and not gpg-agent. */
117 : int use_uiserver; /* Use the standard UI server. */
118 : const char *raw_socket; /* Name of socket to connect in raw mode. */
119 : const char *tcp_socket; /* Name of server to connect in tcp mode. */
120 : int exec; /* Run the pgm given on the command line. */
121 : unsigned int connect_flags; /* Flags used for connecting. */
122 : int enable_varsubst; /* Set if variable substitution is enabled. */
123 : int trim_leading_spaces;
124 : } opt;
125 :
126 :
127 :
128 : /* Definitions for /definq commands and a global linked list with all
129 : the definitions. */
130 : struct definq_s
131 : {
132 : struct definq_s *next;
133 : char *name; /* Name of inquiry or NULL for any name. */
134 : int is_var; /* True if FILE is a variable name. */
135 : int is_prog; /* True if FILE is a program to run. */
136 : char file[1]; /* Name of file or program. */
137 : };
138 : typedef struct definq_s *definq_t;
139 :
140 : static definq_t definq_list;
141 : static definq_t *definq_list_tail = &definq_list;
142 :
143 :
144 : /* Variable definitions and glovbal table. */
145 : struct variable_s
146 : {
147 : struct variable_s *next;
148 : char *value; /* Malloced value - always a string. */
149 : char name[1]; /* Name of the variable. */
150 : };
151 : typedef struct variable_s *variable_t;
152 :
153 : static variable_t variable_table;
154 :
155 :
156 : /* To implement loops we store entire lines in a linked list. */
157 : struct loopline_s
158 : {
159 : struct loopline_s *next;
160 : char line[1];
161 : };
162 : typedef struct loopline_s *loopline_t;
163 :
164 :
165 : /* This is used to store the pid of the server. */
166 : static pid_t server_pid = (pid_t)(-1);
167 :
168 : /* The current datasink file or NULL. */
169 : static FILE *current_datasink;
170 :
171 : /* A list of open file descriptors. */
172 : static struct
173 : {
174 : int inuse;
175 : #ifdef HAVE_W32_SYSTEM
176 : HANDLE handle;
177 : #endif
178 : } open_fd_table[256];
179 :
180 :
181 : /*-- local prototypes --*/
182 : static char *substitute_line_copy (const char *buffer);
183 : static int read_and_print_response (assuan_context_t ctx, int withhash,
184 : int *r_goterr);
185 : static assuan_context_t start_agent (void);
186 :
187 :
188 :
189 :
190 : /* Print usage information and and provide strings for help. */
191 : static const char *
192 0 : my_strusage( int level )
193 : {
194 : const char *p;
195 :
196 0 : switch (level)
197 : {
198 0 : case 11: p = "@GPG@-connect-agent (@GNUPG@)";
199 0 : break;
200 0 : case 13: p = VERSION; break;
201 0 : case 17: p = PRINTABLE_OS_NAME; break;
202 0 : case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
203 :
204 : case 1:
205 0 : case 40: p = _("Usage: @GPG@-connect-agent [options] (-h for help)");
206 0 : break;
207 : case 41:
208 0 : p = _("Syntax: @GPG@-connect-agent [options]\n"
209 : "Connect to a running agent and send commands\n");
210 0 : break;
211 0 : case 31: p = "\nHome: "; break;
212 0 : case 32: p = gnupg_homedir (); break;
213 0 : case 33: p = "\n"; break;
214 :
215 0 : default: p = NULL; break;
216 : }
217 0 : return p;
218 : }
219 :
220 :
221 : /* Unescape STRING and returned the malloced result. The surrounding
222 : quotes must already be removed from STRING. */
223 : static char *
224 0 : unescape_string (const char *string)
225 : {
226 : const unsigned char *s;
227 : int esc;
228 : size_t n;
229 : char *buffer;
230 : unsigned char *d;
231 :
232 0 : n = 0;
233 0 : for (s = (const unsigned char*)string, esc=0; *s; s++)
234 : {
235 0 : if (esc)
236 : {
237 0 : switch (*s)
238 : {
239 : case 'b':
240 : case 't':
241 : case 'v':
242 : case 'n':
243 : case 'f':
244 : case 'r':
245 : case '"':
246 : case '\'':
247 0 : case '\\': n++; break;
248 : case 'x':
249 0 : if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
250 0 : n++;
251 0 : break;
252 :
253 : default:
254 0 : if (s[1] && s[2]
255 0 : && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
256 0 : n++;
257 0 : break;
258 : }
259 0 : esc = 0;
260 : }
261 0 : else if (*s == '\\')
262 0 : esc = 1;
263 : else
264 0 : n++;
265 : }
266 :
267 0 : buffer = xmalloc (n+1);
268 0 : d = (unsigned char*)buffer;
269 0 : for (s = (const unsigned char*)string, esc=0; *s; s++)
270 : {
271 0 : if (esc)
272 : {
273 0 : switch (*s)
274 : {
275 0 : case 'b': *d++ = '\b'; break;
276 0 : case 't': *d++ = '\t'; break;
277 0 : case 'v': *d++ = '\v'; break;
278 0 : case 'n': *d++ = '\n'; break;
279 0 : case 'f': *d++ = '\f'; break;
280 0 : case 'r': *d++ = '\r'; break;
281 0 : case '"': *d++ = '\"'; break;
282 0 : case '\'': *d++ = '\''; break;
283 0 : case '\\': *d++ = '\\'; break;
284 : case 'x':
285 0 : if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
286 : {
287 0 : s++;
288 0 : *d++ = xtoi_2 (s);
289 0 : s++;
290 : }
291 0 : break;
292 :
293 : default:
294 0 : if (s[1] && s[2]
295 0 : && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
296 : {
297 0 : *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
298 0 : s += 2;
299 : }
300 0 : break;
301 : }
302 0 : esc = 0;
303 : }
304 0 : else if (*s == '\\')
305 0 : esc = 1;
306 : else
307 0 : *d++ = *s;
308 : }
309 0 : *d = 0;
310 0 : return buffer;
311 : }
312 :
313 :
314 : /* Do the percent unescaping and return a newly malloced string.
315 : If WITH_PLUS is set '+' characters will be changed to space. */
316 : static char *
317 0 : unpercent_string (const char *string, int with_plus)
318 : {
319 : const unsigned char *s;
320 : unsigned char *buffer, *p;
321 : size_t n;
322 :
323 0 : n = 0;
324 0 : for (s=(const unsigned char *)string; *s; s++)
325 : {
326 0 : if (*s == '%' && s[1] && s[2])
327 : {
328 0 : s++;
329 0 : n++;
330 0 : s++;
331 : }
332 0 : else if (with_plus && *s == '+')
333 0 : n++;
334 : else
335 0 : n++;
336 : }
337 :
338 0 : buffer = xmalloc (n+1);
339 0 : p = buffer;
340 0 : for (s=(const unsigned char *)string; *s; s++)
341 : {
342 0 : if (*s == '%' && s[1] && s[2])
343 : {
344 0 : s++;
345 0 : *p++ = xtoi_2 (s);
346 0 : s++;
347 : }
348 0 : else if (with_plus && *s == '+')
349 0 : *p++ = ' ';
350 : else
351 0 : *p++ = *s;
352 : }
353 0 : *p = 0;
354 0 : return (char*)buffer;
355 : }
356 :
357 :
358 :
359 :
360 :
361 : static const char *
362 47 : set_var (const char *name, const char *value)
363 : {
364 : variable_t var;
365 :
366 47 : for (var = variable_table; var; var = var->next)
367 0 : if (!strcmp (var->name, name))
368 0 : break;
369 47 : if (!var)
370 : {
371 47 : var = xmalloc (sizeof *var + strlen (name));
372 47 : var->value = NULL;
373 47 : strcpy (var->name, name);
374 47 : var->next = variable_table;
375 47 : variable_table = var;
376 : }
377 47 : xfree (var->value);
378 47 : var->value = value? xstrdup (value) : NULL;
379 47 : return var->value;
380 : }
381 :
382 :
383 : static void
384 47 : set_int_var (const char *name, int value)
385 : {
386 : char numbuf[35];
387 :
388 47 : snprintf (numbuf, sizeof numbuf, "%d", value);
389 47 : set_var (name, numbuf);
390 47 : }
391 :
392 :
393 : /* Return the value of a variable. That value is valid until a
394 : variable of the name is changed. Return NULL if not found. Note
395 : that envvars are copied to our variable list at the first access
396 : and not at oprogram start. */
397 : static const char *
398 0 : get_var (const char *name)
399 : {
400 : variable_t var;
401 : const char *s;
402 :
403 0 : if (!*name)
404 0 : return "";
405 0 : for (var = variable_table; var; var = var->next)
406 0 : if (!strcmp (var->name, name))
407 0 : break;
408 0 : if (!var && (s = getenv (name)))
409 0 : return set_var (name, s);
410 0 : if (!var || !var->value)
411 0 : return NULL;
412 0 : return var->value;
413 : }
414 :
415 :
416 : /* Perform some simple arithmetic operations. Caller must release
417 : the return value. On error the return value is NULL. */
418 : static char *
419 0 : arithmetic_op (int operator, const char *operands)
420 : {
421 : long result, value;
422 : char numbuf[35];
423 :
424 0 : while ( spacep (operands) )
425 0 : operands++;
426 0 : if (!*operands)
427 0 : return NULL;
428 0 : result = strtol (operands, NULL, 0);
429 0 : while (*operands && !spacep (operands) )
430 0 : operands++;
431 0 : if (operator == '!')
432 0 : result = !result;
433 :
434 0 : while (*operands)
435 : {
436 0 : while ( spacep (operands) )
437 0 : operands++;
438 0 : if (!*operands)
439 0 : break;
440 0 : value = strtol (operands, NULL, 0);
441 0 : while (*operands && !spacep (operands) )
442 0 : operands++;
443 0 : switch (operator)
444 : {
445 0 : case '+': result += value; break;
446 0 : case '-': result -= value; break;
447 0 : case '*': result *= value; break;
448 : case '/':
449 0 : if (!value)
450 0 : return NULL;
451 0 : result /= value;
452 0 : break;
453 : case '%':
454 0 : if (!value)
455 0 : return NULL;
456 0 : result %= value;
457 0 : break;
458 0 : case '!': result = !value; break;
459 0 : case '|': result = result || value; break;
460 0 : case '&': result = result && value; break;
461 : default:
462 0 : log_error ("unknown arithmetic operator '%c'\n", operator);
463 0 : return NULL;
464 : }
465 : }
466 0 : snprintf (numbuf, sizeof numbuf, "%ld", result);
467 0 : return xstrdup (numbuf);
468 : }
469 :
470 :
471 :
472 : /* Extended version of get_var. This returns a malloced string and
473 : understand the function syntax: "func args".
474 :
475 : Defined functions are
476 :
477 : get - Return a value described by the next argument:
478 : cwd - The current working directory.
479 : homedir - The gnupg homedir.
480 : sysconfdir - GnuPG's system configuration directory.
481 : bindir - GnuPG's binary directory.
482 : libdir - GnuPG's library directory.
483 : libexecdir - GnuPG's library directory for executable files.
484 : datadir - GnuPG's data directory.
485 : serverpid - The PID of the current server.
486 :
487 : unescape ARGS
488 : Remove C-style escapes from string. Note that "\0" and
489 : "\x00" terminate the string implictly. Use "\x7d" to
490 : represent the closing brace. The args start right after
491 : the first space after the function name.
492 :
493 : unpercent ARGS
494 : unpercent+ ARGS
495 : Remove percent style ecaping from string. Note that "%00
496 : terminates the string implicitly. Use "%7d" to represetn
497 : the closing brace. The args start right after the first
498 : space after the function name. "unpercent+" also maps '+'
499 : to space.
500 :
501 : percent ARGS
502 : percent+ ARGS
503 : Escape the args using the percent style. Tabs, formfeeds,
504 : linefeeds, carriage return, and the plus sign are also
505 : escaped. "percent+" also maps spaces to plus characters.
506 :
507 : errcode ARG
508 : Assuming ARG is an integer, return the gpg-error code.
509 :
510 : errsource ARG
511 : Assuming ARG is an integer, return the gpg-error source.
512 :
513 : errstring ARG
514 : Assuming ARG is an integer return a formatted fpf error string.
515 :
516 :
517 : Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg"
518 :
519 : */
520 : static char *
521 0 : get_var_ext (const char *name)
522 : {
523 : static int recursion_count;
524 : const char *s;
525 : char *result;
526 : char *p;
527 0 : char *free_me = NULL;
528 : int intvalue;
529 :
530 0 : if (recursion_count > 50)
531 : {
532 0 : log_error ("variables nested too deeply\n");
533 0 : return NULL;
534 : }
535 :
536 0 : recursion_count++;
537 0 : free_me = opt.enable_varsubst? substitute_line_copy (name) : NULL;
538 0 : if (free_me)
539 0 : name = free_me;
540 0 : for (s=name; *s && !spacep (s); s++)
541 : ;
542 0 : if (!*s)
543 : {
544 0 : s = get_var (name);
545 0 : result = s? xstrdup (s): NULL;
546 : }
547 0 : else if ( (s - name) == 3 && !strncmp (name, "get", 3))
548 : {
549 0 : while ( spacep (s) )
550 0 : s++;
551 0 : if (!strcmp (s, "cwd"))
552 : {
553 0 : result = gnupg_getcwd ();
554 0 : if (!result)
555 0 : log_error ("getcwd failed: %s\n", strerror (errno));
556 : }
557 0 : else if (!strcmp (s, "homedir"))
558 0 : result = xstrdup (gnupg_homedir ());
559 0 : else if (!strcmp (s, "sysconfdir"))
560 0 : result = xstrdup (gnupg_sysconfdir ());
561 0 : else if (!strcmp (s, "bindir"))
562 0 : result = xstrdup (gnupg_bindir ());
563 0 : else if (!strcmp (s, "libdir"))
564 0 : result = xstrdup (gnupg_libdir ());
565 0 : else if (!strcmp (s, "libexecdir"))
566 0 : result = xstrdup (gnupg_libexecdir ());
567 0 : else if (!strcmp (s, "datadir"))
568 0 : result = xstrdup (gnupg_datadir ());
569 0 : else if (!strcmp (s, "serverpid"))
570 0 : result = xasprintf ("%d", (int)server_pid);
571 : else
572 : {
573 0 : log_error ("invalid argument '%s' for variable function 'get'\n", s);
574 0 : log_info ("valid are: cwd, "
575 : "{home,bin,lib,libexec,data}dir, serverpid\n");
576 0 : result = NULL;
577 : }
578 : }
579 0 : else if ( (s - name) == 8 && !strncmp (name, "unescape", 8))
580 : {
581 0 : s++;
582 0 : result = unescape_string (s);
583 : }
584 0 : else if ( (s - name) == 9 && !strncmp (name, "unpercent", 9))
585 : {
586 0 : s++;
587 0 : result = unpercent_string (s, 0);
588 : }
589 0 : else if ( (s - name) == 10 && !strncmp (name, "unpercent+", 10))
590 : {
591 0 : s++;
592 0 : result = unpercent_string (s, 1);
593 : }
594 0 : else if ( (s - name) == 7 && !strncmp (name, "percent", 7))
595 : {
596 0 : s++;
597 0 : result = percent_escape (s, "+\t\r\n\f\v");
598 : }
599 0 : else if ( (s - name) == 8 && !strncmp (name, "percent+", 8))
600 : {
601 0 : s++;
602 0 : result = percent_escape (s, "+\t\r\n\f\v");
603 0 : for (p=result; *p; p++)
604 0 : if (*p == ' ')
605 0 : *p = '+';
606 : }
607 0 : else if ( (s - name) == 7 && !strncmp (name, "errcode", 7))
608 : {
609 0 : s++;
610 0 : intvalue = (int)strtol (s, NULL, 0);
611 0 : result = xasprintf ("%d", gpg_err_code (intvalue));
612 : }
613 0 : else if ( (s - name) == 9 && !strncmp (name, "errsource", 9))
614 : {
615 0 : s++;
616 0 : intvalue = (int)strtol (s, NULL, 0);
617 0 : result = xasprintf ("%d", gpg_err_source (intvalue));
618 : }
619 0 : else if ( (s - name) == 9 && !strncmp (name, "errstring", 9))
620 : {
621 0 : s++;
622 0 : intvalue = (int)strtol (s, NULL, 0);
623 0 : result = xasprintf ("%s <%s>",
624 : gpg_strerror (intvalue), gpg_strsource (intvalue));
625 : }
626 0 : else if ( (s - name) == 1 && strchr ("+-*/%!|&", *name))
627 : {
628 0 : result = arithmetic_op (*name, s+1);
629 : }
630 : else
631 : {
632 0 : log_error ("unknown variable function '%.*s'\n", (int)(s-name), name);
633 0 : result = NULL;
634 : }
635 :
636 0 : xfree (free_me);
637 0 : recursion_count--;
638 0 : return result;
639 : }
640 :
641 :
642 : /* Substitute variables in LINE and return a new allocated buffer if
643 : required. The function might modify LINE if the expanded version
644 : fits into it. */
645 : static char *
646 0 : substitute_line (char *buffer)
647 : {
648 0 : char *line = buffer;
649 : char *p, *pend;
650 : const char *value;
651 : size_t valuelen, n;
652 0 : char *result = NULL;
653 0 : char *freeme = NULL;
654 :
655 0 : while (*line)
656 : {
657 0 : p = strchr (line, '$');
658 0 : if (!p)
659 0 : return result; /* No more variables. */
660 :
661 0 : if (p[1] == '$') /* Escaped dollar sign. */
662 : {
663 0 : memmove (p, p+1, strlen (p+1)+1);
664 0 : line = p + 1;
665 0 : continue;
666 : }
667 0 : if (p[1] == '{')
668 : {
669 0 : int count = 0;
670 :
671 0 : for (pend=p+2; *pend; pend++)
672 : {
673 0 : if (*pend == '{')
674 0 : count++;
675 0 : else if (*pend == '}')
676 : {
677 0 : if (--count < 0)
678 0 : break;
679 : }
680 : }
681 0 : if (!*pend)
682 0 : return result; /* Unclosed - don't substitute. */
683 : }
684 : else
685 : {
686 0 : for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++)
687 : ;
688 : }
689 0 : if (p[1] == '{' && *pend == '}')
690 0 : {
691 0 : int save = *pend;
692 0 : *pend = 0;
693 0 : freeme = get_var_ext (p+2);
694 0 : value = freeme;
695 0 : *pend++ = save;
696 : }
697 0 : else if (*pend)
698 : {
699 0 : int save = *pend;
700 0 : *pend = 0;
701 0 : value = get_var (p+1);
702 0 : *pend = save;
703 : }
704 : else
705 0 : value = get_var (p+1);
706 0 : if (!value)
707 0 : value = "";
708 0 : valuelen = strlen (value);
709 0 : if (valuelen <= pend - p)
710 : {
711 0 : memcpy (p, value, valuelen);
712 0 : p += valuelen;
713 0 : n = pend - p;
714 0 : if (n)
715 0 : memmove (p, p+n, strlen (p+n)+1);
716 0 : line = p;
717 : }
718 : else
719 : {
720 0 : char *src = result? result : buffer;
721 : char *dst;
722 :
723 0 : dst = xmalloc (strlen (src) + valuelen + 1);
724 0 : n = p - src;
725 0 : memcpy (dst, src, n);
726 0 : memcpy (dst + n, value, valuelen);
727 0 : n += valuelen;
728 0 : strcpy (dst + n, pend);
729 0 : line = dst + n;
730 0 : xfree (result);
731 0 : result = dst;
732 : }
733 0 : xfree (freeme);
734 0 : freeme = NULL;
735 : }
736 0 : return result;
737 : }
738 :
739 : /* Same as substitute_line but do not modify BUFFER. */
740 : static char *
741 0 : substitute_line_copy (const char *buffer)
742 : {
743 : char *result, *p;
744 :
745 0 : p = xstrdup (buffer?buffer:"");
746 0 : result = substitute_line (p);
747 0 : if (!result)
748 0 : result = p;
749 : else
750 0 : xfree (p);
751 0 : return result;
752 : }
753 :
754 :
755 : static void
756 0 : assign_variable (char *line, int syslet)
757 : {
758 : char *name, *p, *tmp, *free_me, *buffer;
759 :
760 : /* Get the name. */
761 0 : name = line;
762 0 : for (p=name; *p && !spacep (p); p++)
763 : ;
764 0 : if (*p)
765 0 : *p++ = 0;
766 0 : while (spacep (p))
767 0 : p++;
768 :
769 0 : if (!*p)
770 0 : set_var (name, NULL); /* Remove variable. */
771 0 : else if (syslet)
772 : {
773 0 : free_me = opt.enable_varsubst? substitute_line_copy (p) : NULL;
774 0 : if (free_me)
775 0 : p = free_me;
776 0 : buffer = xmalloc (4 + strlen (p) + 1);
777 0 : strcpy (stpcpy (buffer, "get "), p);
778 0 : tmp = get_var_ext (buffer);
779 0 : xfree (buffer);
780 0 : set_var (name, tmp);
781 0 : xfree (tmp);
782 0 : xfree (free_me);
783 : }
784 : else
785 : {
786 0 : tmp = opt.enable_varsubst? substitute_line_copy (p) : NULL;
787 0 : if (tmp)
788 : {
789 0 : set_var (name, tmp);
790 0 : xfree (tmp);
791 : }
792 : else
793 0 : set_var (name, p);
794 : }
795 0 : }
796 :
797 :
798 : static void
799 0 : show_variables (void)
800 : {
801 : variable_t var;
802 :
803 0 : for (var = variable_table; var; var = var->next)
804 0 : if (var->value)
805 0 : printf ("%-20s %s\n", var->name, var->value);
806 0 : }
807 :
808 :
809 : /* Store an inquire response pattern. Note, that this function may
810 : change the content of LINE. We assume that leading white spaces
811 : are already removed. */
812 : static void
813 0 : add_definq (char *line, int is_var, int is_prog)
814 : {
815 : definq_t d;
816 : char *name, *p;
817 :
818 : /* Get name. */
819 0 : name = line;
820 0 : for (p=name; *p && !spacep (p); p++)
821 : ;
822 0 : if (*p)
823 0 : *p++ = 0;
824 0 : while (spacep (p))
825 0 : p++;
826 :
827 0 : d = xmalloc (sizeof *d + strlen (p) );
828 0 : strcpy (d->file, p);
829 0 : d->is_var = is_var;
830 0 : d->is_prog = is_prog;
831 0 : if ( !strcmp (name, "*"))
832 0 : d->name = NULL;
833 : else
834 0 : d->name = xstrdup (name);
835 :
836 0 : d->next = NULL;
837 0 : *definq_list_tail = d;
838 0 : definq_list_tail = &d->next;
839 0 : }
840 :
841 :
842 : /* Show all inquiry defintions. */
843 : static void
844 0 : show_definq (void)
845 : {
846 : definq_t d;
847 :
848 0 : for (d=definq_list; d; d = d->next)
849 0 : if (d->name)
850 0 : printf ("%-20s %c %s\n",
851 0 : d->name, d->is_var? 'v' : d->is_prog? 'p':'f', d->file);
852 0 : for (d=definq_list; d; d = d->next)
853 0 : if (!d->name)
854 0 : printf ("%-20s %c %s\n", "*",
855 0 : d->is_var? 'v': d->is_prog? 'p':'f', d->file);
856 0 : }
857 :
858 :
859 : /* Clear all inquiry definitions. */
860 : static void
861 0 : clear_definq (void)
862 : {
863 0 : while (definq_list)
864 : {
865 0 : definq_t tmp = definq_list->next;
866 0 : xfree (definq_list->name);
867 0 : xfree (definq_list);
868 0 : definq_list = tmp;
869 : }
870 0 : definq_list_tail = &definq_list;
871 0 : }
872 :
873 :
874 : static void
875 0 : do_sendfd (assuan_context_t ctx, char *line)
876 : {
877 : FILE *fp;
878 : char *name, *mode, *p;
879 : int rc, fd;
880 :
881 : /* Get file name. */
882 0 : name = line;
883 0 : for (p=name; *p && !spacep (p); p++)
884 : ;
885 0 : if (*p)
886 0 : *p++ = 0;
887 0 : while (spacep (p))
888 0 : p++;
889 :
890 : /* Get mode. */
891 0 : mode = p;
892 0 : if (!*mode)
893 0 : mode = "r";
894 : else
895 : {
896 0 : for (p=mode; *p && !spacep (p); p++)
897 : ;
898 0 : if (*p)
899 0 : *p++ = 0;
900 : }
901 :
902 : /* Open and send. */
903 0 : fp = fopen (name, mode);
904 0 : if (!fp)
905 : {
906 0 : log_error ("can't open '%s' in \"%s\" mode: %s\n",
907 0 : name, mode, strerror (errno));
908 0 : return;
909 : }
910 0 : fd = fileno (fp);
911 :
912 0 : if (opt.verbose)
913 0 : log_error ("file '%s' opened in \"%s\" mode, fd=%d\n",
914 : name, mode, fd);
915 :
916 0 : rc = assuan_sendfd (ctx, INT2FD (fd) );
917 0 : if (rc)
918 0 : log_error ("sending descriptor %d failed: %s\n", fd, gpg_strerror (rc));
919 0 : fclose (fp);
920 : }
921 :
922 :
923 : static void
924 0 : do_recvfd (assuan_context_t ctx, char *line)
925 : {
926 : (void)ctx;
927 : (void)line;
928 0 : log_info ("This command has not yet been implemented\n");
929 0 : }
930 :
931 :
932 : static void
933 0 : do_open (char *line)
934 : {
935 : FILE *fp;
936 : char *varname, *name, *mode, *p;
937 : int fd;
938 :
939 : #ifdef HAVE_W32_SYSTEM
940 : if (server_pid == (pid_t)(-1))
941 : {
942 : log_error ("the pid of the server is unknown\n");
943 : log_info ("use command \"/serverpid\" first\n");
944 : return;
945 : }
946 : #endif
947 :
948 : /* Get variable name. */
949 0 : varname = line;
950 0 : for (p=varname; *p && !spacep (p); p++)
951 : ;
952 0 : if (*p)
953 0 : *p++ = 0;
954 0 : while (spacep (p))
955 0 : p++;
956 :
957 : /* Get file name. */
958 0 : name = p;
959 0 : for (p=name; *p && !spacep (p); p++)
960 : ;
961 0 : if (*p)
962 0 : *p++ = 0;
963 0 : while (spacep (p))
964 0 : p++;
965 :
966 : /* Get mode. */
967 0 : mode = p;
968 0 : if (!*mode)
969 0 : mode = "r";
970 : else
971 : {
972 0 : for (p=mode; *p && !spacep (p); p++)
973 : ;
974 0 : if (*p)
975 0 : *p++ = 0;
976 : }
977 :
978 : /* Open and send. */
979 0 : fp = fopen (name, mode);
980 0 : if (!fp)
981 : {
982 0 : log_error ("can't open '%s' in \"%s\" mode: %s\n",
983 0 : name, mode, strerror (errno));
984 0 : return;
985 : }
986 0 : fd = fileno (fp);
987 0 : if (fd >= 0 && fd < DIM (open_fd_table))
988 : {
989 0 : open_fd_table[fd].inuse = 1;
990 : #ifdef HAVE_W32CE_SYSTEM
991 : # warning fixme: implement our pipe emulation.
992 : #endif
993 : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
994 : {
995 : HANDLE prochandle, handle, newhandle;
996 :
997 : handle = (void*)_get_osfhandle (fd);
998 :
999 : prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
1000 : if (!prochandle)
1001 : {
1002 : log_error ("failed to open the server process\n");
1003 : close (fd);
1004 : return;
1005 : }
1006 :
1007 : if (!DuplicateHandle (GetCurrentProcess(), handle,
1008 : prochandle, &newhandle, 0,
1009 : TRUE, DUPLICATE_SAME_ACCESS ))
1010 : {
1011 : log_error ("failed to duplicate the handle\n");
1012 : close (fd);
1013 : CloseHandle (prochandle);
1014 : return;
1015 : }
1016 : CloseHandle (prochandle);
1017 : open_fd_table[fd].handle = newhandle;
1018 : }
1019 : if (opt.verbose)
1020 : log_info ("file '%s' opened in \"%s\" mode, fd=%d (libc=%d)\n",
1021 : name, mode, (int)open_fd_table[fd].handle, fd);
1022 : set_int_var (varname, (int)open_fd_table[fd].handle);
1023 : #else
1024 0 : if (opt.verbose)
1025 0 : log_info ("file '%s' opened in \"%s\" mode, fd=%d\n",
1026 : name, mode, fd);
1027 0 : set_int_var (varname, fd);
1028 : #endif
1029 : }
1030 : else
1031 : {
1032 0 : log_error ("can't put fd %d into table\n", fd);
1033 0 : close (fd);
1034 : }
1035 : }
1036 :
1037 :
1038 : static void
1039 0 : do_close (char *line)
1040 : {
1041 0 : int fd = atoi (line);
1042 :
1043 : #ifdef HAVE_W32_SYSTEM
1044 : int i;
1045 :
1046 : for (i=0; i < DIM (open_fd_table); i++)
1047 : if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd)
1048 : break;
1049 : if (i < DIM (open_fd_table))
1050 : fd = i;
1051 : else
1052 : {
1053 : log_error ("given fd (system handle) has not been opened\n");
1054 : return;
1055 : }
1056 : #endif
1057 :
1058 0 : if (fd < 0 || fd >= DIM (open_fd_table))
1059 : {
1060 0 : log_error ("invalid fd\n");
1061 0 : return;
1062 : }
1063 :
1064 0 : if (!open_fd_table[fd].inuse)
1065 : {
1066 0 : log_error ("given fd has not been opened\n");
1067 0 : return;
1068 : }
1069 : #ifdef HAVE_W32_SYSTEM
1070 : CloseHandle (open_fd_table[fd].handle); /* Close duped handle. */
1071 : #endif
1072 0 : close (fd);
1073 0 : open_fd_table[fd].inuse = 0;
1074 : }
1075 :
1076 :
1077 : static void
1078 0 : do_showopen (void)
1079 : {
1080 : int i;
1081 :
1082 0 : for (i=0; i < DIM (open_fd_table); i++)
1083 0 : if (open_fd_table[i].inuse)
1084 : {
1085 : #ifdef HAVE_W32_SYSTEM
1086 : printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i);
1087 : #else
1088 0 : printf ("%-15d\n", i);
1089 : #endif
1090 : }
1091 0 : }
1092 :
1093 :
1094 :
1095 : static gpg_error_t
1096 0 : getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
1097 : {
1098 0 : membuf_t *mb = opaque;
1099 0 : put_membuf (mb, buffer, length);
1100 0 : return 0;
1101 : }
1102 :
1103 : /* Get the pid of the server and store it locally. */
1104 : static void
1105 0 : do_serverpid (assuan_context_t ctx)
1106 : {
1107 : int rc;
1108 : membuf_t mb;
1109 : char *buffer;
1110 :
1111 0 : init_membuf (&mb, 100);
1112 0 : rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb,
1113 : NULL, NULL, NULL, NULL);
1114 0 : put_membuf (&mb, "", 1);
1115 0 : buffer = get_membuf (&mb, NULL);
1116 0 : if (rc || !buffer)
1117 0 : log_error ("command \"%s\" failed: %s\n",
1118 : "GETINFO pid", gpg_strerror (rc));
1119 : else
1120 : {
1121 0 : server_pid = (pid_t)strtoul (buffer, NULL, 10);
1122 0 : if (opt.verbose)
1123 0 : log_info ("server's PID is %lu\n", (unsigned long)server_pid);
1124 : }
1125 0 : xfree (buffer);
1126 0 : }
1127 :
1128 :
1129 : /* Return true if the command is either "HELP" or "SCD HELP". */
1130 : static int
1131 47 : help_cmd_p (const char *line)
1132 : {
1133 47 : if (!ascii_strncasecmp (line, "SCD", 3)
1134 0 : && (spacep (line+3) || !line[3]))
1135 : {
1136 0 : for (line += 3; spacep (line); line++)
1137 : ;
1138 : }
1139 :
1140 94 : return (!ascii_strncasecmp (line, "HELP", 4)
1141 47 : && (spacep (line+4) || !line[4]));
1142 : }
1143 :
1144 :
1145 : /* gpg-connect-agent's entry point. */
1146 : int
1147 92 : main (int argc, char **argv)
1148 : {
1149 : ARGPARSE_ARGS pargs;
1150 92 : int no_more_options = 0;
1151 : assuan_context_t ctx;
1152 : char *line, *p;
1153 : char *tmpline;
1154 : size_t linesize;
1155 : int rc;
1156 : int cmderr;
1157 92 : const char *opt_run = NULL;
1158 92 : FILE *script_fp = NULL;
1159 : int use_tty, keep_line;
1160 : struct {
1161 : int collecting;
1162 : loopline_t head;
1163 : loopline_t *tail;
1164 : loopline_t current;
1165 : unsigned int nestlevel;
1166 : int oneshot;
1167 : char *condition;
1168 : } loopstack[20];
1169 : int loopidx;
1170 92 : char **cmdline_commands = NULL;
1171 :
1172 92 : early_system_init ();
1173 92 : gnupg_rl_initialize ();
1174 92 : set_strusage (my_strusage);
1175 92 : log_set_prefix ("gpg-connect-agent", GPGRT_LOG_WITH_PREFIX);
1176 :
1177 : /* Make sure that our subsystems are ready. */
1178 92 : i18n_init();
1179 92 : init_common_subsystems (&argc, &argv);
1180 :
1181 92 : assuan_set_gpg_err_source (0);
1182 :
1183 :
1184 92 : opt.autostart = 1;
1185 92 : opt.connect_flags = 1;
1186 :
1187 : /* Parse the command line. */
1188 92 : pargs.argc = &argc;
1189 92 : pargs.argv = &argv;
1190 92 : pargs.flags = 1; /* Do not remove the args. */
1191 366 : while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
1192 : {
1193 182 : switch (pargs.r_opt)
1194 : {
1195 0 : case oQuiet: opt.quiet = 1; break;
1196 91 : case oVerbose: opt.verbose++; break;
1197 0 : case oNoVerbose: opt.verbose = 0; break;
1198 0 : case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
1199 45 : case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
1200 0 : case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
1201 46 : case oNoAutostart: opt.autostart = 0; break;
1202 0 : case oHex: opt.hex = 1; break;
1203 0 : case oDecode: opt.decode = 1; break;
1204 0 : case oDirmngr: opt.use_dirmngr = 1; break;
1205 0 : case oUIServer: opt.use_uiserver = 1; break;
1206 0 : case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
1207 0 : case oTcpSocket: opt.tcp_socket = pargs.r.ret_str; break;
1208 0 : case oExec: opt.exec = 1; break;
1209 0 : case oNoExtConnect: opt.connect_flags &= ~(1); break;
1210 0 : case oRun: opt_run = pargs.r.ret_str; break;
1211 : case oSubst:
1212 0 : opt.enable_varsubst = 1;
1213 0 : opt.trim_leading_spaces = 1;
1214 0 : break;
1215 :
1216 0 : default: pargs.err = 2; break;
1217 : }
1218 : }
1219 :
1220 92 : if (log_get_errorcount (0))
1221 0 : exit (2);
1222 :
1223 : /* --uiserver is a shortcut for a specific raw socket. This comes
1224 : in particular handy on Windows. */
1225 92 : if (opt.use_uiserver)
1226 : {
1227 0 : opt.raw_socket = make_absfilename (gnupg_homedir (), "S.uiserver", NULL);
1228 : }
1229 :
1230 : /* Print a warning if an argument looks like an option. */
1231 92 : if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
1232 : {
1233 : int i;
1234 :
1235 229 : for (i=0; i < argc; i++)
1236 137 : if (argv[i][0] == '-' && argv[i][1] == '-')
1237 0 : log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
1238 : }
1239 :
1240 :
1241 92 : use_tty = (gnupg_isatty (fileno (stdin)) && gnupg_isatty (fileno (stdout)));
1242 :
1243 92 : if (opt.exec)
1244 : {
1245 0 : if (!argc)
1246 : {
1247 0 : log_error (_("option \"%s\" requires a program "
1248 : "and optional arguments\n"), "--exec" );
1249 0 : exit (1);
1250 : }
1251 : }
1252 92 : else if (argc)
1253 91 : cmdline_commands = argv;
1254 :
1255 92 : if (opt.exec && opt.raw_socket)
1256 : {
1257 0 : opt.raw_socket = NULL;
1258 0 : log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1259 : "--raw-socket", "--exec");
1260 : }
1261 92 : if (opt.exec && opt.tcp_socket)
1262 : {
1263 0 : opt.tcp_socket = NULL;
1264 0 : log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1265 : "--tcp-socket", "--exec");
1266 : }
1267 92 : if (opt.tcp_socket && opt.raw_socket)
1268 : {
1269 0 : opt.tcp_socket = NULL;
1270 0 : log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1271 : "--tcp-socket", "--raw-socket");
1272 : }
1273 :
1274 92 : if (opt_run && !(script_fp = fopen (opt_run, "r")))
1275 : {
1276 0 : log_error ("cannot open run file '%s': %s\n",
1277 0 : opt_run, strerror (errno));
1278 0 : exit (1);
1279 : }
1280 :
1281 :
1282 92 : if (opt.exec)
1283 : {
1284 : assuan_fd_t no_close[3];
1285 :
1286 0 : no_close[0] = assuan_fd_from_posix_fd (es_fileno (es_stderr));
1287 0 : no_close[1] = assuan_fd_from_posix_fd (log_get_fd ());
1288 0 : no_close[2] = ASSUAN_INVALID_FD;
1289 :
1290 0 : rc = assuan_new (&ctx);
1291 0 : if (rc)
1292 : {
1293 0 : log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
1294 0 : exit (1);
1295 : }
1296 :
1297 0 : rc = assuan_pipe_connect
1298 : (ctx, *argv, (const char **)argv, no_close, NULL, NULL,
1299 0 : (opt.connect_flags & 1) ? ASSUAN_PIPE_CONNECT_FDPASSING : 0);
1300 0 : if (rc)
1301 : {
1302 0 : log_error ("assuan_pipe_connect_ext failed: %s\n",
1303 : gpg_strerror (rc));
1304 0 : exit (1);
1305 : }
1306 :
1307 0 : if (opt.verbose)
1308 0 : log_info ("server '%s' started\n", *argv);
1309 :
1310 : }
1311 92 : else if (opt.raw_socket)
1312 : {
1313 0 : rc = assuan_new (&ctx);
1314 0 : if (rc)
1315 : {
1316 0 : log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
1317 0 : exit (1);
1318 : }
1319 :
1320 0 : rc = assuan_socket_connect
1321 : (ctx, opt.raw_socket, 0,
1322 0 : (opt.connect_flags & 1) ? ASSUAN_SOCKET_CONNECT_FDPASSING : 0);
1323 0 : if (rc)
1324 : {
1325 0 : log_error ("can't connect to socket '%s': %s\n",
1326 : opt.raw_socket, gpg_strerror (rc));
1327 0 : exit (1);
1328 : }
1329 :
1330 0 : if (opt.verbose)
1331 0 : log_info ("connection to socket '%s' established\n", opt.raw_socket);
1332 : }
1333 92 : else if (opt.tcp_socket)
1334 : {
1335 : char *url;
1336 :
1337 0 : url = xstrconcat ("assuan://", opt.tcp_socket, NULL);
1338 :
1339 0 : rc = assuan_new (&ctx);
1340 0 : if (rc)
1341 : {
1342 0 : log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
1343 0 : exit (1);
1344 : }
1345 :
1346 0 : rc = assuan_socket_connect (ctx, opt.tcp_socket, 0, 0);
1347 0 : if (rc)
1348 : {
1349 0 : log_error ("can't connect to server '%s': %s\n",
1350 : opt.tcp_socket, gpg_strerror (rc));
1351 0 : exit (1);
1352 : }
1353 :
1354 0 : if (opt.verbose)
1355 0 : log_info ("connection to socket '%s' established\n", url);
1356 :
1357 0 : xfree (url);
1358 : }
1359 : else
1360 92 : ctx = start_agent ();
1361 :
1362 : /* See whether there is a line pending from the server (in case
1363 : assuan did not run the initial handshaking). */
1364 92 : if (assuan_pending_line (ctx))
1365 : {
1366 0 : rc = read_and_print_response (ctx, 0, &cmderr);
1367 0 : if (rc)
1368 0 : log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1369 : }
1370 :
1371 :
1372 1932 : for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
1373 1840 : loopstack[loopidx].collecting = 0;
1374 92 : loopidx = -1;
1375 92 : line = NULL;
1376 92 : linesize = 0;
1377 92 : keep_line = 1;
1378 : for (;;)
1379 : {
1380 : int n;
1381 139 : size_t maxlength = 2048;
1382 :
1383 139 : assert (loopidx < (int)DIM (loopstack));
1384 139 : if (loopidx >= 0 && loopstack[loopidx].current)
1385 : {
1386 0 : keep_line = 0;
1387 0 : xfree (line);
1388 0 : line = xstrdup (loopstack[loopidx].current->line);
1389 0 : n = strlen (line);
1390 : /* Never go beyond of the final /end. */
1391 0 : if (loopstack[loopidx].current->next)
1392 0 : loopstack[loopidx].current = loopstack[loopidx].current->next;
1393 0 : else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1394 : ;
1395 : else
1396 0 : log_fatal ("/end command vanished\n");
1397 : }
1398 139 : else if (cmdline_commands && *cmdline_commands && !script_fp)
1399 : {
1400 137 : keep_line = 0;
1401 137 : xfree (line);
1402 137 : line = xstrdup (*cmdline_commands);
1403 137 : cmdline_commands++;
1404 137 : n = strlen (line);
1405 274 : if (n >= maxlength)
1406 0 : maxlength = 0;
1407 : }
1408 2 : else if (use_tty && !script_fp)
1409 : {
1410 0 : keep_line = 0;
1411 0 : xfree (line);
1412 0 : line = tty_get ("> ");
1413 0 : n = strlen (line);
1414 0 : if (n==1 && *line == CONTROL_D)
1415 0 : n = 0;
1416 0 : if (n >= maxlength)
1417 0 : maxlength = 0;
1418 : }
1419 : else
1420 : {
1421 2 : if (!keep_line)
1422 : {
1423 0 : xfree (line);
1424 0 : line = NULL;
1425 0 : linesize = 0;
1426 0 : keep_line = 1;
1427 : }
1428 2 : n = read_line (script_fp? script_fp:stdin,
1429 : &line, &linesize, &maxlength);
1430 : }
1431 139 : if (n < 0)
1432 : {
1433 0 : log_error (_("error reading input: %s\n"), strerror (errno));
1434 0 : if (script_fp)
1435 : {
1436 0 : fclose (script_fp);
1437 0 : script_fp = NULL;
1438 0 : log_error ("stopping script execution\n");
1439 0 : continue;
1440 : }
1441 0 : exit (1);
1442 : }
1443 139 : if (!n)
1444 : {
1445 : /* EOF */
1446 1 : if (script_fp)
1447 : {
1448 0 : fclose (script_fp);
1449 0 : script_fp = NULL;
1450 0 : if (opt.verbose)
1451 0 : log_info ("end of script\n");
1452 0 : continue;
1453 : }
1454 93 : break;
1455 : }
1456 138 : if (!maxlength)
1457 : {
1458 0 : log_error (_("line too long - skipped\n"));
1459 0 : continue;
1460 : }
1461 138 : if (memchr (line, 0, n))
1462 0 : log_info (_("line shortened due to embedded Nul character\n"));
1463 138 : if (line[n-1] == '\n')
1464 0 : line[n-1] = 0;
1465 :
1466 138 : if (opt.trim_leading_spaces)
1467 : {
1468 0 : const char *s = line;
1469 :
1470 0 : while (spacep (s))
1471 0 : s++;
1472 0 : if (s != line)
1473 : {
1474 0 : for (p=line; *s;)
1475 0 : *p++ = *s++;
1476 0 : *p = 0;
1477 0 : n = p - line;
1478 : }
1479 : }
1480 :
1481 138 : if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
1482 : {
1483 : loopline_t ll;
1484 :
1485 0 : ll = xmalloc (sizeof *ll + strlen (line));
1486 0 : ll->next = NULL;
1487 0 : strcpy (ll->line, line);
1488 0 : *loopstack[loopidx+1].tail = ll;
1489 0 : loopstack[loopidx+1].tail = &ll->next;
1490 :
1491 0 : if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1492 0 : loopstack[loopidx+1].nestlevel--;
1493 0 : else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
1494 0 : loopstack[loopidx+1].nestlevel++;
1495 :
1496 0 : if (loopstack[loopidx+1].nestlevel)
1497 0 : continue;
1498 : /* We reached the corresponding /end. */
1499 0 : loopstack[loopidx+1].collecting = 0;
1500 0 : loopidx++;
1501 : }
1502 :
1503 138 : if (*line == '/')
1504 : {
1505 : /* Handle control commands. */
1506 91 : char *cmd = line+1;
1507 :
1508 91 : for (p=cmd; *p && !spacep (p); p++)
1509 : ;
1510 91 : if (*p)
1511 0 : *p++ = 0;
1512 182 : while (spacep (p))
1513 0 : p++;
1514 91 : if (!strcmp (cmd, "let"))
1515 : {
1516 0 : assign_variable (p, 0);
1517 : }
1518 91 : else if (!strcmp (cmd, "slet"))
1519 : {
1520 : /* Deprecated - never used in a released version. */
1521 0 : assign_variable (p, 1);
1522 : }
1523 91 : else if (!strcmp (cmd, "showvar"))
1524 : {
1525 0 : show_variables ();
1526 : }
1527 91 : else if (!strcmp (cmd, "definq"))
1528 : {
1529 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1530 0 : if (tmpline)
1531 : {
1532 0 : add_definq (tmpline, 1, 0);
1533 0 : xfree (tmpline);
1534 : }
1535 : else
1536 0 : add_definq (p, 1, 0);
1537 : }
1538 91 : else if (!strcmp (cmd, "definqfile"))
1539 : {
1540 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1541 0 : if (tmpline)
1542 : {
1543 0 : add_definq (tmpline, 0, 0);
1544 0 : xfree (tmpline);
1545 : }
1546 : else
1547 0 : add_definq (p, 0, 0);
1548 : }
1549 91 : else if (!strcmp (cmd, "definqprog"))
1550 : {
1551 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1552 0 : if (tmpline)
1553 : {
1554 0 : add_definq (tmpline, 0, 1);
1555 0 : xfree (tmpline);
1556 : }
1557 : else
1558 0 : add_definq (p, 0, 1);
1559 : }
1560 91 : else if (!strcmp (cmd, "datafile"))
1561 : {
1562 : const char *fname;
1563 :
1564 0 : if (current_datasink)
1565 : {
1566 0 : if (current_datasink != stdout)
1567 0 : fclose (current_datasink);
1568 0 : current_datasink = NULL;
1569 : }
1570 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1571 0 : fname = tmpline? tmpline : p;
1572 0 : if (fname && !strcmp (fname, "-"))
1573 0 : current_datasink = stdout;
1574 0 : else if (fname && *fname)
1575 : {
1576 0 : current_datasink = fopen (fname, "wb");
1577 0 : if (!current_datasink)
1578 0 : log_error ("can't open '%s': %s\n",
1579 0 : fname, strerror (errno));
1580 : }
1581 0 : xfree (tmpline);
1582 : }
1583 91 : else if (!strcmp (cmd, "showdef"))
1584 : {
1585 0 : show_definq ();
1586 : }
1587 91 : else if (!strcmp (cmd, "cleardef"))
1588 : {
1589 0 : clear_definq ();
1590 : }
1591 91 : else if (!strcmp (cmd, "echo"))
1592 : {
1593 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1594 0 : if (tmpline)
1595 : {
1596 0 : puts (tmpline);
1597 0 : xfree (tmpline);
1598 : }
1599 : else
1600 0 : puts (p);
1601 : }
1602 91 : else if (!strcmp (cmd, "sendfd"))
1603 : {
1604 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1605 0 : if (tmpline)
1606 : {
1607 0 : do_sendfd (ctx, tmpline);
1608 0 : xfree (tmpline);
1609 : }
1610 : else
1611 0 : do_sendfd (ctx, p);
1612 0 : continue;
1613 : }
1614 91 : else if (!strcmp (cmd, "recvfd"))
1615 : {
1616 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1617 0 : if (tmpline)
1618 : {
1619 0 : do_recvfd (ctx, tmpline);
1620 0 : xfree (tmpline);
1621 : }
1622 : else
1623 0 : do_recvfd (ctx, p);
1624 0 : continue;
1625 : }
1626 91 : else if (!strcmp (cmd, "open"))
1627 : {
1628 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1629 0 : if (tmpline)
1630 : {
1631 0 : do_open (tmpline);
1632 0 : xfree (tmpline);
1633 : }
1634 : else
1635 0 : do_open (p);
1636 : }
1637 91 : else if (!strcmp (cmd, "close"))
1638 : {
1639 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1640 0 : if (tmpline)
1641 : {
1642 0 : do_close (tmpline);
1643 0 : xfree (tmpline);
1644 : }
1645 : else
1646 0 : do_close (p);
1647 : }
1648 91 : else if (!strcmp (cmd, "showopen"))
1649 : {
1650 0 : do_showopen ();
1651 : }
1652 91 : else if (!strcmp (cmd, "serverpid"))
1653 : {
1654 0 : do_serverpid (ctx);
1655 : }
1656 91 : else if (!strcmp (cmd, "hex"))
1657 0 : opt.hex = 1;
1658 91 : else if (!strcmp (cmd, "nohex"))
1659 0 : opt.hex = 0;
1660 91 : else if (!strcmp (cmd, "decode"))
1661 0 : opt.decode = 1;
1662 91 : else if (!strcmp (cmd, "nodecode"))
1663 0 : opt.decode = 0;
1664 91 : else if (!strcmp (cmd, "subst"))
1665 : {
1666 0 : opt.enable_varsubst = 1;
1667 0 : opt.trim_leading_spaces = 1;
1668 : }
1669 91 : else if (!strcmp (cmd, "nosubst"))
1670 0 : opt.enable_varsubst = 0;
1671 91 : else if (!strcmp (cmd, "run"))
1672 : {
1673 : char *p2;
1674 :
1675 0 : for (p2=p; *p2 && !spacep (p2); p2++)
1676 : ;
1677 0 : if (*p2)
1678 0 : *p2++ = 0;
1679 0 : while (spacep (p2))
1680 0 : p++;
1681 0 : if (*p2)
1682 : {
1683 0 : log_error ("syntax error in run command\n");
1684 0 : if (script_fp)
1685 : {
1686 0 : fclose (script_fp);
1687 0 : script_fp = NULL;
1688 : }
1689 : }
1690 0 : else if (script_fp)
1691 : {
1692 0 : log_error ("cannot nest run commands - stop\n");
1693 0 : fclose (script_fp);
1694 0 : script_fp = NULL;
1695 : }
1696 0 : else if (!(script_fp = fopen (p, "r")))
1697 : {
1698 0 : log_error ("cannot open run file '%s': %s\n",
1699 0 : p, strerror (errno));
1700 : }
1701 0 : else if (opt.verbose)
1702 0 : log_info ("running commands from '%s'\n", p);
1703 : }
1704 91 : else if (!strcmp (cmd, "while"))
1705 : {
1706 0 : if (loopidx+2 >= (int)DIM(loopstack))
1707 : {
1708 0 : log_error ("blocks are nested too deep\n");
1709 : /* We should better die or break all loop in this
1710 : case as recovering from this error won't be
1711 : easy. */
1712 : }
1713 : else
1714 : {
1715 0 : loopstack[loopidx+1].head = NULL;
1716 0 : loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1717 0 : loopstack[loopidx+1].current = NULL;
1718 0 : loopstack[loopidx+1].nestlevel = 1;
1719 0 : loopstack[loopidx+1].oneshot = 0;
1720 0 : loopstack[loopidx+1].condition = xstrdup (p);
1721 0 : loopstack[loopidx+1].collecting = 1;
1722 : }
1723 : }
1724 91 : else if (!strcmp (cmd, "if"))
1725 : {
1726 0 : if (loopidx+2 >= (int)DIM(loopstack))
1727 : {
1728 0 : log_error ("blocks are nested too deep\n");
1729 : }
1730 : else
1731 : {
1732 : /* Note that we need to evaluate the condition right
1733 : away and not just at the end of the block as we
1734 : do with a WHILE. */
1735 0 : loopstack[loopidx+1].head = NULL;
1736 0 : loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1737 0 : loopstack[loopidx+1].current = NULL;
1738 0 : loopstack[loopidx+1].nestlevel = 1;
1739 0 : loopstack[loopidx+1].oneshot = 1;
1740 0 : loopstack[loopidx+1].condition = substitute_line_copy (p);
1741 0 : loopstack[loopidx+1].collecting = 1;
1742 : }
1743 : }
1744 91 : else if (!strcmp (cmd, "end"))
1745 : {
1746 0 : if (loopidx < 0)
1747 0 : log_error ("stray /end command encountered - ignored\n");
1748 : else
1749 : {
1750 : char *tmpcond;
1751 : const char *value;
1752 : long condition;
1753 :
1754 : /* Evaluate the condition. */
1755 0 : tmpcond = xstrdup (loopstack[loopidx].condition);
1756 0 : if (loopstack[loopidx].oneshot)
1757 : {
1758 0 : xfree (loopstack[loopidx].condition);
1759 0 : loopstack[loopidx].condition = xstrdup ("0");
1760 : }
1761 0 : tmpline = substitute_line (tmpcond);
1762 0 : value = tmpline? tmpline : tmpcond;
1763 : /* "true" or "yes" are commonly used to mean TRUE;
1764 : all other strings will evaluate to FALSE due to
1765 : the strtoul. */
1766 0 : if (!ascii_strcasecmp (value, "true")
1767 0 : || !ascii_strcasecmp (value, "yes"))
1768 0 : condition = 1;
1769 : else
1770 0 : condition = strtol (value, NULL, 0);
1771 0 : xfree (tmpline);
1772 0 : xfree (tmpcond);
1773 :
1774 0 : if (condition)
1775 : {
1776 : /* Run loop. */
1777 0 : loopstack[loopidx].current = loopstack[loopidx].head;
1778 : }
1779 : else
1780 : {
1781 : /* Cleanup. */
1782 0 : while (loopstack[loopidx].head)
1783 : {
1784 0 : loopline_t tmp = loopstack[loopidx].head->next;
1785 0 : xfree (loopstack[loopidx].head);
1786 0 : loopstack[loopidx].head = tmp;
1787 : }
1788 0 : loopstack[loopidx].tail = NULL;
1789 0 : loopstack[loopidx].current = NULL;
1790 0 : loopstack[loopidx].nestlevel = 0;
1791 0 : loopstack[loopidx].collecting = 0;
1792 0 : loopstack[loopidx].oneshot = 0;
1793 0 : xfree (loopstack[loopidx].condition);
1794 0 : loopstack[loopidx].condition = NULL;
1795 0 : loopidx--;
1796 : }
1797 : }
1798 : }
1799 91 : else if (!strcmp (cmd, "bye"))
1800 : {
1801 91 : break;
1802 : }
1803 0 : else if (!strcmp (cmd, "sleep"))
1804 : {
1805 0 : gnupg_sleep (1);
1806 : }
1807 0 : else if (!strcmp (cmd, "help"))
1808 : {
1809 0 : puts (
1810 : "Available commands:\n"
1811 : "/echo ARGS Echo ARGS.\n"
1812 : "/let NAME VALUE Set variable NAME to VALUE.\n"
1813 : "/showvar Show all variables.\n"
1814 : "/definq NAME VAR Use content of VAR for inquiries with NAME.\n"
1815 : "/definqfile NAME FILE Use content of FILE for inquiries with NAME.\n"
1816 : "/definqprog NAME PGM Run PGM for inquiries with NAME.\n"
1817 : "/datafile [NAME] Write all D line content to file NAME.\n"
1818 : "/showdef Print all definitions.\n"
1819 : "/cleardef Delete all definitions.\n"
1820 : "/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
1821 : "/recvfd Receive FD from server and print.\n"
1822 : "/open VAR FILE MODE Open FILE and assign the file descriptor to VAR.\n"
1823 : "/close FD Close file with descriptor FD.\n"
1824 : "/showopen Show descriptors of all open files.\n"
1825 : "/serverpid Retrieve the pid of the server.\n"
1826 : "/[no]hex Enable hex dumping of received data lines.\n"
1827 : "/[no]decode Enable decoding of received data lines.\n"
1828 : "/[no]subst Enable variable substitution.\n"
1829 : "/run FILE Run commands from FILE.\n"
1830 : "/if VAR Begin conditional block controlled by VAR.\n"
1831 : "/while VAR Begin loop controlled by VAR.\n"
1832 : "/end End loop or condition\n"
1833 : "/bye Terminate gpg-connect-agent.\n"
1834 : "/help Print this help.");
1835 : }
1836 : else
1837 0 : log_error (_("unknown command '%s'\n"), cmd );
1838 :
1839 0 : continue;
1840 : }
1841 :
1842 47 : if (opt.verbose && script_fp)
1843 0 : puts (line);
1844 :
1845 47 : tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
1846 47 : if (tmpline)
1847 : {
1848 0 : rc = assuan_write_line (ctx, tmpline);
1849 0 : xfree (tmpline);
1850 : }
1851 : else
1852 47 : rc = assuan_write_line (ctx, line);
1853 47 : if (rc)
1854 : {
1855 0 : log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
1856 0 : break;
1857 : }
1858 47 : if (*line == '#' || !*line)
1859 0 : continue; /* Don't expect a response for a comment line. */
1860 :
1861 47 : rc = read_and_print_response (ctx, help_cmd_p (line), &cmderr);
1862 47 : if (rc)
1863 0 : log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1864 47 : if ((rc || cmderr) && script_fp)
1865 : {
1866 0 : log_error ("stopping script execution\n");
1867 0 : fclose (script_fp);
1868 0 : script_fp = NULL;
1869 : }
1870 :
1871 :
1872 : /* FIXME: If the last command was BYE or the server died for
1873 : some other reason, we won't notice until we get the next
1874 : input command. Probing the connection with a non-blocking
1875 : read could help to notice termination or other problems
1876 : early. */
1877 47 : }
1878 :
1879 92 : if (opt.verbose)
1880 91 : log_info ("closing connection to agent\n");
1881 :
1882 : /* XXX: We would like to release the context here, but libassuan
1883 : nicely says good bye to the server, which results in a SIGPIPE if
1884 : the server died. Unfortunately, libassuan does not ignore
1885 : SIGPIPE when used with UNIX sockets, hence we simply leak the
1886 : context here. */
1887 : if (0)
1888 : assuan_release (ctx);
1889 : else
1890 92 : gpgrt_annotate_leaked_object (ctx);
1891 92 : xfree (line);
1892 92 : return 0;
1893 : }
1894 :
1895 :
1896 : /* Handle an Inquire from the server. Return False if it could not be
1897 : handled; in this case the caller shll complete the operation. LINE
1898 : is the complete line as received from the server. This function
1899 : may change the content of LINE. */
1900 : static int
1901 0 : handle_inquire (assuan_context_t ctx, char *line)
1902 : {
1903 : const char *name;
1904 : definq_t d;
1905 0 : FILE *fp = NULL;
1906 : char buffer[1024];
1907 : int rc, n;
1908 :
1909 : /* Skip the command and trailing spaces. */
1910 0 : for (; *line && !spacep (line); line++)
1911 : ;
1912 0 : while (spacep (line))
1913 0 : line++;
1914 : /* Get the name. */
1915 0 : name = line;
1916 0 : for (; *line && !spacep (line); line++)
1917 : ;
1918 0 : if (*line)
1919 0 : *line++ = 0;
1920 :
1921 : /* Now match it against our list. The second loop is there to
1922 : detect the match-all entry. */
1923 0 : for (d=definq_list; d; d = d->next)
1924 0 : if (d->name && !strcmp (d->name, name))
1925 0 : break;
1926 0 : if (!d)
1927 0 : for (d=definq_list; d; d = d->next)
1928 0 : if (!d->name)
1929 0 : break;
1930 0 : if (!d)
1931 : {
1932 0 : if (opt.verbose)
1933 0 : log_info ("no handler for inquiry '%s' found\n", name);
1934 0 : return 0;
1935 : }
1936 :
1937 0 : if (d->is_var)
1938 : {
1939 0 : char *tmpvalue = get_var_ext (d->file);
1940 0 : if (tmpvalue)
1941 0 : rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
1942 : else
1943 0 : rc = assuan_send_data (ctx, "", 0);
1944 0 : xfree (tmpvalue);
1945 0 : if (rc)
1946 0 : log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1947 : }
1948 : else
1949 : {
1950 0 : if (d->is_prog)
1951 : {
1952 : #ifdef HAVE_W32CE_SYSTEM
1953 : fp = NULL;
1954 : #else
1955 0 : fp = popen (d->file, "r");
1956 : #endif
1957 0 : if (!fp)
1958 0 : log_error ("error executing '%s': %s\n",
1959 0 : d->file, strerror (errno));
1960 0 : else if (opt.verbose)
1961 0 : log_error ("handling inquiry '%s' by running '%s'\n",
1962 0 : name, d->file);
1963 : }
1964 : else
1965 : {
1966 0 : fp = fopen (d->file, "rb");
1967 0 : if (!fp)
1968 0 : log_error ("error opening '%s': %s\n", d->file, strerror (errno));
1969 0 : else if (opt.verbose)
1970 0 : log_error ("handling inquiry '%s' by returning content of '%s'\n",
1971 0 : name, d->file);
1972 : }
1973 0 : if (!fp)
1974 0 : return 0;
1975 :
1976 0 : while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
1977 : {
1978 0 : rc = assuan_send_data (ctx, buffer, n);
1979 0 : if (rc)
1980 : {
1981 0 : log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1982 0 : break;
1983 : }
1984 : }
1985 0 : if (ferror (fp))
1986 0 : log_error ("error reading from '%s': %s\n", d->file, strerror (errno));
1987 : }
1988 :
1989 0 : rc = assuan_send_data (ctx, NULL, 0);
1990 0 : if (rc)
1991 0 : log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1992 :
1993 0 : if (d->is_var)
1994 : ;
1995 0 : else if (d->is_prog)
1996 : {
1997 : #ifndef HAVE_W32CE_SYSTEM
1998 0 : if (pclose (fp))
1999 0 : log_error ("error running '%s': %s\n", d->file, strerror (errno));
2000 : #endif
2001 : }
2002 : else
2003 0 : fclose (fp);
2004 0 : return 1;
2005 : }
2006 :
2007 :
2008 : /* Read all response lines from server and print them. Returns 0 on
2009 : success or an assuan error code. If WITHHASH istrue, comment lines
2010 : are printed. Sets R_GOTERR to true if the command did not returned
2011 : OK. */
2012 : static int
2013 47 : read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
2014 : {
2015 : char *line;
2016 : size_t linelen;
2017 : gpg_error_t rc;
2018 : int i, j;
2019 47 : int need_lf = 0;
2020 :
2021 47 : *r_goterr = 0;
2022 : for (;;)
2023 : {
2024 : do
2025 : {
2026 47 : rc = assuan_read_line (ctx, &line, &linelen);
2027 47 : if (rc)
2028 0 : return rc;
2029 :
2030 47 : if ((withhash || opt.verbose > 1) && *line == '#')
2031 : {
2032 0 : fwrite (line, linelen, 1, stdout);
2033 0 : putchar ('\n');
2034 : }
2035 : }
2036 47 : while (*line == '#' || !linelen);
2037 :
2038 47 : if (linelen >= 1
2039 47 : && line[0] == 'D' && line[1] == ' ')
2040 : {
2041 0 : if (current_datasink)
2042 : {
2043 : const unsigned char *s;
2044 0 : int c = 0;
2045 :
2046 0 : for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
2047 : {
2048 0 : if (*s == '%' && j+2 < linelen)
2049 : {
2050 0 : s++; j++;
2051 0 : c = xtoi_2 ( s );
2052 0 : s++; j++;
2053 : }
2054 : else
2055 0 : c = *s;
2056 0 : putc (c, current_datasink);
2057 : }
2058 : }
2059 0 : else if (opt.hex)
2060 : {
2061 0 : for (i=2; i < linelen; )
2062 : {
2063 0 : int save_i = i;
2064 :
2065 0 : printf ("D[%04X] ", i-2);
2066 0 : for (j=0; j < 16 ; j++, i++)
2067 : {
2068 0 : if (j == 8)
2069 0 : putchar (' ');
2070 0 : if (i < linelen)
2071 0 : printf (" %02X", ((unsigned char*)line)[i]);
2072 : else
2073 0 : fputs (" ", stdout);
2074 : }
2075 0 : fputs (" ", stdout);
2076 0 : i= save_i;
2077 0 : for (j=0; j < 16; j++, i++)
2078 : {
2079 0 : unsigned int c = ((unsigned char*)line)[i];
2080 0 : if ( i >= linelen )
2081 0 : putchar (' ');
2082 0 : else if (isascii (c) && isprint (c) && !iscntrl (c))
2083 0 : putchar (c);
2084 : else
2085 0 : putchar ('.');
2086 : }
2087 0 : putchar ('\n');
2088 : }
2089 : }
2090 0 : else if (opt.decode)
2091 : {
2092 : const unsigned char *s;
2093 0 : int need_d = 1;
2094 0 : int c = 0;
2095 :
2096 0 : for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
2097 : {
2098 0 : if (need_d)
2099 : {
2100 0 : fputs ("D ", stdout);
2101 0 : need_d = 0;
2102 : }
2103 0 : if (*s == '%' && j+2 < linelen)
2104 : {
2105 0 : s++; j++;
2106 0 : c = xtoi_2 ( s );
2107 0 : s++; j++;
2108 : }
2109 : else
2110 0 : c = *s;
2111 0 : if (c == '\n')
2112 0 : need_d = 1;
2113 0 : putchar (c);
2114 : }
2115 0 : need_lf = (c != '\n');
2116 : }
2117 : else
2118 : {
2119 0 : fwrite (line, linelen, 1, stdout);
2120 0 : putchar ('\n');
2121 : }
2122 : }
2123 : else
2124 : {
2125 47 : if (need_lf)
2126 : {
2127 0 : if (!current_datasink || current_datasink != stdout)
2128 0 : putchar ('\n');
2129 0 : need_lf = 0;
2130 : }
2131 :
2132 47 : if (linelen >= 1
2133 47 : && line[0] == 'S'
2134 0 : && (line[1] == '\0' || line[1] == ' '))
2135 : {
2136 0 : if (!current_datasink || current_datasink != stdout)
2137 : {
2138 0 : fwrite (line, linelen, 1, stdout);
2139 0 : putchar ('\n');
2140 : }
2141 : }
2142 47 : else if (linelen >= 2
2143 47 : && line[0] == 'O' && line[1] == 'K'
2144 47 : && (line[2] == '\0' || line[2] == ' '))
2145 : {
2146 47 : if (!current_datasink || current_datasink != stdout)
2147 : {
2148 47 : fwrite (line, linelen, 1, stdout);
2149 47 : putchar ('\n');
2150 : }
2151 47 : set_int_var ("?", 0);
2152 47 : return 0;
2153 : }
2154 0 : else if (linelen >= 3
2155 0 : && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
2156 0 : && (line[3] == '\0' || line[3] == ' '))
2157 : {
2158 : int errval;
2159 :
2160 0 : errval = strtol (line+3, NULL, 10);
2161 0 : if (!errval)
2162 0 : errval = -1;
2163 0 : set_int_var ("?", errval);
2164 0 : if (!current_datasink || current_datasink != stdout)
2165 : {
2166 0 : fwrite (line, linelen, 1, stdout);
2167 0 : putchar ('\n');
2168 : }
2169 0 : *r_goterr = 1;
2170 0 : return 0;
2171 : }
2172 0 : else if (linelen >= 7
2173 0 : && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
2174 0 : && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
2175 0 : && line[6] == 'E'
2176 0 : && (line[7] == '\0' || line[7] == ' '))
2177 : {
2178 0 : if (!current_datasink || current_datasink != stdout)
2179 : {
2180 0 : fwrite (line, linelen, 1, stdout);
2181 0 : putchar ('\n');
2182 : }
2183 0 : if (!handle_inquire (ctx, line))
2184 0 : assuan_write_line (ctx, "CANCEL");
2185 : }
2186 0 : else if (linelen >= 3
2187 0 : && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
2188 0 : && (line[3] == '\0' || line[3] == ' '))
2189 : {
2190 0 : if (!current_datasink || current_datasink != stdout)
2191 : {
2192 0 : fwrite (line, linelen, 1, stdout);
2193 0 : putchar ('\n');
2194 : }
2195 : /* Received from server, thus more responses are expected. */
2196 : }
2197 : else
2198 0 : return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
2199 : }
2200 0 : }
2201 : }
2202 :
2203 :
2204 :
2205 :
2206 : /* Connect to the agent and send the standard options. */
2207 : static assuan_context_t
2208 92 : start_agent (void)
2209 : {
2210 : gpg_error_t err;
2211 : assuan_context_t ctx;
2212 : session_env_t session_env;
2213 :
2214 92 : session_env = session_env_new ();
2215 92 : if (!session_env)
2216 0 : log_fatal ("error allocating session environment block: %s\n",
2217 0 : strerror (errno));
2218 92 : if (opt.use_dirmngr)
2219 0 : err = start_new_dirmngr (&ctx,
2220 : GPG_ERR_SOURCE_DEFAULT,
2221 : opt.dirmngr_program,
2222 : opt.autostart,
2223 0 : !opt.quiet, 0,
2224 : NULL, NULL);
2225 : else
2226 92 : err = start_new_gpg_agent (&ctx,
2227 : GPG_ERR_SOURCE_DEFAULT,
2228 : opt.agent_program,
2229 : NULL, NULL,
2230 : session_env,
2231 : opt.autostart,
2232 92 : !opt.quiet, 0,
2233 : NULL, NULL);
2234 :
2235 92 : session_env_release (session_env);
2236 92 : if (err)
2237 : {
2238 0 : if (!opt.autostart
2239 0 : && (gpg_err_code (err)
2240 : == opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT))
2241 : {
2242 : /* In the no-autostart case we don't make gpg-connect-agent
2243 : fail on a missing server. */
2244 0 : log_info (opt.use_dirmngr?
2245 : _("no dirmngr running in this session\n"):
2246 : _("no gpg-agent running in this session\n"));
2247 0 : exit (0);
2248 : }
2249 : else
2250 : {
2251 0 : log_error (_("error sending standard options: %s\n"),
2252 : gpg_strerror (err));
2253 0 : exit (1);
2254 : }
2255 : }
2256 :
2257 92 : return ctx;
2258 : }
|