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