source: trunk/third/openssh/ssh-keysign.c @ 18759

Revision 18759, 5.9 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18758, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2002 Markus Friedl.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24#include "includes.h"
25RCSID("$OpenBSD: ssh-keysign.c,v 1.7 2002/07/03 14:21:05 markus Exp $");
26
27#include <openssl/evp.h>
28#include <openssl/rand.h>
29#include <openssl/rsa.h>
30
31#include "log.h"
32#include "key.h"
33#include "ssh.h"
34#include "ssh2.h"
35#include "misc.h"
36#include "xmalloc.h"
37#include "buffer.h"
38#include "bufaux.h"
39#include "authfile.h"
40#include "msg.h"
41#include "canohost.h"
42#include "pathnames.h"
43#include "readconf.h"
44
45uid_t original_real_uid;        /* XXX readconf.c needs this */
46
47#ifdef HAVE___PROGNAME
48extern char *__progname;
49#else
50char *__progname;
51#endif
52
53static int
54valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
55    u_int datalen)
56{
57        Buffer b;
58        Key *key;
59        u_char *pkblob;
60        u_int blen, len;
61        char *pkalg, *p;
62        int pktype, fail;
63
64        fail = 0;
65
66        buffer_init(&b);
67        buffer_append(&b, data, datalen);
68
69        /* session id, currently limited to SHA1 (20 bytes) */
70        p = buffer_get_string(&b, &len);
71        if (len != 20)
72                fail++;
73        xfree(p);
74
75        if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
76                fail++;
77
78        /* server user */
79        buffer_skip_string(&b);
80
81        /* service */
82        p = buffer_get_string(&b, NULL);
83        if (strcmp("ssh-connection", p) != 0)
84                fail++;
85        xfree(p);
86
87        /* method */
88        p = buffer_get_string(&b, NULL);
89        if (strcmp("hostbased", p) != 0)
90                fail++;
91        xfree(p);
92
93        /* pubkey */
94        pkalg = buffer_get_string(&b, NULL);
95        pkblob = buffer_get_string(&b, &blen);
96
97        pktype = key_type_from_name(pkalg);
98        if (pktype == KEY_UNSPEC)
99                fail++;
100        else if ((key = key_from_blob(pkblob, blen)) == NULL)
101                fail++;
102        else if (key->type != pktype)
103                fail++;
104        xfree(pkalg);
105        xfree(pkblob);
106
107        /* client host name, handle trailing dot */
108        p = buffer_get_string(&b, &len);
109        debug2("valid_request: check expect chost %s got %s", host, p);
110        if (strlen(host) != len - 1)
111                fail++;
112        else if (p[len - 1] != '.')
113                fail++;
114        else if (strncasecmp(host, p, len - 1) != 0)
115                fail++;
116        xfree(p);
117
118        /* local user */
119        p = buffer_get_string(&b, NULL);
120
121        if (strcmp(pw->pw_name, p) != 0)
122                fail++;
123        xfree(p);
124
125        /* end of message */
126        if (buffer_len(&b) != 0)
127                fail++;
128
129        debug3("valid_request: fail %d", fail);
130
131        if (fail && key != NULL)
132                key_free(key);
133        else
134                *ret = key;
135
136        return (fail ? -1 : 0);
137}
138
139int
140main(int argc, char **argv)
141{
142        Buffer b;
143        Options options;
144        Key *keys[2], *key;
145        struct passwd *pw;
146        int key_fd[2], i, found, version = 2, fd;
147        u_char *signature, *data;
148        char *host;
149        u_int slen, dlen;
150        u_int32_t rnd[256];
151
152        key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
153        key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
154
155        seteuid(getuid());
156        setuid(getuid());
157
158        init_rng();
159        seed_rng();
160        arc4random_stir();
161
162#ifdef DEBUG_SSH_KEYSIGN
163        log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
164#endif
165
166        /* verify that ssh-keysign is enabled by the admin */
167        original_real_uid = getuid();   /* XXX readconf.c needs this */
168        initialize_options(&options);
169        (void)read_config_file(_PATH_HOST_CONFIG_FILE, "", &options);
170        fill_default_options(&options);
171        if (options.hostbased_authentication != 1)
172                fatal("Hostbased authentication not enabled in %s",
173                    _PATH_HOST_CONFIG_FILE);
174
175        if (key_fd[0] == -1 && key_fd[1] == -1)
176                fatal("could not open any host key");
177
178        if ((pw = getpwuid(getuid())) == NULL)
179                fatal("getpwuid failed");
180        pw = pwcopy(pw);
181
182        SSLeay_add_all_algorithms();
183        for (i = 0; i < 256; i++)
184                rnd[i] = arc4random();
185        RAND_seed(rnd, sizeof(rnd));
186
187        found = 0;
188        for (i = 0; i < 2; i++) {
189                keys[i] = NULL;
190                if (key_fd[i] == -1)
191                        continue;
192                keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
193                    NULL, NULL);
194                close(key_fd[i]);
195                if (keys[i] != NULL && keys[i]->type == KEY_RSA) {
196                        if (RSA_blinding_on(keys[i]->rsa, NULL) != 1) {
197                                error("RSA_blinding_on failed");
198                                key_free(keys[i]);
199                                keys[i] = NULL;
200                        }
201                }
202                if (keys[i] != NULL)
203                        found = 1;
204        }
205        if (!found)
206                fatal("no hostkey found");
207
208        buffer_init(&b);
209        if (ssh_msg_recv(STDIN_FILENO, &b) < 0)
210                fatal("ssh_msg_recv failed");
211        if (buffer_get_char(&b) != version)
212                fatal("bad version");
213        fd = buffer_get_int(&b);
214        if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
215                fatal("bad fd");
216        if ((host = get_local_name(fd)) == NULL)
217                fatal("cannot get sockname for fd");
218
219        data = buffer_get_string(&b, &dlen);
220        if (valid_request(pw, host, &key, data, dlen) < 0)
221                fatal("not a valid request");
222        xfree(host);
223
224        found = 0;
225        for (i = 0; i < 2; i++) {
226                if (keys[i] != NULL &&
227                    key_equal(key, keys[i])) {
228                        found = 1;
229                        break;
230                }
231        }
232        if (!found)
233                fatal("no matching hostkey found");
234
235        if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
236                fatal("key_sign failed");
237        xfree(data);
238
239        /* send reply */
240        buffer_clear(&b);
241        buffer_put_string(&b, signature, slen);
242        ssh_msg_send(STDOUT_FILENO, version, &b);
243
244        return (0);
245}
Note: See TracBrowser for help on using the repository browser.