]> andersk Git - openssh.git/blob - ssh-add.c
- Merged OpenBSD CVS changes:
[openssh.git] / ssh-add.c
1 /*
2
3 ssh-add.c
4
5 Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7 Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8                    All rights reserved
9
10 Created: Thu Apr  6 00:52:24 1995 ylo
11
12 Adds an identity to the authentication server, or removes an identity.
13
14 */
15
16 #include "includes.h"
17 RCSID("$Id$");
18
19 #include "rsa.h"
20 #include "ssh.h"
21 #include "xmalloc.h"
22 #include "authfd.h"
23
24 void
25 delete_file(AuthenticationConnection *ac, const char *filename)
26 {
27   RSA *key;
28   char *comment;
29
30   key = RSA_new();
31   if (!load_public_key(filename, key, &comment))
32     {
33       printf("Bad key file %s: %s\n", filename, strerror(errno));
34       return;
35     }
36
37   if (ssh_remove_identity(ac, key))
38     fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
39   else
40     fprintf(stderr, "Could not remove identity: %s\n", filename);
41   RSA_free(key);
42   xfree(comment);
43 }
44
45 void
46 delete_all(AuthenticationConnection *ac)
47 {
48   /* Send a request to remove all identities. */
49   if (ssh_remove_all_identities(ac))
50     fprintf(stderr, "All identities removed.\n");
51   else
52     fprintf(stderr, "Failed to remove all identitities.\n");
53 }
54
55 #define BUFSIZE 1024
56 void
57 add_file(AuthenticationConnection *ac, const char *filename)
58 {
59   RSA *key;
60   RSA *public_key;
61   char *saved_comment, *comment, *pass;
62   int first;
63   int pipes[2];
64   char buf[BUFSIZE];
65   int tmp;
66   pid_t child;
67   FILE *pipef;
68   
69   key = RSA_new();
70   public_key = RSA_new();
71   if (!load_public_key(filename, public_key, &saved_comment))
72     {
73       printf("Bad key file %s: %s\n", filename, strerror(errno));
74       return;
75     }
76   RSA_free(public_key);
77   
78   pass = xstrdup("");
79   first = 1;
80   while (!load_private_key(filename, pass, key, &comment))
81     {
82       /* Free the old passphrase. */
83       memset(pass, 0, strlen(pass));
84       xfree(pass);
85
86       /* Ask for a passphrase. */
87       if (getenv("DISPLAY") && !isatty(fileno(stdin)))
88         {
89           if (pipe(pipes) ==-1)
90             {
91               fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno));
92               exit(1);
93             }
94           if (fflush(NULL)==EOF)
95             {
96               fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno));
97               exit(1);
98             }
99           switch (child=fork())
100             {
101             case -1:
102               fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
103               exit(1);
104             case 0:
105               close(pipes[0]);
106               if (dup2(pipes[1], 1) ==-1)
107                 {
108                   fprintf(stderr, "dup2 failed: %s\n", strerror(errno));
109                   exit(1);
110                 }
111               tmp=snprintf(buf, BUFSIZE, "Need passphrase for %s (%s)",
112                            filename, saved_comment);
113               /* skip the prompt if it won't fit */
114               if (tmp < 0 || tmp >= BUFSIZE)
115                 tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", 0);
116               else
117                 tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0);
118               if (tmp==-1)
119                 {
120                   fprintf(stderr, "Executing ssh-askpass failed: %s\n",
121                           strerror(errno));
122                   exit(1);
123                 }
124               break;
125             default:
126               close(pipes[1]);
127               if ( (pipef=fdopen(pipes[0], "r")) ==NULL)
128                 {
129                   fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
130                   exit(1);
131                 }
132               if(fgets(buf, sizeof(buf), pipef)==NULL)
133                 {
134                   xfree(saved_comment);
135                   return;
136                 }
137               fclose(pipef);
138               if (strchr(buf, '\n'))
139                 *strchr(buf, '\n') = 0;
140               pass = xstrdup(buf);
141               memset(buf, 0, sizeof(buf));
142               if (waitpid(child, NULL, 0) ==-1)
143                 {
144                   fprintf(stderr, "Waiting for child failed: %s\n",
145                           strerror(errno));
146                   exit(1);
147                 }
148               if (strcmp(pass, "") == 0)
149                 {
150                   xfree(saved_comment);
151                   xfree(pass);
152                   return;
153                 }
154             }
155         }
156       else
157         {
158           if (first)
159             printf("Need passphrase for %s (%s).\n", filename, saved_comment);
160           else
161             printf("Bad passphrase.\n");
162           pass = read_passphrase("Enter passphrase: ", 1);
163           if (strcmp(pass, "") == 0)
164             {
165               xfree(saved_comment);
166               xfree(pass);
167               return;
168             }
169         }
170       first = 0;
171     }
172   memset(pass, 0, strlen(pass));
173   xfree(pass);
174
175   xfree(saved_comment);
176
177   if (ssh_add_identity(ac, key, comment))
178     fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
179   else
180     fprintf(stderr, "Could not add identity: %s\n", filename);
181   RSA_free(key);
182   xfree(comment);
183 }
184
185 void
186 list_identities(AuthenticationConnection *ac)
187 {
188   BIGNUM *e, *n;
189   int bits, status;
190   char *comment;
191   int had_identities;
192
193   e = BN_new();
194   n = BN_new();
195   had_identities = 0;
196   for (status = ssh_get_first_identity(ac, &bits, e, n, &comment);
197        status;
198        status = ssh_get_next_identity(ac, &bits, e, n, &comment))
199     {
200       char *buf;
201       had_identities = 1;
202       printf("%d ", bits);
203       buf = BN_bn2dec(e);
204       if (buf != NULL) {
205         printf("%s ", buf);
206         free (buf);
207       } else {
208         error("list_identities: BN_bn2dec #1 failed.");
209       }
210       buf = BN_bn2dec(n);
211       if (buf != NULL) {
212         printf("%s %s\n", buf, comment);
213         free (buf);
214       } else {
215         error("list_identities: BN_bn2dec #2 failed.");
216       }
217       xfree(comment);
218     }
219   BN_clear_free(e);
220   BN_clear_free(n);
221   if (!had_identities)
222     printf("The agent has no identities.\n");
223 }
224
225 int
226 main(int argc, char **argv)
227 {
228   AuthenticationConnection *ac = NULL;
229   struct passwd *pw;
230   char buf[1024];
231   int no_files = 1;
232   int i;
233   int deleting = 0;
234
235   /* check if RSA support exists */
236   if (rsa_alive() == 0) {
237     extern char *__progname;
238
239     fprintf(stderr,
240       "%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
241       __progname);
242     exit(1);
243   }
244
245   /* At first, get a connection to the authentication agent. */
246   ac = ssh_get_authentication_connection();
247   if (ac == NULL) {
248     fprintf(stderr, "Could not open a connection to your authentication agent.\n");
249     exit(1);
250   }
251
252   for (i = 1; i < argc; i++)
253     {
254       if (strcmp(argv[i], "-l") == 0)
255         {
256           list_identities(ac);
257           no_files = 0; /* Don't default-add/delete if -l. */
258           continue;
259         }
260       if (strcmp(argv[i], "-d") == 0)
261         {
262           deleting = 1;
263           continue;
264         }
265       if (strcmp(argv[i], "-D") == 0)
266         {
267           delete_all(ac);
268           no_files = 0;
269           continue;
270         }
271       no_files = 0;
272       if (deleting)
273         delete_file(ac, argv[i]);
274       else
275         add_file(ac, argv[i]);
276     }
277   if (no_files)
278     {
279       pw = getpwuid(getuid());
280       if (!pw)
281         {
282           fprintf(stderr, "No user found with uid %d\n", (int)getuid());
283           ssh_close_authentication_connection(ac);
284           exit(1);
285         }
286       snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
287       if (deleting)
288         delete_file(ac, buf);
289       else
290         add_file(ac, buf);
291     }
292   ssh_close_authentication_connection(ac);
293   exit(0);
294 }
This page took 0.056209 seconds and 5 git commands to generate.