source: trunk/third/openssh/ssh-add.c @ 16801

Revision 16801, 7.5 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16800, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 * Adds an identity to the authentication server, or removes an identity.
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose.  Any derived versions of this
9 * software must be clearly marked as such, and if the derived work is
10 * incompatible with the protocol description in the RFC file, it must be
11 * called by a name other than "ssh" or "Secure Shell".
12 *
13 * SSH2 implementation,
14 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "includes.h"
38RCSID("$OpenBSD: ssh-add.c,v 1.45 2001/08/03 10:31:30 jakob Exp $");
39
40#include <openssl/evp.h>
41
42#include "ssh.h"
43#include "rsa.h"
44#include "log.h"
45#include "xmalloc.h"
46#include "key.h"
47#include "authfd.h"
48#include "authfile.h"
49#include "pathnames.h"
50#include "readpass.h"
51
52#ifdef HAVE___PROGNAME
53extern char *__progname;
54#else
55char *__progname;
56#endif
57
58/* argv0 */
59extern char *__progname;
60
61/* we keep a cache of one passphrases */
62static char *pass = NULL;
63static void
64clear_pass(void)
65{
66        if (pass) {
67                memset(pass, 0, strlen(pass));
68                xfree(pass);
69                pass = NULL;
70        }
71}
72
73static void
74delete_file(AuthenticationConnection *ac, const char *filename)
75{
76        Key *public;
77        char *comment = NULL;
78
79        public = key_load_public(filename, &comment);
80        if (public == NULL) {
81                printf("Bad key file %s\n", filename);
82                return;
83        }
84        if (ssh_remove_identity(ac, public))
85                fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
86        else
87                fprintf(stderr, "Could not remove identity: %s\n", filename);
88        key_free(public);
89        xfree(comment);
90}
91
92/* Send a request to remove all identities. */
93static void
94delete_all(AuthenticationConnection *ac)
95{
96        int success = 1;
97
98        if (!ssh_remove_all_identities(ac, 1))
99                success = 0;
100        /* ignore error-code for ssh2 */
101        ssh_remove_all_identities(ac, 2);
102
103        if (success)
104                fprintf(stderr, "All identities removed.\n");
105        else
106                fprintf(stderr, "Failed to remove all identities.\n");
107}
108
109static void
110add_file(AuthenticationConnection *ac, const char *filename)
111{
112        struct stat st;
113        Key *private;
114        char *comment = NULL;
115        char msg[1024];
116
117        if (stat(filename, &st) < 0) {
118                perror(filename);
119                exit(1);
120        }
121        /* At first, try empty passphrase */
122        private = key_load_private(filename, "", &comment);
123        if (comment == NULL)
124                comment = xstrdup(filename);
125        /* try last */
126        if (private == NULL && pass != NULL)
127                private = key_load_private(filename, pass, NULL);
128        if (private == NULL) {
129                /* clear passphrase since it did not work */
130                clear_pass();
131                snprintf(msg, sizeof msg, "Enter passphrase for %.200s: ",
132                   comment);
133                for (;;) {
134                        pass = read_passphrase(msg, RP_ALLOW_STDIN);
135                        if (strcmp(pass, "") == 0) {
136                                clear_pass();
137                                xfree(comment);
138                                return;
139                        }
140                        private = key_load_private(filename, pass, &comment);
141                        if (private != NULL)
142                                break;
143                        clear_pass();
144                        strlcpy(msg, "Bad passphrase, try again: ", sizeof msg);
145                }
146        }
147        if (ssh_add_identity(ac, private, comment))
148                fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
149        else
150                fprintf(stderr, "Could not add identity: %s\n", filename);
151        xfree(comment);
152        key_free(private);
153}
154
155static void
156update_card(AuthenticationConnection *ac, int add, const char *id)
157{
158        if (ssh_update_card(ac, add, id))
159                fprintf(stderr, "Card %s: %s\n",
160                     add ? "added" : "removed", id);
161        else
162                fprintf(stderr, "Could not %s card: %s\n",
163                     add ? "add" : "remove", id);
164}
165
166static void
167list_identities(AuthenticationConnection *ac, int do_fp)
168{
169        Key *key;
170        char *comment, *fp;
171        int had_identities = 0;
172        int version;
173
174        for (version = 1; version <= 2; version++) {
175                for (key = ssh_get_first_identity(ac, &comment, version);
176                     key != NULL;
177                     key = ssh_get_next_identity(ac, &comment, version)) {
178                        had_identities = 1;
179                        if (do_fp) {
180                                fp = key_fingerprint(key, SSH_FP_MD5,
181                                    SSH_FP_HEX);
182                                printf("%d %s %s (%s)\n",
183                                    key_size(key), fp, comment, key_type(key));
184                                xfree(fp);
185                        } else {
186                                if (!key_write(key, stdout))
187                                        fprintf(stderr, "key_write failed");
188                                fprintf(stdout, " %s\n", comment);
189                        }
190                        key_free(key);
191                        xfree(comment);
192                }
193        }
194        if (!had_identities)
195                printf("The agent has no identities.\n");
196}
197
198static void
199usage(void)
200{
201        fprintf(stderr, "Usage: %s [options]\n", __progname);
202        fprintf(stderr, "Options:\n");
203        fprintf(stderr, "  -l          List fingerprints of all identities.\n");
204        fprintf(stderr, "  -L          List public key parameters of all identities.\n");
205        fprintf(stderr, "  -d          Delete identity.\n");
206        fprintf(stderr, "  -D          Delete all identities.\n");
207#ifdef SMARTCARD
208        fprintf(stderr, "  -s reader   Add key in smartcard reader.\n");
209        fprintf(stderr, "  -e reader   Remove key in smartcard reader.\n");
210#endif
211}
212
213int
214main(int argc, char **argv)
215{
216        extern char *optarg;
217        extern int optind;
218        AuthenticationConnection *ac = NULL;
219        struct passwd *pw;
220        char buf[1024];
221        char *sc_reader_id = NULL;
222        int i, ch, deleting = 0;
223
224        __progname = get_progname(argv[0]);
225        init_rng();
226        seed_rng();
227
228        SSLeay_add_all_algorithms();
229
230        /* At first, get a connection to the authentication agent. */
231        ac = ssh_get_authentication_connection();
232        if (ac == NULL) {
233                fprintf(stderr, "Could not open a connection to your authentication agent.\n");
234                exit(1);
235        }
236        while ((ch = getopt(argc, argv, "lLdDe:s:")) != -1) {
237                switch (ch) {
238                case 'l':
239                case 'L':
240                        list_identities(ac, ch == 'l' ? 1 : 0);
241                        goto done;
242                        break;
243                case 'd':
244                        deleting = 1;
245                        break;
246                case 'D':
247                        delete_all(ac);
248                        goto done;
249                        break;
250                case 's':
251                        sc_reader_id = optarg;
252                        break;
253                case 'e':
254                        deleting = 1;
255                        sc_reader_id = optarg;
256                        break;
257                default:
258                        usage();
259                        exit(1);
260                        break;
261                }
262        }
263        argc -= optind;
264        argv += optind;
265        if (sc_reader_id != NULL) {
266                update_card(ac, !deleting, sc_reader_id);
267                goto done;
268        }
269        if (argc == 0) {
270                pw = getpwuid(getuid());
271                if (!pw) {
272                        fprintf(stderr, "No user found with uid %u\n",
273                            (u_int)getuid());
274                        ssh_close_authentication_connection(ac);
275                        exit(1);
276                }
277                snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_CLIENT_IDENTITY);
278                if (deleting)
279                        delete_file(ac, buf);
280                else
281                        add_file(ac, buf);
282        } else {
283                for (i = 0; i < argc; i++) {
284                        if (deleting)
285                                delete_file(ac, argv[i]);
286                        else
287                                add_file(ac, argv[i]);
288                }
289        }
290        clear_pass();
291
292done:
293        ssh_close_authentication_connection(ac);
294        exit(0);
295}
Note: See TracBrowser for help on using the repository browser.