Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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