1
1
/* command-ssh.c - gpg-agent's ssh-agent emulation layer
2
* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
2
* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4
4
* This file is part of GnuPG.
6
6
* GnuPG is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
8
* the Free Software Foundation; either version 3 of the License, or
9
9
* (at your option) any later version.
11
11
* GnuPG is distributed in the hope that it will be useful,
14
14
* GNU General Public License for more details.
16
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17
* along with this program; if not, see <http://www.gnu.org/licenses/>.
22
20
/* Only v2 of the ssh-agent protocol is implemented. */
578
583
if (ret || (! bytes_read))
581
err = gpg_error_from_errno (errno);
586
err = gpg_error_from_syserror ();
584
589
ret = es_write (dst, buffer, bytes_read, NULL);
587
err = gpg_error_from_errno (errno);
592
err = gpg_error_from_syserror ();
614
619
stream = es_fopen (filename, "r");
617
err = gpg_error_from_errno (errno);
622
err = gpg_error_from_syserror ();
621
626
ret = fstat (es_fileno (stream), &statbuf);
624
err = gpg_error_from_errno (errno);
629
err = gpg_error_from_syserror ();
628
633
buffer_new = xtrymalloc (statbuf.st_size);
629
634
if (! buffer_new)
631
err = gpg_error_from_errno (errno);
636
err = gpg_error_from_syserror ();
788
793
time_t atime = time (NULL);
790
/* Not yet in the file - add it. Becuase the file has been
795
/* Not yet in the file - add it. Because the file has been
791
796
opened in append mode, we simply need to write to it. */
792
797
tp = localtime (&atime);
793
798
fprintf (fp, "# Key added on %04d-%02d-%02d %02d:%02d:%02d\n%s %d\n",
853
858
elems_public = key_spec.elems_key_public;
854
859
elems_public_n = strlen (elems_public);
856
mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1));
861
mpis = xtrycalloc (elems_n + 1, sizeof *mpis );
859
err = gpg_error_from_errno (errno);
864
err = gpg_error_from_syserror ();
863
memset (mpis, 0, sizeof (*mpis) * (elems_n + 1));
865
868
elem_is_secret = 0;
866
869
for (i = 0; i < elems_n; i++)
1145
1148
elems_n = strlen (elems);
1146
mpis_new = xtrymalloc (sizeof (*mpis_new) * (elems_n + 1));
1149
mpis_new = xtrycalloc (elems_n + 1, sizeof *mpis_new );
1149
err = gpg_error_from_errno (errno);
1152
err = gpg_error_from_syserror ();
1152
memset (mpis_new, 0, sizeof (*mpis_new) * (elems_n + 1));
1154
1156
value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0);
1155
1157
if (! value_list)
2055
2057
elems = spec.elems_signature;
2056
2058
elems_n = strlen (elems);
2058
mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1));
2060
mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
2061
err = gpg_error_from_errno (errno);
2063
err = gpg_error_from_syserror ();
2064
memset (mpis, 0, sizeof (*mpis) * (elems_n + 1));
2066
2067
for (i = 0; i < elems_n; i++)
2093
2094
sig_blob_n = es_ftell (stream);
2094
2095
if (sig_blob_n == -1)
2096
err = gpg_error_from_errno (errno);
2097
err = gpg_error_from_syserror ();
2100
2101
sig_blob = xtrymalloc (sig_blob_n);
2101
2102
if (! sig_blob)
2103
err = gpg_error_from_errno (errno);
2104
err = gpg_error_from_syserror ();
2107
2108
ret = es_fseek (stream, 0, SEEK_SET);
2110
err = gpg_error_from_errno (errno);
2111
err = gpg_error_from_syserror ();
2316
/* Callback function to compare the first entered PIN with the one
2317
currently being entered. */
2319
reenter_compare_cb (struct pin_entry_info_s *pi)
2321
const char *pin1 = pi->check_cb_arg;
2323
if (!strcmp (pin1, pi->pin))
2324
return 0; /* okay */
2315
2328
/* Store the ssh KEY into our local key storage and protect it after
2316
2329
asking for a passphrase. Cache that passphrase. TTL is the
2317
2330
maximum caching time for that key. If the key already exists in
2321
2334
ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
2323
2336
gpg_error_t err;
2324
unsigned char key_grip_raw[21];
2337
unsigned char key_grip_raw[20];
2325
2338
char key_grip[41];
2326
2339
unsigned char *buffer = NULL;
2327
unsigned int buffer_n;
2328
2341
char *description = NULL;
2342
const char *description2 = _("Please re-enter this passphrase");
2329
2343
char *comment = NULL;
2344
const char *initial_errtext = NULL;
2330
2345
unsigned int i;
2331
struct pin_entry_info_s *pi = NULL;
2346
struct pin_entry_info_s *pi = NULL, *pi2;
2333
2348
err = ssh_key_grip (key, key_grip_raw);
2337
key_grip_raw[sizeof (key_grip_raw) - 1] = 0; /* FIXME: Why?? */
2339
2352
/* Check whether the key is already in our key storage. Don't do
2340
2353
anything then. */
2341
2354
if ( !agent_key_available (key_grip_raw) )
2353
2366
"within gpg-agent's key storage"),
2354
2367
comment ? comment : "?") < 0)
2356
err = gpg_error_from_errno (errno);
2369
err = gpg_error_from_syserror ();
2361
pi = gcry_calloc_secure (1, sizeof (*pi) + 100 + 1);
2374
pi = gcry_calloc_secure (2, sizeof (*pi) + 100 + 1);
2364
err = gpg_error_from_errno (errno);
2377
err = gpg_error_from_syserror ();
2380
pi2 = pi + (sizeof *pi + 100 + 1);
2367
2381
pi->max_length = 100;
2368
2382
pi->max_tries = 1;
2369
err = agent_askpin (ctrl, description, NULL, NULL, pi);
2383
pi2->max_length = 100;
2385
pi2->check_cb = reenter_compare_cb;
2386
pi2->check_cb_arg = pi->pin;
2389
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi);
2390
initial_errtext = NULL;
2394
/* Unless the passphrase is empty, ask to confirm it. */
2395
if (pi->pin && *pi->pin)
2397
err = agent_askpin (ctrl, description2, NULL, NULL, pi2);
2399
{ /* The re-entered one did not match and the user did not
2401
initial_errtext = _("does not match - try again");
2373
2406
err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n);
2679
2713
secret key material. The response does not have to be stored in
2680
2714
secure memory, since we never give out secret keys.
2682
FIXME: This is a pretty good DoS. We only have a limited amount
2683
of secure memory, we can't throw in everything we get from a
2716
Note: we only have little secure memory, but there is NO
2717
possibility of DoS here; only trusted clients are allowed to
2718
connect to the agent. What could happen is that the agent
2719
returns out-of-secure-memory errors on requests in case the
2720
agent's owner floods his own agent with many large messages.
2686
2723
/* Retrieve request. */
2687
2724
err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
2714
2751
request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
2717
err = gpg_error_from_errno (errno);
2754
err = gpg_error_from_syserror ();
2720
2757
ret = es_setvbuf (request, NULL, _IONBF, 0);
2723
err = gpg_error_from_errno (errno);
2760
err = gpg_error_from_syserror ();
2726
2763
err = stream_write_data (request, request_data + 1, request_data_size - 1);
2816
2853
/* Start serving client on SOCK_CLIENT. */
2818
start_command_handler_ssh (int sock_client)
2855
start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
2820
struct server_control_s ctrl;
2821
2857
estream_t stream_sock;
2822
2858
gpg_error_t err;
2825
/* Setup control structure. */
2827
memset (&ctrl, 0, sizeof (ctrl));
2828
agent_init_default_ctrl (&ctrl);
2829
ctrl.connection_fd = sock_client;
2831
2861
/* Because the ssh protocol does not send us information about the
2832
2862
the current TTY setting, we resort here to use those from startup
2833
2863
or those explictly set. */
2834
if (!ctrl.display && opt.startup_display)
2835
ctrl.display = strdup (opt.startup_display);
2836
if (!ctrl.ttyname && opt.startup_ttyname)
2837
ctrl.ttyname = strdup (opt.startup_ttyname);
2838
if (!ctrl.ttytype && opt.startup_ttytype)
2839
ctrl.ttytype = strdup (opt.startup_ttytype);
2840
if (!ctrl.lc_ctype && opt.startup_lc_ctype)
2841
ctrl.lc_ctype = strdup (opt.startup_lc_ctype);
2842
if (!ctrl.lc_messages && opt.startup_lc_messages)
2843
ctrl.lc_messages = strdup (opt.startup_lc_messages);
2864
if (!ctrl->display && opt.startup_display)
2865
ctrl->display = strdup (opt.startup_display);
2866
if (!ctrl->ttyname && opt.startup_ttyname)
2867
ctrl->ttyname = strdup (opt.startup_ttyname);
2868
if (!ctrl->ttytype && opt.startup_ttytype)
2869
ctrl->ttytype = strdup (opt.startup_ttytype);
2870
if (!ctrl->lc_ctype && opt.startup_lc_ctype)
2871
ctrl->lc_ctype = strdup (opt.startup_lc_ctype);
2872
if (!ctrl->lc_messages && opt.startup_lc_messages)
2873
ctrl->lc_messages = strdup (opt.startup_lc_messages);
2874
if (!ctrl->xauthority && opt.startup_xauthority)
2875
ctrl->xauthority = strdup (opt.startup_xauthority);
2876
if (!ctrl->pinentry_user_data && opt.startup_pinentry_user_data)
2877
ctrl->pinentry_user_data = strdup (opt.startup_pinentry_user_data);
2846
2880
/* Create stream from socket. */
2847
stream_sock = es_fdopen (sock_client, "r+");
2881
stream_sock = es_fdopen (FD2INT(sock_client), "r+");
2848
2882
if (!stream_sock)
2850
err = gpg_error_from_errno (errno);
2884
err = gpg_error_from_syserror ();
2851
2885
log_error (_("failed to create stream from socket: %s\n"),
2852
2886
gpg_strerror (err));
2857
2891
ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
2860
err = gpg_error_from_errno (errno);
2861
log_error (_("failed to disable buffering "
2862
"on socket stream: %s\n"), gpg_strerror (err));
2894
err = gpg_error_from_syserror ();
2895
log_error ("failed to disable buffering "
2896
"on socket stream: %s\n", gpg_strerror (err));
2866
2900
/* Main processing loop. */
2867
while ( !ssh_request_process (&ctrl, stream_sock) )
2901
while ( !ssh_request_process (ctrl, stream_sock) )
2903
/* Check wether we have reached EOF before trying to read
2907
c = es_fgetc (stream_sock);
2910
es_ungetc (c, stream_sock);
2870
2913
/* Reset the SCD in case it has been used. */
2871
agent_reset_scd (&ctrl);
2914
agent_reset_scd (ctrl);
2875
2918
if (stream_sock)
2876
2919
es_fclose (stream_sock);
2878
free (ctrl.display);
2879
free (ctrl.ttyname);
2880
free (ctrl.ttytype);
2881
free (ctrl.lc_ctype);
2882
free (ctrl.lc_messages);