Annotation of src/usr.bin/ssh/ssh-keysign.c, Revision 1.6
1.1 markus 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"
1.6 ! markus 25: RCSID("$OpenBSD: ssh-keysign.c,v 1.5 2002/06/26 22:27:32 markus Exp $");
1.1 markus 26:
27: #include <openssl/evp.h>
1.6 ! markus 28: #include <openssl/rand.h>
! 29: #include <openssl/rsa.h>
1.1 markus 30:
31: #include "log.h"
32: #include "key.h"
33: #include "ssh2.h"
34: #include "misc.h"
35: #include "xmalloc.h"
36: #include "buffer.h"
37: #include "bufaux.h"
38: #include "authfile.h"
39: #include "msg.h"
1.2 markus 40: #include "canohost.h"
1.1 markus 41: #include "pathnames.h"
42:
43: static int
1.2 markus 44: valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
45: u_int datalen)
1.1 markus 46: {
47: Buffer b;
48: Key *key;
1.2 markus 49: u_char *pkblob;
50: u_int blen, len;
51: char *pkalg, *p;
1.1 markus 52: int pktype, fail;
53:
54: fail = 0;
55:
56: buffer_init(&b);
57: buffer_append(&b, data, datalen);
1.4 deraadt 58:
1.3 markus 59: /* session id, currently limited to SHA1 (20 bytes) */
60: p = buffer_get_string(&b, &len);
61: if (len != 20)
62: fail++;
63: xfree(p);
64:
1.1 markus 65: if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
66: fail++;
67:
68: /* server user */
69: buffer_skip_string(&b);
70:
71: /* service */
72: p = buffer_get_string(&b, NULL);
73: if (strcmp("ssh-connection", p) != 0)
74: fail++;
75: xfree(p);
76:
77: /* method */
78: p = buffer_get_string(&b, NULL);
79: if (strcmp("hostbased", p) != 0)
80: fail++;
81: xfree(p);
82:
83: /* pubkey */
84: pkalg = buffer_get_string(&b, NULL);
85: pkblob = buffer_get_string(&b, &blen);
86:
87: pktype = key_type_from_name(pkalg);
88: if (pktype == KEY_UNSPEC)
89: fail++;
90: else if ((key = key_from_blob(pkblob, blen)) == NULL)
91: fail++;
92: else if (key->type != pktype)
93: fail++;
94: xfree(pkalg);
95: xfree(pkblob);
96:
1.2 markus 97: /* client host name, handle trailing dot */
98: p = buffer_get_string(&b, &len);
99: debug2("valid_request: check expect chost %s got %s", host, p);
100: if (strlen(host) != len - 1)
101: fail++;
102: else if (p[len - 1] != '.')
1.4 deraadt 103: fail++;
1.2 markus 104: else if (strncasecmp(host, p, len - 1) != 0)
1.4 deraadt 105: fail++;
1.2 markus 106: xfree(p);
1.1 markus 107:
108: /* local user */
109: p = buffer_get_string(&b, NULL);
1.2 markus 110:
1.1 markus 111: if (strcmp(pw->pw_name, p) != 0)
112: fail++;
113: xfree(p);
114:
115: /* end of message */
116: if (buffer_len(&b) != 0)
117: fail++;
118:
119: debug3("valid_request: fail %d", fail);
120:
121: if (fail && key != NULL)
122: key_free(key);
123: else
124: *ret = key;
125:
126: return (fail ? -1 : 0);
127: }
128:
129: int
130: main(int argc, char **argv)
131: {
132: Buffer b;
133: Key *keys[2], *key;
134: struct passwd *pw;
1.2 markus 135: int key_fd[2], i, found, version = 2, fd;
1.1 markus 136: u_char *signature, *data;
1.2 markus 137: char *host;
1.1 markus 138: u_int slen, dlen;
1.6 ! markus 139: u_int32_t rnd[256];
1.1 markus 140:
141: key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
142: key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
143:
144: seteuid(getuid());
145: setuid(getuid());
146:
147: #ifdef DEBUG_SSH_KEYSIGN
148: log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
1.4 deraadt 149: #endif
1.1 markus 150:
151: if (key_fd[0] == -1 && key_fd[1] == -1)
152: fatal("could not open any host key");
153:
154: if ((pw = getpwuid(getuid())) == NULL)
155: fatal("getpwuid failed");
1.4 deraadt 156: pw = pwcopy(pw);
1.1 markus 157:
158: SSLeay_add_all_algorithms();
1.6 ! markus 159: for (i = 0; i < 256; i++)
! 160: rnd[i] = arc4random();
! 161: RAND_seed(rnd, sizeof(rnd));
1.1 markus 162:
163: found = 0;
164: for (i = 0; i < 2; i++) {
165: keys[i] = NULL;
166: if (key_fd[i] == -1)
167: continue;
168: keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
169: NULL, NULL);
170: close(key_fd[i]);
1.6 ! markus 171: if (keys[i] != NULL && keys[i]->type == KEY_RSA) {
! 172: if (RSA_blinding_on(keys[i]->rsa, NULL) != 1) {
! 173: error("RSA_blinding_on failed");
! 174: key_free(keys[i]);
! 175: keys[i] = NULL;
! 176: }
! 177: }
1.1 markus 178: if (keys[i] != NULL)
179: found = 1;
180: }
181: if (!found)
182: fatal("no hostkey found");
183:
184: buffer_init(&b);
185: if (msg_recv(STDIN_FILENO, &b) < 0)
186: fatal("msg_recv failed");
187: if (buffer_get_char(&b) != version)
188: fatal("bad version");
1.2 markus 189: fd = buffer_get_int(&b);
190: if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
191: fatal("bad fd");
192: if ((host = get_local_name(fd)) == NULL)
193: fatal("cannot get sockname for fd");
1.4 deraadt 194:
1.1 markus 195: data = buffer_get_string(&b, &dlen);
1.2 markus 196: if (valid_request(pw, host, &key, data, dlen) < 0)
1.1 markus 197: fatal("not a valid request");
1.2 markus 198: xfree(host);
1.1 markus 199:
200: found = 0;
201: for (i = 0; i < 2; i++) {
202: if (keys[i] != NULL &&
203: key_equal(key, keys[i])) {
204: found = 1;
205: break;
206: }
207: }
208: if (!found)
209: fatal("no matching hostkey found");
210:
211: if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
212: fatal("key_sign failed");
1.5 markus 213: xfree(data);
1.4 deraadt 214:
1.1 markus 215: /* send reply */
216: buffer_clear(&b);
217: buffer_put_string(&b, signature, slen);
218: msg_send(STDOUT_FILENO, version, &b);
219:
220: return (0);
221: }