diff options
320 files changed, 17917 insertions, 7663 deletions
@@ -1,3 +1,934 @@ | |||
1 | 20131006 | ||
2 | - (djm) Release OpenSSH-6.7 | ||
3 | |||
4 | 20141003 | ||
5 | - (djm) [sshd_config.5] typo; from Iain Morgan | ||
6 | |||
7 | 20141001 | ||
8 | - (djm) [openbsd-compat/Makefile.in openbsd-compat/kludge-fd_set.c] | ||
9 | [openbsd-compat/openbsd-compat.h] Kludge around bad glibc | ||
10 | _FORTIFY_SOURCE check that doesn't grok heap-allocated fd_sets; | ||
11 | ok dtucker@ | ||
12 | |||
13 | 20140910 | ||
14 | - (djm) [sandbox-seccomp-filter.c] Allow mremap and exit for DietLibc; | ||
15 | patch from Felix von Leitner; ok dtucker | ||
16 | |||
17 | 20140908 | ||
18 | - (dtucker) [INSTALL] Update info about egd. ok djm@ | ||
19 | |||
20 | 20140904 | ||
21 | - (djm) [openbsd-compat/arc4random.c] Zero seed after keying PRNG | ||
22 | |||
23 | 20140903 | ||
24 | - (djm) [defines.h sshbuf.c] Move __predict_true|false to defines.h and | ||
25 | conditionalise to avoid duplicate definition. | ||
26 | - (djm) [contrib/cygwin/ssh-host-config] Fix old code leading to | ||
27 | permissions/ACLs; from Corinna Vinschen | ||
28 | |||
29 | 20140830 | ||
30 | - (djm) [openbsd-compat/openssl-compat.h] add | ||
31 | OPENSSL_[RD]SA_MAX_MODULUS_BITS defines for OpenSSL that lacks them | ||
32 | - (djm) [misc.c] Missing newline between functions | ||
33 | - (djm) [openbsd-compat/openssl-compat.h] add include guard | ||
34 | - (djm) [Makefile.in] Make TEST_SHELL a variable; "good idea" tim@ | ||
35 | |||
36 | 20140827 | ||
37 | - (djm) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c] | ||
38 | [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] | ||
39 | [regress/unittests/sshkey/common.c] | ||
40 | [regress/unittests/sshkey/test_file.c] | ||
41 | [regress/unittests/sshkey/test_fuzz.c] | ||
42 | [regress/unittests/sshkey/test_sshkey.c] Don't include openssl/ec.h | ||
43 | on !ECC OpenSSL systems | ||
44 | - (djm) [monitor.c sshd.c] SIGXFSZ needs to be ignored in postauth | ||
45 | monitor, not preauth; bz#2263 | ||
46 | - (djm) [openbsd-compat/explicit_bzero.c] implement explicit_bzero() | ||
47 | using memset_s() where possible; improve fallback to indirect bzero | ||
48 | via a volatile pointer to give it more of a chance to avoid being | ||
49 | optimised away. | ||
50 | |||
51 | 20140825 | ||
52 | - (djm) [bufec.c] Skip this file on !ECC OpenSSL | ||
53 | - (djm) [INSTALL] Recommend libcrypto be built -fPIC, mention LibreSSL, | ||
54 | update OpenSSL version requirement. | ||
55 | |||
56 | 20140824 | ||
57 | - (djm) [sftp-server.c] Some systems (e.g. Irix) have prctl() but not | ||
58 | PR_SET_DUMPABLE, so adjust ifdef; reported by Tom Christensen | ||
59 | |||
60 | 20140823 | ||
61 | - (djm) [sshd.c] Ignore SIGXFSZ in preauth monitor child; can explode on | ||
62 | lastlog writing on platforms with high UIDs; bz#2263 | ||
63 | - (djm) [configure.ac] We now require a working vsnprintf everywhere (not | ||
64 | just for systems that lack asprintf); check for it always and extend | ||
65 | test to catch more brokenness. Fixes builds on Solaris <= 9 | ||
66 | |||
67 | 20140822 | ||
68 | - (djm) [configure.ac] include leading zero characters in OpenSSL version | ||
69 | number; fixes test for unsupported versions | ||
70 | - (djm) [sshbuf-getput-crypto.c] Fix compilation when OpenSSL lacks ECC | ||
71 | - (djm) [openbsd-compat/bsd-snprintf.c] Fix compilation failure (prototype/ | ||
72 | definition mismatch) and warning for broken/missing snprintf case. | ||
73 | - (djm) [configure.ac] double braces to appease autoconf | ||
74 | |||
75 | 20140821 | ||
76 | - (djm) [Makefile.in] fix reference to libtest_helper.a in sshkey test too. | ||
77 | - (djm) [key.h] Fix ifdefs for no-ECC OpenSSL | ||
78 | - (djm) [regress/unittests/test_helper/test_helper.c] Fix for systems that | ||
79 | don't set __progname. Diagnosed by Tom Christensen. | ||
80 | |||
81 | 20140820 | ||
82 | - (djm) [configure.ac] Check OpenSSL version is supported at configure time; | ||
83 | suggested by Kevin Brott | ||
84 | - (djm) [Makefile.in] refer to libtest_helper.a by explicit path rather than | ||
85 | -L/-l; fixes linking problems on some platforms | ||
86 | - (djm) [sshkey.h] Fix compilation when OpenSSL lacks ECC | ||
87 | - (djm) [contrib/cygwin/README] Correct build instructions; from Corinna | ||
88 | |||
89 | 20140819 | ||
90 | - (djm) [serverloop.c] Fix syntax error on Cygwin; from Corinna Vinschen | ||
91 | - (djm) [sshbuf.h] Fix compilation on systems without OPENSSL_HAS_ECC. | ||
92 | - (djm) [ssh-dss.c] Include openssl/dsa.h for DSA_SIG | ||
93 | - (djm) [INSTALL contrib/caldera/openssh.spec contrib/cygwin/README] | ||
94 | [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Remove mentions | ||
95 | of TCP wrappers. | ||
96 | |||
97 | 20140811 | ||
98 | - (djm) [myproposal.h] Make curve25519 KEX dependent on | ||
99 | HAVE_EVP_SHA256 instead of OPENSSL_HAS_ECC. | ||
100 | |||
101 | 20140810 | ||
102 | - (djm) [README contrib/caldera/openssh.spec] | ||
103 | [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Update versions | ||
104 | |||
105 | 20140801 | ||
106 | - (djm) [regress/multiplex.sh] Skip test for non-OpenBSD netcat. We need | ||
107 | a better solution, but this will have to do for now. | ||
108 | - (djm) [regress/multiplex.sh] Instruct nc not to quit as soon as stdin | ||
109 | is closed; avoid regress failures when stdin is /dev/null | ||
110 | - (djm) [regress/multiplex.sh] Use -d (detach stdin) flag to disassociate | ||
111 | nc from stdin, it's more portable | ||
112 | |||
113 | 20140730 | ||
114 | - OpenBSD CVS Sync | ||
115 | - millert@cvs.openbsd.org 2014/07/24 22:57:10 | ||
116 | [ssh.1] | ||
117 | Mention UNIX-domain socket forwarding too. OK jmc@ deraadt@ | ||
118 | - dtucker@cvs.openbsd.org 2014/07/25 21:22:03 | ||
119 | [ssh-agent.c] | ||
120 | Clear buffer used for handling messages. This prevents keys being | ||
121 | left in memory after they have been expired or deleted in some cases | ||
122 | (but note that ssh-agent is setgid so you would still need root to | ||
123 | access them). Pointed out by Kevin Burns, ok deraadt | ||
124 | - schwarze@cvs.openbsd.org 2014/07/28 15:40:08 | ||
125 | [sftp-server.8 sshd_config.5] | ||
126 | some systems no longer need /dev/log; | ||
127 | issue noticed by jirib; | ||
128 | ok deraadt | ||
129 | |||
130 | 20140725 | ||
131 | - (djm) [regress/multiplex.sh] restore incorrectly deleted line; | ||
132 | pointed out by Christian Hesse | ||
133 | |||
134 | 20140722 | ||
135 | - (djm) [regress/multiplex.sh] ssh mux master lost -N somehow; | ||
136 | put it back | ||
137 | - (djm) [regress/multiplex.sh] change the test for still-open Unix | ||
138 | domain sockets to be robust against nc implementations that produce | ||
139 | error messages. | ||
140 | - (dtucker) [regress/unittests/sshkey/test_{file,fuzz,sshkey}.c] Wrap ecdsa- | ||
141 | specific tests inside OPENSSL_HAS_ECC. | ||
142 | - (dtucker) OpenBSD CVS Sync | ||
143 | - dtucker@cvs.openbsd.org 2014/07/22 01:18:50 | ||
144 | [key.c] | ||
145 | Prevent spam from key_load_private_pem during hostbased auth. ok djm@ | ||
146 | - guenther@cvs.openbsd.org 2014/07/22 07:13:42 | ||
147 | [umac.c] | ||
148 | Convert from <sys/endian.h> to the shiney new <endian.h> | ||
149 | ok dtucker@, who also confirmed that -portable handles this already | ||
150 | (ID sync only, includes.h pulls in endian.h if available.) | ||
151 | - djm@cvs.openbsd.org 2014/07/22 01:32:12 | ||
152 | [regress/multiplex.sh] | ||
153 | change the test for still-open Unix domain sockets to be robust against | ||
154 | nc implementations that produce error messages. from -portable | ||
155 | (Id sync only) | ||
156 | - dtucker@cvs.openbsd.org 2014/07/22 23:23:22 | ||
157 | [regress/unittests/sshkey/mktestdata.sh] | ||
158 | Sign test certs with ed25519 instead of ecdsa so that they'll work in | ||
159 | -portable on platforms that don't have ECDSA in their OpenSSL. ok djm | ||
160 | - dtucker@cvs.openbsd.org 2014/07/22 23:57:40 | ||
161 | [regress/unittests/sshkey/mktestdata.sh] | ||
162 | Add $OpenBSD tag to make syncs easier | ||
163 | - dtucker@cvs.openbsd.org 2014/07/22 23:35:38 | ||
164 | [regress/unittests/sshkey/testdata/*] | ||
165 | Regenerate test keys with certs signed with ed25519 instead of ecdsa. | ||
166 | These can be used in -portable on platforms that don't support ECDSA. | ||
167 | |||
168 | 20140721 | ||
169 | - OpenBSD CVS Sync | ||
170 | - millert@cvs.openbsd.org 2014/07/15 15:54:15 | ||
171 | [forwarding.sh multiplex.sh] | ||
172 | Add support for Unix domain socket forwarding. A remote TCP port | ||
173 | may be forwarded to a local Unix domain socket and vice versa or | ||
174 | both ends may be a Unix domain socket. This is a reimplementation | ||
175 | of the streamlocal patches by William Ahern from: | ||
176 | http://www.25thandclement.com/~william/projects/streamlocal.html | ||
177 | OK djm@ markus@ | ||
178 | - (djm) [regress/multiplex.sh] Not all netcat accept the -N option. | ||
179 | - (dtucker) [sshkey.c] ifdef out unused variable when compiling without | ||
180 | OPENSSL_HAS_ECC. | ||
181 | |||
182 | 20140721 | ||
183 | - (dtucker) [cipher.c openbsd-compat/openssl-compat.h] Restore the bits | ||
184 | needed to build AES CTR mode against OpenSSL 0.9.8f and above. ok djm | ||
185 | - (dtucker) [regress/unittests/sshkey/ | ||
186 | {common,test_file,test_fuzz,test_sshkey}.c] Wrap stdint.h includes in | ||
187 | ifdefs. | ||
188 | |||
189 | 20140719 | ||
190 | - (tim) [openbsd-compat/port-uw.c] Include misc.h for fwd_opts, used | ||
191 | in servconf.h. | ||
192 | |||
193 | 20140718 | ||
194 | - OpenBSD CVS Sync | ||
195 | - millert@cvs.openbsd.org 2014/07/15 15:54:14 | ||
196 | [PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c] | ||
197 | [auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c] | ||
198 | [auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h] | ||
199 | [clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c] | ||
200 | [readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c] | ||
201 | [ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c] | ||
202 | [sshd_config.5 sshlogin.c] | ||
203 | Add support for Unix domain socket forwarding. A remote TCP port | ||
204 | may be forwarded to a local Unix domain socket and vice versa or | ||
205 | both ends may be a Unix domain socket. This is a reimplementation | ||
206 | of the streamlocal patches by William Ahern from: | ||
207 | http://www.25thandclement.com/~william/projects/streamlocal.html | ||
208 | OK djm@ markus@ | ||
209 | - jmc@cvs.openbsd.org 2014/07/16 14:48:57 | ||
210 | [ssh.1] | ||
211 | add the streamlocal* options to ssh's -o list; millert says they're | ||
212 | irrelevant for scp/sftp; | ||
213 | ok markus millert | ||
214 | - djm@cvs.openbsd.org 2014/07/17 00:10:56 | ||
215 | [sandbox-systrace.c] | ||
216 | ifdef SYS_sendsyslog so this will compile without patching on -stable | ||
217 | - djm@cvs.openbsd.org 2014/07/17 00:10:18 | ||
218 | [mux.c] | ||
219 | preserve errno across syscall | ||
220 | - djm@cvs.openbsd.org 2014/07/17 00:12:03 | ||
221 | [key.c] | ||
222 | silence "incorrect passphrase" error spam; reported and ok dtucker@ | ||
223 | - djm@cvs.openbsd.org 2014/07/17 07:22:19 | ||
224 | [mux.c ssh.c] | ||
225 | reflect stdio-forward ("ssh -W host:port ...") failures in exit status. | ||
226 | previously we were always returning 0. bz#2255 reported by Brendan | ||
227 | Germain; ok dtucker | ||
228 | - djm@cvs.openbsd.org 2014/07/18 02:46:01 | ||
229 | [ssh-agent.c] | ||
230 | restore umask around listener socket creation (dropped in streamlocal patch | ||
231 | merge) | ||
232 | - (dtucker) [auth2-gss.c gss-serv-krb5.c] Include misc.h for fwd_opts, used | ||
233 | in servconf.h. | ||
234 | - (dtucker) [Makefile.in] Add a t-exec target to run just the executable | ||
235 | tests. | ||
236 | - (dtucker) [key.c sshkey.c] Put new ecdsa bits inside ifdef OPENSSL_HAS_ECC. | ||
237 | |||
238 | 20140717 | ||
239 | - (djm) [digest-openssl.c] Preserve array order when disabling digests. | ||
240 | Reported by Petr Lautrbach. | ||
241 | - OpenBSD CVS Sync | ||
242 | - deraadt@cvs.openbsd.org 2014/07/11 08:09:54 | ||
243 | [sandbox-systrace.c] | ||
244 | Permit use of SYS_sendsyslog from inside the sandbox. Clock is ticking, | ||
245 | update your kernels and sshd soon.. libc will start using sendsyslog() | ||
246 | in about 4 days. | ||
247 | - tedu@cvs.openbsd.org 2014/07/11 13:54:34 | ||
248 | [myproposal.h] | ||
249 | by popular demand, add back hamc-sha1 to server proposal for better compat | ||
250 | with many clients still in use. ok deraadt | ||
251 | |||
252 | 20140715 | ||
253 | - (djm) [configure.ac] Delay checks for arc4random* until after libcrypto | ||
254 | has been located; fixes builds agains libressl-portable | ||
255 | |||
256 | 20140711 | ||
257 | - OpenBSD CVS Sync | ||
258 | - benno@cvs.openbsd.org 2014/07/09 14:15:56 | ||
259 | [ssh-add.c] | ||
260 | fix ssh-add crash while loading more than one key | ||
261 | ok markus@ | ||
262 | |||
263 | 20140709 | ||
264 | - OpenBSD CVS Sync | ||
265 | - djm@cvs.openbsd.org 2014/07/07 08:19:12 | ||
266 | [ssh_config.5] | ||
267 | mention that ProxyCommand is executed using shell "exec" to avoid | ||
268 | a lingering process; bz#1977 | ||
269 | - djm@cvs.openbsd.org 2014/07/09 01:45:10 | ||
270 | [sftp.c] | ||
271 | more useful error message when GLOB_NOSPACE occurs; | ||
272 | bz#2254, patch from Orion Poplawski | ||
273 | - djm@cvs.openbsd.org 2014/07/09 03:02:15 | ||
274 | [key.c] | ||
275 | downgrade more error() to debug() to better match what old authfile.c | ||
276 | did; suppresses spurious errors with hostbased authentication enabled | ||
277 | - djm@cvs.openbsd.org 2014/07/06 07:42:03 | ||
278 | [multiplex.sh test-exec.sh] | ||
279 | add a hook to the cleanup() function to kill $SSH_PID if it is set | ||
280 | |||
281 | use it to kill the mux master started in multiplex.sh (it was being left | ||
282 | around on fatal failures) | ||
283 | - djm@cvs.openbsd.org 2014/07/07 08:15:26 | ||
284 | [multiplex.sh] | ||
285 | remove forced-fatal that I stuck in there to test the new cleanup | ||
286 | logic and forgot to remove... | ||
287 | |||
288 | 20140706 | ||
289 | - OpenBSD CVS Sync | ||
290 | - djm@cvs.openbsd.org 2014/07/03 23:18:35 | ||
291 | [authfile.h] | ||
292 | remove leakmalloc droppings | ||
293 | - djm@cvs.openbsd.org 2014/07/05 23:11:48 | ||
294 | [channels.c] | ||
295 | fix remote-forward cancel regression; ok markus@ | ||
296 | |||
297 | 20140704 | ||
298 | - OpenBSD CVS Sync | ||
299 | - jsing@cvs.openbsd.org 2014/07/03 12:42:16 | ||
300 | [cipher-chachapoly.c] | ||
301 | Call chacha_ivsetup() immediately before chacha_encrypt_bytes() - this | ||
302 | makes it easier to verify that chacha_encrypt_bytes() is only called once | ||
303 | per chacha_ivsetup() call. | ||
304 | ok djm@ | ||
305 | - djm@cvs.openbsd.org 2014/07/03 22:23:46 | ||
306 | [sshconnect.c] | ||
307 | when rekeying, skip file/DNS lookup if it is the same as the key sent | ||
308 | during initial key exchange. bz#2154 patch from Iain Morgan; ok markus@ | ||
309 | - djm@cvs.openbsd.org 2014/07/03 22:33:41 | ||
310 | [channels.c] | ||
311 | allow explicit ::1 and 127.0.0.1 forwarding bind addresses when | ||
312 | GatewayPorts=no; allows client to choose address family; | ||
313 | bz#2222 ok markus@ | ||
314 | - djm@cvs.openbsd.org 2014/07/03 22:40:43 | ||
315 | [servconf.c servconf.h session.c sshd.8 sshd_config.5] | ||
316 | Add a sshd_config PermitUserRC option to control whether ~/.ssh/rc is | ||
317 | executed, mirroring the no-user-rc authorized_keys option; | ||
318 | bz#2160; ok markus@ | ||
319 | |||
320 | 20140703 | ||
321 | - (djm) [digest-openssl.c configure.ac] Disable RIPEMD160 if libcrypto | ||
322 | doesn't support it. | ||
323 | - (djm) [monitor_fdpass.c] Use sys/poll.h if poll.h doesn't exist; | ||
324 | bz#2237 | ||
325 | - OpenBSD CVS Sync | ||
326 | - djm@cvs.openbsd.org 2014/07/03 01:45:38 | ||
327 | [sshkey.c] | ||
328 | make Ed25519 keys' title fit properly in the randomart border; bz#2247 | ||
329 | based on patch from Christian Hesse | ||
330 | - djm@cvs.openbsd.org 2014/07/03 03:11:03 | ||
331 | [ssh-agent.c] | ||
332 | Only cleanup agent socket in the main agent process and not in any | ||
333 | subprocesses it may have started (e.g. forked askpass). Fixes | ||
334 | agent sockets being zapped when askpass processes fatal(); | ||
335 | bz#2236 patch from Dmitry V. Levin | ||
336 | - djm@cvs.openbsd.org 2014/07/03 03:15:01 | ||
337 | [ssh-add.c] | ||
338 | make stdout line-buffered; saves partial output getting lost when | ||
339 | ssh-add fatal()s part-way through (e.g. when listing keys from an | ||
340 | agent that supports key types that ssh-add doesn't); | ||
341 | bz#2234, reported by Phil Pennock | ||
342 | - djm@cvs.openbsd.org 2014/07/03 03:26:43 | ||
343 | [digest-openssl.c] | ||
344 | use EVP_Digest() for one-shot hash instead of creating, updating, | ||
345 | finalising and destroying a context. | ||
346 | bz#2231, based on patch from Timo Teras | ||
347 | - djm@cvs.openbsd.org 2014/07/03 03:34:09 | ||
348 | [gss-serv.c session.c ssh-keygen.c] | ||
349 | standardise on NI_MAXHOST for gethostname() string lengths; about | ||
350 | 1/2 the cases were using it already. Fixes bz#2239 en passant | ||
351 | - djm@cvs.openbsd.org 2014/07/03 03:47:27 | ||
352 | [ssh-keygen.c] | ||
353 | When hashing or removing hosts using ssh-keygen, don't choke on | ||
354 | @revoked markers and don't remove @cert-authority markers; | ||
355 | bz#2241, reported by mlindgren AT runelind.net | ||
356 | - djm@cvs.openbsd.org 2014/07/03 04:36:45 | ||
357 | [digest.h] | ||
358 | forward-declare struct sshbuf so consumers don't need to include sshbuf.h | ||
359 | - djm@cvs.openbsd.org 2014/07/03 05:32:36 | ||
360 | [ssh_config.5] | ||
361 | mention '%%' escape sequence in HostName directives and how it may | ||
362 | be used to specify IPv6 link-local addresses | ||
363 | - djm@cvs.openbsd.org 2014/07/03 05:38:17 | ||
364 | [ssh.1] | ||
365 | document that -g will only work in the multiplexed case if applied to | ||
366 | the mux master | ||
367 | - djm@cvs.openbsd.org 2014/07/03 06:39:19 | ||
368 | [ssh.c ssh_config.5] | ||
369 | Add a %C escape sequence for LocalCommand and ControlPath that expands | ||
370 | to a unique identifer based on a has of the tuple of (local host, | ||
371 | remote user, hostname, port). | ||
372 | |||
373 | Helps avoid exceeding sockaddr_un's miserly pathname limits for mux | ||
374 | control paths. | ||
375 | |||
376 | bz#2220, based on patch from mancha1 AT zoho.com; ok markus@ | ||
377 | - jmc@cvs.openbsd.org 2014/07/03 07:45:27 | ||
378 | [ssh_config.5] | ||
379 | escape %C since groff thinks it part of an Rs/Re block; | ||
380 | - djm@cvs.openbsd.org 2014/07/03 11:16:55 | ||
381 | [auth.c auth.h auth1.c auth2.c] | ||
382 | make the "Too many authentication failures" message include the | ||
383 | user, source address, port and protocol in a format similar to the | ||
384 | authentication success / failure messages; bz#2199, ok dtucker | ||
385 | |||
386 | 20140702 | ||
387 | - OpenBSD CVS Sync | ||
388 | - deraadt@cvs.openbsd.org 2014/06/13 08:26:29 | ||
389 | [sandbox-systrace.c] | ||
390 | permit SYS_getentropy | ||
391 | from matthew | ||
392 | - matthew@cvs.openbsd.org 2014/06/18 02:59:13 | ||
393 | [sandbox-systrace.c] | ||
394 | Now that we have a dedicated getentropy(2) system call for | ||
395 | arc4random(3), we can disallow __sysctl(2) in OpenSSH's systrace | ||
396 | sandbox. | ||
397 | |||
398 | ok djm | ||
399 | - naddy@cvs.openbsd.org 2014/06/18 15:42:09 | ||
400 | [sshbuf-getput-crypto.c] | ||
401 | The ssh_get_bignum functions must accept the same range of bignums | ||
402 | the corresponding ssh_put_bignum functions create. This fixes the | ||
403 | use of 16384-bit RSA keys (bug reported by Eivind Evensen). | ||
404 | ok djm@ | ||
405 | - djm@cvs.openbsd.org 2014/06/24 00:52:02 | ||
406 | [krl.c] | ||
407 | fix bug in KRL generation: multiple consecutive revoked certificate | ||
408 | serial number ranges could be serialised to an invalid format. | ||
409 | |||
410 | Readers of a broken KRL caused by this bug will fail closed, so no | ||
411 | should-have-been-revoked key will be accepted. | ||
412 | - djm@cvs.openbsd.org 2014/06/24 01:13:21 | ||
413 | [Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c | ||
414 | [auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c | ||
415 | [cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h | ||
416 | [digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h | ||
417 | [hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h | ||
418 | [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c | ||
419 | [ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c | ||
420 | [ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c | ||
421 | [sshconnect2.c sshd.c sshkey.c sshkey.h | ||
422 | [openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h] | ||
423 | New key API: refactor key-related functions to be more library-like, | ||
424 | existing API is offered as a set of wrappers. | ||
425 | |||
426 | with and ok markus@ | ||
427 | |||
428 | Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew | ||
429 | Dempsky and Ron Bowes for a detailed review a few months ago. | ||
430 | NB. This commit also removes portable OpenSSH support for OpenSSL | ||
431 | <0.9.8e. | ||
432 | - djm@cvs.openbsd.org 2014/06/24 02:19:48 | ||
433 | [ssh.c] | ||
434 | don't fatal() when hostname canonicalisation fails with a | ||
435 | ProxyCommand in use; continue and allow the ProxyCommand to | ||
436 | connect anyway (e.g. to a host with a name outside the DNS | ||
437 | behind a bastion) | ||
438 | - djm@cvs.openbsd.org 2014/06/24 02:21:01 | ||
439 | [scp.c] | ||
440 | when copying local->remote fails during read, don't send uninitialised | ||
441 | heap to the remote end. Reported by Jann Horn | ||
442 | - deraadt@cvs.openbsd.org 2014/06/25 14:16:09 | ||
443 | [sshbuf.c] | ||
444 | unblock SIGSEGV before raising it | ||
445 | ok djm | ||
446 | - markus@cvs.openbsd.org 2014/06/27 16:41:56 | ||
447 | [channels.c channels.h clientloop.c ssh.c] | ||
448 | fix remote fwding with same listen port but different listen address | ||
449 | with gerhard@, ok djm@ | ||
450 | - markus@cvs.openbsd.org 2014/06/27 18:50:39 | ||
451 | [ssh-add.c] | ||
452 | fix loading of private keys | ||
453 | - djm@cvs.openbsd.org 2014/06/30 12:54:39 | ||
454 | [key.c] | ||
455 | suppress spurious error message when loading key with a passphrase; | ||
456 | reported by kettenis@ ok markus@ | ||
457 | - djm@cvs.openbsd.org 2014/07/02 04:59:06 | ||
458 | [cipher-3des1.c] | ||
459 | fix ssh protocol 1 on the server that regressed with the sshkey change | ||
460 | (sometimes fatal() after auth completed), make file return useful status | ||
461 | codes. | ||
462 | NB. Id sync only for these two. They were bundled into the sshkey merge | ||
463 | above, since it was easier to sync the entire file and then apply | ||
464 | portable-specific changed atop it. | ||
465 | - djm@cvs.openbsd.org 2014/04/30 05:32:00 | ||
466 | [regress/Makefile] | ||
467 | unit tests for new buffer API; including basic fuzz testing | ||
468 | NB. Id sync only. | ||
469 | - djm@cvs.openbsd.org 2014/05/21 07:04:21 | ||
470 | [regress/integrity.sh] | ||
471 | when failing because of unexpected output, show the offending output | ||
472 | - djm@cvs.openbsd.org 2014/06/24 01:04:43 | ||
473 | [regress/krl.sh] | ||
474 | regress test for broken consecutive revoked serial number ranges | ||
475 | - djm@cvs.openbsd.org 2014/06/24 01:14:17 | ||
476 | [Makefile.in regress/Makefile regress/unittests/Makefile] | ||
477 | [regress/unittests/sshkey/Makefile] | ||
478 | [regress/unittests/sshkey/common.c] | ||
479 | [regress/unittests/sshkey/common.h] | ||
480 | [regress/unittests/sshkey/mktestdata.sh] | ||
481 | [regress/unittests/sshkey/test_file.c] | ||
482 | [regress/unittests/sshkey/test_fuzz.c] | ||
483 | [regress/unittests/sshkey/test_sshkey.c] | ||
484 | [regress/unittests/sshkey/tests.c] | ||
485 | [regress/unittests/sshkey/testdata/dsa_1] | ||
486 | [regress/unittests/sshkey/testdata/dsa_1-cert.fp] | ||
487 | [regress/unittests/sshkey/testdata/dsa_1-cert.pub] | ||
488 | [regress/unittests/sshkey/testdata/dsa_1.fp] | ||
489 | [regress/unittests/sshkey/testdata/dsa_1.fp.bb] | ||
490 | [regress/unittests/sshkey/testdata/dsa_1.param.g] | ||
491 | [regress/unittests/sshkey/testdata/dsa_1.param.priv] | ||
492 | [regress/unittests/sshkey/testdata/dsa_1.param.pub] | ||
493 | [regress/unittests/sshkey/testdata/dsa_1.pub] | ||
494 | [regress/unittests/sshkey/testdata/dsa_1_pw] | ||
495 | [regress/unittests/sshkey/testdata/dsa_2] | ||
496 | [regress/unittests/sshkey/testdata/dsa_2.fp] | ||
497 | [regress/unittests/sshkey/testdata/dsa_2.fp.bb] | ||
498 | [regress/unittests/sshkey/testdata/dsa_2.pub] | ||
499 | [regress/unittests/sshkey/testdata/dsa_n] | ||
500 | [regress/unittests/sshkey/testdata/dsa_n_pw] | ||
501 | [regress/unittests/sshkey/testdata/ecdsa_1] | ||
502 | [regress/unittests/sshkey/testdata/ecdsa_1-cert.fp] | ||
503 | [regress/unittests/sshkey/testdata/ecdsa_1-cert.pub] | ||
504 | [regress/unittests/sshkey/testdata/ecdsa_1.fp] | ||
505 | [regress/unittests/sshkey/testdata/ecdsa_1.fp.bb] | ||
506 | [regress/unittests/sshkey/testdata/ecdsa_1.param.curve] | ||
507 | [regress/unittests/sshkey/testdata/ecdsa_1.param.priv] | ||
508 | [regress/unittests/sshkey/testdata/ecdsa_1.param.pub] | ||
509 | [regress/unittests/sshkey/testdata/ecdsa_1.pub] | ||
510 | [regress/unittests/sshkey/testdata/ecdsa_1_pw] | ||
511 | [regress/unittests/sshkey/testdata/ecdsa_2] | ||
512 | [regress/unittests/sshkey/testdata/ecdsa_2.fp] | ||
513 | [regress/unittests/sshkey/testdata/ecdsa_2.fp.bb] | ||
514 | [regress/unittests/sshkey/testdata/ecdsa_2.param.curve] | ||
515 | [regress/unittests/sshkey/testdata/ecdsa_2.param.priv] | ||
516 | [regress/unittests/sshkey/testdata/ecdsa_2.param.pub] | ||
517 | [regress/unittests/sshkey/testdata/ecdsa_2.pub] | ||
518 | [regress/unittests/sshkey/testdata/ecdsa_n] | ||
519 | [regress/unittests/sshkey/testdata/ecdsa_n_pw] | ||
520 | [regress/unittests/sshkey/testdata/ed25519_1] | ||
521 | [regress/unittests/sshkey/testdata/ed25519_1-cert.fp] | ||
522 | [regress/unittests/sshkey/testdata/ed25519_1-cert.pub] | ||
523 | [regress/unittests/sshkey/testdata/ed25519_1.fp] | ||
524 | [regress/unittests/sshkey/testdata/ed25519_1.fp.bb] | ||
525 | [regress/unittests/sshkey/testdata/ed25519_1.pub] | ||
526 | [regress/unittests/sshkey/testdata/ed25519_1_pw] | ||
527 | [regress/unittests/sshkey/testdata/ed25519_2] | ||
528 | [regress/unittests/sshkey/testdata/ed25519_2.fp] | ||
529 | [regress/unittests/sshkey/testdata/ed25519_2.fp.bb] | ||
530 | [regress/unittests/sshkey/testdata/ed25519_2.pub] | ||
531 | [regress/unittests/sshkey/testdata/pw] | ||
532 | [regress/unittests/sshkey/testdata/rsa1_1] | ||
533 | [regress/unittests/sshkey/testdata/rsa1_1.fp] | ||
534 | [regress/unittests/sshkey/testdata/rsa1_1.fp.bb] | ||
535 | [regress/unittests/sshkey/testdata/rsa1_1.param.n] | ||
536 | [regress/unittests/sshkey/testdata/rsa1_1.pub] | ||
537 | [regress/unittests/sshkey/testdata/rsa1_1_pw] | ||
538 | [regress/unittests/sshkey/testdata/rsa1_2] | ||
539 | [regress/unittests/sshkey/testdata/rsa1_2.fp] | ||
540 | [regress/unittests/sshkey/testdata/rsa1_2.fp.bb] | ||
541 | [regress/unittests/sshkey/testdata/rsa1_2.param.n] | ||
542 | [regress/unittests/sshkey/testdata/rsa1_2.pub] | ||
543 | [regress/unittests/sshkey/testdata/rsa_1] | ||
544 | [regress/unittests/sshkey/testdata/rsa_1-cert.fp] | ||
545 | [regress/unittests/sshkey/testdata/rsa_1-cert.pub] | ||
546 | [regress/unittests/sshkey/testdata/rsa_1.fp] | ||
547 | [regress/unittests/sshkey/testdata/rsa_1.fp.bb] | ||
548 | [regress/unittests/sshkey/testdata/rsa_1.param.n] | ||
549 | [regress/unittests/sshkey/testdata/rsa_1.param.p] | ||
550 | [regress/unittests/sshkey/testdata/rsa_1.param.q] | ||
551 | [regress/unittests/sshkey/testdata/rsa_1.pub] | ||
552 | [regress/unittests/sshkey/testdata/rsa_1_pw] | ||
553 | [regress/unittests/sshkey/testdata/rsa_2] | ||
554 | [regress/unittests/sshkey/testdata/rsa_2.fp] | ||
555 | [regress/unittests/sshkey/testdata/rsa_2.fp.bb] | ||
556 | [regress/unittests/sshkey/testdata/rsa_2.param.n] | ||
557 | [regress/unittests/sshkey/testdata/rsa_2.param.p] | ||
558 | [regress/unittests/sshkey/testdata/rsa_2.param.q] | ||
559 | [regress/unittests/sshkey/testdata/rsa_2.pub] | ||
560 | [regress/unittests/sshkey/testdata/rsa_n] | ||
561 | [regress/unittests/sshkey/testdata/rsa_n_pw] | ||
562 | unit and fuzz tests for new key API | ||
563 | - (djm) [sshkey.c] Conditionalise inclusion of util.h | ||
564 | - (djm) [regress/Makefile] fix execution of sshkey unit/fuzz test | ||
565 | |||
566 | 20140618 | ||
567 | - (tim) [openssh/session.c] Work around to get chroot sftp working on UnixWare | ||
568 | |||
569 | 20140617 | ||
570 | - (dtucker) [entropy.c openbsd-compat/openssl-compat.{c,h} | ||
571 | openbsd-compat/regress/{.cvsignore,Makefile.in,opensslvertest.c}] | ||
572 | Move the OpenSSL header/library version test into its own function and add | ||
573 | tests for it. Fix it to allow fix version upgrades (but not downgrades). | ||
574 | Prompted by chl@ via OpenSMTPD (issue #462) and Debian (bug #748150). | ||
575 | ok djm@ chl@ | ||
576 | |||
577 | 20140616 | ||
578 | - (dtucker) [defines.h] Fix undef of _PATH_MAILDIR. From rak at debian via | ||
579 | OpenSMTPD and chl@ | ||
580 | |||
581 | 20140612 | ||
582 | - (dtucker) [configure.ac] Remove tcpwrappers support, support has already | ||
583 | been removed from sshd.c. | ||
584 | |||
585 | 20140611 | ||
586 | - (dtucker) [defines.h] Add va_copy if we don't already have it, taken from | ||
587 | openbsd-compat/bsd-asprintf.c. | ||
588 | - (dtucker) [regress/unittests/sshbuf/*.c regress/unittests/test_helper/*] | ||
589 | Wrap stdlib.h include an ifdef for platforms that don't have it. | ||
590 | - (tim) [regress/unittests/test_helper/test_helper.h] Add includes.h for | ||
591 | u_intXX_t types. | ||
592 | |||
593 | 20140610 | ||
594 | - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c | ||
595 | regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] Only do NISTP256 | ||
596 | curve tests if OpenSSL has them. | ||
597 | - (dtucker) [myprosal.h] Don't include curve25519-sha256@libssh.org in | ||
598 | the proposal if the version of OpenSSL we're using doesn't support ECC. | ||
599 | - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] ifdef | ||
600 | ECC variable too. | ||
601 | - (dtucker) OpenBSD CVS Sync | ||
602 | - djm@cvs.openbsd.org 2014/06/05 22:17:50 | ||
603 | [sshconnect2.c] | ||
604 | fix inverted test that caused PKCS#11 keys that were explicitly listed | ||
605 | not to be preferred. Reported by Dirk-Willem van Gulik | ||
606 | - dtucker@cvs.openbsd.org 2014/06/10 21:46:11 | ||
607 | [sshbuf.h] | ||
608 | Group ECC functions together to make things a little easier in -portable. | ||
609 | "doesn't bother me" deraadt@ | ||
610 | - (dtucker) [sshbuf.h] Only declare ECC functions if building without | ||
611 | OpenSSL or if OpenSSL has ECC. | ||
612 | - (dtucker) [openbsd-compat/arc4random.c] Use explicit_bzero instead of an | ||
613 | assigment that might get optimized out. ok djm@ | ||
614 | - (dtucker) [bufaux.c bufbn.c bufec.c buffer.c] Pull in includes.h for | ||
615 | compat stuff, specifically whether or not OpenSSL has ECC. | ||
616 | |||
617 | 20140527 | ||
618 | - (djm) [cipher.c] Fix merge botch. | ||
619 | - (djm) [contrib/cygwin/ssh-host-config] Updated Cygwin ssh-host-config | ||
620 | from Corinna Vinschen, fixing a number of bugs and preparing for | ||
621 | Cygwin 1.7.30. | ||
622 | - (djm) [configure.ac openbsd-compat/bsd-cygwin_util.c] | ||
623 | [openbsd-compat/bsd-cygwin_util.h] On Cygwin, determine privilege | ||
624 | separation user at runtime, since it may need to be a domain account. | ||
625 | Patch from Corinna Vinschen. | ||
626 | |||
627 | 20140522 | ||
628 | - (djm) [Makefile.in] typo in path | ||
629 | |||
630 | 20140521 | ||
631 | - (djm) [commit configure.ac defines.h sshpty.c] don't attempt to use | ||
632 | vhangup on Linux. It doens't work for non-root users, and for them | ||
633 | it just messes up the tty settings. | ||
634 | - (djm) [misc.c] Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC | ||
635 | when it is available. It takes into account time spent suspended, | ||
636 | thereby ensuring timeouts (e.g. for expiring agent keys) fire | ||
637 | correctly. bz#2228 reported by John Haxby | ||
638 | |||
639 | 20140519 | ||
640 | - (djm) [rijndael.c rijndael.h] Sync with newly-ressurected versions ine | ||
641 | OpenBSD | ||
642 | - OpenBSD CVS Sync | ||
643 | - logan@cvs.openbsd.org 2014/04/20 09:24:26 | ||
644 | [dns.c dns.h ssh-keygen.c] | ||
645 | Add support for SSHFP DNS records for ED25519 key types. | ||
646 | OK from djm@ | ||
647 | - logan@cvs.openbsd.org 2014/04/21 14:36:16 | ||
648 | [sftp-client.c sftp-client.h sftp.c] | ||
649 | Implement sftp upload resume support. | ||
650 | OK from djm@, with input from guenther@, mlarkin@ and | ||
651 | okan@ | ||
652 | - logan@cvs.openbsd.org 2014/04/22 10:07:12 | ||
653 | [sftp.c] | ||
654 | Sort the sftp command list. | ||
655 | OK from djm@ | ||
656 | - logan@cvs.openbsd.org 2014/04/22 12:42:04 | ||
657 | [sftp.1] | ||
658 | Document sftp upload resume. | ||
659 | OK from djm@, with feedback from okan@. | ||
660 | - jmc@cvs.openbsd.org 2014/04/22 14:16:30 | ||
661 | [sftp.1] | ||
662 | zap eol whitespace; | ||
663 | - djm@cvs.openbsd.org 2014/04/23 12:42:34 | ||
664 | [readconf.c] | ||
665 | don't record duplicate IdentityFiles | ||
666 | - djm@cvs.openbsd.org 2014/04/28 03:09:18 | ||
667 | [authfile.c bufaux.c buffer.h channels.c krl.c mux.c packet.c packet.h] | ||
668 | [ssh-keygen.c] | ||
669 | buffer_get_string_ptr's return should be const to remind | ||
670 | callers that futzing with it will futz with the actual buffer | ||
671 | contents | ||
672 | - djm@cvs.openbsd.org 2014/04/29 13:10:30 | ||
673 | [clientloop.c serverloop.c] | ||
674 | bz#1818 - don't send channel success/failre replies on channels that | ||
675 | have sent a close already; analysis and patch from Simon Tatham; | ||
676 | ok markus@ | ||
677 | - markus@cvs.openbsd.org 2014/04/29 18:01:49 | ||
678 | [auth.c authfd.c authfile.c bufaux.c cipher.c cipher.h hostfile.c] | ||
679 | [kex.c key.c mac.c monitor.c monitor_wrap.c myproposal.h packet.c] | ||
680 | [roaming_client.c ssh-agent.c ssh-keygen.c ssh-keyscan.c ssh-keysign.c] | ||
681 | [ssh-pkcs11.h ssh.c sshconnect.c sshconnect2.c sshd.c] | ||
682 | make compiling against OpenSSL optional (make OPENSSL=no); | ||
683 | reduces algorithms to curve25519, aes-ctr, chacha, ed25519; | ||
684 | allows us to explore further options; with and ok djm | ||
685 | - dtucker@cvs.openbsd.org 2014/04/29 19:58:50 | ||
686 | [sftp.c] | ||
687 | Move nulling of variable next to where it's freed. ok markus@ | ||
688 | - dtucker@cvs.openbsd.org 2014/04/29 20:36:51 | ||
689 | [sftp.c] | ||
690 | Don't attempt to append a nul quote char to the filename. Should prevent | ||
691 | fatal'ing with "el_insertstr failed" when there's a single quote char | ||
692 | somewhere in the string. bz#2238, ok markus@ | ||
693 | - djm@cvs.openbsd.org 2014/04/30 05:29:56 | ||
694 | [bufaux.c bufbn.c bufec.c buffer.c buffer.h sshbuf-getput-basic.c] | ||
695 | [sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c sshbuf.h ssherr.c] | ||
696 | [ssherr.h] | ||
697 | New buffer API; the first installment of the conversion/replacement | ||
698 | of OpenSSH's internals to make them usable as a standalone library. | ||
699 | |||
700 | This includes a set of wrappers to make it compatible with the | ||
701 | existing buffer API so replacement can occur incrementally. | ||
702 | |||
703 | With and ok markus@ | ||
704 | |||
705 | Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew | ||
706 | Dempsky and Ron Bowes for a detailed review. | ||
707 | - naddy@cvs.openbsd.org 2014/04/30 19:07:48 | ||
708 | [mac.c myproposal.h umac.c] | ||
709 | UMAC can use our local fallback implementation of AES when OpenSSL isn't | ||
710 | available. Glue code straight from Ted Krovetz's original umac.c. | ||
711 | ok markus@ | ||
712 | - djm@cvs.openbsd.org 2014/05/02 03:27:54 | ||
713 | [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c] | ||
714 | [misc.h poly1305.h ssh-pkcs11.c defines.h] | ||
715 | revert __bounded change; it causes way more problems for portable than | ||
716 | it solves; pointed out by dtucker@ | ||
717 | - markus@cvs.openbsd.org 2014/05/03 17:20:34 | ||
718 | [monitor.c packet.c packet.h] | ||
719 | unbreak compression, by re-init-ing the compression code in the | ||
720 | post-auth child. the new buffer code is more strict, and requires | ||
721 | buffer_init() while the old code was happy after a bzero(); | ||
722 | originally from djm@ | ||
723 | - logan@cvs.openbsd.org 2014/05/05 07:02:30 | ||
724 | [sftp.c] | ||
725 | Zap extra whitespace. | ||
726 | |||
727 | OK from djm@ and dtucker@ | ||
728 | - (djm) [configure.ac] Unconditionally define WITH_OPENSSL until we write | ||
729 | portability glue to support building without libcrypto | ||
730 | - (djm) [Makefile.in configure.ac sshbuf-getput-basic.c] | ||
731 | [sshbuf-getput-crypto.c sshbuf.c] compilation and portability fixes | ||
732 | - OpenBSD CVS Sync | ||
733 | - djm@cvs.openbsd.org 2014/03/13 20:44:49 | ||
734 | [login-timeout.sh] | ||
735 | this test is a sorry mess of race conditions; add another sleep | ||
736 | to avoid a failure on slow machines (at least until I find a | ||
737 | better way) | ||
738 | - djm@cvs.openbsd.org 2014/04/21 22:15:37 | ||
739 | [dhgex.sh integrity.sh kextype.sh rekey.sh try-ciphers.sh] | ||
740 | repair regress tests broken by server-side default cipher/kex/mac changes | ||
741 | by ensuring that the option under test is included in the server's | ||
742 | algorithm list | ||
743 | - dtucker@cvs.openbsd.org 2014/05/03 18:46:14 | ||
744 | [proxy-connect.sh] | ||
745 | Add tests for with and without compression, with and without privsep. | ||
746 | - logan@cvs.openbsd.org 2014/05/04 10:40:59 | ||
747 | [connect-privsep.sh] | ||
748 | Remove the Z flag from the list of malloc options as it | ||
749 | was removed from malloc.c 10 days ago. | ||
750 | |||
751 | OK from miod@ | ||
752 | - (djm) [regress/unittests/Makefile] | ||
753 | [regress/unittests/Makefile.inc] | ||
754 | [regress/unittests/sshbuf/Makefile] | ||
755 | [regress/unittests/sshbuf/test_sshbuf.c] | ||
756 | [regress/unittests/sshbuf/test_sshbuf_fixed.c] | ||
757 | [regress/unittests/sshbuf/test_sshbuf_fuzz.c] | ||
758 | [regress/unittests/sshbuf/test_sshbuf_getput_basic.c] | ||
759 | [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c] | ||
760 | [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] | ||
761 | [regress/unittests/sshbuf/test_sshbuf_misc.c] | ||
762 | [regress/unittests/sshbuf/tests.c] | ||
763 | [regress/unittests/test_helper/Makefile] | ||
764 | [regress/unittests/test_helper/fuzz.c] | ||
765 | [regress/unittests/test_helper/test_helper.c] | ||
766 | [regress/unittests/test_helper/test_helper.h] | ||
767 | Import new unit tests from OpenBSD; not yet hooked up to build. | ||
768 | - (djm) [regress/Makefile Makefile.in] | ||
769 | [regress/unittests/sshbuf/test_sshbuf.c | ||
770 | [regress/unittests/sshbuf/test_sshbuf_fixed.c] | ||
771 | [regress/unittests/sshbuf/test_sshbuf_fuzz.c] | ||
772 | [regress/unittests/sshbuf/test_sshbuf_getput_basic.c] | ||
773 | [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c] | ||
774 | [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] | ||
775 | [regress/unittests/sshbuf/test_sshbuf_misc.c] | ||
776 | [regress/unittests/sshbuf/tests.c] | ||
777 | [regress/unittests/test_helper/fuzz.c] | ||
778 | [regress/unittests/test_helper/test_helper.c] | ||
779 | Hook new unit tests into the build and "make tests" | ||
780 | - (djm) [sshbuf.c] need __predict_false | ||
781 | |||
782 | 20140430 | ||
783 | - (dtucker) [defines.h] Define __GNUC_PREREQ__ macro if we don't already | ||
784 | have it. Only attempt to use __attribute__(__bounded__) for gcc. | ||
785 | |||
786 | 20140420 | ||
787 | - OpenBSD CVS Sync | ||
788 | - djm@cvs.openbsd.org 2014/03/03 22:22:30 | ||
789 | [session.c] | ||
790 | ignore enviornment variables with embedded '=' or '\0' characters; | ||
791 | spotted by Jann Horn; ok deraadt@ | ||
792 | Id sync only - portable already has this. | ||
793 | - djm@cvs.openbsd.org 2014/03/12 04:44:58 | ||
794 | [ssh-keyscan.c] | ||
795 | scan for Ed25519 keys by default too | ||
796 | - djm@cvs.openbsd.org 2014/03/12 04:50:32 | ||
797 | [auth-bsdauth.c ssh-keygen.c] | ||
798 | don't count on things that accept arguments by reference to clear | ||
799 | things for us on error; most things do, but it's unsafe form. | ||
800 | - djm@cvs.openbsd.org 2014/03/12 04:51:12 | ||
801 | [authfile.c] | ||
802 | correct test that kdf name is not "none" or "bcrypt" | ||
803 | - naddy@cvs.openbsd.org 2014/03/12 13:06:59 | ||
804 | [ssh-keyscan.1] | ||
805 | scan for Ed25519 keys by default too | ||
806 | - deraadt@cvs.openbsd.org 2014/03/15 17:28:26 | ||
807 | [ssh-agent.c ssh-keygen.1 ssh-keygen.c] | ||
808 | Improve usage() and documentation towards the standard form. | ||
809 | In particular, this line saves a lot of man page reading time. | ||
810 | usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] | ||
811 | [-N new_passphrase] [-C comment] [-f output_keyfile] | ||
812 | ok schwarze jmc | ||
813 | - tedu@cvs.openbsd.org 2014/03/17 19:44:10 | ||
814 | [ssh.1] | ||
815 | old descriptions of des and blowfish are old. maybe ok deraadt | ||
816 | - tedu@cvs.openbsd.org 2014/03/19 14:42:44 | ||
817 | [scp.1] | ||
818 | there is no need for rcp anymore | ||
819 | ok deraadt millert | ||
820 | - markus@cvs.openbsd.org 2014/03/25 09:40:03 | ||
821 | [myproposal.h] | ||
822 | trimm default proposals. | ||
823 | |||
824 | This commit removes the weaker pre-SHA2 hashes, the broken ciphers | ||
825 | (arcfour), and the broken modes (CBC) from the default configuration | ||
826 | (the patch only changes the default, all the modes are still available | ||
827 | for the config files). | ||
828 | |||
829 | ok djm@, reminded by tedu@ & naddy@ and discussed with many | ||
830 | - deraadt@cvs.openbsd.org 2014/03/26 17:16:26 | ||
831 | [myproposal.h] | ||
832 | The current sharing of myproposal[] between both client and server code | ||
833 | makes the previous diff highly unpallatable. We want to go in that | ||
834 | direction for the server, but not for the client. Sigh. | ||
835 | Brought up by naddy. | ||
836 | - markus@cvs.openbsd.org 2014/03/27 23:01:27 | ||
837 | [myproposal.h ssh-keyscan.c sshconnect2.c sshd.c] | ||
838 | disable weak proposals in sshd, but keep them in ssh; ok djm@ | ||
839 | - djm@cvs.openbsd.org 2014/03/26 04:55:35 | ||
840 | [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c | ||
841 | [misc.h poly1305.h ssh-pkcs11.c] | ||
842 | use __bounded(...) attribute recently added to sys/cdefs.h instead of | ||
843 | longform __attribute__(__bounded(...)); | ||
844 | |||
845 | for brevity and a warning free compilation with llvm/clang | ||
846 | - tedu@cvs.openbsd.org 2014/03/26 19:58:37 | ||
847 | [sshd.8 sshd.c] | ||
848 | remove libwrap support. ok deraadt djm mfriedl | ||
849 | - naddy@cvs.openbsd.org 2014/03/28 05:17:11 | ||
850 | [ssh_config.5 sshd_config.5] | ||
851 | sync available and default algorithms, improve algorithm list formatting | ||
852 | help from jmc@ and schwarze@, ok deraadt@ | ||
853 | - jmc@cvs.openbsd.org 2014/03/31 13:39:34 | ||
854 | [ssh-keygen.1] | ||
855 | the text for the -K option was inserted in the wrong place in -r1.108; | ||
856 | fix From: Matthew Clarke | ||
857 | - djm@cvs.openbsd.org 2014/04/01 02:05:27 | ||
858 | [ssh-keysign.c] | ||
859 | include fingerprint of key not found | ||
860 | use arc4random_buf() instead of loop+arc4random() | ||
861 | - djm@cvs.openbsd.org 2014/04/01 03:34:10 | ||
862 | [sshconnect.c] | ||
863 | When using VerifyHostKeyDNS with a DNSSEC resolver, down-convert any | ||
864 | certificate keys to plain keys and attempt SSHFP resolution. | ||
865 | |||
866 | Prevents a server from skipping SSHFP lookup and forcing a new-hostkey | ||
867 | dialog by offering only certificate keys. | ||
868 | |||
869 | Reported by mcv21 AT cam.ac.uk | ||
870 | - djm@cvs.openbsd.org 2014/04/01 05:32:57 | ||
871 | [packet.c] | ||
872 | demote a debug3 to PACKET_DEBUG; ok markus@ | ||
873 | - djm@cvs.openbsd.org 2014/04/12 04:55:53 | ||
874 | [sshd.c] | ||
875 | avoid crash at exit: check that pmonitor!=NULL before dereferencing; | ||
876 | bz#2225, patch from kavi AT juniper.net | ||
877 | - djm@cvs.openbsd.org 2014/04/16 23:22:45 | ||
878 | [bufaux.c] | ||
879 | skip leading zero bytes in buffer_put_bignum2_from_string(); | ||
880 | reported by jan AT mojzis.com; ok markus@ | ||
881 | - djm@cvs.openbsd.org 2014/04/16 23:28:12 | ||
882 | [ssh-agent.1] | ||
883 | remove the identity files from this manpage - ssh-agent doesn't deal | ||
884 | with them at all and the same information is duplicated in ssh-add.1 | ||
885 | (which does deal with them); prodded by deraadt@ | ||
886 | - djm@cvs.openbsd.org 2014/04/18 23:52:25 | ||
887 | [compat.c compat.h sshconnect2.c sshd.c version.h] | ||
888 | OpenSSH 6.5 and 6.6 have a bug that causes ~0.2% of connections | ||
889 | using the curve25519-sha256@libssh.org KEX exchange method to fail | ||
890 | when connecting with something that implements the spec properly. | ||
891 | |||
892 | Disable this KEX method when speaking to one of the affected | ||
893 | versions. | ||
894 | |||
895 | reported by Aris Adamantiadis; ok markus@ | ||
896 | - djm@cvs.openbsd.org 2014/04/19 05:54:59 | ||
897 | [compat.c] | ||
898 | missing wildcard; pointed out by naddy@ | ||
899 | - tedu@cvs.openbsd.org 2014/04/19 14:53:48 | ||
900 | [ssh-keysign.c sshd.c] | ||
901 | Delete futile calls to RAND_seed. ok djm | ||
902 | NB. Id sync only. This only applies to OpenBSD's libcrypto slashathon | ||
903 | - tedu@cvs.openbsd.org 2014/04/19 18:15:16 | ||
904 | [sshd.8] | ||
905 | remove some really old rsh references | ||
906 | - tedu@cvs.openbsd.org 2014/04/19 18:42:19 | ||
907 | [ssh.1] | ||
908 | delete .xr to hosts.equiv. there's still an unfortunate amount of | ||
909 | documentation referring to rhosts equivalency in here. | ||
910 | - djm@cvs.openbsd.org 2014/04/20 02:30:25 | ||
911 | [misc.c misc.h umac.c] | ||
912 | use get/put_u32 to load values rather than *((UINT32 *)p) that breaks on | ||
913 | strict-alignment architectures; reported by and ok stsp@ | ||
914 | - djm@cvs.openbsd.org 2014/04/20 02:49:32 | ||
915 | [compat.c] | ||
916 | add a canonical 6.6 + curve25519 bignum fix fake version that I can | ||
917 | recommend people use ahead of the openssh-6.7 release | ||
918 | |||
919 | 20140401 | ||
920 | - (djm) On platforms that support it, use prctl() to prevent sftp-server | ||
921 | from accessing /proc/self/{mem,maps}; patch from jann AT thejh.net | ||
922 | - (djm) Use full release (e.g. 6.5p1) in debug output rather than just | ||
923 | version. From des@des.no | ||
924 | |||
925 | 20140317 | ||
926 | - (djm) [sandbox-seccomp-filter.c] Soft-fail stat() syscalls. Add XXX to | ||
927 | remind myself to add sandbox violation logging via the log socket. | ||
928 | |||
929 | 20140314 | ||
930 | - (tim) [opensshd.init.in] Add support for ed25519 | ||
931 | |||
1 | 20140313 | 932 | 20140313 |
2 | - (djm) Release OpenSSH 6.6 | 933 | - (djm) Release OpenSSH 6.6 |
3 | 934 | ||
@@ -2884,4 +3815,3 @@ | |||
2884 | [contrib/suse/openssh.spec] Update for release 6.0 | 3815 | [contrib/suse/openssh.spec] Update for release 6.0 |
2885 | - (djm) [README] Update URL to release notes. | 3816 | - (djm) [README] Update URL to release notes. |
2886 | - (djm) Release openssh-6.0 | 3817 | - (djm) Release openssh-6.0 |
2887 | |||
@@ -1,22 +1,26 @@ | |||
1 | 1. Prerequisites | 1 | 1. Prerequisites |
2 | ---------------- | 2 | ---------------- |
3 | 3 | ||
4 | You will need working installations of Zlib and OpenSSL. | 4 | You will need working installations of Zlib and libcrypto (LibreSSL / |
5 | OpenSSL) | ||
5 | 6 | ||
6 | Zlib 1.1.4 or 1.2.1.2 or greater (ealier 1.2.x versions have problems): | 7 | Zlib 1.1.4 or 1.2.1.2 or greater (ealier 1.2.x versions have problems): |
7 | http://www.gzip.org/zlib/ | 8 | http://www.gzip.org/zlib/ |
8 | 9 | ||
9 | OpenSSL 0.9.6 or greater: | 10 | libcrypto (LibreSSL or OpenSSL >= 0.9.8f) |
10 | http://www.openssl.org/ | 11 | LibreSSL http://www.libressl.org/ ; or |
12 | OpenSSL http://www.openssl.org/ | ||
11 | 13 | ||
12 | (OpenSSL 0.9.5a is partially supported, but some ciphers (SSH protocol 1 | 14 | LibreSSL/OpenSSL should be compiled as a position-independent library |
13 | Blowfish) do not work correctly.) | 15 | (i.e. with -fPIC) otherwise OpenSSH will not be able to link with it. |
16 | If you must use a non-position-independent libcrypto, then you may need | ||
17 | to configure OpenSSH --without-pie. | ||
14 | 18 | ||
15 | The remaining items are optional. | 19 | The remaining items are optional. |
16 | 20 | ||
17 | NB. If you operating system supports /dev/random, you should configure | 21 | NB. If you operating system supports /dev/random, you should configure |
18 | OpenSSL to use it. OpenSSH relies on OpenSSL's direct support of | 22 | libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's |
19 | /dev/random, or failing that, either prngd or egd | 23 | direct support of /dev/random, or failing that, either prngd or egd |
20 | 24 | ||
21 | PRNGD: | 25 | PRNGD: |
22 | 26 | ||
@@ -27,10 +31,10 @@ http://prngd.sourceforge.net/ | |||
27 | 31 | ||
28 | EGD: | 32 | EGD: |
29 | 33 | ||
30 | The Entropy Gathering Daemon (EGD) is supported if you have a system which | 34 | If the kernel lacks /dev/random the Entropy Gathering Daemon (EGD) is |
31 | lacks /dev/random and don't want to use OpenSSH's internal entropy collection. | 35 | supported only if libcrypto supports it. |
32 | 36 | ||
33 | http://www.lothar.com/tech/crypto/ | 37 | http://egd.sourceforge.net/ |
34 | 38 | ||
35 | PAM: | 39 | PAM: |
36 | 40 | ||
@@ -55,15 +59,6 @@ passphrase requester. This is maintained separately at: | |||
55 | 59 | ||
56 | http://www.jmknoble.net/software/x11-ssh-askpass/ | 60 | http://www.jmknoble.net/software/x11-ssh-askpass/ |
57 | 61 | ||
58 | TCP Wrappers: | ||
59 | |||
60 | If you wish to use the TCP wrappers functionality you will need at least | ||
61 | tcpd.h and libwrap.a, either in the standard include and library paths, | ||
62 | or in the directory specified by --with-tcp-wrappers. Version 7.6 is | ||
63 | known to work. | ||
64 | |||
65 | http://ftp.porcupine.org/pub/security/index.html | ||
66 | |||
67 | S/Key Libraries: | 62 | S/Key Libraries: |
68 | 63 | ||
69 | If you wish to use --with-skey then you will need the library below | 64 | If you wish to use --with-skey then you will need the library below |
@@ -180,9 +175,6 @@ Integration Architecture. The default for OSF1 machines is enable. | |||
180 | --with-skey=PATH will enable S/Key one time password support. You will | 175 | --with-skey=PATH will enable S/Key one time password support. You will |
181 | need the S/Key libraries and header files installed for this to work. | 176 | need the S/Key libraries and header files installed for this to work. |
182 | 177 | ||
183 | --with-tcp-wrappers will enable TCP Wrappers (/etc/hosts.allow|deny) | ||
184 | support. | ||
185 | |||
186 | --with-md5-passwords will enable the use of MD5 passwords. Enable this | 178 | --with-md5-passwords will enable the use of MD5 passwords. Enable this |
187 | if your operating system uses MD5 passwords and the system crypt() does | 179 | if your operating system uses MD5 passwords and the system crypt() does |
188 | not support them directly (see the crypt(3/3c) man page). If enabled, the | 180 | not support them directly (see the crypt(3/3c) man page). If enabled, the |
@@ -204,10 +196,11 @@ created. | |||
204 | 196 | ||
205 | --with-xauth=PATH specifies the location of the xauth binary | 197 | --with-xauth=PATH specifies the location of the xauth binary |
206 | 198 | ||
207 | --with-ssl-dir=DIR allows you to specify where your OpenSSL libraries | 199 | --with-ssl-dir=DIR allows you to specify where your Libre/OpenSSL |
200 | libraries | ||
208 | are installed. | 201 | are installed. |
209 | 202 | ||
210 | --with-ssl-engine enables OpenSSL's (hardware) ENGINE support | 203 | --with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support |
211 | 204 | ||
212 | --with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to | 205 | --with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to |
213 | real (AF_INET) IPv4 addresses. Works around some quirks on Linux. | 206 | real (AF_INET) IPv4 addresses. Works around some quirks on Linux. |
@@ -266,4 +259,4 @@ Please refer to the "reporting bugs" section of the webpage at | |||
266 | http://www.openssh.com/ | 259 | http://www.openssh.com/ |
267 | 260 | ||
268 | 261 | ||
269 | $Id: INSTALL,v 1.88 2013/03/07 01:33:35 dtucker Exp $ | 262 | $Id: INSTALL,v 1.91 2014/09/09 02:23:11 dtucker Exp $ |
diff --git a/Makefile.in b/Makefile.in index 7d192bb7c..4eab574a7 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile.in,v 1.356 2014/02/04 00:12:56 djm Exp $ | 1 | # $Id: Makefile.in,v 1.365 2014/08/30 06:23:07 djm Exp $ |
2 | 2 | ||
3 | # uncomment if you run a non bourne compatable shell. Ie. csh | 3 | # uncomment if you run a non bourne compatable shell. Ie. csh |
4 | #SHELL = @SH@ | 4 | #SHELL = @SH@ |
@@ -29,6 +29,7 @@ SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper | |||
29 | PRIVSEP_PATH=@PRIVSEP_PATH@ | 29 | PRIVSEP_PATH=@PRIVSEP_PATH@ |
30 | SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ | 30 | SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ |
31 | STRIP_OPT=@STRIP_OPT@ | 31 | STRIP_OPT=@STRIP_OPT@ |
32 | TEST_SHELL=@TEST_SHELL@ | ||
32 | 33 | ||
33 | PATHS= -DSSHDIR=\"$(sysconfdir)\" \ | 34 | PATHS= -DSSHDIR=\"$(sysconfdir)\" \ |
34 | -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ | 35 | -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ |
@@ -63,7 +64,16 @@ MANFMT=@MANFMT@ | |||
63 | 64 | ||
64 | TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) | 65 | TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) |
65 | 66 | ||
66 | LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ | 67 | LIBOPENSSH_OBJS=\ |
68 | ssherr.o \ | ||
69 | sshbuf.o \ | ||
70 | sshkey.o \ | ||
71 | sshbuf-getput-basic.o \ | ||
72 | sshbuf-misc.o \ | ||
73 | sshbuf-getput-crypto.o | ||
74 | |||
75 | LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ | ||
76 | authfd.o authfile.o bufaux.o bufbn.o buffer.o \ | ||
67 | canohost.o channels.o cipher.o cipher-aes.o \ | 77 | canohost.o channels.o cipher.o cipher-aes.o \ |
68 | cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ | 78 | cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ |
69 | compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \ | 79 | compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \ |
@@ -137,7 +147,7 @@ $(SSHOBJS): Makefile.in config.h | |||
137 | $(SSHDOBJS): Makefile.in config.h | 147 | $(SSHDOBJS): Makefile.in config.h |
138 | 148 | ||
139 | .c.o: | 149 | .c.o: |
140 | $(CC) $(CFLAGS) $(CPPFLAGS) -c $< | 150 | $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ |
141 | 151 | ||
142 | LIBCOMPAT=openbsd-compat/libopenbsd-compat.a | 152 | LIBCOMPAT=openbsd-compat/libopenbsd-compat.a |
143 | $(LIBCOMPAT): always | 153 | $(LIBCOMPAT): always |
@@ -216,6 +226,12 @@ umac128.o: umac.c | |||
216 | clean: regressclean | 226 | clean: regressclean |
217 | rm -f *.o *.a $(TARGETS) logintest config.cache config.log | 227 | rm -f *.o *.a $(TARGETS) logintest config.cache config.log |
218 | rm -f *.out core survey | 228 | rm -f *.out core survey |
229 | rm -f regress/unittests/test_helper/*.a | ||
230 | rm -f regress/unittests/test_helper/*.o | ||
231 | rm -f regress/unittests/sshbuf/*.o | ||
232 | rm -f regress/unittests/sshbuf/test_sshbuf | ||
233 | rm -f regress/unittests/sshkey/*.o | ||
234 | rm -f regress/unittests/sshkey/test_sshkey | ||
219 | (cd openbsd-compat && $(MAKE) clean) | 235 | (cd openbsd-compat && $(MAKE) clean) |
220 | 236 | ||
221 | distclean: regressclean | 237 | distclean: regressclean |
@@ -224,6 +240,12 @@ distclean: regressclean | |||
224 | rm -f Makefile buildpkg.sh config.h config.status | 240 | rm -f Makefile buildpkg.sh config.h config.status |
225 | rm -f survey.sh openbsd-compat/regress/Makefile *~ | 241 | rm -f survey.sh openbsd-compat/regress/Makefile *~ |
226 | rm -rf autom4te.cache | 242 | rm -rf autom4te.cache |
243 | rm -f regress/unittests/test_helper/*.a | ||
244 | rm -f regress/unittests/test_helper/*.o | ||
245 | rm -f regress/unittests/sshbuf/*.o | ||
246 | rm -f regress/unittests/sshbuf/test_sshbuf | ||
247 | rm -f regress/unittests/sshkey/*.o | ||
248 | rm -f regress/unittests/sshkey/test_sshkey | ||
227 | (cd openbsd-compat && $(MAKE) distclean) | 249 | (cd openbsd-compat && $(MAKE) distclean) |
228 | if test -d pkg ; then \ | 250 | if test -d pkg ; then \ |
229 | rm -fr pkg ; \ | 251 | rm -fr pkg ; \ |
@@ -397,23 +419,71 @@ uninstall: | |||
397 | -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 | 419 | -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 |
398 | -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 | 420 | -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 |
399 | 421 | ||
400 | regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c | 422 | regress-prep: |
401 | [ -d `pwd`/regress ] || mkdir -p `pwd`/regress | 423 | [ -d `pwd`/regress ] || mkdir -p `pwd`/regress |
424 | [ -d `pwd`/regress/unittests ] || mkdir -p `pwd`/regress/unittests | ||
425 | [ -d `pwd`/regress/unittests/test_helper ] || \ | ||
426 | mkdir -p `pwd`/regress/unittests/test_helper | ||
427 | [ -d `pwd`/regress/unittests/sshbuf ] || \ | ||
428 | mkdir -p `pwd`/regress/unittests/sshbuf | ||
429 | [ -d `pwd`/regress/unittests/sshkey ] || \ | ||
430 | mkdir -p `pwd`/regress/unittests/sshkey | ||
402 | [ -f `pwd`/regress/Makefile ] || \ | 431 | [ -f `pwd`/regress/Makefile ] || \ |
403 | ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile | 432 | ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile |
433 | |||
434 | regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c | ||
404 | $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ | 435 | $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ |
405 | $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) | 436 | $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) |
406 | 437 | ||
407 | regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c | 438 | regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c |
408 | [ -d `pwd`/regress ] || mkdir -p `pwd`/regress | ||
409 | [ -f `pwd`/regress/Makefile ] || \ | ||
410 | ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile | ||
411 | $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ | 439 | $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ |
412 | $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) | 440 | $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) |
413 | 441 | ||
414 | tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$(EXEEXT) | 442 | UNITTESTS_TEST_HELPER_OBJS=\ |
443 | regress/unittests/test_helper/test_helper.o \ | ||
444 | regress/unittests/test_helper/fuzz.o | ||
445 | |||
446 | regress/unittests/test_helper/libtest_helper.a: ${UNITTESTS_TEST_HELPER_OBJS} | ||
447 | $(AR) rv $@ $(UNITTESTS_TEST_HELPER_OBJS) | ||
448 | $(RANLIB) $@ | ||
449 | |||
450 | UNITTESTS_TEST_SSHBUF_OBJS=\ | ||
451 | regress/unittests/sshbuf/tests.o \ | ||
452 | regress/unittests/sshbuf/test_sshbuf.o \ | ||
453 | regress/unittests/sshbuf/test_sshbuf_getput_basic.o \ | ||
454 | regress/unittests/sshbuf/test_sshbuf_getput_crypto.o \ | ||
455 | regress/unittests/sshbuf/test_sshbuf_misc.o \ | ||
456 | regress/unittests/sshbuf/test_sshbuf_fuzz.o \ | ||
457 | regress/unittests/sshbuf/test_sshbuf_getput_fuzz.o \ | ||
458 | regress/unittests/sshbuf/test_sshbuf_fixed.o | ||
459 | |||
460 | regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \ | ||
461 | regress/unittests/test_helper/libtest_helper.a libssh.a | ||
462 | $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHBUF_OBJS) \ | ||
463 | regress/unittests/test_helper/libtest_helper.a \ | ||
464 | -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) | ||
465 | |||
466 | UNITTESTS_TEST_SSHKEY_OBJS=\ | ||
467 | regress/unittests/sshkey/test_fuzz.o \ | ||
468 | regress/unittests/sshkey/tests.o \ | ||
469 | regress/unittests/sshkey/common.o \ | ||
470 | regress/unittests/sshkey/test_file.o \ | ||
471 | regress/unittests/sshkey/test_sshkey.o | ||
472 | |||
473 | regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ | ||
474 | regress/unittests/test_helper/libtest_helper.a libssh.a | ||
475 | $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHKEY_OBJS) \ | ||
476 | regress/unittests/test_helper/libtest_helper.a \ | ||
477 | -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) | ||
478 | |||
479 | REGRESS_BINARIES=\ | ||
480 | regress/modpipe$(EXEEXT) \ | ||
481 | regress/setuid-allowed$(EXEEXT) \ | ||
482 | regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ | ||
483 | regress/unittests/sshkey/test_sshkey$(EXEEXT) | ||
484 | |||
485 | tests interop-tests t-exec: regress-prep $(TARGETS) $(REGRESS_BINARIES) | ||
415 | BUILDDIR=`pwd`; \ | 486 | BUILDDIR=`pwd`; \ |
416 | TEST_SHELL="@TEST_SHELL@"; \ | ||
417 | TEST_SSH_SCP="$${BUILDDIR}/scp"; \ | 487 | TEST_SSH_SCP="$${BUILDDIR}/scp"; \ |
418 | TEST_SSH_SSH="$${BUILDDIR}/ssh"; \ | 488 | TEST_SSH_SSH="$${BUILDDIR}/ssh"; \ |
419 | TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \ | 489 | TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \ |
@@ -437,7 +507,6 @@ tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$ | |||
437 | OBJ="$${BUILDDIR}/regress/" \ | 507 | OBJ="$${BUILDDIR}/regress/" \ |
438 | PATH="$${BUILDDIR}:$${PATH}" \ | 508 | PATH="$${BUILDDIR}:$${PATH}" \ |
439 | TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ | 509 | TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ |
440 | TEST_SHELL="$${TEST_SHELL}" \ | ||
441 | TEST_SSH_SCP="$${TEST_SSH_SCP}" \ | 510 | TEST_SSH_SCP="$${TEST_SSH_SCP}" \ |
442 | TEST_SSH_SSH="$${TEST_SSH_SSH}" \ | 511 | TEST_SSH_SSH="$${TEST_SSH_SSH}" \ |
443 | TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \ | 512 | TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \ |
@@ -453,6 +522,7 @@ tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$ | |||
453 | TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \ | 522 | TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \ |
454 | TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \ | 523 | TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \ |
455 | TEST_SSH_ECC="$${TEST_SSH_ECC}" \ | 524 | TEST_SSH_ECC="$${TEST_SSH_ECC}" \ |
525 | TEST_SHELL="${TEST_SHELL}" \ | ||
456 | EXEEXT="$(EXEEXT)" \ | 526 | EXEEXT="$(EXEEXT)" \ |
457 | $@ && echo all tests passed | 527 | $@ && echo all tests passed |
458 | 528 | ||
@@ -232,6 +232,56 @@ The contents of the "data" field for layer 2 packets is: | |||
232 | The "frame" field contains an IEEE 802.3 Ethernet frame, including | 232 | The "frame" field contains an IEEE 802.3 Ethernet frame, including |
233 | header. | 233 | header. |
234 | 234 | ||
235 | 2.4. connection: Unix domain socket forwarding | ||
236 | |||
237 | OpenSSH supports local and remote Unix domain socket forwarding | ||
238 | using the "streamlocal" extension. Forwarding is initiated as per | ||
239 | TCP sockets but with a single path instead of a host and port. | ||
240 | |||
241 | Similar to direct-tcpip, direct-streamlocal is sent by the client | ||
242 | to request that the server make a connection to a Unix domain socket. | ||
243 | |||
244 | byte SSH_MSG_CHANNEL_OPEN | ||
245 | string "direct-streamlocal@openssh.com" | ||
246 | uint32 sender channel | ||
247 | uint32 initial window size | ||
248 | uint32 maximum packet size | ||
249 | string socket path | ||
250 | string reserved for future use | ||
251 | |||
252 | Similar to forwarded-tcpip, forwarded-streamlocal is sent by the | ||
253 | server when the client has previously send the server a streamlocal-forward | ||
254 | GLOBAL_REQUEST. | ||
255 | |||
256 | byte SSH_MSG_CHANNEL_OPEN | ||
257 | string "forwarded-streamlocal@openssh.com" | ||
258 | uint32 sender channel | ||
259 | uint32 initial window size | ||
260 | uint32 maximum packet size | ||
261 | string socket path | ||
262 | string reserved for future use | ||
263 | |||
264 | The reserved field is not currently defined and is ignored on the | ||
265 | remote end. It is intended to be used in the future to pass | ||
266 | information about the socket file, such as ownership and mode. | ||
267 | The client currently sends the empty string for this field. | ||
268 | |||
269 | Similar to tcpip-forward, streamlocal-forward is sent by the client | ||
270 | to request remote forwarding of a Unix domain socket. | ||
271 | |||
272 | byte SSH2_MSG_GLOBAL_REQUEST | ||
273 | string "streamlocal-forward@openssh.com" | ||
274 | boolean TRUE | ||
275 | string socket path | ||
276 | |||
277 | Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent | ||
278 | by the client cancel the forwarding of a Unix domain socket. | ||
279 | |||
280 | byte SSH2_MSG_GLOBAL_REQUEST | ||
281 | string "cancel-streamlocal-forward@openssh.com" | ||
282 | boolean FALSE | ||
283 | string socket path | ||
284 | |||
235 | 3. SFTP protocol changes | 285 | 3. SFTP protocol changes |
236 | 286 | ||
237 | 3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK | 287 | 3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK |
@@ -356,4 +406,4 @@ respond with a SSH_FXP_STATUS message. | |||
356 | This extension is advertised in the SSH_FXP_VERSION hello with version | 406 | This extension is advertised in the SSH_FXP_VERSION hello with version |
357 | "1". | 407 | "1". |
358 | 408 | ||
359 | $OpenBSD: PROTOCOL,v 1.23 2013/12/01 23:19:05 djm Exp $ | 409 | $OpenBSD: PROTOCOL,v 1.24 2014/07/15 15:54:14 millert Exp $ |
@@ -1,4 +1,4 @@ | |||
1 | See http://www.openssh.com/txt/release-6.6 for the release notes. | 1 | See http://www.openssh.com/txt/release-6.7 for the release notes. |
2 | 2 | ||
3 | - A Japanese translation of this document and of the OpenSSH FAQ is | 3 | - A Japanese translation of this document and of the OpenSSH FAQ is |
4 | - available at http://www.unixuser.org/~haruyama/security/openssh/index.html | 4 | - available at http://www.unixuser.org/~haruyama/security/openssh/index.html |
@@ -62,4 +62,4 @@ References - | |||
62 | [6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9 | 62 | [6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9 |
63 | [7] http://www.openssh.com/faq.html | 63 | [7] http://www.openssh.com/faq.html |
64 | 64 | ||
65 | $Id: README,v 1.86 2014/02/27 23:03:53 djm Exp $ | 65 | $Id: README,v 1.87 2014/08/10 01:35:06 djm Exp $ |
diff --git a/auth-bsdauth.c b/auth-bsdauth.c index 0b3262b49..37ff893e6 100644 --- a/auth-bsdauth.c +++ b/auth-bsdauth.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-bsdauth.c,v 1.11 2007/09/21 08:15:29 djm Exp $ */ | 1 | /* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -26,6 +26,8 @@ | |||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | 27 | ||
28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
29 | #include <stdarg.h> | ||
30 | #include <stdio.h> | ||
29 | 31 | ||
30 | #include <stdarg.h> | 32 | #include <stdarg.h> |
31 | 33 | ||
@@ -54,6 +56,11 @@ bsdauth_query(void *ctx, char **name, char **infotxt, | |||
54 | Authctxt *authctxt = ctx; | 56 | Authctxt *authctxt = ctx; |
55 | char *challenge = NULL; | 57 | char *challenge = NULL; |
56 | 58 | ||
59 | *infotxt = NULL; | ||
60 | *numprompts = 0; | ||
61 | *prompts = NULL; | ||
62 | *echo_on = NULL; | ||
63 | |||
57 | if (authctxt->as != NULL) { | 64 | if (authctxt->as != NULL) { |
58 | debug2("bsdauth_query: try reuse session"); | 65 | debug2("bsdauth_query: try reuse session"); |
59 | challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); | 66 | challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); |
diff --git a/auth-chall.c b/auth-chall.c index 0005aa88b..5c26a403d 100644 --- a/auth-chall.c +++ b/auth-chall.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-chall.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -26,6 +26,9 @@ | |||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | 27 | ||
28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
29 | #include <stdarg.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <stdio.h> | ||
29 | 32 | ||
30 | #include <stdarg.h> | 33 | #include <stdarg.h> |
31 | 34 | ||
@@ -34,6 +37,7 @@ | |||
34 | #include "hostfile.h" | 37 | #include "hostfile.h" |
35 | #include "auth.h" | 38 | #include "auth.h" |
36 | #include "log.h" | 39 | #include "log.h" |
40 | #include "misc.h" | ||
37 | #include "servconf.h" | 41 | #include "servconf.h" |
38 | 42 | ||
39 | /* limited protocol v1 interface to kbd-interactive authentication */ | 43 | /* limited protocol v1 interface to kbd-interactive authentication */ |
diff --git a/auth-krb5.c b/auth-krb5.c index 69a1a53e2..ec4786924 100644 --- a/auth-krb5.c +++ b/auth-krb5.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "packet.h" | 40 | #include "packet.h" |
41 | #include "log.h" | 41 | #include "log.h" |
42 | #include "buffer.h" | 42 | #include "buffer.h" |
43 | #include "misc.h" | ||
43 | #include "servconf.h" | 44 | #include "servconf.h" |
44 | #include "uidswap.h" | 45 | #include "uidswap.h" |
45 | #include "key.h" | 46 | #include "key.h" |
diff --git a/auth-options.c b/auth-options.c index df6133037..d4d22d7a5 100644 --- a/auth-options.c +++ b/auth-options.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-options.c,v 1.62 2013/12/19 00:27:57 djm Exp $ */ | 1 | /* $OpenBSD: auth-options.c,v 1.64 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -26,9 +26,9 @@ | |||
26 | #include "log.h" | 26 | #include "log.h" |
27 | #include "canohost.h" | 27 | #include "canohost.h" |
28 | #include "buffer.h" | 28 | #include "buffer.h" |
29 | #include "misc.h" | ||
29 | #include "channels.h" | 30 | #include "channels.h" |
30 | #include "servconf.h" | 31 | #include "servconf.h" |
31 | #include "misc.h" | ||
32 | #include "key.h" | 32 | #include "key.h" |
33 | #include "auth-options.h" | 33 | #include "auth-options.h" |
34 | #include "hostfile.h" | 34 | #include "hostfile.h" |
@@ -339,6 +339,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) | |||
339 | patterns[i] = '\0'; | 339 | patterns[i] = '\0'; |
340 | opts++; | 340 | opts++; |
341 | p = patterns; | 341 | p = patterns; |
342 | /* XXX - add streamlocal support */ | ||
342 | host = hpdelim(&p); | 343 | host = hpdelim(&p); |
343 | if (host == NULL || strlen(host) >= NI_MAXHOST) { | 344 | if (host == NULL || strlen(host) >= NI_MAXHOST) { |
344 | debug("%.100s, line %lu: Bad permitopen " | 345 | debug("%.100s, line %lu: Bad permitopen " |
@@ -603,8 +604,8 @@ auth_cert_options(Key *k, struct passwd *pw) | |||
603 | 604 | ||
604 | if (key_cert_is_legacy(k)) { | 605 | if (key_cert_is_legacy(k)) { |
605 | /* All options are in the one field for v00 certs */ | 606 | /* All options are in the one field for v00 certs */ |
606 | if (parse_option_list(buffer_ptr(&k->cert->critical), | 607 | if (parse_option_list(buffer_ptr(k->cert->critical), |
607 | buffer_len(&k->cert->critical), pw, | 608 | buffer_len(k->cert->critical), pw, |
608 | OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, | 609 | OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, |
609 | &cert_no_port_forwarding_flag, | 610 | &cert_no_port_forwarding_flag, |
610 | &cert_no_agent_forwarding_flag, | 611 | &cert_no_agent_forwarding_flag, |
@@ -616,14 +617,14 @@ auth_cert_options(Key *k, struct passwd *pw) | |||
616 | return -1; | 617 | return -1; |
617 | } else { | 618 | } else { |
618 | /* Separate options and extensions for v01 certs */ | 619 | /* Separate options and extensions for v01 certs */ |
619 | if (parse_option_list(buffer_ptr(&k->cert->critical), | 620 | if (parse_option_list(buffer_ptr(k->cert->critical), |
620 | buffer_len(&k->cert->critical), pw, | 621 | buffer_len(k->cert->critical), pw, |
621 | OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, | 622 | OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, |
622 | &cert_forced_command, | 623 | &cert_forced_command, |
623 | &cert_source_address_done) == -1) | 624 | &cert_source_address_done) == -1) |
624 | return -1; | 625 | return -1; |
625 | if (parse_option_list(buffer_ptr(&k->cert->extensions), | 626 | if (parse_option_list(buffer_ptr(k->cert->extensions), |
626 | buffer_len(&k->cert->extensions), pw, | 627 | buffer_len(k->cert->extensions), pw, |
627 | OPTIONS_EXTENSIONS, 1, | 628 | OPTIONS_EXTENSIONS, 1, |
628 | &cert_no_port_forwarding_flag, | 629 | &cert_no_port_forwarding_flag, |
629 | &cert_no_agent_forwarding_flag, | 630 | &cert_no_agent_forwarding_flag, |
diff --git a/auth-passwd.c b/auth-passwd.c index 68bbd18dd..63ccf3cab 100644 --- a/auth-passwd.c +++ b/auth-passwd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */ | 1 | /* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -48,6 +48,7 @@ | |||
48 | #include "packet.h" | 48 | #include "packet.h" |
49 | #include "buffer.h" | 49 | #include "buffer.h" |
50 | #include "log.h" | 50 | #include "log.h" |
51 | #include "misc.h" | ||
51 | #include "servconf.h" | 52 | #include "servconf.h" |
52 | #include "key.h" | 53 | #include "key.h" |
53 | #include "hostfile.h" | 54 | #include "hostfile.h" |
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c index b21a0f4a2..b7fd064e7 100644 --- a/auth-rh-rsa.c +++ b/auth-rh-rsa.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */ | 1 | /* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -24,6 +24,7 @@ | |||
24 | #include "uidswap.h" | 24 | #include "uidswap.h" |
25 | #include "log.h" | 25 | #include "log.h" |
26 | #include "buffer.h" | 26 | #include "buffer.h" |
27 | #include "misc.h" | ||
27 | #include "servconf.h" | 28 | #include "servconf.h" |
28 | #include "key.h" | 29 | #include "key.h" |
29 | #include "hostfile.h" | 30 | #include "hostfile.h" |
diff --git a/auth-rhosts.c b/auth-rhosts.c index f20278797..11fcca643 100644 --- a/auth-rhosts.c +++ b/auth-rhosts.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */ | 1 | /* $OpenBSD: auth-rhosts.c,v 1.45 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -34,12 +34,12 @@ | |||
34 | #include "uidswap.h" | 34 | #include "uidswap.h" |
35 | #include "pathnames.h" | 35 | #include "pathnames.h" |
36 | #include "log.h" | 36 | #include "log.h" |
37 | #include "misc.h" | ||
37 | #include "servconf.h" | 38 | #include "servconf.h" |
38 | #include "canohost.h" | 39 | #include "canohost.h" |
39 | #include "key.h" | 40 | #include "key.h" |
40 | #include "hostfile.h" | 41 | #include "hostfile.h" |
41 | #include "auth.h" | 42 | #include "auth.h" |
42 | #include "misc.h" | ||
43 | 43 | ||
44 | /* import */ | 44 | /* import */ |
45 | extern ServerOptions options; | 45 | extern ServerOptions options; |
diff --git a/auth-rsa.c b/auth-rsa.c index 260ce2f98..5d7bdcbfc 100644 --- a/auth-rsa.c +++ b/auth-rsa.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-rsa.c,v 1.86 2014/01/27 19:18:54 markus Exp $ */ | 1 | /* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,6 +35,7 @@ | |||
35 | #include "buffer.h" | 35 | #include "buffer.h" |
36 | #include "pathnames.h" | 36 | #include "pathnames.h" |
37 | #include "log.h" | 37 | #include "log.h" |
38 | #include "misc.h" | ||
38 | #include "servconf.h" | 39 | #include "servconf.h" |
39 | #include "key.h" | 40 | #include "key.h" |
40 | #include "auth-options.h" | 41 | #include "auth-options.h" |
@@ -45,7 +46,6 @@ | |||
45 | #endif | 46 | #endif |
46 | #include "monitor_wrap.h" | 47 | #include "monitor_wrap.h" |
47 | #include "ssh.h" | 48 | #include "ssh.h" |
48 | #include "misc.h" | ||
49 | 49 | ||
50 | #include "digest.h" | 50 | #include "digest.h" |
51 | 51 | ||
@@ -144,7 +144,8 @@ auth_rsa_challenge_dialog(Key *key) | |||
144 | challenge = PRIVSEP(auth_rsa_generate_challenge(key)); | 144 | challenge = PRIVSEP(auth_rsa_generate_challenge(key)); |
145 | 145 | ||
146 | /* Encrypt the challenge with the public key. */ | 146 | /* Encrypt the challenge with the public key. */ |
147 | rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); | 147 | if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0) |
148 | fatal("%s: rsa_public_encrypt failed", __func__); | ||
148 | 149 | ||
149 | /* Send the encrypted challenge to the client. */ | 150 | /* Send the encrypted challenge to the client. */ |
150 | packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); | 151 | packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.103 2013/05/19 02:42:42 djm Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.106 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -56,6 +56,7 @@ | |||
56 | #include "groupaccess.h" | 56 | #include "groupaccess.h" |
57 | #include "log.h" | 57 | #include "log.h" |
58 | #include "buffer.h" | 58 | #include "buffer.h" |
59 | #include "misc.h" | ||
59 | #include "servconf.h" | 60 | #include "servconf.h" |
60 | #include "key.h" | 61 | #include "key.h" |
61 | #include "hostfile.h" | 62 | #include "hostfile.h" |
@@ -63,7 +64,6 @@ | |||
63 | #include "auth-options.h" | 64 | #include "auth-options.h" |
64 | #include "canohost.h" | 65 | #include "canohost.h" |
65 | #include "uidswap.h" | 66 | #include "uidswap.h" |
66 | #include "misc.h" | ||
67 | #include "packet.h" | 67 | #include "packet.h" |
68 | #include "loginrec.h" | 68 | #include "loginrec.h" |
69 | #ifdef GSSAPI | 69 | #ifdef GSSAPI |
@@ -326,6 +326,20 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, | |||
326 | #endif | 326 | #endif |
327 | } | 327 | } |
328 | 328 | ||
329 | |||
330 | void | ||
331 | auth_maxtries_exceeded(Authctxt *authctxt) | ||
332 | { | ||
333 | packet_disconnect("Too many authentication failures for " | ||
334 | "%s%.100s from %.200s port %d %s", | ||
335 | authctxt->valid ? "" : "invalid user ", | ||
336 | authctxt->user, | ||
337 | get_remote_ipaddr(), | ||
338 | get_remote_port(), | ||
339 | compat20 ? "ssh2" : "ssh1"); | ||
340 | /* NOTREACHED */ | ||
341 | } | ||
342 | |||
329 | /* | 343 | /* |
330 | * Check whether root logins are disallowed. | 344 | * Check whether root logins are disallowed. |
331 | */ | 345 | */ |
@@ -656,6 +670,7 @@ getpwnamallow(const char *user) | |||
656 | int | 670 | int |
657 | auth_key_is_revoked(Key *key) | 671 | auth_key_is_revoked(Key *key) |
658 | { | 672 | { |
673 | #ifdef WITH_OPENSSL | ||
659 | char *key_fp; | 674 | char *key_fp; |
660 | 675 | ||
661 | if (options.revoked_keys_file == NULL) | 676 | if (options.revoked_keys_file == NULL) |
@@ -668,6 +683,7 @@ auth_key_is_revoked(Key *key) | |||
668 | default: | 683 | default: |
669 | goto revoked; | 684 | goto revoked; |
670 | } | 685 | } |
686 | #endif | ||
671 | debug3("%s: treating %s as a key list", __func__, | 687 | debug3("%s: treating %s as a key list", __func__, |
672 | options.revoked_keys_file); | 688 | options.revoked_keys_file); |
673 | switch (key_in_file(key, options.revoked_keys_file, 0)) { | 689 | switch (key_in_file(key, options.revoked_keys_file, 0)) { |
@@ -679,6 +695,7 @@ auth_key_is_revoked(Key *key) | |||
679 | error("Revoked keys file is unreadable: refusing public key " | 695 | error("Revoked keys file is unreadable: refusing public key " |
680 | "authentication"); | 696 | "authentication"); |
681 | return 1; | 697 | return 1; |
698 | #ifdef WITH_OPENSSL | ||
682 | case 1: | 699 | case 1: |
683 | revoked: | 700 | revoked: |
684 | /* Key revoked */ | 701 | /* Key revoked */ |
@@ -687,6 +704,7 @@ auth_key_is_revoked(Key *key) | |||
687 | "%s key %s ", key_type(key), key_fp); | 704 | "%s key %s ", key_type(key), key_fp); |
688 | free(key_fp); | 705 | free(key_fp); |
689 | return 1; | 706 | return 1; |
707 | #endif | ||
690 | } | 708 | } |
691 | fatal("key_in_file returned junk"); | 709 | fatal("key_in_file returned junk"); |
692 | } | 710 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.h,v 1.77 2014/01/29 06:18:35 djm Exp $ */ | 1 | /* $OpenBSD: auth.h,v 1.78 2014/07/03 11:16:55 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -155,6 +155,7 @@ void auth_info(Authctxt *authctxt, const char *, ...) | |||
155 | __attribute__((__format__ (printf, 2, 3))) | 155 | __attribute__((__format__ (printf, 2, 3))) |
156 | __attribute__((__nonnull__ (2))); | 156 | __attribute__((__nonnull__ (2))); |
157 | void auth_log(Authctxt *, int, int, const char *, const char *); | 157 | void auth_log(Authctxt *, int, int, const char *, const char *); |
158 | void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn)); | ||
158 | void userauth_finish(Authctxt *, int, const char *, const char *); | 159 | void userauth_finish(Authctxt *, int, const char *, const char *); |
159 | int auth_root_allowed(const char *); | 160 | int auth_root_allowed(const char *); |
160 | 161 | ||
@@ -211,8 +212,6 @@ struct passwd *fakepw(void); | |||
211 | 212 | ||
212 | int sys_auth_passwd(Authctxt *, const char *); | 213 | int sys_auth_passwd(Authctxt *, const char *); |
213 | 214 | ||
214 | #define AUTH_FAIL_MSG "Too many authentication failures for %.100s" | ||
215 | |||
216 | #define SKEY_PROMPT "\nS/Key Password: " | 215 | #define SKEY_PROMPT "\nS/Key Password: " |
217 | 216 | ||
218 | #if defined(KRB5) && !defined(HEIMDAL) | 217 | #if defined(KRB5) && !defined(HEIMDAL) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth1.c,v 1.80 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -27,6 +27,7 @@ | |||
27 | #include "packet.h" | 27 | #include "packet.h" |
28 | #include "buffer.h" | 28 | #include "buffer.h" |
29 | #include "log.h" | 29 | #include "log.h" |
30 | #include "misc.h" | ||
30 | #include "servconf.h" | 31 | #include "servconf.h" |
31 | #include "compat.h" | 32 | #include "compat.h" |
32 | #include "key.h" | 33 | #include "key.h" |
@@ -363,7 +364,7 @@ do_authloop(Authctxt *authctxt) | |||
363 | #ifdef SSH_AUDIT_EVENTS | 364 | #ifdef SSH_AUDIT_EVENTS |
364 | PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); | 365 | PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); |
365 | #endif | 366 | #endif |
366 | packet_disconnect(AUTH_FAIL_MSG, authctxt->user); | 367 | auth_maxtries_exceeded(authctxt); |
367 | } | 368 | } |
368 | 369 | ||
369 | packet_start(SSH_SMSG_FAILURE); | 370 | packet_start(SSH_SMSG_FAILURE); |
diff --git a/auth2-chall.c b/auth2-chall.c index 980250a91..ea4eb6952 100644 --- a/auth2-chall.c +++ b/auth2-chall.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "packet.h" | 41 | #include "packet.h" |
42 | #include "dispatch.h" | 42 | #include "dispatch.h" |
43 | #include "log.h" | 43 | #include "log.h" |
44 | #include "misc.h" | ||
44 | #include "servconf.h" | 45 | #include "servconf.h" |
45 | 46 | ||
46 | /* import */ | 47 | /* import */ |
diff --git a/auth2-gss.c b/auth2-gss.c index 3ff2d726b..284f364b0 100644 --- a/auth2-gss.c +++ b/auth2-gss.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "log.h" | 40 | #include "log.h" |
41 | #include "dispatch.h" | 41 | #include "dispatch.h" |
42 | #include "buffer.h" | 42 | #include "buffer.h" |
43 | #include "misc.h" | ||
43 | #include "servconf.h" | 44 | #include "servconf.h" |
44 | #include "packet.h" | 45 | #include "packet.h" |
45 | #include "ssh-gss.h" | 46 | #include "ssh-gss.h" |
diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 488008f62..6787e4ca4 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm Exp $ */ | 1 | /* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -36,6 +36,7 @@ | |||
36 | #include "packet.h" | 36 | #include "packet.h" |
37 | #include "buffer.h" | 37 | #include "buffer.h" |
38 | #include "log.h" | 38 | #include "log.h" |
39 | #include "misc.h" | ||
39 | #include "servconf.h" | 40 | #include "servconf.h" |
40 | #include "compat.h" | 41 | #include "compat.h" |
41 | #include "key.h" | 42 | #include "key.h" |
diff --git a/auth2-kbdint.c b/auth2-kbdint.c index c39bdc62d..bf75c6059 100644 --- a/auth2-kbdint.c +++ b/auth2-kbdint.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-kbdint.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -36,6 +36,7 @@ | |||
36 | #include "auth.h" | 36 | #include "auth.h" |
37 | #include "log.h" | 37 | #include "log.h" |
38 | #include "buffer.h" | 38 | #include "buffer.h" |
39 | #include "misc.h" | ||
39 | #include "servconf.h" | 40 | #include "servconf.h" |
40 | 41 | ||
41 | /* import */ | 42 | /* import */ |
diff --git a/auth2-none.c b/auth2-none.c index c8c6c74a9..e71e2219c 100644 --- a/auth2-none.c +++ b/auth2-none.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-none.c,v 1.16 2010/06/25 08:46:17 djm Exp $ */ | 1 | /* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -30,9 +30,10 @@ | |||
30 | #include <sys/uio.h> | 30 | #include <sys/uio.h> |
31 | 31 | ||
32 | #include <fcntl.h> | 32 | #include <fcntl.h> |
33 | #include <stdarg.h> | ||
34 | #include <string.h> | 33 | #include <string.h> |
35 | #include <unistd.h> | 34 | #include <unistd.h> |
35 | #include <stdarg.h> | ||
36 | #include <stdio.h> | ||
36 | 37 | ||
37 | #include "atomicio.h" | 38 | #include "atomicio.h" |
38 | #include "xmalloc.h" | 39 | #include "xmalloc.h" |
@@ -42,6 +43,7 @@ | |||
42 | #include "packet.h" | 43 | #include "packet.h" |
43 | #include "log.h" | 44 | #include "log.h" |
44 | #include "buffer.h" | 45 | #include "buffer.h" |
46 | #include "misc.h" | ||
45 | #include "servconf.h" | 47 | #include "servconf.h" |
46 | #include "compat.h" | 48 | #include "compat.h" |
47 | #include "ssh2.h" | 49 | #include "ssh2.h" |
diff --git a/auth2-passwd.c b/auth2-passwd.c index 707680cd0..b638e8715 100644 --- a/auth2-passwd.c +++ b/auth2-passwd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-passwd.c,v 1.11 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -41,6 +41,7 @@ | |||
41 | #include "ssh-gss.h" | 41 | #include "ssh-gss.h" |
42 | #endif | 42 | #endif |
43 | #include "monitor_wrap.h" | 43 | #include "monitor_wrap.h" |
44 | #include "misc.h" | ||
44 | #include "servconf.h" | 45 | #include "servconf.h" |
45 | 46 | ||
46 | /* import */ | 47 | /* import */ |
diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 7c5692750..f78b046b8 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-pubkey.c,v 1.39 2013/12/30 23:52:27 djm Exp $ */ | 1 | /* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -48,6 +48,7 @@ | |||
48 | #include "packet.h" | 48 | #include "packet.h" |
49 | #include "buffer.h" | 49 | #include "buffer.h" |
50 | #include "log.h" | 50 | #include "log.h" |
51 | #include "misc.h" | ||
51 | #include "servconf.h" | 52 | #include "servconf.h" |
52 | #include "compat.h" | 53 | #include "compat.h" |
53 | #include "key.h" | 54 | #include "key.h" |
@@ -61,7 +62,6 @@ | |||
61 | #include "ssh-gss.h" | 62 | #include "ssh-gss.h" |
62 | #endif | 63 | #endif |
63 | #include "monitor_wrap.h" | 64 | #include "monitor_wrap.h" |
64 | #include "misc.h" | ||
65 | #include "authfile.h" | 65 | #include "authfile.h" |
66 | #include "match.h" | 66 | #include "match.h" |
67 | 67 | ||
@@ -230,7 +230,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) | |||
230 | } | 230 | } |
231 | 231 | ||
232 | static int | 232 | static int |
233 | match_principals_option(const char *principal_list, struct KeyCert *cert) | 233 | match_principals_option(const char *principal_list, struct sshkey_cert *cert) |
234 | { | 234 | { |
235 | char *result; | 235 | char *result; |
236 | u_int i; | 236 | u_int i; |
@@ -250,7 +250,7 @@ match_principals_option(const char *principal_list, struct KeyCert *cert) | |||
250 | } | 250 | } |
251 | 251 | ||
252 | static int | 252 | static int |
253 | match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert) | 253 | match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert) |
254 | { | 254 | { |
255 | FILE *f; | 255 | FILE *f; |
256 | char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; | 256 | char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2.c,v 1.130 2014/01/29 06:18:35 djm Exp $ */ | 1 | /* $OpenBSD: auth2.c,v 1.132 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -41,6 +41,7 @@ | |||
41 | #include "packet.h" | 41 | #include "packet.h" |
42 | #include "log.h" | 42 | #include "log.h" |
43 | #include "buffer.h" | 43 | #include "buffer.h" |
44 | #include "misc.h" | ||
44 | #include "servconf.h" | 45 | #include "servconf.h" |
45 | #include "compat.h" | 46 | #include "compat.h" |
46 | #include "key.h" | 47 | #include "key.h" |
@@ -370,7 +371,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, | |||
370 | #ifdef SSH_AUDIT_EVENTS | 371 | #ifdef SSH_AUDIT_EVENTS |
371 | PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); | 372 | PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); |
372 | #endif | 373 | #endif |
373 | packet_disconnect(AUTH_FAIL_MSG, authctxt->user); | 374 | auth_maxtries_exceeded(authctxt); |
374 | } | 375 | } |
375 | methods = authmethods_get(authctxt); | 376 | methods = authmethods_get(authctxt); |
376 | debug3("%s: failure partial=%d next methods=\"%s\"", __func__, | 377 | debug3("%s: failure partial=%d next methods=\"%s\"", __func__, |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfd.c,v 1.92 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: authfd.c,v 1.93 2014/04/29 18:01:49 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -41,9 +41,6 @@ | |||
41 | #include <sys/un.h> | 41 | #include <sys/un.h> |
42 | #include <sys/socket.h> | 42 | #include <sys/socket.h> |
43 | 43 | ||
44 | #include <openssl/evp.h> | ||
45 | #include <openssl/crypto.h> | ||
46 | |||
47 | #include <fcntl.h> | 44 | #include <fcntl.h> |
48 | #include <stdlib.h> | 45 | #include <stdlib.h> |
49 | #include <signal.h> | 46 | #include <signal.h> |
@@ -313,8 +310,10 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi | |||
313 | Key * | 310 | Key * |
314 | ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) | 311 | ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) |
315 | { | 312 | { |
313 | #ifdef WITH_SSH1 | ||
316 | int keybits; | 314 | int keybits; |
317 | u_int bits; | 315 | u_int bits; |
316 | #endif | ||
318 | u_char *blob; | 317 | u_char *blob; |
319 | u_int blen; | 318 | u_int blen; |
320 | Key *key = NULL; | 319 | Key *key = NULL; |
@@ -328,6 +327,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio | |||
328 | * error if the packet is too short or contains corrupt data. | 327 | * error if the packet is too short or contains corrupt data. |
329 | */ | 328 | */ |
330 | switch (version) { | 329 | switch (version) { |
330 | #ifdef WITH_SSH1 | ||
331 | case 1: | 331 | case 1: |
332 | key = key_new(KEY_RSA1); | 332 | key = key_new(KEY_RSA1); |
333 | bits = buffer_get_int(&auth->identities); | 333 | bits = buffer_get_int(&auth->identities); |
@@ -339,6 +339,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio | |||
339 | logit("Warning: identity keysize mismatch: actual %d, announced %u", | 339 | logit("Warning: identity keysize mismatch: actual %d, announced %u", |
340 | BN_num_bits(key->rsa->n), bits); | 340 | BN_num_bits(key->rsa->n), bits); |
341 | break; | 341 | break; |
342 | #endif | ||
342 | case 2: | 343 | case 2: |
343 | blob = buffer_get_string(&auth->identities, &blen); | 344 | blob = buffer_get_string(&auth->identities, &blen); |
344 | *comment = buffer_get_string(&auth->identities, NULL); | 345 | *comment = buffer_get_string(&auth->identities, NULL); |
@@ -361,6 +362,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio | |||
361 | * supported) and 1 corresponding to protocol version 1.1. | 362 | * supported) and 1 corresponding to protocol version 1.1. |
362 | */ | 363 | */ |
363 | 364 | ||
365 | #ifdef WITH_SSH1 | ||
364 | int | 366 | int |
365 | ssh_decrypt_challenge(AuthenticationConnection *auth, | 367 | ssh_decrypt_challenge(AuthenticationConnection *auth, |
366 | Key* key, BIGNUM *challenge, | 368 | Key* key, BIGNUM *challenge, |
@@ -410,6 +412,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth, | |||
410 | buffer_free(&buffer); | 412 | buffer_free(&buffer); |
411 | return success; | 413 | return success; |
412 | } | 414 | } |
415 | #endif | ||
413 | 416 | ||
414 | /* ask agent to sign data, returns -1 on error, 0 on success */ | 417 | /* ask agent to sign data, returns -1 on error, 0 on success */ |
415 | int | 418 | int |
@@ -457,6 +460,7 @@ ssh_agent_sign(AuthenticationConnection *auth, | |||
457 | 460 | ||
458 | /* Encode key for a message to the agent. */ | 461 | /* Encode key for a message to the agent. */ |
459 | 462 | ||
463 | #ifdef WITH_SSH1 | ||
460 | static void | 464 | static void |
461 | ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) | 465 | ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) |
462 | { | 466 | { |
@@ -470,6 +474,7 @@ ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) | |||
470 | buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ | 474 | buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ |
471 | buffer_put_cstring(b, comment); | 475 | buffer_put_cstring(b, comment); |
472 | } | 476 | } |
477 | #endif | ||
473 | 478 | ||
474 | static void | 479 | static void |
475 | ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) | 480 | ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) |
@@ -493,6 +498,7 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, | |||
493 | buffer_init(&msg); | 498 | buffer_init(&msg); |
494 | 499 | ||
495 | switch (key->type) { | 500 | switch (key->type) { |
501 | #ifdef WITH_SSH1 | ||
496 | case KEY_RSA1: | 502 | case KEY_RSA1: |
497 | type = constrained ? | 503 | type = constrained ? |
498 | SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : | 504 | SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : |
@@ -500,6 +506,8 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, | |||
500 | buffer_put_char(&msg, type); | 506 | buffer_put_char(&msg, type); |
501 | ssh_encode_identity_rsa1(&msg, key->rsa, comment); | 507 | ssh_encode_identity_rsa1(&msg, key->rsa, comment); |
502 | break; | 508 | break; |
509 | #endif | ||
510 | #ifdef WITH_OPENSSL | ||
503 | case KEY_RSA: | 511 | case KEY_RSA: |
504 | case KEY_RSA_CERT: | 512 | case KEY_RSA_CERT: |
505 | case KEY_RSA_CERT_V00: | 513 | case KEY_RSA_CERT_V00: |
@@ -508,6 +516,7 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, | |||
508 | case KEY_DSA_CERT_V00: | 516 | case KEY_DSA_CERT_V00: |
509 | case KEY_ECDSA: | 517 | case KEY_ECDSA: |
510 | case KEY_ECDSA_CERT: | 518 | case KEY_ECDSA_CERT: |
519 | #endif | ||
511 | case KEY_ED25519: | 520 | case KEY_ED25519: |
512 | case KEY_ED25519_CERT: | 521 | case KEY_ED25519_CERT: |
513 | type = constrained ? | 522 | type = constrained ? |
@@ -552,12 +561,15 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key) | |||
552 | 561 | ||
553 | buffer_init(&msg); | 562 | buffer_init(&msg); |
554 | 563 | ||
564 | #ifdef WITH_SSH1 | ||
555 | if (key->type == KEY_RSA1) { | 565 | if (key->type == KEY_RSA1) { |
556 | buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); | 566 | buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); |
557 | buffer_put_int(&msg, BN_num_bits(key->rsa->n)); | 567 | buffer_put_int(&msg, BN_num_bits(key->rsa->n)); |
558 | buffer_put_bignum(&msg, key->rsa->e); | 568 | buffer_put_bignum(&msg, key->rsa->e); |
559 | buffer_put_bignum(&msg, key->rsa->n); | 569 | buffer_put_bignum(&msg, key->rsa->n); |
560 | } else if (key->type != KEY_UNSPEC) { | 570 | } else |
571 | #endif | ||
572 | if (key->type != KEY_UNSPEC) { | ||
561 | key_to_blob(key, &blob, &blen); | 573 | key_to_blob(key, &blob, &blen); |
562 | buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); | 574 | buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); |
563 | buffer_put_string(&msg, blob, blen); | 575 | buffer_put_string(&msg, blob, blen); |
diff --git a/authfile.c b/authfile.c index d7eaa9dec..e93d86738 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,18 +1,5 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.103 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.107 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | ||
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
5 | * All rights reserved | ||
6 | * This file contains functions for reading and writing identity files, and | ||
7 | * for reading the passphrase from the user. | ||
8 | * | ||
9 | * As far as I am concerned, the code I have written for this software | ||
10 | * can be used freely for any purpose. Any derived versions of this | ||
11 | * software must be clearly marked as such, and if the derived work is | ||
12 | * incompatible with the protocol description in the RFC file, it must be | ||
13 | * called by a name other than "ssh" or "Secure Shell". | ||
14 | * | ||
15 | * | ||
16 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. |
17 | * | 4 | * |
18 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
@@ -43,30 +30,15 @@ | |||
43 | #include <sys/param.h> | 30 | #include <sys/param.h> |
44 | #include <sys/uio.h> | 31 | #include <sys/uio.h> |
45 | 32 | ||
46 | #include <openssl/err.h> | ||
47 | #include <openssl/evp.h> | ||
48 | #include <openssl/pem.h> | ||
49 | |||
50 | /* compatibility with old or broken OpenSSL versions */ | ||
51 | #include "openbsd-compat/openssl-compat.h" | ||
52 | |||
53 | #include "crypto_api.h" | ||
54 | |||
55 | #include <errno.h> | 33 | #include <errno.h> |
56 | #include <fcntl.h> | 34 | #include <fcntl.h> |
57 | #include <stdarg.h> | ||
58 | #include <stdio.h> | 35 | #include <stdio.h> |
36 | #include <stdarg.h> | ||
59 | #include <stdlib.h> | 37 | #include <stdlib.h> |
60 | #include <string.h> | 38 | #include <string.h> |
61 | #include <unistd.h> | 39 | #include <unistd.h> |
62 | 40 | ||
63 | #ifdef HAVE_UTIL_H | ||
64 | #include <util.h> | ||
65 | #endif | ||
66 | |||
67 | #include "xmalloc.h" | ||
68 | #include "cipher.h" | 41 | #include "cipher.h" |
69 | #include "buffer.h" | ||
70 | #include "key.h" | 42 | #include "key.h" |
71 | #include "ssh.h" | 43 | #include "ssh.h" |
72 | #include "log.h" | 44 | #include "log.h" |
@@ -74,903 +46,159 @@ | |||
74 | #include "rsa.h" | 46 | #include "rsa.h" |
75 | #include "misc.h" | 47 | #include "misc.h" |
76 | #include "atomicio.h" | 48 | #include "atomicio.h" |
77 | #include "uuencode.h" | 49 | #include "sshbuf.h" |
78 | 50 | #include "ssherr.h" | |
79 | /* openssh private key file format */ | ||
80 | #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" | ||
81 | #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" | ||
82 | #define KDFNAME "bcrypt" | ||
83 | #define AUTH_MAGIC "openssh-key-v1" | ||
84 | #define SALT_LEN 16 | ||
85 | #define DEFAULT_CIPHERNAME "aes256-cbc" | ||
86 | #define DEFAULT_ROUNDS 16 | ||
87 | 51 | ||
88 | #define MAX_KEY_FILE_SIZE (1024 * 1024) | 52 | #define MAX_KEY_FILE_SIZE (1024 * 1024) |
89 | 53 | ||
90 | /* Version identification string for SSH v1 identity files. */ | ||
91 | static const char authfile_id_string[] = | ||
92 | "SSH PRIVATE KEY FILE FORMAT 1.1\n"; | ||
93 | |||
94 | static int | ||
95 | key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase, | ||
96 | const char *comment, const char *ciphername, int rounds) | ||
97 | { | ||
98 | u_char *key, *cp, salt[SALT_LEN]; | ||
99 | size_t keylen, ivlen, blocksize, authlen; | ||
100 | u_int len, check; | ||
101 | int i, n; | ||
102 | const Cipher *c; | ||
103 | Buffer encoded, b, kdf; | ||
104 | CipherContext ctx; | ||
105 | const char *kdfname = KDFNAME; | ||
106 | |||
107 | if (rounds <= 0) | ||
108 | rounds = DEFAULT_ROUNDS; | ||
109 | if (passphrase == NULL || !strlen(passphrase)) { | ||
110 | ciphername = "none"; | ||
111 | kdfname = "none"; | ||
112 | } else if (ciphername == NULL) | ||
113 | ciphername = DEFAULT_CIPHERNAME; | ||
114 | else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) | ||
115 | fatal("invalid cipher"); | ||
116 | |||
117 | if ((c = cipher_by_name(ciphername)) == NULL) | ||
118 | fatal("unknown cipher name"); | ||
119 | buffer_init(&kdf); | ||
120 | blocksize = cipher_blocksize(c); | ||
121 | keylen = cipher_keylen(c); | ||
122 | ivlen = cipher_ivlen(c); | ||
123 | authlen = cipher_authlen(c); | ||
124 | key = xcalloc(1, keylen + ivlen); | ||
125 | if (strcmp(kdfname, "none") != 0) { | ||
126 | arc4random_buf(salt, SALT_LEN); | ||
127 | if (bcrypt_pbkdf(passphrase, strlen(passphrase), | ||
128 | salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) | ||
129 | fatal("bcrypt_pbkdf failed"); | ||
130 | buffer_put_string(&kdf, salt, SALT_LEN); | ||
131 | buffer_put_int(&kdf, rounds); | ||
132 | } | ||
133 | cipher_init(&ctx, c, key, keylen, key + keylen , ivlen, 1); | ||
134 | explicit_bzero(key, keylen + ivlen); | ||
135 | free(key); | ||
136 | |||
137 | buffer_init(&encoded); | ||
138 | buffer_append(&encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC)); | ||
139 | buffer_put_cstring(&encoded, ciphername); | ||
140 | buffer_put_cstring(&encoded, kdfname); | ||
141 | buffer_put_string(&encoded, buffer_ptr(&kdf), buffer_len(&kdf)); | ||
142 | buffer_put_int(&encoded, 1); /* number of keys */ | ||
143 | key_to_blob(prv, &cp, &len); /* public key */ | ||
144 | buffer_put_string(&encoded, cp, len); | ||
145 | |||
146 | explicit_bzero(cp, len); | ||
147 | free(cp); | ||
148 | |||
149 | buffer_free(&kdf); | ||
150 | |||
151 | /* set up the buffer that will be encrypted */ | ||
152 | buffer_init(&b); | ||
153 | |||
154 | /* Random check bytes */ | ||
155 | check = arc4random(); | ||
156 | buffer_put_int(&b, check); | ||
157 | buffer_put_int(&b, check); | ||
158 | |||
159 | /* append private key and comment*/ | ||
160 | key_private_serialize(prv, &b); | ||
161 | buffer_put_cstring(&b, comment); | ||
162 | |||
163 | /* padding */ | ||
164 | i = 0; | ||
165 | while (buffer_len(&b) % blocksize) | ||
166 | buffer_put_char(&b, ++i & 0xff); | ||
167 | |||
168 | /* length */ | ||
169 | buffer_put_int(&encoded, buffer_len(&b)); | ||
170 | |||
171 | /* encrypt */ | ||
172 | cp = buffer_append_space(&encoded, buffer_len(&b) + authlen); | ||
173 | if (cipher_crypt(&ctx, 0, cp, buffer_ptr(&b), buffer_len(&b), 0, | ||
174 | authlen) != 0) | ||
175 | fatal("%s: cipher_crypt failed", __func__); | ||
176 | buffer_free(&b); | ||
177 | cipher_cleanup(&ctx); | ||
178 | |||
179 | /* uuencode */ | ||
180 | len = 2 * buffer_len(&encoded); | ||
181 | cp = xmalloc(len); | ||
182 | n = uuencode(buffer_ptr(&encoded), buffer_len(&encoded), | ||
183 | (char *)cp, len); | ||
184 | if (n < 0) | ||
185 | fatal("%s: uuencode", __func__); | ||
186 | |||
187 | buffer_clear(blob); | ||
188 | buffer_append(blob, MARK_BEGIN, sizeof(MARK_BEGIN) - 1); | ||
189 | for (i = 0; i < n; i++) { | ||
190 | buffer_put_char(blob, cp[i]); | ||
191 | if (i % 70 == 69) | ||
192 | buffer_put_char(blob, '\n'); | ||
193 | } | ||
194 | if (i % 70 != 69) | ||
195 | buffer_put_char(blob, '\n'); | ||
196 | buffer_append(blob, MARK_END, sizeof(MARK_END) - 1); | ||
197 | free(cp); | ||
198 | |||
199 | return buffer_len(blob); | ||
200 | } | ||
201 | |||
202 | static Key * | ||
203 | key_parse_private2(Buffer *blob, int type, const char *passphrase, | ||
204 | char **commentp) | ||
205 | { | ||
206 | u_char *key = NULL, *cp, *salt = NULL, pad, last; | ||
207 | char *comment = NULL, *ciphername = NULL, *kdfname = NULL, *kdfp; | ||
208 | u_int keylen = 0, ivlen, blocksize, slen, klen, len, rounds, nkeys; | ||
209 | u_int check1, check2, m1len, m2len; | ||
210 | size_t authlen; | ||
211 | const Cipher *c; | ||
212 | Buffer b, encoded, copy, kdf; | ||
213 | CipherContext ctx; | ||
214 | Key *k = NULL; | ||
215 | int dlen, ret, i; | ||
216 | |||
217 | buffer_init(&b); | ||
218 | buffer_init(&kdf); | ||
219 | buffer_init(&encoded); | ||
220 | buffer_init(©); | ||
221 | |||
222 | /* uudecode */ | ||
223 | m1len = sizeof(MARK_BEGIN) - 1; | ||
224 | m2len = sizeof(MARK_END) - 1; | ||
225 | cp = buffer_ptr(blob); | ||
226 | len = buffer_len(blob); | ||
227 | if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) { | ||
228 | debug("%s: missing begin marker", __func__); | ||
229 | goto out; | ||
230 | } | ||
231 | cp += m1len; | ||
232 | len -= m1len; | ||
233 | while (len) { | ||
234 | if (*cp != '\n' && *cp != '\r') | ||
235 | buffer_put_char(&encoded, *cp); | ||
236 | last = *cp; | ||
237 | len--; | ||
238 | cp++; | ||
239 | if (last == '\n') { | ||
240 | if (len >= m2len && !memcmp(cp, MARK_END, m2len)) { | ||
241 | buffer_put_char(&encoded, '\0'); | ||
242 | break; | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | if (!len) { | ||
247 | debug("%s: no end marker", __func__); | ||
248 | goto out; | ||
249 | } | ||
250 | len = buffer_len(&encoded); | ||
251 | if ((cp = buffer_append_space(©, len)) == NULL) { | ||
252 | error("%s: buffer_append_space", __func__); | ||
253 | goto out; | ||
254 | } | ||
255 | if ((dlen = uudecode(buffer_ptr(&encoded), cp, len)) < 0) { | ||
256 | error("%s: uudecode failed", __func__); | ||
257 | goto out; | ||
258 | } | ||
259 | if ((u_int)dlen > len) { | ||
260 | error("%s: crazy uudecode length %d > %u", __func__, dlen, len); | ||
261 | goto out; | ||
262 | } | ||
263 | buffer_consume_end(©, len - dlen); | ||
264 | if (buffer_len(©) < sizeof(AUTH_MAGIC) || | ||
265 | memcmp(buffer_ptr(©), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { | ||
266 | error("%s: bad magic", __func__); | ||
267 | goto out; | ||
268 | } | ||
269 | buffer_consume(©, sizeof(AUTH_MAGIC)); | ||
270 | |||
271 | ciphername = buffer_get_cstring_ret(©, NULL); | ||
272 | if (ciphername == NULL || | ||
273 | (c = cipher_by_name(ciphername)) == NULL) { | ||
274 | error("%s: unknown cipher name", __func__); | ||
275 | goto out; | ||
276 | } | ||
277 | if ((passphrase == NULL || !strlen(passphrase)) && | ||
278 | strcmp(ciphername, "none") != 0) { | ||
279 | /* passphrase required */ | ||
280 | goto out; | ||
281 | } | ||
282 | kdfname = buffer_get_cstring_ret(©, NULL); | ||
283 | if (kdfname == NULL || | ||
284 | (!strcmp(kdfname, "none") && !strcmp(kdfname, "bcrypt"))) { | ||
285 | error("%s: unknown kdf name", __func__); | ||
286 | goto out; | ||
287 | } | ||
288 | if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) { | ||
289 | error("%s: cipher %s requires kdf", __func__, ciphername); | ||
290 | goto out; | ||
291 | } | ||
292 | /* kdf options */ | ||
293 | kdfp = buffer_get_string_ptr_ret(©, &klen); | ||
294 | if (kdfp == NULL) { | ||
295 | error("%s: kdf options not set", __func__); | ||
296 | goto out; | ||
297 | } | ||
298 | if (klen > 0) { | ||
299 | if ((cp = buffer_append_space(&kdf, klen)) == NULL) { | ||
300 | error("%s: kdf alloc failed", __func__); | ||
301 | goto out; | ||
302 | } | ||
303 | memcpy(cp, kdfp, klen); | ||
304 | } | ||
305 | /* number of keys */ | ||
306 | if (buffer_get_int_ret(&nkeys, ©) < 0) { | ||
307 | error("%s: key counter missing", __func__); | ||
308 | goto out; | ||
309 | } | ||
310 | if (nkeys != 1) { | ||
311 | error("%s: only one key supported", __func__); | ||
312 | goto out; | ||
313 | } | ||
314 | /* pubkey */ | ||
315 | if ((cp = buffer_get_string_ret(©, &len)) == NULL) { | ||
316 | error("%s: pubkey not found", __func__); | ||
317 | goto out; | ||
318 | } | ||
319 | free(cp); /* XXX check pubkey against decrypted private key */ | ||
320 | |||
321 | /* size of encrypted key blob */ | ||
322 | len = buffer_get_int(©); | ||
323 | blocksize = cipher_blocksize(c); | ||
324 | authlen = cipher_authlen(c); | ||
325 | if (len < blocksize) { | ||
326 | error("%s: encrypted data too small", __func__); | ||
327 | goto out; | ||
328 | } | ||
329 | if (len % blocksize) { | ||
330 | error("%s: length not multiple of blocksize", __func__); | ||
331 | goto out; | ||
332 | } | ||
333 | |||
334 | /* setup key */ | ||
335 | keylen = cipher_keylen(c); | ||
336 | ivlen = cipher_ivlen(c); | ||
337 | key = xcalloc(1, keylen + ivlen); | ||
338 | if (!strcmp(kdfname, "bcrypt")) { | ||
339 | if ((salt = buffer_get_string_ret(&kdf, &slen)) == NULL) { | ||
340 | error("%s: salt not set", __func__); | ||
341 | goto out; | ||
342 | } | ||
343 | if (buffer_get_int_ret(&rounds, &kdf) < 0) { | ||
344 | error("%s: rounds not set", __func__); | ||
345 | goto out; | ||
346 | } | ||
347 | if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, | ||
348 | key, keylen + ivlen, rounds) < 0) { | ||
349 | error("%s: bcrypt_pbkdf failed", __func__); | ||
350 | goto out; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | cp = buffer_append_space(&b, len); | ||
355 | cipher_init(&ctx, c, key, keylen, key + keylen, ivlen, 0); | ||
356 | ret = cipher_crypt(&ctx, 0, cp, buffer_ptr(©), len, 0, authlen); | ||
357 | cipher_cleanup(&ctx); | ||
358 | buffer_consume(©, len); | ||
359 | |||
360 | /* fail silently on decryption errors */ | ||
361 | if (ret != 0) { | ||
362 | debug("%s: decrypt failed", __func__); | ||
363 | goto out; | ||
364 | } | ||
365 | |||
366 | if (buffer_len(©) != 0) { | ||
367 | error("%s: key blob has trailing data (len = %u)", __func__, | ||
368 | buffer_len(©)); | ||
369 | goto out; | ||
370 | } | ||
371 | |||
372 | /* check bytes */ | ||
373 | if (buffer_get_int_ret(&check1, &b) < 0 || | ||
374 | buffer_get_int_ret(&check2, &b) < 0) { | ||
375 | error("check bytes missing"); | ||
376 | goto out; | ||
377 | } | ||
378 | if (check1 != check2) { | ||
379 | debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__, | ||
380 | check1, check2); | ||
381 | goto out; | ||
382 | } | ||
383 | |||
384 | k = key_private_deserialize(&b); | ||
385 | |||
386 | /* comment */ | ||
387 | comment = buffer_get_cstring_ret(&b, NULL); | ||
388 | |||
389 | i = 0; | ||
390 | while (buffer_len(&b)) { | ||
391 | if (buffer_get_char_ret(&pad, &b) == -1 || | ||
392 | pad != (++i & 0xff)) { | ||
393 | error("%s: bad padding", __func__); | ||
394 | key_free(k); | ||
395 | k = NULL; | ||
396 | goto out; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | if (k && commentp) { | ||
401 | *commentp = comment; | ||
402 | comment = NULL; | ||
403 | } | ||
404 | |||
405 | /* XXX decode pubkey and check against private */ | ||
406 | out: | ||
407 | free(ciphername); | ||
408 | free(kdfname); | ||
409 | free(salt); | ||
410 | free(comment); | ||
411 | if (key) | ||
412 | explicit_bzero(key, keylen + ivlen); | ||
413 | free(key); | ||
414 | buffer_free(&encoded); | ||
415 | buffer_free(©); | ||
416 | buffer_free(&kdf); | ||
417 | buffer_free(&b); | ||
418 | return k; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * Serialises the authentication (private) key to a blob, encrypting it with | ||
423 | * passphrase. The identification of the blob (lowest 64 bits of n) will | ||
424 | * precede the key to provide identification of the key without needing a | ||
425 | * passphrase. | ||
426 | */ | ||
427 | static int | ||
428 | key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase, | ||
429 | const char *comment) | ||
430 | { | ||
431 | Buffer buffer, encrypted; | ||
432 | u_char buf[100], *cp; | ||
433 | int i, cipher_num; | ||
434 | CipherContext ciphercontext; | ||
435 | const Cipher *cipher; | ||
436 | u_int32_t rnd; | ||
437 | |||
438 | /* | ||
439 | * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting | ||
440 | * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. | ||
441 | */ | ||
442 | cipher_num = (strcmp(passphrase, "") == 0) ? | ||
443 | SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER; | ||
444 | if ((cipher = cipher_by_number(cipher_num)) == NULL) | ||
445 | fatal("save_private_key_rsa: bad cipher"); | ||
446 | |||
447 | /* This buffer is used to built the secret part of the private key. */ | ||
448 | buffer_init(&buffer); | ||
449 | |||
450 | /* Put checkbytes for checking passphrase validity. */ | ||
451 | rnd = arc4random(); | ||
452 | buf[0] = rnd & 0xff; | ||
453 | buf[1] = (rnd >> 8) & 0xff; | ||
454 | buf[2] = buf[0]; | ||
455 | buf[3] = buf[1]; | ||
456 | buffer_append(&buffer, buf, 4); | ||
457 | |||
458 | /* | ||
459 | * Store the private key (n and e will not be stored because they | ||
460 | * will be stored in plain text, and storing them also in encrypted | ||
461 | * format would just give known plaintext). | ||
462 | */ | ||
463 | buffer_put_bignum(&buffer, key->rsa->d); | ||
464 | buffer_put_bignum(&buffer, key->rsa->iqmp); | ||
465 | buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */ | ||
466 | buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */ | ||
467 | |||
468 | /* Pad the part to be encrypted until its size is a multiple of 8. */ | ||
469 | while (buffer_len(&buffer) % 8 != 0) | ||
470 | buffer_put_char(&buffer, 0); | ||
471 | |||
472 | /* This buffer will be used to contain the data in the file. */ | ||
473 | buffer_init(&encrypted); | ||
474 | |||
475 | /* First store keyfile id string. */ | ||
476 | for (i = 0; authfile_id_string[i]; i++) | ||
477 | buffer_put_char(&encrypted, authfile_id_string[i]); | ||
478 | buffer_put_char(&encrypted, 0); | ||
479 | |||
480 | /* Store cipher type. */ | ||
481 | buffer_put_char(&encrypted, cipher_num); | ||
482 | buffer_put_int(&encrypted, 0); /* For future extension */ | ||
483 | |||
484 | /* Store public key. This will be in plain text. */ | ||
485 | buffer_put_int(&encrypted, BN_num_bits(key->rsa->n)); | ||
486 | buffer_put_bignum(&encrypted, key->rsa->n); | ||
487 | buffer_put_bignum(&encrypted, key->rsa->e); | ||
488 | buffer_put_cstring(&encrypted, comment); | ||
489 | |||
490 | /* Allocate space for the private part of the key in the buffer. */ | ||
491 | cp = buffer_append_space(&encrypted, buffer_len(&buffer)); | ||
492 | |||
493 | cipher_set_key_string(&ciphercontext, cipher, passphrase, | ||
494 | CIPHER_ENCRYPT); | ||
495 | if (cipher_crypt(&ciphercontext, 0, cp, | ||
496 | buffer_ptr(&buffer), buffer_len(&buffer), 0, 0) != 0) | ||
497 | fatal("%s: cipher_crypt failed", __func__); | ||
498 | cipher_cleanup(&ciphercontext); | ||
499 | explicit_bzero(&ciphercontext, sizeof(ciphercontext)); | ||
500 | |||
501 | /* Destroy temporary data. */ | ||
502 | explicit_bzero(buf, sizeof(buf)); | ||
503 | buffer_free(&buffer); | ||
504 | |||
505 | buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted)); | ||
506 | buffer_free(&encrypted); | ||
507 | |||
508 | return 1; | ||
509 | } | ||
510 | |||
511 | /* convert SSH v2 key in OpenSSL PEM format */ | ||
512 | static int | ||
513 | key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase, | ||
514 | const char *comment) | ||
515 | { | ||
516 | int success = 0; | ||
517 | int blen, len = strlen(_passphrase); | ||
518 | u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; | ||
519 | #if (OPENSSL_VERSION_NUMBER < 0x00907000L) | ||
520 | const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; | ||
521 | #else | ||
522 | const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; | ||
523 | #endif | ||
524 | const u_char *bptr; | ||
525 | BIO *bio; | ||
526 | |||
527 | if (len > 0 && len <= 4) { | ||
528 | error("passphrase too short: have %d bytes, need > 4", len); | ||
529 | return 0; | ||
530 | } | ||
531 | if ((bio = BIO_new(BIO_s_mem())) == NULL) { | ||
532 | error("%s: BIO_new failed", __func__); | ||
533 | return 0; | ||
534 | } | ||
535 | switch (key->type) { | ||
536 | case KEY_DSA: | ||
537 | success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, | ||
538 | cipher, passphrase, len, NULL, NULL); | ||
539 | break; | ||
540 | #ifdef OPENSSL_HAS_ECC | ||
541 | case KEY_ECDSA: | ||
542 | success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, | ||
543 | cipher, passphrase, len, NULL, NULL); | ||
544 | break; | ||
545 | #endif | ||
546 | case KEY_RSA: | ||
547 | success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, | ||
548 | cipher, passphrase, len, NULL, NULL); | ||
549 | break; | ||
550 | } | ||
551 | if (success) { | ||
552 | if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) | ||
553 | success = 0; | ||
554 | else | ||
555 | buffer_append(blob, bptr, blen); | ||
556 | } | ||
557 | BIO_free(bio); | ||
558 | return success; | ||
559 | } | ||
560 | |||
561 | /* Save a key blob to a file */ | 54 | /* Save a key blob to a file */ |
562 | static int | 55 | static int |
563 | key_save_private_blob(Buffer *keybuf, const char *filename) | 56 | sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) |
564 | { | 57 | { |
565 | int fd; | 58 | int fd, oerrno; |
566 | 59 | ||
567 | if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { | 60 | if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) |
568 | error("open %s failed: %s.", filename, strerror(errno)); | 61 | return SSH_ERR_SYSTEM_ERROR; |
569 | return 0; | 62 | if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf), |
570 | } | 63 | sshbuf_len(keybuf)) != sshbuf_len(keybuf)) { |
571 | if (atomicio(vwrite, fd, buffer_ptr(keybuf), | 64 | oerrno = errno; |
572 | buffer_len(keybuf)) != buffer_len(keybuf)) { | ||
573 | error("write to key file %s failed: %s", filename, | ||
574 | strerror(errno)); | ||
575 | close(fd); | 65 | close(fd); |
576 | unlink(filename); | 66 | unlink(filename); |
577 | return 0; | 67 | errno = oerrno; |
68 | return SSH_ERR_SYSTEM_ERROR; | ||
578 | } | 69 | } |
579 | close(fd); | 70 | close(fd); |
580 | return 1; | 71 | return 0; |
581 | } | ||
582 | |||
583 | /* Serialise "key" to buffer "blob" */ | ||
584 | static int | ||
585 | key_private_to_blob(Key *key, Buffer *blob, const char *passphrase, | ||
586 | const char *comment, int force_new_format, const char *new_format_cipher, | ||
587 | int new_format_rounds) | ||
588 | { | ||
589 | switch (key->type) { | ||
590 | case KEY_RSA1: | ||
591 | return key_private_rsa1_to_blob(key, blob, passphrase, comment); | ||
592 | case KEY_DSA: | ||
593 | case KEY_ECDSA: | ||
594 | case KEY_RSA: | ||
595 | if (force_new_format) { | ||
596 | return key_private_to_blob2(key, blob, passphrase, | ||
597 | comment, new_format_cipher, new_format_rounds); | ||
598 | } | ||
599 | return key_private_pem_to_blob(key, blob, passphrase, comment); | ||
600 | case KEY_ED25519: | ||
601 | return key_private_to_blob2(key, blob, passphrase, | ||
602 | comment, new_format_cipher, new_format_rounds); | ||
603 | default: | ||
604 | error("%s: cannot save key type %d", __func__, key->type); | ||
605 | return 0; | ||
606 | } | ||
607 | } | 72 | } |
608 | 73 | ||
609 | int | 74 | int |
610 | key_save_private(Key *key, const char *filename, const char *passphrase, | 75 | sshkey_save_private(struct sshkey *key, const char *filename, |
611 | const char *comment, int force_new_format, const char *new_format_cipher, | 76 | const char *passphrase, const char *comment, |
612 | int new_format_rounds) | 77 | int force_new_format, const char *new_format_cipher, int new_format_rounds) |
613 | { | 78 | { |
614 | Buffer keyblob; | 79 | struct sshbuf *keyblob = NULL; |
615 | int success = 0; | 80 | int r; |
616 | 81 | ||
617 | buffer_init(&keyblob); | 82 | if ((keyblob = sshbuf_new()) == NULL) |
618 | if (!key_private_to_blob(key, &keyblob, passphrase, comment, | 83 | return SSH_ERR_ALLOC_FAIL; |
619 | force_new_format, new_format_cipher, new_format_rounds)) | 84 | if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment, |
85 | force_new_format, new_format_cipher, new_format_rounds)) != 0) | ||
620 | goto out; | 86 | goto out; |
621 | if (!key_save_private_blob(&keyblob, filename)) | 87 | if ((r = sshkey_save_private_blob(keyblob, filename)) != 0) |
622 | goto out; | 88 | goto out; |
623 | success = 1; | 89 | r = 0; |
624 | out: | 90 | out: |
625 | buffer_free(&keyblob); | 91 | sshbuf_free(keyblob); |
626 | return success; | 92 | return r; |
627 | } | ||
628 | |||
629 | /* | ||
630 | * Parse the public, unencrypted portion of a RSA1 key. | ||
631 | */ | ||
632 | static Key * | ||
633 | key_parse_public_rsa1(Buffer *blob, char **commentp) | ||
634 | { | ||
635 | Key *pub; | ||
636 | Buffer copy; | ||
637 | |||
638 | /* Check that it is at least big enough to contain the ID string. */ | ||
639 | if (buffer_len(blob) < sizeof(authfile_id_string)) { | ||
640 | debug3("Truncated RSA1 identifier"); | ||
641 | return NULL; | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | * Make sure it begins with the id string. Consume the id string | ||
646 | * from the buffer. | ||
647 | */ | ||
648 | if (memcmp(buffer_ptr(blob), authfile_id_string, | ||
649 | sizeof(authfile_id_string)) != 0) { | ||
650 | debug3("Incorrect RSA1 identifier"); | ||
651 | return NULL; | ||
652 | } | ||
653 | buffer_init(©); | ||
654 | buffer_append(©, buffer_ptr(blob), buffer_len(blob)); | ||
655 | buffer_consume(©, sizeof(authfile_id_string)); | ||
656 | |||
657 | /* Skip cipher type and reserved data. */ | ||
658 | (void) buffer_get_char(©); /* cipher type */ | ||
659 | (void) buffer_get_int(©); /* reserved */ | ||
660 | |||
661 | /* Read the public key from the buffer. */ | ||
662 | (void) buffer_get_int(©); | ||
663 | pub = key_new(KEY_RSA1); | ||
664 | buffer_get_bignum(©, pub->rsa->n); | ||
665 | buffer_get_bignum(©, pub->rsa->e); | ||
666 | if (commentp) | ||
667 | *commentp = buffer_get_string(©, NULL); | ||
668 | /* The encrypted private part is not parsed by this function. */ | ||
669 | buffer_free(©); | ||
670 | |||
671 | return pub; | ||
672 | } | 93 | } |
673 | 94 | ||
674 | /* Load a key from a fd into a buffer */ | 95 | /* Load a key from a fd into a buffer */ |
675 | int | 96 | int |
676 | key_load_file(int fd, const char *filename, Buffer *blob) | 97 | sshkey_load_file(int fd, const char *filename, struct sshbuf *blob) |
677 | { | 98 | { |
678 | u_char buf[1024]; | 99 | u_char buf[1024]; |
679 | size_t len; | 100 | size_t len; |
680 | struct stat st; | 101 | struct stat st; |
102 | int r; | ||
681 | 103 | ||
682 | if (fstat(fd, &st) < 0) { | 104 | if (fstat(fd, &st) < 0) |
683 | error("%s: fstat of key file %.200s%sfailed: %.100s", __func__, | 105 | return SSH_ERR_SYSTEM_ERROR; |
684 | filename == NULL ? "" : filename, | ||
685 | filename == NULL ? "" : " ", | ||
686 | strerror(errno)); | ||
687 | return 0; | ||
688 | } | ||
689 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && | 106 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && |
690 | st.st_size > MAX_KEY_FILE_SIZE) { | 107 | st.st_size > MAX_KEY_FILE_SIZE) |
691 | toobig: | 108 | return SSH_ERR_INVALID_FORMAT; |
692 | error("%s: key file %.200s%stoo large", __func__, | ||
693 | filename == NULL ? "" : filename, | ||
694 | filename == NULL ? "" : " "); | ||
695 | return 0; | ||
696 | } | ||
697 | buffer_clear(blob); | ||
698 | for (;;) { | 109 | for (;;) { |
699 | if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { | 110 | if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { |
700 | if (errno == EPIPE) | 111 | if (errno == EPIPE) |
701 | break; | 112 | break; |
702 | debug("%s: read from key file %.200s%sfailed: %.100s", | 113 | r = SSH_ERR_SYSTEM_ERROR; |
703 | __func__, filename == NULL ? "" : filename, | 114 | goto out; |
704 | filename == NULL ? "" : " ", strerror(errno)); | ||
705 | buffer_clear(blob); | ||
706 | explicit_bzero(buf, sizeof(buf)); | ||
707 | return 0; | ||
708 | } | 115 | } |
709 | buffer_append(blob, buf, len); | 116 | if ((r = sshbuf_put(blob, buf, len)) != 0) |
710 | if (buffer_len(blob) > MAX_KEY_FILE_SIZE) { | 117 | goto out; |
711 | buffer_clear(blob); | 118 | if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) { |
712 | explicit_bzero(buf, sizeof(buf)); | 119 | r = SSH_ERR_INVALID_FORMAT; |
713 | goto toobig; | 120 | goto out; |
714 | } | 121 | } |
715 | } | 122 | } |
716 | explicit_bzero(buf, sizeof(buf)); | ||
717 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && | 123 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && |
718 | st.st_size != buffer_len(blob)) { | 124 | st.st_size != (off_t)sshbuf_len(blob)) { |
719 | debug("%s: key file %.200s%schanged size while reading", | 125 | r = SSH_ERR_FILE_CHANGED; |
720 | __func__, filename == NULL ? "" : filename, | 126 | goto out; |
721 | filename == NULL ? "" : " "); | ||
722 | buffer_clear(blob); | ||
723 | return 0; | ||
724 | } | 127 | } |
128 | r = 0; | ||
725 | 129 | ||
726 | return 1; | 130 | out: |
131 | explicit_bzero(buf, sizeof(buf)); | ||
132 | if (r != 0) | ||
133 | sshbuf_reset(blob); | ||
134 | return r; | ||
727 | } | 135 | } |
728 | 136 | ||
137 | #ifdef WITH_SSH1 | ||
729 | /* | 138 | /* |
730 | * Loads the public part of the ssh v1 key file. Returns NULL if an error was | 139 | * Loads the public part of the ssh v1 key file. Returns NULL if an error was |
731 | * encountered (the file does not exist or is not readable), and the key | 140 | * encountered (the file does not exist or is not readable), and the key |
732 | * otherwise. | 141 | * otherwise. |
733 | */ | 142 | */ |
734 | static Key * | 143 | static int |
735 | key_load_public_rsa1(int fd, const char *filename, char **commentp) | 144 | sshkey_load_public_rsa1(int fd, const char *filename, |
145 | struct sshkey **keyp, char **commentp) | ||
736 | { | 146 | { |
737 | Buffer buffer; | 147 | struct sshbuf *b = NULL; |
738 | Key *pub; | 148 | int r; |
739 | |||
740 | buffer_init(&buffer); | ||
741 | if (!key_load_file(fd, filename, &buffer)) { | ||
742 | buffer_free(&buffer); | ||
743 | return NULL; | ||
744 | } | ||
745 | 149 | ||
746 | pub = key_parse_public_rsa1(&buffer, commentp); | 150 | *keyp = NULL; |
747 | if (pub == NULL) | 151 | if (commentp != NULL) |
748 | debug3("Could not load \"%s\" as a RSA1 public key", filename); | 152 | *commentp = NULL; |
749 | buffer_free(&buffer); | ||
750 | return pub; | ||
751 | } | ||
752 | |||
753 | /* load public key from private-key file, works only for SSH v1 */ | ||
754 | Key * | ||
755 | key_load_public_type(int type, const char *filename, char **commentp) | ||
756 | { | ||
757 | Key *pub; | ||
758 | int fd; | ||
759 | 153 | ||
760 | if (type == KEY_RSA1) { | 154 | if ((b = sshbuf_new()) == NULL) |
761 | fd = open(filename, O_RDONLY); | 155 | return SSH_ERR_ALLOC_FAIL; |
762 | if (fd < 0) | 156 | if ((r = sshkey_load_file(fd, filename, b)) != 0) |
763 | return NULL; | 157 | goto out; |
764 | pub = key_load_public_rsa1(fd, filename, commentp); | 158 | if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0) |
765 | close(fd); | 159 | goto out; |
766 | return pub; | 160 | r = 0; |
767 | } | 161 | out: |
768 | return NULL; | 162 | sshbuf_free(b); |
163 | return r; | ||
769 | } | 164 | } |
165 | #endif /* WITH_SSH1 */ | ||
770 | 166 | ||
771 | static Key * | 167 | #ifdef WITH_OPENSSL |
772 | key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp) | 168 | /* XXX Deprecate? */ |
169 | int | ||
170 | sshkey_load_private_pem(int fd, int type, const char *passphrase, | ||
171 | struct sshkey **keyp, char **commentp) | ||
773 | { | 172 | { |
774 | int check1, check2, cipher_type; | 173 | struct sshbuf *buffer = NULL; |
775 | Buffer decrypted; | 174 | int r; |
776 | u_char *cp; | ||
777 | CipherContext ciphercontext; | ||
778 | const Cipher *cipher; | ||
779 | Key *prv = NULL; | ||
780 | Buffer copy; | ||
781 | |||
782 | /* Check that it is at least big enough to contain the ID string. */ | ||
783 | if (buffer_len(blob) < sizeof(authfile_id_string)) { | ||
784 | debug3("Truncated RSA1 identifier"); | ||
785 | return NULL; | ||
786 | } | ||
787 | |||
788 | /* | ||
789 | * Make sure it begins with the id string. Consume the id string | ||
790 | * from the buffer. | ||
791 | */ | ||
792 | if (memcmp(buffer_ptr(blob), authfile_id_string, | ||
793 | sizeof(authfile_id_string)) != 0) { | ||
794 | debug3("Incorrect RSA1 identifier"); | ||
795 | return NULL; | ||
796 | } | ||
797 | buffer_init(©); | ||
798 | buffer_append(©, buffer_ptr(blob), buffer_len(blob)); | ||
799 | buffer_consume(©, sizeof(authfile_id_string)); | ||
800 | |||
801 | /* Read cipher type. */ | ||
802 | cipher_type = buffer_get_char(©); | ||
803 | (void) buffer_get_int(©); /* Reserved data. */ | ||
804 | |||
805 | /* Read the public key from the buffer. */ | ||
806 | (void) buffer_get_int(©); | ||
807 | prv = key_new_private(KEY_RSA1); | ||
808 | |||
809 | buffer_get_bignum(©, prv->rsa->n); | ||
810 | buffer_get_bignum(©, prv->rsa->e); | ||
811 | if (commentp) | ||
812 | *commentp = buffer_get_string(©, NULL); | ||
813 | else | ||
814 | (void)buffer_get_string_ptr(©, NULL); | ||
815 | 175 | ||
816 | /* Check that it is a supported cipher. */ | 176 | *keyp = NULL; |
817 | cipher = cipher_by_number(cipher_type); | ||
818 | if (cipher == NULL) { | ||
819 | debug("Unsupported RSA1 cipher %d", cipher_type); | ||
820 | buffer_free(©); | ||
821 | goto fail; | ||
822 | } | ||
823 | /* Initialize space for decrypted data. */ | ||
824 | buffer_init(&decrypted); | ||
825 | cp = buffer_append_space(&decrypted, buffer_len(©)); | ||
826 | |||
827 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ | ||
828 | cipher_set_key_string(&ciphercontext, cipher, passphrase, | ||
829 | CIPHER_DECRYPT); | ||
830 | if (cipher_crypt(&ciphercontext, 0, cp, | ||
831 | buffer_ptr(©), buffer_len(©), 0, 0) != 0) | ||
832 | fatal("%s: cipher_crypt failed", __func__); | ||
833 | cipher_cleanup(&ciphercontext); | ||
834 | explicit_bzero(&ciphercontext, sizeof(ciphercontext)); | ||
835 | buffer_free(©); | ||
836 | |||
837 | check1 = buffer_get_char(&decrypted); | ||
838 | check2 = buffer_get_char(&decrypted); | ||
839 | if (check1 != buffer_get_char(&decrypted) || | ||
840 | check2 != buffer_get_char(&decrypted)) { | ||
841 | if (strcmp(passphrase, "") != 0) | ||
842 | debug("Bad passphrase supplied for RSA1 key"); | ||
843 | /* Bad passphrase. */ | ||
844 | buffer_free(&decrypted); | ||
845 | goto fail; | ||
846 | } | ||
847 | /* Read the rest of the private key. */ | ||
848 | buffer_get_bignum(&decrypted, prv->rsa->d); | ||
849 | buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */ | ||
850 | /* in SSL and SSH v1 p and q are exchanged */ | ||
851 | buffer_get_bignum(&decrypted, prv->rsa->q); /* p */ | ||
852 | buffer_get_bignum(&decrypted, prv->rsa->p); /* q */ | ||
853 | |||
854 | /* calculate p-1 and q-1 */ | ||
855 | rsa_generate_additional_parameters(prv->rsa); | ||
856 | |||
857 | buffer_free(&decrypted); | ||
858 | |||
859 | /* enable blinding */ | ||
860 | if (RSA_blinding_on(prv->rsa, NULL) != 1) { | ||
861 | error("%s: RSA_blinding_on failed", __func__); | ||
862 | goto fail; | ||
863 | } | ||
864 | return prv; | ||
865 | |||
866 | fail: | ||
867 | if (commentp != NULL) | 177 | if (commentp != NULL) |
868 | free(*commentp); | 178 | *commentp = NULL; |
869 | key_free(prv); | ||
870 | return NULL; | ||
871 | } | ||
872 | |||
873 | static Key * | ||
874 | key_parse_private_pem(Buffer *blob, int type, const char *passphrase, | ||
875 | char **commentp) | ||
876 | { | ||
877 | EVP_PKEY *pk = NULL; | ||
878 | Key *prv = NULL; | ||
879 | char *name = "<no key>"; | ||
880 | BIO *bio; | ||
881 | 179 | ||
882 | if ((bio = BIO_new_mem_buf(buffer_ptr(blob), | 180 | if ((buffer = sshbuf_new()) == NULL) |
883 | buffer_len(blob))) == NULL) { | 181 | return SSH_ERR_ALLOC_FAIL; |
884 | error("%s: BIO_new_mem_buf failed", __func__); | 182 | if ((r = sshkey_load_file(fd, NULL, buffer)) != 0) |
885 | return NULL; | 183 | goto out; |
886 | } | 184 | if ((r = sshkey_parse_private_pem_fileblob(buffer, type, passphrase, |
887 | 185 | keyp, commentp)) != 0) | |
888 | pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase); | 186 | goto out; |
889 | BIO_free(bio); | 187 | r = 0; |
890 | if (pk == NULL) { | 188 | out: |
891 | debug("%s: PEM_read_PrivateKey failed", __func__); | 189 | sshbuf_free(buffer); |
892 | (void)ERR_get_error(); | 190 | return r; |
893 | } else if (pk->type == EVP_PKEY_RSA && | ||
894 | (type == KEY_UNSPEC||type==KEY_RSA)) { | ||
895 | prv = key_new(KEY_UNSPEC); | ||
896 | prv->rsa = EVP_PKEY_get1_RSA(pk); | ||
897 | prv->type = KEY_RSA; | ||
898 | name = "rsa w/o comment"; | ||
899 | #ifdef DEBUG_PK | ||
900 | RSA_print_fp(stderr, prv->rsa, 8); | ||
901 | #endif | ||
902 | if (RSA_blinding_on(prv->rsa, NULL) != 1) { | ||
903 | error("%s: RSA_blinding_on failed", __func__); | ||
904 | key_free(prv); | ||
905 | prv = NULL; | ||
906 | } | ||
907 | } else if (pk->type == EVP_PKEY_DSA && | ||
908 | (type == KEY_UNSPEC||type==KEY_DSA)) { | ||
909 | prv = key_new(KEY_UNSPEC); | ||
910 | prv->dsa = EVP_PKEY_get1_DSA(pk); | ||
911 | prv->type = KEY_DSA; | ||
912 | name = "dsa w/o comment"; | ||
913 | #ifdef DEBUG_PK | ||
914 | DSA_print_fp(stderr, prv->dsa, 8); | ||
915 | #endif | ||
916 | #ifdef OPENSSL_HAS_ECC | ||
917 | } else if (pk->type == EVP_PKEY_EC && | ||
918 | (type == KEY_UNSPEC||type==KEY_ECDSA)) { | ||
919 | prv = key_new(KEY_UNSPEC); | ||
920 | prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); | ||
921 | prv->type = KEY_ECDSA; | ||
922 | if ((prv->ecdsa_nid = key_ecdsa_key_to_nid(prv->ecdsa)) == -1 || | ||
923 | key_curve_nid_to_name(prv->ecdsa_nid) == NULL || | ||
924 | key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), | ||
925 | EC_KEY_get0_public_key(prv->ecdsa)) != 0 || | ||
926 | key_ec_validate_private(prv->ecdsa) != 0) { | ||
927 | error("%s: bad ECDSA key", __func__); | ||
928 | key_free(prv); | ||
929 | prv = NULL; | ||
930 | } | ||
931 | name = "ecdsa w/o comment"; | ||
932 | #ifdef DEBUG_PK | ||
933 | if (prv != NULL && prv->ecdsa != NULL) | ||
934 | key_dump_ec_key(prv->ecdsa); | ||
935 | #endif | ||
936 | #endif /* OPENSSL_HAS_ECC */ | ||
937 | } else { | ||
938 | error("%s: PEM_read_PrivateKey: mismatch or " | ||
939 | "unknown EVP_PKEY save_type %d", __func__, pk->save_type); | ||
940 | } | ||
941 | if (pk != NULL) | ||
942 | EVP_PKEY_free(pk); | ||
943 | if (prv != NULL && commentp) | ||
944 | *commentp = xstrdup(name); | ||
945 | debug("read PEM private key done: type %s", | ||
946 | prv ? key_type(prv) : "<unknown>"); | ||
947 | return prv; | ||
948 | } | ||
949 | |||
950 | Key * | ||
951 | key_load_private_pem(int fd, int type, const char *passphrase, | ||
952 | char **commentp) | ||
953 | { | ||
954 | Buffer buffer; | ||
955 | Key *prv; | ||
956 | |||
957 | buffer_init(&buffer); | ||
958 | if (!key_load_file(fd, NULL, &buffer)) { | ||
959 | buffer_free(&buffer); | ||
960 | return NULL; | ||
961 | } | ||
962 | prv = key_parse_private_pem(&buffer, type, passphrase, commentp); | ||
963 | buffer_free(&buffer); | ||
964 | return prv; | ||
965 | } | 191 | } |
192 | #endif /* WITH_OPENSSL */ | ||
966 | 193 | ||
194 | /* XXX remove error() calls from here? */ | ||
967 | int | 195 | int |
968 | key_perm_ok(int fd, const char *filename) | 196 | sshkey_perm_ok(int fd, const char *filename) |
969 | { | 197 | { |
970 | struct stat st; | 198 | struct stat st; |
971 | 199 | ||
972 | if (fstat(fd, &st) < 0) | 200 | if (fstat(fd, &st) < 0) |
973 | return 0; | 201 | return SSH_ERR_SYSTEM_ERROR; |
974 | /* | 202 | /* |
975 | * if a key owned by the user is accessed, then we check the | 203 | * if a key owned by the user is accessed, then we check the |
976 | * permissions of the file. if the key owned by a different user, | 204 | * permissions of the file. if the key owned by a different user, |
@@ -985,298 +213,311 @@ key_perm_ok(int fd, const char *filename) | |||
985 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | 213 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
986 | error("Permissions 0%3.3o for '%s' are too open.", | 214 | error("Permissions 0%3.3o for '%s' are too open.", |
987 | (u_int)st.st_mode & 0777, filename); | 215 | (u_int)st.st_mode & 0777, filename); |
988 | error("It is required that your private key files are NOT accessible by others."); | 216 | error("It is recommended that your private key files are NOT accessible by others."); |
989 | error("This private key will be ignored."); | 217 | error("This private key will be ignored."); |
990 | return 0; | 218 | return SSH_ERR_KEY_BAD_PERMISSIONS; |
991 | } | 219 | } |
992 | return 1; | 220 | return 0; |
993 | } | 221 | } |
994 | 222 | ||
995 | static Key * | 223 | /* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */ |
996 | key_parse_private_type(Buffer *blob, int type, const char *passphrase, | 224 | int |
997 | char **commentp) | 225 | sshkey_load_private_type(int type, const char *filename, const char *passphrase, |
226 | struct sshkey **keyp, char **commentp, int *perm_ok) | ||
998 | { | 227 | { |
999 | Key *k; | 228 | int fd, r; |
229 | struct sshbuf *buffer = NULL; | ||
1000 | 230 | ||
1001 | switch (type) { | 231 | *keyp = NULL; |
1002 | case KEY_RSA1: | 232 | if (commentp != NULL) |
1003 | return key_parse_private_rsa1(blob, passphrase, commentp); | 233 | *commentp = NULL; |
1004 | case KEY_DSA: | ||
1005 | case KEY_ECDSA: | ||
1006 | case KEY_RSA: | ||
1007 | return key_parse_private_pem(blob, type, passphrase, commentp); | ||
1008 | case KEY_ED25519: | ||
1009 | return key_parse_private2(blob, type, passphrase, commentp); | ||
1010 | case KEY_UNSPEC: | ||
1011 | if ((k = key_parse_private2(blob, type, passphrase, commentp))) | ||
1012 | return k; | ||
1013 | return key_parse_private_pem(blob, type, passphrase, commentp); | ||
1014 | default: | ||
1015 | error("%s: cannot parse key type %d", __func__, type); | ||
1016 | break; | ||
1017 | } | ||
1018 | return NULL; | ||
1019 | } | ||
1020 | |||
1021 | Key * | ||
1022 | key_load_private_type(int type, const char *filename, const char *passphrase, | ||
1023 | char **commentp, int *perm_ok) | ||
1024 | { | ||
1025 | int fd; | ||
1026 | Key *ret; | ||
1027 | Buffer buffer; | ||
1028 | 234 | ||
1029 | fd = open(filename, O_RDONLY); | 235 | if ((fd = open(filename, O_RDONLY)) < 0) { |
1030 | if (fd < 0) { | ||
1031 | debug("could not open key file '%s': %s", filename, | ||
1032 | strerror(errno)); | ||
1033 | if (perm_ok != NULL) | 236 | if (perm_ok != NULL) |
1034 | *perm_ok = 0; | 237 | *perm_ok = 0; |
1035 | return NULL; | 238 | return SSH_ERR_SYSTEM_ERROR; |
1036 | } | 239 | } |
1037 | if (!key_perm_ok(fd, filename)) { | 240 | if (sshkey_perm_ok(fd, filename) != 0) { |
1038 | if (perm_ok != NULL) | 241 | if (perm_ok != NULL) |
1039 | *perm_ok = 0; | 242 | *perm_ok = 0; |
1040 | error("bad permissions: ignore key: %s", filename); | 243 | r = SSH_ERR_KEY_BAD_PERMISSIONS; |
1041 | close(fd); | 244 | goto out; |
1042 | return NULL; | ||
1043 | } | 245 | } |
1044 | if (perm_ok != NULL) | 246 | if (perm_ok != NULL) |
1045 | *perm_ok = 1; | 247 | *perm_ok = 1; |
1046 | 248 | ||
1047 | buffer_init(&buffer); | 249 | if ((buffer = sshbuf_new()) == NULL) { |
1048 | if (!key_load_file(fd, filename, &buffer)) { | 250 | r = SSH_ERR_ALLOC_FAIL; |
1049 | buffer_free(&buffer); | 251 | goto out; |
1050 | close(fd); | ||
1051 | return NULL; | ||
1052 | } | 252 | } |
253 | if ((r = sshkey_load_file(fd, filename, buffer)) != 0) | ||
254 | goto out; | ||
255 | if ((r = sshkey_parse_private_fileblob_type(buffer, type, passphrase, | ||
256 | keyp, commentp)) != 0) | ||
257 | goto out; | ||
258 | r = 0; | ||
259 | out: | ||
1053 | close(fd); | 260 | close(fd); |
1054 | ret = key_parse_private_type(&buffer, type, passphrase, commentp); | 261 | if (buffer != NULL) |
1055 | buffer_free(&buffer); | 262 | sshbuf_free(buffer); |
1056 | return ret; | 263 | return r; |
1057 | } | 264 | } |
1058 | 265 | ||
1059 | Key * | 266 | /* XXX this is almost identical to sshkey_load_private_type() */ |
1060 | key_parse_private(Buffer *buffer, const char *filename, | 267 | int |
1061 | const char *passphrase, char **commentp) | 268 | sshkey_load_private(const char *filename, const char *passphrase, |
269 | struct sshkey **keyp, char **commentp) | ||
1062 | { | 270 | { |
1063 | Key *pub, *prv; | 271 | struct sshbuf *buffer = NULL; |
1064 | 272 | int r, fd; | |
1065 | /* it's a SSH v1 key if the public key part is readable */ | ||
1066 | pub = key_parse_public_rsa1(buffer, commentp); | ||
1067 | if (pub == NULL) { | ||
1068 | prv = key_parse_private_type(buffer, KEY_UNSPEC, | ||
1069 | passphrase, NULL); | ||
1070 | /* use the filename as a comment for PEM */ | ||
1071 | if (commentp && prv) | ||
1072 | *commentp = xstrdup(filename); | ||
1073 | } else { | ||
1074 | key_free(pub); | ||
1075 | /* key_parse_public_rsa1() has already loaded the comment */ | ||
1076 | prv = key_parse_private_type(buffer, KEY_RSA1, passphrase, | ||
1077 | NULL); | ||
1078 | } | ||
1079 | return prv; | ||
1080 | } | ||
1081 | 273 | ||
1082 | Key * | 274 | *keyp = NULL; |
1083 | key_load_private(const char *filename, const char *passphrase, | 275 | if (commentp != NULL) |
1084 | char **commentp) | 276 | *commentp = NULL; |
1085 | { | ||
1086 | Key *prv; | ||
1087 | Buffer buffer; | ||
1088 | int fd; | ||
1089 | 277 | ||
1090 | fd = open(filename, O_RDONLY); | 278 | if ((fd = open(filename, O_RDONLY)) < 0) |
1091 | if (fd < 0) { | 279 | return SSH_ERR_SYSTEM_ERROR; |
1092 | debug("could not open key file '%s': %s", filename, | 280 | if (sshkey_perm_ok(fd, filename) != 0) { |
1093 | strerror(errno)); | 281 | r = SSH_ERR_KEY_BAD_PERMISSIONS; |
1094 | return NULL; | 282 | goto out; |
1095 | } | ||
1096 | if (!key_perm_ok(fd, filename)) { | ||
1097 | error("bad permissions: ignore key: %s", filename); | ||
1098 | close(fd); | ||
1099 | return NULL; | ||
1100 | } | 283 | } |
1101 | 284 | ||
1102 | buffer_init(&buffer); | 285 | if ((buffer = sshbuf_new()) == NULL) { |
1103 | if (!key_load_file(fd, filename, &buffer)) { | 286 | r = SSH_ERR_ALLOC_FAIL; |
1104 | buffer_free(&buffer); | 287 | goto out; |
1105 | close(fd); | ||
1106 | return NULL; | ||
1107 | } | 288 | } |
289 | if ((r = sshkey_load_file(fd, filename, buffer)) != 0 || | ||
290 | (r = sshkey_parse_private_fileblob(buffer, passphrase, filename, | ||
291 | keyp, commentp)) != 0) | ||
292 | goto out; | ||
293 | r = 0; | ||
294 | out: | ||
1108 | close(fd); | 295 | close(fd); |
1109 | 296 | if (buffer != NULL) | |
1110 | prv = key_parse_private(&buffer, filename, passphrase, commentp); | 297 | sshbuf_free(buffer); |
1111 | buffer_free(&buffer); | 298 | return r; |
1112 | return prv; | ||
1113 | } | 299 | } |
1114 | 300 | ||
1115 | static int | 301 | static int |
1116 | key_try_load_public(Key *k, const char *filename, char **commentp) | 302 | sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) |
1117 | { | 303 | { |
1118 | FILE *f; | 304 | FILE *f; |
1119 | char line[SSH_MAX_PUBKEY_BYTES]; | 305 | char line[SSH_MAX_PUBKEY_BYTES]; |
1120 | char *cp; | 306 | char *cp; |
1121 | u_long linenum = 0; | 307 | u_long linenum = 0; |
308 | int r; | ||
1122 | 309 | ||
1123 | f = fopen(filename, "r"); | 310 | if (commentp != NULL) |
1124 | if (f != NULL) { | 311 | *commentp = NULL; |
1125 | while (read_keyfile_line(f, filename, line, sizeof(line), | 312 | if ((f = fopen(filename, "r")) == NULL) |
1126 | &linenum) != -1) { | 313 | return SSH_ERR_SYSTEM_ERROR; |
1127 | cp = line; | 314 | while (read_keyfile_line(f, filename, line, sizeof(line), |
1128 | switch (*cp) { | 315 | &linenum) != -1) { |
1129 | case '#': | 316 | cp = line; |
1130 | case '\n': | 317 | switch (*cp) { |
1131 | case '\0': | 318 | case '#': |
1132 | continue; | 319 | case '\n': |
1133 | } | 320 | case '\0': |
1134 | /* Abort loading if this looks like a private key */ | 321 | continue; |
1135 | if (strncmp(cp, "-----BEGIN", 10) == 0) | 322 | } |
1136 | break; | 323 | /* Abort loading if this looks like a private key */ |
1137 | /* Skip leading whitespace. */ | 324 | if (strncmp(cp, "-----BEGIN", 10) == 0 || |
1138 | for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) | 325 | strcmp(cp, "SSH PRIVATE KEY FILE") == 0) |
1139 | ; | 326 | break; |
1140 | if (*cp) { | 327 | /* Skip leading whitespace. */ |
1141 | if (key_read(k, &cp) == 1) { | 328 | for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) |
1142 | cp[strcspn(cp, "\r\n")] = '\0'; | 329 | ; |
1143 | if (commentp) { | 330 | if (*cp) { |
1144 | *commentp = xstrdup(*cp ? | 331 | if ((r = sshkey_read(k, &cp)) == 0) { |
1145 | cp : filename); | 332 | cp[strcspn(cp, "\r\n")] = '\0'; |
1146 | } | 333 | if (commentp) { |
1147 | fclose(f); | 334 | *commentp = strdup(*cp ? |
1148 | return 1; | 335 | cp : filename); |
336 | if (*commentp == NULL) | ||
337 | r = SSH_ERR_ALLOC_FAIL; | ||
1149 | } | 338 | } |
339 | fclose(f); | ||
340 | return r; | ||
1150 | } | 341 | } |
1151 | } | 342 | } |
1152 | fclose(f); | ||
1153 | } | 343 | } |
1154 | return 0; | 344 | fclose(f); |
345 | return SSH_ERR_INVALID_FORMAT; | ||
1155 | } | 346 | } |
1156 | 347 | ||
1157 | /* load public key from ssh v1 private or any pubkey file */ | 348 | /* load public key from ssh v1 private or any pubkey file */ |
1158 | Key * | 349 | int |
1159 | key_load_public(const char *filename, char **commentp) | 350 | sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) |
1160 | { | 351 | { |
1161 | Key *pub; | 352 | struct sshkey *pub = NULL; |
1162 | char file[MAXPATHLEN]; | 353 | char file[MAXPATHLEN]; |
354 | int r, fd; | ||
355 | |||
356 | if (keyp != NULL) | ||
357 | *keyp = NULL; | ||
358 | if (commentp != NULL) | ||
359 | *commentp = NULL; | ||
1163 | 360 | ||
361 | if ((fd = open(filename, O_RDONLY)) < 0) | ||
362 | goto skip; | ||
363 | #ifdef WITH_SSH1 | ||
1164 | /* try rsa1 private key */ | 364 | /* try rsa1 private key */ |
1165 | pub = key_load_public_type(KEY_RSA1, filename, commentp); | 365 | r = sshkey_load_public_rsa1(fd, filename, keyp, commentp); |
1166 | if (pub != NULL) | 366 | close(fd); |
1167 | return pub; | 367 | switch (r) { |
368 | case SSH_ERR_INTERNAL_ERROR: | ||
369 | case SSH_ERR_ALLOC_FAIL: | ||
370 | case SSH_ERR_INVALID_ARGUMENT: | ||
371 | case SSH_ERR_SYSTEM_ERROR: | ||
372 | case 0: | ||
373 | return r; | ||
374 | } | ||
375 | #endif /* WITH_SSH1 */ | ||
1168 | 376 | ||
377 | /* try ssh2 public key */ | ||
378 | if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) | ||
379 | return SSH_ERR_ALLOC_FAIL; | ||
380 | if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { | ||
381 | if (keyp != NULL) | ||
382 | *keyp = pub; | ||
383 | return 0; | ||
384 | } | ||
385 | sshkey_free(pub); | ||
386 | |||
387 | #ifdef WITH_SSH1 | ||
1169 | /* try rsa1 public key */ | 388 | /* try rsa1 public key */ |
1170 | pub = key_new(KEY_RSA1); | 389 | if ((pub = sshkey_new(KEY_RSA1)) == NULL) |
1171 | if (key_try_load_public(pub, filename, commentp) == 1) | 390 | return SSH_ERR_ALLOC_FAIL; |
1172 | return pub; | 391 | if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { |
1173 | key_free(pub); | 392 | if (keyp != NULL) |
393 | *keyp = pub; | ||
394 | return 0; | ||
395 | } | ||
396 | sshkey_free(pub); | ||
397 | #endif /* WITH_SSH1 */ | ||
1174 | 398 | ||
1175 | /* try ssh2 public key */ | 399 | skip: |
1176 | pub = key_new(KEY_UNSPEC); | 400 | /* try .pub suffix */ |
1177 | if (key_try_load_public(pub, filename, commentp) == 1) | 401 | if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) |
1178 | return pub; | 402 | return SSH_ERR_ALLOC_FAIL; |
403 | r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */ | ||
1179 | if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && | 404 | if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && |
1180 | (strlcat(file, ".pub", sizeof file) < sizeof(file)) && | 405 | (strlcat(file, ".pub", sizeof file) < sizeof(file)) && |
1181 | (key_try_load_public(pub, file, commentp) == 1)) | 406 | (r = sshkey_try_load_public(pub, file, commentp)) == 0) { |
1182 | return pub; | 407 | if (keyp != NULL) |
1183 | key_free(pub); | 408 | *keyp = pub; |
1184 | return NULL; | 409 | return 0; |
410 | } | ||
411 | sshkey_free(pub); | ||
412 | return r; | ||
1185 | } | 413 | } |
1186 | 414 | ||
1187 | /* Load the certificate associated with the named private key */ | 415 | /* Load the certificate associated with the named private key */ |
1188 | Key * | 416 | int |
1189 | key_load_cert(const char *filename) | 417 | sshkey_load_cert(const char *filename, struct sshkey **keyp) |
1190 | { | 418 | { |
1191 | Key *pub; | 419 | struct sshkey *pub = NULL; |
1192 | char *file; | 420 | char *file = NULL; |
421 | int r = SSH_ERR_INTERNAL_ERROR; | ||
1193 | 422 | ||
1194 | pub = key_new(KEY_UNSPEC); | 423 | *keyp = NULL; |
1195 | xasprintf(&file, "%s-cert.pub", filename); | 424 | |
1196 | if (key_try_load_public(pub, file, NULL) == 1) { | 425 | if (asprintf(&file, "%s-cert.pub", filename) == -1) |
1197 | free(file); | 426 | return SSH_ERR_ALLOC_FAIL; |
1198 | return pub; | 427 | |
428 | if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { | ||
429 | goto out; | ||
1199 | } | 430 | } |
1200 | free(file); | 431 | if ((r = sshkey_try_load_public(pub, file, NULL)) != 0) |
1201 | key_free(pub); | 432 | goto out; |
1202 | return NULL; | 433 | |
434 | *keyp = pub; | ||
435 | pub = NULL; | ||
436 | r = 0; | ||
437 | |||
438 | out: | ||
439 | if (file != NULL) | ||
440 | free(file); | ||
441 | if (pub != NULL) | ||
442 | sshkey_free(pub); | ||
443 | return r; | ||
1203 | } | 444 | } |
1204 | 445 | ||
1205 | /* Load private key and certificate */ | 446 | /* Load private key and certificate */ |
1206 | Key * | 447 | int |
1207 | key_load_private_cert(int type, const char *filename, const char *passphrase, | 448 | sshkey_load_private_cert(int type, const char *filename, const char *passphrase, |
1208 | int *perm_ok) | 449 | struct sshkey **keyp, int *perm_ok) |
1209 | { | 450 | { |
1210 | Key *key, *pub; | 451 | struct sshkey *key = NULL, *cert = NULL; |
452 | int r; | ||
453 | |||
454 | *keyp = NULL; | ||
1211 | 455 | ||
1212 | switch (type) { | 456 | switch (type) { |
457 | #ifdef WITH_OPENSSL | ||
1213 | case KEY_RSA: | 458 | case KEY_RSA: |
1214 | case KEY_DSA: | 459 | case KEY_DSA: |
1215 | case KEY_ECDSA: | 460 | case KEY_ECDSA: |
1216 | case KEY_ED25519: | 461 | case KEY_ED25519: |
462 | #endif /* WITH_OPENSSL */ | ||
463 | case KEY_UNSPEC: | ||
1217 | break; | 464 | break; |
1218 | default: | 465 | default: |
1219 | error("%s: unsupported key type", __func__); | 466 | return SSH_ERR_KEY_TYPE_UNKNOWN; |
1220 | return NULL; | ||
1221 | } | 467 | } |
1222 | 468 | ||
1223 | if ((key = key_load_private_type(type, filename, | 469 | if ((r = sshkey_load_private_type(type, filename, |
1224 | passphrase, NULL, perm_ok)) == NULL) | 470 | passphrase, &key, NULL, perm_ok)) != 0 || |
1225 | return NULL; | 471 | (r = sshkey_load_cert(filename, &cert)) != 0) |
1226 | 472 | goto out; | |
1227 | if ((pub = key_load_cert(filename)) == NULL) { | ||
1228 | key_free(key); | ||
1229 | return NULL; | ||
1230 | } | ||
1231 | 473 | ||
1232 | /* Make sure the private key matches the certificate */ | 474 | /* Make sure the private key matches the certificate */ |
1233 | if (key_equal_public(key, pub) == 0) { | 475 | if (sshkey_equal_public(key, cert) == 0) { |
1234 | error("%s: certificate does not match private key %s", | 476 | r = SSH_ERR_KEY_CERT_MISMATCH; |
1235 | __func__, filename); | 477 | goto out; |
1236 | } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) { | ||
1237 | error("%s: key_to_certified failed", __func__); | ||
1238 | } else { | ||
1239 | key_cert_copy(pub, key); | ||
1240 | key_free(pub); | ||
1241 | return key; | ||
1242 | } | 478 | } |
1243 | 479 | ||
1244 | key_free(key); | 480 | if ((r = sshkey_to_certified(key, sshkey_cert_is_legacy(cert))) != 0 || |
1245 | key_free(pub); | 481 | (r = sshkey_cert_copy(cert, key)) != 0) |
1246 | return NULL; | 482 | goto out; |
483 | r = 0; | ||
484 | *keyp = key; | ||
485 | key = NULL; | ||
486 | out: | ||
487 | if (key != NULL) | ||
488 | sshkey_free(key); | ||
489 | if (cert != NULL) | ||
490 | sshkey_free(cert); | ||
491 | return r; | ||
1247 | } | 492 | } |
1248 | 493 | ||
1249 | /* | 494 | /* |
1250 | * Returns 1 if the specified "key" is listed in the file "filename", | 495 | * Returns success if the specified "key" is listed in the file "filename", |
1251 | * 0 if the key is not listed or -1 on error. | 496 | * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. |
1252 | * If strict_type is set then the key type must match exactly, | 497 | * If strict_type is set then the key type must match exactly, |
1253 | * otherwise a comparison that ignores certficiate data is performed. | 498 | * otherwise a comparison that ignores certficiate data is performed. |
1254 | */ | 499 | */ |
1255 | int | 500 | int |
1256 | key_in_file(Key *key, const char *filename, int strict_type) | 501 | sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) |
1257 | { | 502 | { |
1258 | FILE *f; | 503 | FILE *f; |
1259 | char line[SSH_MAX_PUBKEY_BYTES]; | 504 | char line[SSH_MAX_PUBKEY_BYTES]; |
1260 | char *cp; | 505 | char *cp; |
1261 | u_long linenum = 0; | 506 | u_long linenum = 0; |
1262 | int ret = 0; | 507 | int r = 0; |
1263 | Key *pub; | 508 | struct sshkey *pub = NULL; |
1264 | int (*key_compare)(const Key *, const Key *) = strict_type ? | 509 | int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) = |
1265 | key_equal : key_equal_public; | 510 | strict_type ? sshkey_equal : sshkey_equal_public; |
1266 | 511 | ||
1267 | if ((f = fopen(filename, "r")) == NULL) { | 512 | if ((f = fopen(filename, "r")) == NULL) { |
1268 | if (errno == ENOENT) { | 513 | if (errno == ENOENT) |
1269 | debug("%s: keyfile \"%s\" missing", __func__, filename); | 514 | return SSH_ERR_KEY_NOT_FOUND; |
1270 | return 0; | 515 | else |
1271 | } else { | 516 | return SSH_ERR_SYSTEM_ERROR; |
1272 | error("%s: could not open keyfile \"%s\": %s", __func__, | ||
1273 | filename, strerror(errno)); | ||
1274 | return -1; | ||
1275 | } | ||
1276 | } | 517 | } |
1277 | 518 | ||
1278 | while (read_keyfile_line(f, filename, line, sizeof(line), | 519 | while (read_keyfile_line(f, filename, line, sizeof(line), |
1279 | &linenum) != -1) { | 520 | &linenum) != -1) { |
1280 | cp = line; | 521 | cp = line; |
1281 | 522 | ||
1282 | /* Skip leading whitespace. */ | 523 | /* Skip leading whitespace. */ |
@@ -1291,18 +532,24 @@ key_in_file(Key *key, const char *filename, int strict_type) | |||
1291 | continue; | 532 | continue; |
1292 | } | 533 | } |
1293 | 534 | ||
1294 | pub = key_new(KEY_UNSPEC); | 535 | if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { |
1295 | if (key_read(pub, &cp) != 1) { | 536 | r = SSH_ERR_ALLOC_FAIL; |
1296 | key_free(pub); | 537 | goto out; |
1297 | continue; | ||
1298 | } | 538 | } |
1299 | if (key_compare(key, pub)) { | 539 | if ((r = sshkey_read(pub, &cp)) != 0) |
1300 | ret = 1; | 540 | goto out; |
1301 | key_free(pub); | 541 | if (sshkey_compare(key, pub)) { |
1302 | break; | 542 | r = 0; |
543 | goto out; | ||
1303 | } | 544 | } |
1304 | key_free(pub); | 545 | sshkey_free(pub); |
546 | pub = NULL; | ||
1305 | } | 547 | } |
548 | r = SSH_ERR_KEY_NOT_FOUND; | ||
549 | out: | ||
550 | if (pub != NULL) | ||
551 | sshkey_free(pub); | ||
1306 | fclose(f); | 552 | fclose(f); |
1307 | return ret; | 553 | return r; |
1308 | } | 554 | } |
555 | |||
diff --git a/authfile.h b/authfile.h index 8ba1c2dbe..03bc3958c 100644 --- a/authfile.h +++ b/authfile.h | |||
@@ -1,32 +1,47 @@ | |||
1 | /* $OpenBSD: authfile.h,v 1.17 2013/12/06 13:34:54 markus Exp $ */ | 1 | /* $OpenBSD: authfile.h,v 1.19 2014/07/03 23:18:35 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. |
5 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
6 | * All rights reserved | ||
7 | * | 5 | * |
8 | * As far as I am concerned, the code I have written for this software | 6 | * Redistribution and use in source and binary forms, with or without |
9 | * can be used freely for any purpose. Any derived versions of this | 7 | * modification, are permitted provided that the following conditions |
10 | * software must be clearly marked as such, and if the derived work is | 8 | * are met: |
11 | * incompatible with the protocol description in the RFC file, it must be | 9 | * 1. Redistributions of source code must retain the above copyright |
12 | * called by a name other than "ssh" or "Secure Shell". | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
13 | */ | 25 | */ |
14 | 26 | ||
15 | #ifndef AUTHFILE_H | 27 | #ifndef AUTHFILE_H |
16 | #define AUTHFILE_H | 28 | #define AUTHFILE_H |
17 | 29 | ||
18 | int key_save_private(Key *, const char *, const char *, const char *, | 30 | struct sshbuf; |
19 | int, const char *, int); | 31 | struct sshkey; |
20 | int key_load_file(int, const char *, Buffer *); | 32 | |
21 | Key *key_load_cert(const char *); | 33 | int sshkey_save_private(struct sshkey *, const char *, |
22 | Key *key_load_public(const char *, char **); | 34 | const char *, const char *, int, const char *, int); |
23 | Key *key_load_public_type(int, const char *, char **); | 35 | int sshkey_load_file(int, const char *, struct sshbuf *); |
24 | Key *key_parse_private(Buffer *, const char *, const char *, char **); | 36 | int sshkey_load_cert(const char *, struct sshkey **); |
25 | Key *key_load_private(const char *, const char *, char **); | 37 | int sshkey_load_public(const char *, struct sshkey **, char **); |
26 | Key *key_load_private_cert(int, const char *, const char *, int *); | 38 | int sshkey_load_private(const char *, const char *, struct sshkey **, char **); |
27 | Key *key_load_private_type(int, const char *, const char *, char **, int *); | 39 | int sshkey_load_private_cert(int, const char *, const char *, |
28 | Key *key_load_private_pem(int, int, const char *, char **); | 40 | struct sshkey **, int *); |
29 | int key_perm_ok(int, const char *); | 41 | int sshkey_load_private_type(int, const char *, const char *, |
30 | int key_in_file(Key *, const char *, int); | 42 | struct sshkey **, char **, int *); |
43 | int sshkey_load_private_pem(int, int, const char *, struct sshkey **, char **); | ||
44 | int sshkey_perm_ok(int, const char *); | ||
45 | int sshkey_in_file(struct sshkey *, const char *, int); | ||
31 | 46 | ||
32 | #endif | 47 | #endif |
@@ -1,70 +1,40 @@ | |||
1 | /* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */ | 1 | /* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Copyright (c) 2012 Damien Miller <djm@mindrot.org> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
5 | * All rights reserved | ||
6 | * Auxiliary functions for storing and retrieving various data types to/from | ||
7 | * Buffers. | ||
8 | * | 4 | * |
9 | * As far as I am concerned, the code I have written for this software | 5 | * Permission to use, copy, modify, and distribute this software for any |
10 | * can be used freely for any purpose. Any derived versions of this | 6 | * purpose with or without fee is hereby granted, provided that the above |
11 | * software must be clearly marked as such, and if the derived work is | 7 | * copyright notice and this permission notice appear in all copies. |
12 | * incompatible with the protocol description in the RFC file, it must be | ||
13 | * called by a name other than "ssh" or "Secure Shell". | ||
14 | * | 8 | * |
15 | * | 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
16 | * SSH2 packet format added by Markus Friedl | 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
17 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
18 | * | 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
19 | * Redistribution and use in source and binary forms, with or without | 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
20 | * modification, are permitted provided that the following conditions | 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
21 | * are met: | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
22 | * 1. Redistributions of source code must retain the above copyright | ||
23 | * notice, this list of conditions and the following disclaimer. | ||
24 | * 2. Redistributions in binary form must reproduce the above copyright | ||
25 | * notice, this list of conditions and the following disclaimer in the | ||
26 | * documentation and/or other materials provided with the distribution. | ||
27 | * | ||
28 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
29 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
30 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
31 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
32 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
33 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
37 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | */ | 16 | */ |
39 | 17 | ||
18 | /* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ | ||
19 | |||
40 | #include "includes.h" | 20 | #include "includes.h" |
41 | 21 | ||
42 | #include <sys/types.h> | 22 | #include <sys/types.h> |
43 | 23 | ||
44 | #include <openssl/bn.h> | ||
45 | |||
46 | #include <string.h> | ||
47 | #include <stdarg.h> | ||
48 | #include <stdlib.h> | ||
49 | |||
50 | #include "xmalloc.h" | ||
51 | #include "buffer.h" | 24 | #include "buffer.h" |
52 | #include "log.h" | 25 | #include "log.h" |
53 | #include "misc.h" | 26 | #include "ssherr.h" |
54 | |||
55 | /* | ||
56 | * Returns integers from the buffer (msb first). | ||
57 | */ | ||
58 | 27 | ||
59 | int | 28 | int |
60 | buffer_get_short_ret(u_short *ret, Buffer *buffer) | 29 | buffer_get_short_ret(u_short *v, Buffer *buffer) |
61 | { | 30 | { |
62 | u_char buf[2]; | 31 | int ret; |
63 | 32 | ||
64 | if (buffer_get_ret(buffer, (char *) buf, 2) == -1) | 33 | if ((ret = sshbuf_get_u16(buffer, v)) != 0) { |
65 | return (-1); | 34 | error("%s: %s", __func__, ssh_err(ret)); |
66 | *ret = get_u16(buf); | 35 | return -1; |
67 | return (0); | 36 | } |
37 | return 0; | ||
68 | } | 38 | } |
69 | 39 | ||
70 | u_short | 40 | u_short |
@@ -73,21 +43,21 @@ buffer_get_short(Buffer *buffer) | |||
73 | u_short ret; | 43 | u_short ret; |
74 | 44 | ||
75 | if (buffer_get_short_ret(&ret, buffer) == -1) | 45 | if (buffer_get_short_ret(&ret, buffer) == -1) |
76 | fatal("buffer_get_short: buffer error"); | 46 | fatal("%s: buffer error", __func__); |
77 | 47 | ||
78 | return (ret); | 48 | return (ret); |
79 | } | 49 | } |
80 | 50 | ||
81 | int | 51 | int |
82 | buffer_get_int_ret(u_int *ret, Buffer *buffer) | 52 | buffer_get_int_ret(u_int *v, Buffer *buffer) |
83 | { | 53 | { |
84 | u_char buf[4]; | 54 | int ret; |
85 | 55 | ||
86 | if (buffer_get_ret(buffer, (char *) buf, 4) == -1) | 56 | if ((ret = sshbuf_get_u32(buffer, v)) != 0) { |
87 | return (-1); | 57 | error("%s: %s", __func__, ssh_err(ret)); |
88 | if (ret != NULL) | 58 | return -1; |
89 | *ret = get_u32(buf); | 59 | } |
90 | return (0); | 60 | return 0; |
91 | } | 61 | } |
92 | 62 | ||
93 | u_int | 63 | u_int |
@@ -96,21 +66,21 @@ buffer_get_int(Buffer *buffer) | |||
96 | u_int ret; | 66 | u_int ret; |
97 | 67 | ||
98 | if (buffer_get_int_ret(&ret, buffer) == -1) | 68 | if (buffer_get_int_ret(&ret, buffer) == -1) |
99 | fatal("buffer_get_int: buffer error"); | 69 | fatal("%s: buffer error", __func__); |
100 | 70 | ||
101 | return (ret); | 71 | return (ret); |
102 | } | 72 | } |
103 | 73 | ||
104 | int | 74 | int |
105 | buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) | 75 | buffer_get_int64_ret(u_int64_t *v, Buffer *buffer) |
106 | { | 76 | { |
107 | u_char buf[8]; | 77 | int ret; |
108 | 78 | ||
109 | if (buffer_get_ret(buffer, (char *) buf, 8) == -1) | 79 | if ((ret = sshbuf_get_u64(buffer, v)) != 0) { |
110 | return (-1); | 80 | error("%s: %s", __func__, ssh_err(ret)); |
111 | if (ret != NULL) | 81 | return -1; |
112 | *ret = get_u64(buf); | 82 | } |
113 | return (0); | 83 | return 0; |
114 | } | 84 | } |
115 | 85 | ||
116 | u_int64_t | 86 | u_int64_t |
@@ -119,78 +89,52 @@ buffer_get_int64(Buffer *buffer) | |||
119 | u_int64_t ret; | 89 | u_int64_t ret; |
120 | 90 | ||
121 | if (buffer_get_int64_ret(&ret, buffer) == -1) | 91 | if (buffer_get_int64_ret(&ret, buffer) == -1) |
122 | fatal("buffer_get_int: buffer error"); | 92 | fatal("%s: buffer error", __func__); |
123 | 93 | ||
124 | return (ret); | 94 | return (ret); |
125 | } | 95 | } |
126 | 96 | ||
127 | /* | ||
128 | * Stores integers in the buffer, msb first. | ||
129 | */ | ||
130 | void | 97 | void |
131 | buffer_put_short(Buffer *buffer, u_short value) | 98 | buffer_put_short(Buffer *buffer, u_short value) |
132 | { | 99 | { |
133 | char buf[2]; | 100 | int ret; |
134 | 101 | ||
135 | put_u16(buf, value); | 102 | if ((ret = sshbuf_put_u16(buffer, value)) != 0) |
136 | buffer_append(buffer, buf, 2); | 103 | fatal("%s: %s", __func__, ssh_err(ret)); |
137 | } | 104 | } |
138 | 105 | ||
139 | void | 106 | void |
140 | buffer_put_int(Buffer *buffer, u_int value) | 107 | buffer_put_int(Buffer *buffer, u_int value) |
141 | { | 108 | { |
142 | char buf[4]; | 109 | int ret; |
143 | 110 | ||
144 | put_u32(buf, value); | 111 | if ((ret = sshbuf_put_u32(buffer, value)) != 0) |
145 | buffer_append(buffer, buf, 4); | 112 | fatal("%s: %s", __func__, ssh_err(ret)); |
146 | } | 113 | } |
147 | 114 | ||
148 | void | 115 | void |
149 | buffer_put_int64(Buffer *buffer, u_int64_t value) | 116 | buffer_put_int64(Buffer *buffer, u_int64_t value) |
150 | { | 117 | { |
151 | char buf[8]; | 118 | int ret; |
152 | 119 | ||
153 | put_u64(buf, value); | 120 | if ((ret = sshbuf_put_u64(buffer, value)) != 0) |
154 | buffer_append(buffer, buf, 8); | 121 | fatal("%s: %s", __func__, ssh_err(ret)); |
155 | } | 122 | } |
156 | 123 | ||
157 | /* | ||
158 | * Returns an arbitrary binary string from the buffer. The string cannot | ||
159 | * be longer than 256k. The returned value points to memory allocated | ||
160 | * with xmalloc; it is the responsibility of the calling function to free | ||
161 | * the data. If length_ptr is non-NULL, the length of the returned data | ||
162 | * will be stored there. A null character will be automatically appended | ||
163 | * to the returned string, and is not counted in length. | ||
164 | */ | ||
165 | void * | 124 | void * |
166 | buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) | 125 | buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) |
167 | { | 126 | { |
127 | size_t len; | ||
128 | int ret; | ||
168 | u_char *value; | 129 | u_char *value; |
169 | u_int len; | ||
170 | 130 | ||
171 | /* Get the length. */ | 131 | if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) { |
172 | if (buffer_get_int_ret(&len, buffer) != 0) { | 132 | error("%s: %s", __func__, ssh_err(ret)); |
173 | error("buffer_get_string_ret: cannot extract length"); | 133 | return NULL; |
174 | return (NULL); | ||
175 | } | ||
176 | if (len > 256 * 1024) { | ||
177 | error("buffer_get_string_ret: bad string length %u", len); | ||
178 | return (NULL); | ||
179 | } | ||
180 | /* Allocate space for the string. Add one byte for a null character. */ | ||
181 | value = xmalloc(len + 1); | ||
182 | /* Get the string. */ | ||
183 | if (buffer_get_ret(buffer, value, len) == -1) { | ||
184 | error("buffer_get_string_ret: buffer_get failed"); | ||
185 | free(value); | ||
186 | return (NULL); | ||
187 | } | 134 | } |
188 | /* Append a null character to make processing easier. */ | 135 | if (length_ptr != NULL) |
189 | value[len] = '\0'; | 136 | *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ |
190 | /* Optionally return the length of the string. */ | 137 | return value; |
191 | if (length_ptr) | ||
192 | *length_ptr = len; | ||
193 | return (value); | ||
194 | } | 138 | } |
195 | 139 | ||
196 | void * | 140 | void * |
@@ -199,31 +143,24 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr) | |||
199 | void *ret; | 143 | void *ret; |
200 | 144 | ||
201 | if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) | 145 | if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) |
202 | fatal("buffer_get_string: buffer error"); | 146 | fatal("%s: buffer error", __func__); |
203 | return (ret); | 147 | return (ret); |
204 | } | 148 | } |
205 | 149 | ||
206 | char * | 150 | char * |
207 | buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) | 151 | buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) |
208 | { | 152 | { |
209 | u_int length; | 153 | size_t len; |
210 | char *cp, *ret = buffer_get_string_ret(buffer, &length); | 154 | int ret; |
155 | char *value; | ||
211 | 156 | ||
212 | if (ret == NULL) | 157 | if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) { |
158 | error("%s: %s", __func__, ssh_err(ret)); | ||
213 | return NULL; | 159 | return NULL; |
214 | if ((cp = memchr(ret, '\0', length)) != NULL) { | ||
215 | /* XXX allow \0 at end-of-string for a while, remove later */ | ||
216 | if (cp == ret + length - 1) | ||
217 | error("buffer_get_cstring_ret: string contains \\0"); | ||
218 | else { | ||
219 | explicit_bzero(ret, length); | ||
220 | free(ret); | ||
221 | return NULL; | ||
222 | } | ||
223 | } | 160 | } |
224 | if (length_ptr != NULL) | 161 | if (length_ptr != NULL) |
225 | *length_ptr = length; | 162 | *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ |
226 | return ret; | 163 | return value; |
227 | } | 164 | } |
228 | 165 | ||
229 | char * | 166 | char * |
@@ -232,162 +169,91 @@ buffer_get_cstring(Buffer *buffer, u_int *length_ptr) | |||
232 | char *ret; | 169 | char *ret; |
233 | 170 | ||
234 | if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) | 171 | if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) |
235 | fatal("buffer_get_cstring: buffer error"); | 172 | fatal("%s: buffer error", __func__); |
236 | return ret; | 173 | return ret; |
237 | } | 174 | } |
238 | 175 | ||
239 | void * | 176 | const void * |
240 | buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) | 177 | buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) |
241 | { | 178 | { |
242 | void *ptr; | 179 | size_t len; |
243 | u_int len; | 180 | int ret; |
181 | const u_char *value; | ||
244 | 182 | ||
245 | if (buffer_get_int_ret(&len, buffer) != 0) | 183 | if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) { |
246 | return NULL; | 184 | error("%s: %s", __func__, ssh_err(ret)); |
247 | if (len > 256 * 1024) { | ||
248 | error("buffer_get_string_ptr: bad string length %u", len); | ||
249 | return NULL; | 185 | return NULL; |
250 | } | 186 | } |
251 | ptr = buffer_ptr(buffer); | 187 | if (length_ptr != NULL) |
252 | buffer_consume(buffer, len); | 188 | *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ |
253 | if (length_ptr) | 189 | return value; |
254 | *length_ptr = len; | ||
255 | return (ptr); | ||
256 | } | 190 | } |
257 | 191 | ||
258 | void * | 192 | const void * |
259 | buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) | 193 | buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) |
260 | { | 194 | { |
261 | void *ret; | 195 | const void *ret; |
262 | 196 | ||
263 | if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) | 197 | if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) |
264 | fatal("buffer_get_string_ptr: buffer error"); | 198 | fatal("%s: buffer error", __func__); |
265 | return (ret); | 199 | return (ret); |
266 | } | 200 | } |
267 | 201 | ||
268 | /* | ||
269 | * Stores and arbitrary binary string in the buffer. | ||
270 | */ | ||
271 | void | 202 | void |
272 | buffer_put_string(Buffer *buffer, const void *buf, u_int len) | 203 | buffer_put_string(Buffer *buffer, const void *buf, u_int len) |
273 | { | 204 | { |
274 | buffer_put_int(buffer, len); | 205 | int ret; |
275 | buffer_append(buffer, buf, len); | 206 | |
207 | if ((ret = sshbuf_put_string(buffer, buf, len)) != 0) | ||
208 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
276 | } | 209 | } |
210 | |||
277 | void | 211 | void |
278 | buffer_put_cstring(Buffer *buffer, const char *s) | 212 | buffer_put_cstring(Buffer *buffer, const char *s) |
279 | { | 213 | { |
280 | if (s == NULL) | 214 | int ret; |
281 | fatal("buffer_put_cstring: s == NULL"); | 215 | |
282 | buffer_put_string(buffer, s, strlen(s)); | 216 | if ((ret = sshbuf_put_cstring(buffer, s)) != 0) |
217 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
283 | } | 218 | } |
284 | 219 | ||
285 | /* | ||
286 | * Returns a character from the buffer (0 - 255). | ||
287 | */ | ||
288 | int | 220 | int |
289 | buffer_get_char_ret(u_char *ret, Buffer *buffer) | 221 | buffer_get_char_ret(char *v, Buffer *buffer) |
290 | { | 222 | { |
291 | if (buffer_get_ret(buffer, ret, 1) == -1) { | 223 | int ret; |
292 | error("buffer_get_char_ret: buffer_get_ret failed"); | 224 | |
293 | return (-1); | 225 | if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) { |
226 | error("%s: %s", __func__, ssh_err(ret)); | ||
227 | return -1; | ||
294 | } | 228 | } |
295 | return (0); | 229 | return 0; |
296 | } | 230 | } |
297 | 231 | ||
298 | int | 232 | int |
299 | buffer_get_char(Buffer *buffer) | 233 | buffer_get_char(Buffer *buffer) |
300 | { | 234 | { |
301 | u_char ch; | 235 | char ch; |
302 | 236 | ||
303 | if (buffer_get_char_ret(&ch, buffer) == -1) | 237 | if (buffer_get_char_ret(&ch, buffer) == -1) |
304 | fatal("buffer_get_char: buffer error"); | 238 | fatal("%s: buffer error", __func__); |
305 | return ch; | 239 | return (u_char) ch; |
306 | } | 240 | } |
307 | 241 | ||
308 | /* | ||
309 | * Stores a character in the buffer. | ||
310 | */ | ||
311 | void | 242 | void |
312 | buffer_put_char(Buffer *buffer, int value) | 243 | buffer_put_char(Buffer *buffer, int value) |
313 | { | 244 | { |
314 | char ch = value; | 245 | int ret; |
315 | 246 | ||
316 | buffer_append(buffer, &ch, 1); | 247 | if ((ret = sshbuf_put_u8(buffer, value)) != 0) |
248 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
317 | } | 249 | } |
318 | 250 | ||
319 | /* Pseudo bignum functions */ | ||
320 | |||
321 | void * | ||
322 | buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr) | ||
323 | { | ||
324 | u_int len; | ||
325 | u_char *bin, *p, *ret; | ||
326 | |||
327 | if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) { | ||
328 | error("%s: invalid bignum", __func__); | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | if (len > 0 && (bin[0] & 0x80)) { | ||
333 | error("%s: negative numbers not supported", __func__); | ||
334 | free(bin); | ||
335 | return NULL; | ||
336 | } | ||
337 | if (len > 8 * 1024) { | ||
338 | error("%s: cannot handle BN of size %d", __func__, len); | ||
339 | free(bin); | ||
340 | return NULL; | ||
341 | } | ||
342 | /* Skip zero prefix on numbers with the MSB set */ | ||
343 | if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) { | ||
344 | p++; | ||
345 | len--; | ||
346 | } | ||
347 | ret = xmalloc(len); | ||
348 | memcpy(ret, p, len); | ||
349 | explicit_bzero(p, len); | ||
350 | free(bin); | ||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | void * | ||
355 | buffer_get_bignum2_as_string(Buffer *buffer, u_int *l) | ||
356 | { | ||
357 | void *ret = buffer_get_bignum2_as_string_ret(buffer, l); | ||
358 | |||
359 | if (ret == NULL) | ||
360 | fatal("%s: buffer error", __func__); | ||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * Stores a string using the bignum encoding rules (\0 pad if MSB set). | ||
366 | */ | ||
367 | void | 251 | void |
368 | buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) | 252 | buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) |
369 | { | 253 | { |
370 | u_char *buf, *p; | 254 | int ret; |
371 | int pad = 0; | ||
372 | |||
373 | if (l > 8 * 1024) | ||
374 | fatal("%s: length %u too long", __func__, l); | ||
375 | /* Skip leading zero bytes */ | ||
376 | for (; l > 0 && *s == 0; l--, s++) | ||
377 | ; | ||
378 | p = buf = xmalloc(l + 1); | ||
379 | /* | ||
380 | * If most significant bit is set then prepend a zero byte to | ||
381 | * avoid interpretation as a negative number. | ||
382 | */ | ||
383 | if (l > 0 && (s[0] & 0x80) != 0) { | ||
384 | *p++ = '\0'; | ||
385 | pad = 1; | ||
386 | } | ||
387 | memcpy(p, s, l); | ||
388 | buffer_put_string(buffer, buf, l + pad); | ||
389 | explicit_bzero(buf, l + pad); | ||
390 | free(buf); | ||
391 | } | ||
392 | 255 | ||
256 | if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0) | ||
257 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
258 | } | ||
393 | 259 | ||
@@ -1,229 +1,103 @@ | |||
1 | /* $OpenBSD: bufbn.c,v 1.11 2014/02/27 08:25:09 djm Exp $*/ | 1 | /* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */ |
2 | |||
2 | /* | 3 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Copyright (c) 2012 Damien Miller <djm@mindrot.org> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
5 | * All rights reserved | ||
6 | * Auxiliary functions for storing and retrieving various data types to/from | ||
7 | * Buffers. | ||
8 | * | ||
9 | * As far as I am concerned, the code I have written for this software | ||
10 | * can be used freely for any purpose. Any derived versions of this | ||
11 | * software must be clearly marked as such, and if the derived work is | ||
12 | * incompatible with the protocol description in the RFC file, it must be | ||
13 | * called by a name other than "ssh" or "Secure Shell". | ||
14 | * | ||
15 | * | ||
16 | * SSH2 packet format added by Markus Friedl | ||
17 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
18 | * | 5 | * |
19 | * Redistribution and use in source and binary forms, with or without | 6 | * Permission to use, copy, modify, and distribute this software for any |
20 | * modification, are permitted provided that the following conditions | 7 | * purpose with or without fee is hereby granted, provided that the above |
21 | * are met: | 8 | * copyright notice and this permission notice appear in all copies. |
22 | * 1. Redistributions of source code must retain the above copyright | ||
23 | * notice, this list of conditions and the following disclaimer. | ||
24 | * 2. Redistributions in binary form must reproduce the above copyright | ||
25 | * notice, this list of conditions and the following disclaimer in the | ||
26 | * documentation and/or other materials provided with the distribution. | ||
27 | * | 9 | * |
28 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
29 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
30 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
31 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
32 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
33 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
37 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | */ | 17 | */ |
39 | 18 | ||
19 | /* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ | ||
20 | |||
40 | #include "includes.h" | 21 | #include "includes.h" |
41 | 22 | ||
42 | #include <sys/types.h> | 23 | #include <sys/types.h> |
43 | 24 | ||
44 | #include <openssl/bn.h> | ||
45 | |||
46 | #include <string.h> | ||
47 | #include <stdarg.h> | ||
48 | #include <stdlib.h> | ||
49 | |||
50 | #include "xmalloc.h" | ||
51 | #include "buffer.h" | 25 | #include "buffer.h" |
52 | #include "log.h" | 26 | #include "log.h" |
53 | #include "misc.h" | 27 | #include "ssherr.h" |
54 | 28 | ||
55 | /* | ||
56 | * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed | ||
57 | * by (bits+7)/8 bytes of binary data, msb first. | ||
58 | */ | ||
59 | int | 29 | int |
60 | buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) | 30 | buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) |
61 | { | 31 | { |
62 | int bits = BN_num_bits(value); | 32 | int ret; |
63 | int bin_size = (bits + 7) / 8; | ||
64 | u_char *buf = xmalloc(bin_size); | ||
65 | int oi; | ||
66 | char msg[2]; | ||
67 | |||
68 | /* Get the value of in binary */ | ||
69 | oi = BN_bn2bin(value, buf); | ||
70 | if (oi != bin_size) { | ||
71 | error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d", | ||
72 | oi, bin_size); | ||
73 | free(buf); | ||
74 | return (-1); | ||
75 | } | ||
76 | |||
77 | /* Store the number of bits in the buffer in two bytes, msb first. */ | ||
78 | put_u16(msg, bits); | ||
79 | buffer_append(buffer, msg, 2); | ||
80 | /* Store the binary data. */ | ||
81 | buffer_append(buffer, buf, oi); | ||
82 | |||
83 | explicit_bzero(buf, bin_size); | ||
84 | free(buf); | ||
85 | 33 | ||
86 | return (0); | 34 | if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) { |
35 | error("%s: %s", __func__, ssh_err(ret)); | ||
36 | return -1; | ||
37 | } | ||
38 | return 0; | ||
87 | } | 39 | } |
88 | 40 | ||
89 | void | 41 | void |
90 | buffer_put_bignum(Buffer *buffer, const BIGNUM *value) | 42 | buffer_put_bignum(Buffer *buffer, const BIGNUM *value) |
91 | { | 43 | { |
92 | if (buffer_put_bignum_ret(buffer, value) == -1) | 44 | if (buffer_put_bignum_ret(buffer, value) == -1) |
93 | fatal("buffer_put_bignum: buffer error"); | 45 | fatal("%s: buffer error", __func__); |
94 | } | 46 | } |
95 | 47 | ||
96 | /* | ||
97 | * Retrieves a BIGNUM from the buffer. | ||
98 | */ | ||
99 | int | 48 | int |
100 | buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) | 49 | buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) |
101 | { | 50 | { |
102 | u_int bits, bytes; | 51 | int ret; |
103 | u_char buf[2], *bin; | ||
104 | 52 | ||
105 | /* Get the number of bits. */ | 53 | if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) { |
106 | if (buffer_get_ret(buffer, (char *) buf, 2) == -1) { | 54 | error("%s: %s", __func__, ssh_err(ret)); |
107 | error("buffer_get_bignum_ret: invalid length"); | 55 | return -1; |
108 | return (-1); | ||
109 | } | 56 | } |
110 | bits = get_u16(buf); | 57 | return 0; |
111 | if (bits > 65535-7) { | ||
112 | error("buffer_get_bignum_ret: cannot handle BN of size %d", | ||
113 | bits); | ||
114 | return (-1); | ||
115 | } | ||
116 | /* Compute the number of binary bytes that follow. */ | ||
117 | bytes = (bits + 7) / 8; | ||
118 | if (bytes > 8 * 1024) { | ||
119 | error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes); | ||
120 | return (-1); | ||
121 | } | ||
122 | if (buffer_len(buffer) < bytes) { | ||
123 | error("buffer_get_bignum_ret: input buffer too small"); | ||
124 | return (-1); | ||
125 | } | ||
126 | bin = buffer_ptr(buffer); | ||
127 | if (BN_bin2bn(bin, bytes, value) == NULL) { | ||
128 | error("buffer_get_bignum_ret: BN_bin2bn failed"); | ||
129 | return (-1); | ||
130 | } | ||
131 | if (buffer_consume_ret(buffer, bytes) == -1) { | ||
132 | error("buffer_get_bignum_ret: buffer_consume failed"); | ||
133 | return (-1); | ||
134 | } | ||
135 | return (0); | ||
136 | } | 58 | } |
137 | 59 | ||
138 | void | 60 | void |
139 | buffer_get_bignum(Buffer *buffer, BIGNUM *value) | 61 | buffer_get_bignum(Buffer *buffer, BIGNUM *value) |
140 | { | 62 | { |
141 | if (buffer_get_bignum_ret(buffer, value) == -1) | 63 | if (buffer_get_bignum_ret(buffer, value) == -1) |
142 | fatal("buffer_get_bignum: buffer error"); | 64 | fatal("%s: buffer error", __func__); |
143 | } | 65 | } |
144 | 66 | ||
145 | /* | ||
146 | * Stores a BIGNUM in the buffer in SSH2 format. | ||
147 | */ | ||
148 | int | 67 | int |
149 | buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) | 68 | buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) |
150 | { | 69 | { |
151 | u_int bytes; | 70 | int ret; |
152 | u_char *buf; | 71 | |
153 | int oi; | 72 | if ((ret = sshbuf_put_bignum2(buffer, value)) != 0) { |
154 | u_int hasnohigh = 0; | 73 | error("%s: %s", __func__, ssh_err(ret)); |
155 | 74 | return -1; | |
156 | if (BN_is_zero(value)) { | ||
157 | buffer_put_int(buffer, 0); | ||
158 | return 0; | ||
159 | } | ||
160 | if (value->neg) { | ||
161 | error("buffer_put_bignum2_ret: negative numbers not supported"); | ||
162 | return (-1); | ||
163 | } | ||
164 | bytes = BN_num_bytes(value) + 1; /* extra padding byte */ | ||
165 | if (bytes < 2) { | ||
166 | error("buffer_put_bignum2_ret: BN too small"); | ||
167 | return (-1); | ||
168 | } | ||
169 | buf = xmalloc(bytes); | ||
170 | buf[0] = 0x00; | ||
171 | /* Get the value of in binary */ | ||
172 | oi = BN_bn2bin(value, buf+1); | ||
173 | if (oi < 0 || (u_int)oi != bytes - 1) { | ||
174 | error("buffer_put_bignum2_ret: BN_bn2bin() failed: " | ||
175 | "oi %d != bin_size %d", oi, bytes); | ||
176 | free(buf); | ||
177 | return (-1); | ||
178 | } | 75 | } |
179 | hasnohigh = (buf[1] & 0x80) ? 0 : 1; | 76 | return 0; |
180 | buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); | ||
181 | explicit_bzero(buf, bytes); | ||
182 | free(buf); | ||
183 | return (0); | ||
184 | } | 77 | } |
185 | 78 | ||
186 | void | 79 | void |
187 | buffer_put_bignum2(Buffer *buffer, const BIGNUM *value) | 80 | buffer_put_bignum2(Buffer *buffer, const BIGNUM *value) |
188 | { | 81 | { |
189 | if (buffer_put_bignum2_ret(buffer, value) == -1) | 82 | if (buffer_put_bignum2_ret(buffer, value) == -1) |
190 | fatal("buffer_put_bignum2: buffer error"); | 83 | fatal("%s: buffer error", __func__); |
191 | } | 84 | } |
192 | 85 | ||
193 | int | 86 | int |
194 | buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) | 87 | buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) |
195 | { | 88 | { |
196 | u_int len; | 89 | int ret; |
197 | u_char *bin; | ||
198 | 90 | ||
199 | if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) { | 91 | if ((ret = sshbuf_get_bignum2(buffer, value)) != 0) { |
200 | error("buffer_get_bignum2_ret: invalid bignum"); | 92 | error("%s: %s", __func__, ssh_err(ret)); |
201 | return (-1); | 93 | return -1; |
202 | } | ||
203 | |||
204 | if (len > 0 && (bin[0] & 0x80)) { | ||
205 | error("buffer_get_bignum2_ret: negative numbers not supported"); | ||
206 | free(bin); | ||
207 | return (-1); | ||
208 | } | ||
209 | if (len > 8 * 1024) { | ||
210 | error("buffer_get_bignum2_ret: cannot handle BN of size %d", | ||
211 | len); | ||
212 | free(bin); | ||
213 | return (-1); | ||
214 | } | ||
215 | if (BN_bin2bn(bin, len, value) == NULL) { | ||
216 | error("buffer_get_bignum2_ret: BN_bin2bn failed"); | ||
217 | free(bin); | ||
218 | return (-1); | ||
219 | } | 94 | } |
220 | free(bin); | 95 | return 0; |
221 | return (0); | ||
222 | } | 96 | } |
223 | 97 | ||
224 | void | 98 | void |
225 | buffer_get_bignum2(Buffer *buffer, BIGNUM *value) | 99 | buffer_get_bignum2(Buffer *buffer, BIGNUM *value) |
226 | { | 100 | { |
227 | if (buffer_get_bignum2_ret(buffer, value) == -1) | 101 | if (buffer_get_bignum2_ret(buffer, value) == -1) |
228 | fatal("buffer_get_bignum2: buffer error"); | 102 | fatal("%s: buffer error", __func__); |
229 | } | 103 | } |
@@ -1,6 +1,7 @@ | |||
1 | /* $OpenBSD: bufec.c,v 1.3 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: bufec.c,v 1.4 2014/04/30 05:29:56 djm Exp $ */ |
2 | |||
2 | /* | 3 | /* |
3 | * Copyright (c) 2010 Damien Miller <djm@mindrot.org> | 4 | * Copyright (c) 2012 Damien Miller <djm@mindrot.org> |
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and distribute this software for any | 6 | * Permission to use, copy, modify, and distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -15,73 +16,29 @@ | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 17 | */ |
17 | 18 | ||
18 | #include "includes.h" | 19 | /* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ |
19 | 20 | ||
20 | #ifdef OPENSSL_HAS_ECC | 21 | #include "includes.h" |
21 | 22 | ||
22 | #include <sys/types.h> | 23 | #include <sys/types.h> |
23 | 24 | ||
24 | #include <openssl/bn.h> | ||
25 | #include <openssl/ec.h> | ||
26 | |||
27 | #include <string.h> | ||
28 | #include <stdarg.h> | ||
29 | |||
30 | #include "xmalloc.h" | ||
31 | #include "buffer.h" | 25 | #include "buffer.h" |
32 | #include "log.h" | 26 | #include "log.h" |
33 | #include "misc.h" | 27 | #include "ssherr.h" |
34 | 28 | ||
35 | /* | 29 | #ifdef OPENSSL_HAS_ECC |
36 | * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed | ||
37 | * encoding represents this as two bitstring points that should each | ||
38 | * be no longer than the field length, SEC1 specifies a 1 byte | ||
39 | * point type header. | ||
40 | * Being paranoid here may insulate us to parsing problems in | ||
41 | * EC_POINT_oct2point. | ||
42 | */ | ||
43 | #define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1) | ||
44 | 30 | ||
45 | /* | ||
46 | * Append an EC_POINT to the buffer as a string containing a SEC1 encoded | ||
47 | * uncompressed point. Fortunately OpenSSL handles the gory details for us. | ||
48 | */ | ||
49 | int | 31 | int |
50 | buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, | 32 | buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, |
51 | const EC_POINT *point) | 33 | const EC_POINT *point) |
52 | { | 34 | { |
53 | u_char *buf = NULL; | 35 | int ret; |
54 | size_t len; | ||
55 | BN_CTX *bnctx; | ||
56 | int ret = -1; | ||
57 | 36 | ||
58 | /* Determine length */ | 37 | if ((ret = sshbuf_put_ec(buffer, point, curve)) != 0) { |
59 | if ((bnctx = BN_CTX_new()) == NULL) | 38 | error("%s: %s", __func__, ssh_err(ret)); |
60 | fatal("%s: BN_CTX_new failed", __func__); | 39 | return -1; |
61 | len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, | ||
62 | NULL, 0, bnctx); | ||
63 | if (len > BUFFER_MAX_ECPOINT_LEN) { | ||
64 | error("%s: giant EC point: len = %lu (max %u)", | ||
65 | __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN); | ||
66 | goto out; | ||
67 | } | ||
68 | /* Convert */ | ||
69 | buf = xmalloc(len); | ||
70 | if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, | ||
71 | buf, len, bnctx) != len) { | ||
72 | error("%s: EC_POINT_point2oct length mismatch", __func__); | ||
73 | goto out; | ||
74 | } | ||
75 | /* Append */ | ||
76 | buffer_put_string(buffer, buf, len); | ||
77 | ret = 0; | ||
78 | out: | ||
79 | if (buf != NULL) { | ||
80 | explicit_bzero(buf, len); | ||
81 | free(buf); | ||
82 | } | 40 | } |
83 | BN_CTX_free(bnctx); | 41 | return 0; |
84 | return ret; | ||
85 | } | 42 | } |
86 | 43 | ||
87 | void | 44 | void |
@@ -96,43 +53,13 @@ int | |||
96 | buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, | 53 | buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, |
97 | EC_POINT *point) | 54 | EC_POINT *point) |
98 | { | 55 | { |
99 | u_char *buf; | 56 | int ret; |
100 | u_int len; | ||
101 | BN_CTX *bnctx; | ||
102 | int ret = -1; | ||
103 | 57 | ||
104 | if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) { | 58 | if ((ret = sshbuf_get_ec(buffer, point, curve)) != 0) { |
105 | error("%s: invalid point", __func__); | 59 | error("%s: %s", __func__, ssh_err(ret)); |
106 | return -1; | 60 | return -1; |
107 | } | 61 | } |
108 | if ((bnctx = BN_CTX_new()) == NULL) | 62 | return 0; |
109 | fatal("%s: BN_CTX_new failed", __func__); | ||
110 | if (len > BUFFER_MAX_ECPOINT_LEN) { | ||
111 | error("%s: EC_POINT too long: %u > max %u", __func__, | ||
112 | len, BUFFER_MAX_ECPOINT_LEN); | ||
113 | goto out; | ||
114 | } | ||
115 | if (len == 0) { | ||
116 | error("%s: EC_POINT buffer is empty", __func__); | ||
117 | goto out; | ||
118 | } | ||
119 | if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) { | ||
120 | error("%s: EC_POINT is in an incorrect form: " | ||
121 | "0x%02x (want 0x%02x)", __func__, buf[0], | ||
122 | POINT_CONVERSION_UNCOMPRESSED); | ||
123 | goto out; | ||
124 | } | ||
125 | if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) { | ||
126 | error("buffer_get_bignum2_ret: BN_bin2bn failed"); | ||
127 | goto out; | ||
128 | } | ||
129 | /* EC_POINT_oct2point verifies that the point is on the curve for us */ | ||
130 | ret = 0; | ||
131 | out: | ||
132 | BN_CTX_free(bnctx); | ||
133 | explicit_bzero(buf, len); | ||
134 | free(buf); | ||
135 | return ret; | ||
136 | } | 63 | } |
137 | 64 | ||
138 | void | 65 | void |
@@ -144,3 +71,4 @@ buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve, | |||
144 | } | 71 | } |
145 | 72 | ||
146 | #endif /* OPENSSL_HAS_ECC */ | 73 | #endif /* OPENSSL_HAS_ECC */ |
74 | |||
@@ -1,253 +1,118 @@ | |||
1 | /* $OpenBSD: buffer.c,v 1.35 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: buffer.c,v 1.36 2014/04/30 05:29:56 djm Exp $ */ |
2 | |||
2 | /* | 3 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Copyright (c) 2012 Damien Miller <djm@mindrot.org> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 5 | * |
5 | * All rights reserved | 6 | * Permission to use, copy, modify, and distribute this software for any |
6 | * Functions for manipulating fifo buffers (that can grow if needed). | 7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | 9 | * |
8 | * As far as I am concerned, the code I have written for this software | 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * can be used freely for any purpose. Any derived versions of this | 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * software must be clearly marked as such, and if the derived work is | 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * incompatible with the protocol description in the RFC file, it must be | 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * called by a name other than "ssh" or "Secure Shell". | 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
13 | */ | 17 | */ |
14 | 18 | ||
15 | #include "includes.h" | 19 | /* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ |
16 | 20 | ||
17 | #include <sys/param.h> | 21 | #include "includes.h" |
18 | 22 | ||
19 | #include <stdio.h> | 23 | #include <sys/types.h> |
20 | #include <string.h> | ||
21 | #include <stdarg.h> | ||
22 | #include <stdlib.h> | ||
23 | 24 | ||
24 | #include "xmalloc.h" | ||
25 | #include "buffer.h" | 25 | #include "buffer.h" |
26 | #include "log.h" | 26 | #include "log.h" |
27 | 27 | #include "ssherr.h" | |
28 | #define BUFFER_MAX_CHUNK 0x100000 | ||
29 | #define BUFFER_MAX_LEN 0xa00000 | ||
30 | #define BUFFER_ALLOCSZ 0x008000 | ||
31 | |||
32 | /* Initializes the buffer structure. */ | ||
33 | |||
34 | void | ||
35 | buffer_init(Buffer *buffer) | ||
36 | { | ||
37 | const u_int len = 4096; | ||
38 | |||
39 | buffer->alloc = 0; | ||
40 | buffer->buf = xmalloc(len); | ||
41 | buffer->alloc = len; | ||
42 | buffer->offset = 0; | ||
43 | buffer->end = 0; | ||
44 | } | ||
45 | |||
46 | /* Frees any memory used for the buffer. */ | ||
47 | |||
48 | void | ||
49 | buffer_free(Buffer *buffer) | ||
50 | { | ||
51 | if (buffer->alloc > 0) { | ||
52 | explicit_bzero(buffer->buf, buffer->alloc); | ||
53 | buffer->alloc = 0; | ||
54 | free(buffer->buf); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * Clears any data from the buffer, making it empty. This does not actually | ||
60 | * zero the memory. | ||
61 | */ | ||
62 | |||
63 | void | ||
64 | buffer_clear(Buffer *buffer) | ||
65 | { | ||
66 | buffer->offset = 0; | ||
67 | buffer->end = 0; | ||
68 | } | ||
69 | |||
70 | /* Appends data to the buffer, expanding it if necessary. */ | ||
71 | 28 | ||
72 | void | 29 | void |
73 | buffer_append(Buffer *buffer, const void *data, u_int len) | 30 | buffer_append(Buffer *buffer, const void *data, u_int len) |
74 | { | 31 | { |
75 | void *p; | 32 | int ret; |
76 | p = buffer_append_space(buffer, len); | ||
77 | memcpy(p, data, len); | ||
78 | } | ||
79 | 33 | ||
80 | static int | 34 | if ((ret = sshbuf_put(buffer, data, len)) != 0) |
81 | buffer_compact(Buffer *buffer) | 35 | fatal("%s: %s", __func__, ssh_err(ret)); |
82 | { | ||
83 | /* | ||
84 | * If the buffer is quite empty, but all data is at the end, move the | ||
85 | * data to the beginning. | ||
86 | */ | ||
87 | if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) { | ||
88 | memmove(buffer->buf, buffer->buf + buffer->offset, | ||
89 | buffer->end - buffer->offset); | ||
90 | buffer->end -= buffer->offset; | ||
91 | buffer->offset = 0; | ||
92 | return (1); | ||
93 | } | ||
94 | return (0); | ||
95 | } | 36 | } |
96 | 37 | ||
97 | /* | ||
98 | * Appends space to the buffer, expanding the buffer if necessary. This does | ||
99 | * not actually copy the data into the buffer, but instead returns a pointer | ||
100 | * to the allocated region. | ||
101 | */ | ||
102 | |||
103 | void * | 38 | void * |
104 | buffer_append_space(Buffer *buffer, u_int len) | 39 | buffer_append_space(Buffer *buffer, u_int len) |
105 | { | 40 | { |
106 | u_int newlen; | 41 | int ret; |
107 | void *p; | 42 | u_char *p; |
108 | 43 | ||
109 | if (len > BUFFER_MAX_CHUNK) | 44 | if ((ret = sshbuf_reserve(buffer, len, &p)) != 0) |
110 | fatal("buffer_append_space: len %u not supported", len); | 45 | fatal("%s: %s", __func__, ssh_err(ret)); |
111 | 46 | return p; | |
112 | /* If the buffer is empty, start using it from the beginning. */ | ||
113 | if (buffer->offset == buffer->end) { | ||
114 | buffer->offset = 0; | ||
115 | buffer->end = 0; | ||
116 | } | ||
117 | restart: | ||
118 | /* If there is enough space to store all data, store it now. */ | ||
119 | if (buffer->end + len < buffer->alloc) { | ||
120 | p = buffer->buf + buffer->end; | ||
121 | buffer->end += len; | ||
122 | return p; | ||
123 | } | ||
124 | |||
125 | /* Compact data back to the start of the buffer if necessary */ | ||
126 | if (buffer_compact(buffer)) | ||
127 | goto restart; | ||
128 | |||
129 | /* Increase the size of the buffer and retry. */ | ||
130 | newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ); | ||
131 | if (newlen > BUFFER_MAX_LEN) | ||
132 | fatal("buffer_append_space: alloc %u not supported", | ||
133 | newlen); | ||
134 | buffer->buf = xrealloc(buffer->buf, 1, newlen); | ||
135 | buffer->alloc = newlen; | ||
136 | goto restart; | ||
137 | /* NOTREACHED */ | ||
138 | } | 47 | } |
139 | 48 | ||
140 | /* | ||
141 | * Check whether an allocation of 'len' will fit in the buffer | ||
142 | * This must follow the same math as buffer_append_space | ||
143 | */ | ||
144 | int | 49 | int |
145 | buffer_check_alloc(Buffer *buffer, u_int len) | 50 | buffer_check_alloc(Buffer *buffer, u_int len) |
146 | { | 51 | { |
147 | if (buffer->offset == buffer->end) { | 52 | int ret = sshbuf_check_reserve(buffer, len); |
148 | buffer->offset = 0; | ||
149 | buffer->end = 0; | ||
150 | } | ||
151 | restart: | ||
152 | if (buffer->end + len < buffer->alloc) | ||
153 | return (1); | ||
154 | if (buffer_compact(buffer)) | ||
155 | goto restart; | ||
156 | if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN) | ||
157 | return (1); | ||
158 | return (0); | ||
159 | } | ||
160 | |||
161 | /* Returns the number of bytes of data in the buffer. */ | ||
162 | 53 | ||
163 | u_int | 54 | if (ret == 0) |
164 | buffer_len(const Buffer *buffer) | 55 | return 1; |
165 | { | 56 | if (ret == SSH_ERR_NO_BUFFER_SPACE) |
166 | return buffer->end - buffer->offset; | 57 | return 0; |
58 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
167 | } | 59 | } |
168 | 60 | ||
169 | /* Gets data from the beginning of the buffer. */ | ||
170 | |||
171 | int | 61 | int |
172 | buffer_get_ret(Buffer *buffer, void *buf, u_int len) | 62 | buffer_get_ret(Buffer *buffer, void *buf, u_int len) |
173 | { | 63 | { |
174 | if (len > buffer->end - buffer->offset) { | 64 | int ret; |
175 | error("buffer_get_ret: trying to get more bytes %d than in buffer %d", | 65 | |
176 | len, buffer->end - buffer->offset); | 66 | if ((ret = sshbuf_get(buffer, buf, len)) != 0) { |
177 | return (-1); | 67 | error("%s: %s", __func__, ssh_err(ret)); |
68 | return -1; | ||
178 | } | 69 | } |
179 | memcpy(buf, buffer->buf + buffer->offset, len); | 70 | return 0; |
180 | buffer->offset += len; | ||
181 | return (0); | ||
182 | } | 71 | } |
183 | 72 | ||
184 | void | 73 | void |
185 | buffer_get(Buffer *buffer, void *buf, u_int len) | 74 | buffer_get(Buffer *buffer, void *buf, u_int len) |
186 | { | 75 | { |
187 | if (buffer_get_ret(buffer, buf, len) == -1) | 76 | if (buffer_get_ret(buffer, buf, len) == -1) |
188 | fatal("buffer_get: buffer error"); | 77 | fatal("%s: buffer error", __func__); |
189 | } | 78 | } |
190 | 79 | ||
191 | /* Consumes the given number of bytes from the beginning of the buffer. */ | ||
192 | |||
193 | int | 80 | int |
194 | buffer_consume_ret(Buffer *buffer, u_int bytes) | 81 | buffer_consume_ret(Buffer *buffer, u_int bytes) |
195 | { | 82 | { |
196 | if (bytes > buffer->end - buffer->offset) { | 83 | int ret = sshbuf_consume(buffer, bytes); |
197 | error("buffer_consume_ret: trying to get more bytes than in buffer"); | 84 | |
198 | return (-1); | 85 | if (ret == 0) |
199 | } | 86 | return 0; |
200 | buffer->offset += bytes; | 87 | if (ret == SSH_ERR_MESSAGE_INCOMPLETE) |
201 | return (0); | 88 | return -1; |
89 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
202 | } | 90 | } |
203 | 91 | ||
204 | void | 92 | void |
205 | buffer_consume(Buffer *buffer, u_int bytes) | 93 | buffer_consume(Buffer *buffer, u_int bytes) |
206 | { | 94 | { |
207 | if (buffer_consume_ret(buffer, bytes) == -1) | 95 | if (buffer_consume_ret(buffer, bytes) == -1) |
208 | fatal("buffer_consume: buffer error"); | 96 | fatal("%s: buffer error", __func__); |
209 | } | 97 | } |
210 | 98 | ||
211 | /* Consumes the given number of bytes from the end of the buffer. */ | ||
212 | |||
213 | int | 99 | int |
214 | buffer_consume_end_ret(Buffer *buffer, u_int bytes) | 100 | buffer_consume_end_ret(Buffer *buffer, u_int bytes) |
215 | { | 101 | { |
216 | if (bytes > buffer->end - buffer->offset) | 102 | int ret = sshbuf_consume_end(buffer, bytes); |
217 | return (-1); | 103 | |
218 | buffer->end -= bytes; | 104 | if (ret == 0) |
219 | return (0); | 105 | return 0; |
106 | if (ret == SSH_ERR_MESSAGE_INCOMPLETE) | ||
107 | return -1; | ||
108 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
220 | } | 109 | } |
221 | 110 | ||
222 | void | 111 | void |
223 | buffer_consume_end(Buffer *buffer, u_int bytes) | 112 | buffer_consume_end(Buffer *buffer, u_int bytes) |
224 | { | 113 | { |
225 | if (buffer_consume_end_ret(buffer, bytes) == -1) | 114 | if (buffer_consume_end_ret(buffer, bytes) == -1) |
226 | fatal("buffer_consume_end: trying to get more bytes than in buffer"); | 115 | fatal("%s: buffer error", __func__); |
227 | } | ||
228 | |||
229 | /* Returns a pointer to the first used byte in the buffer. */ | ||
230 | |||
231 | void * | ||
232 | buffer_ptr(const Buffer *buffer) | ||
233 | { | ||
234 | return buffer->buf + buffer->offset; | ||
235 | } | 116 | } |
236 | 117 | ||
237 | /* Dumps the contents of the buffer to stderr. */ | ||
238 | 118 | ||
239 | void | ||
240 | buffer_dump(const Buffer *buffer) | ||
241 | { | ||
242 | u_int i; | ||
243 | u_char *ucp = buffer->buf; | ||
244 | |||
245 | for (i = buffer->offset; i < buffer->end; i++) { | ||
246 | fprintf(stderr, "%02x", ucp[i]); | ||
247 | if ((i-buffer->offset)%16==15) | ||
248 | fprintf(stderr, "\r\n"); | ||
249 | else if ((i-buffer->offset)%2==1) | ||
250 | fprintf(stderr, " "); | ||
251 | } | ||
252 | fprintf(stderr, "\r\n"); | ||
253 | } | ||
@@ -1,57 +1,58 @@ | |||
1 | /* $OpenBSD: buffer.h,v 1.23 2014/01/12 08:13:13 djm Exp $ */ | 1 | /* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Copyright (c) 2012 Damien Miller <djm@mindrot.org> |
5 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
6 | * All rights reserved | ||
7 | * Code for manipulating FIFO buffers. | ||
8 | * | 5 | * |
9 | * As far as I am concerned, the code I have written for this software | 6 | * Permission to use, copy, modify, and distribute this software for any |
10 | * can be used freely for any purpose. Any derived versions of this | 7 | * purpose with or without fee is hereby granted, provided that the above |
11 | * software must be clearly marked as such, and if the derived work is | 8 | * copyright notice and this permission notice appear in all copies. |
12 | * incompatible with the protocol description in the RFC file, it must be | 9 | * |
13 | * called by a name other than "ssh" or "Secure Shell". | 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
14 | */ | 17 | */ |
15 | 18 | ||
19 | /* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ | ||
20 | |||
16 | #ifndef BUFFER_H | 21 | #ifndef BUFFER_H |
17 | #define BUFFER_H | 22 | #define BUFFER_H |
18 | 23 | ||
19 | typedef struct { | 24 | #include "sshbuf.h" |
20 | u_char *buf; /* Buffer for data. */ | 25 | |
21 | u_int alloc; /* Number of bytes allocated for data. */ | 26 | typedef struct sshbuf Buffer; |
22 | u_int offset; /* Offset of first byte containing data. */ | ||
23 | u_int end; /* Offset of last byte containing data. */ | ||
24 | } Buffer; | ||
25 | 27 | ||
26 | void buffer_init(Buffer *); | 28 | #define buffer_init(b) sshbuf_init(b) |
27 | void buffer_clear(Buffer *); | 29 | #define buffer_clear(b) sshbuf_reset(b) |
28 | void buffer_free(Buffer *); | 30 | #define buffer_free(b) sshbuf_free(b) |
31 | #define buffer_dump(b) sshbuf_dump(b, stderr) | ||
29 | 32 | ||
30 | u_int buffer_len(const Buffer *); | 33 | /* XXX cast is safe: sshbuf never stores more than len 2^31 */ |
31 | void *buffer_ptr(const Buffer *); | 34 | #define buffer_len(b) ((u_int) sshbuf_len(b)) |
35 | #define buffer_ptr(b) sshbuf_mutable_ptr(b) | ||
32 | 36 | ||
33 | void buffer_append(Buffer *, const void *, u_int); | 37 | void buffer_append(Buffer *, const void *, u_int); |
34 | void *buffer_append_space(Buffer *, u_int); | 38 | void *buffer_append_space(Buffer *, u_int); |
35 | |||
36 | int buffer_check_alloc(Buffer *, u_int); | 39 | int buffer_check_alloc(Buffer *, u_int); |
37 | |||
38 | void buffer_get(Buffer *, void *, u_int); | 40 | void buffer_get(Buffer *, void *, u_int); |
39 | 41 | ||
40 | void buffer_consume(Buffer *, u_int); | 42 | void buffer_consume(Buffer *, u_int); |
41 | void buffer_consume_end(Buffer *, u_int); | 43 | void buffer_consume_end(Buffer *, u_int); |
42 | 44 | ||
43 | void buffer_dump(const Buffer *); | ||
44 | 45 | ||
45 | int buffer_get_ret(Buffer *, void *, u_int); | 46 | int buffer_get_ret(Buffer *, void *, u_int); |
46 | int buffer_consume_ret(Buffer *, u_int); | 47 | int buffer_consume_ret(Buffer *, u_int); |
47 | int buffer_consume_end_ret(Buffer *, u_int); | 48 | int buffer_consume_end_ret(Buffer *, u_int); |
48 | 49 | ||
49 | #include <openssl/bn.h> | 50 | #include <openssl/bn.h> |
50 | |||
51 | void buffer_put_bignum(Buffer *, const BIGNUM *); | 51 | void buffer_put_bignum(Buffer *, const BIGNUM *); |
52 | void buffer_put_bignum2(Buffer *, const BIGNUM *); | 52 | void buffer_put_bignum2(Buffer *, const BIGNUM *); |
53 | void buffer_get_bignum(Buffer *, BIGNUM *); | 53 | void buffer_get_bignum(Buffer *, BIGNUM *); |
54 | void buffer_get_bignum2(Buffer *, BIGNUM *); | 54 | void buffer_get_bignum2(Buffer *, BIGNUM *); |
55 | void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int); | ||
55 | 56 | ||
56 | u_short buffer_get_short(Buffer *); | 57 | u_short buffer_get_short(Buffer *); |
57 | void buffer_put_short(Buffer *, u_short); | 58 | void buffer_put_short(Buffer *, u_short); |
@@ -66,13 +67,12 @@ int buffer_get_char(Buffer *); | |||
66 | void buffer_put_char(Buffer *, int); | 67 | void buffer_put_char(Buffer *, int); |
67 | 68 | ||
68 | void *buffer_get_string(Buffer *, u_int *); | 69 | void *buffer_get_string(Buffer *, u_int *); |
69 | void *buffer_get_string_ptr(Buffer *, u_int *); | 70 | const void *buffer_get_string_ptr(Buffer *, u_int *); |
70 | void buffer_put_string(Buffer *, const void *, u_int); | 71 | void buffer_put_string(Buffer *, const void *, u_int); |
71 | char *buffer_get_cstring(Buffer *, u_int *); | 72 | char *buffer_get_cstring(Buffer *, u_int *); |
72 | void buffer_put_cstring(Buffer *, const char *); | 73 | void buffer_put_cstring(Buffer *, const char *); |
73 | 74 | ||
74 | #define buffer_skip_string(b) \ | 75 | #define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL); |
75 | do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while (0) | ||
76 | 76 | ||
77 | int buffer_put_bignum_ret(Buffer *, const BIGNUM *); | 77 | int buffer_put_bignum_ret(Buffer *, const BIGNUM *); |
78 | int buffer_get_bignum_ret(Buffer *, BIGNUM *); | 78 | int buffer_get_bignum_ret(Buffer *, BIGNUM *); |
@@ -83,20 +83,16 @@ int buffer_get_int_ret(u_int *, Buffer *); | |||
83 | int buffer_get_int64_ret(u_int64_t *, Buffer *); | 83 | int buffer_get_int64_ret(u_int64_t *, Buffer *); |
84 | void *buffer_get_string_ret(Buffer *, u_int *); | 84 | void *buffer_get_string_ret(Buffer *, u_int *); |
85 | char *buffer_get_cstring_ret(Buffer *, u_int *); | 85 | char *buffer_get_cstring_ret(Buffer *, u_int *); |
86 | void *buffer_get_string_ptr_ret(Buffer *, u_int *); | 86 | const void *buffer_get_string_ptr_ret(Buffer *, u_int *); |
87 | int buffer_get_char_ret(u_char *, Buffer *); | 87 | int buffer_get_char_ret(char *, Buffer *); |
88 | |||
89 | void *buffer_get_bignum2_as_string_ret(Buffer *, u_int *); | ||
90 | void *buffer_get_bignum2_as_string(Buffer *, u_int *); | ||
91 | void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int); | ||
92 | 88 | ||
93 | #ifdef OPENSSL_HAS_ECC | 89 | #ifdef OPENSSL_HAS_ECC |
94 | #include <openssl/ec.h> | 90 | #include <openssl/ec.h> |
95 | |||
96 | int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *); | 91 | int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *); |
97 | void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *); | 92 | void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *); |
98 | int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *); | 93 | int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *); |
99 | void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *); | 94 | void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *); |
100 | #endif | 95 | #endif |
101 | 96 | ||
102 | #endif /* BUFFER_H */ | 97 | #endif /* BUFFER_H */ |
98 | |||
diff --git a/canohost.c b/canohost.c index a61a8c94d..a3e3bbff8 100644 --- a/canohost.c +++ b/canohost.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: canohost.c,v 1.70 2014/01/19 04:17:29 dtucker Exp $ */ | 1 | /* $OpenBSD: canohost.c,v 1.71 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <sys/types.h> | 17 | #include <sys/types.h> |
18 | #include <sys/socket.h> | 18 | #include <sys/socket.h> |
19 | #include <sys/un.h> | ||
19 | 20 | ||
20 | #include <netinet/in.h> | 21 | #include <netinet/in.h> |
21 | #include <arpa/inet.h> | 22 | #include <arpa/inet.h> |
@@ -262,6 +263,11 @@ get_socket_address(int sock, int remote, int flags) | |||
262 | if (addr.ss_family == AF_INET6) | 263 | if (addr.ss_family == AF_INET6) |
263 | addrlen = sizeof(struct sockaddr_in6); | 264 | addrlen = sizeof(struct sockaddr_in6); |
264 | 265 | ||
266 | if (addr.ss_family == AF_UNIX) { | ||
267 | /* Get the Unix domain socket path. */ | ||
268 | return xstrdup(((struct sockaddr_un *)&addr)->sun_path); | ||
269 | } | ||
270 | |||
265 | ipv64_normalise_mapped(&addr, &addrlen); | 271 | ipv64_normalise_mapped(&addr, &addrlen); |
266 | 272 | ||
267 | /* Get the address in ascii. */ | 273 | /* Get the address in ascii. */ |
@@ -384,6 +390,10 @@ get_sock_port(int sock, int local) | |||
384 | if (from.ss_family == AF_INET6) | 390 | if (from.ss_family == AF_INET6) |
385 | fromlen = sizeof(struct sockaddr_in6); | 391 | fromlen = sizeof(struct sockaddr_in6); |
386 | 392 | ||
393 | /* Unix domain sockets don't have a port number. */ | ||
394 | if (from.ss_family == AF_UNIX) | ||
395 | return 0; | ||
396 | |||
387 | /* Return port number. */ | 397 | /* Return port number. */ |
388 | if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, | 398 | if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, |
389 | strport, sizeof(strport), NI_NUMERICSERV)) != 0) | 399 | strport, sizeof(strport), NI_NUMERICSERV)) != 0) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: chacha.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ | 1 | /* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | chacha-merged.c version 20080118 | 4 | chacha-merged.c version 20080118 |
diff --git a/channels.c b/channels.c index 9efe89c9c..d67fdf48b 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.331 2014/02/26 20:29:29 djm Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.336 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -42,6 +42,7 @@ | |||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | 43 | ||
44 | #include <sys/types.h> | 44 | #include <sys/types.h> |
45 | #include <sys/stat.h> | ||
45 | #include <sys/ioctl.h> | 46 | #include <sys/ioctl.h> |
46 | #include <sys/un.h> | 47 | #include <sys/un.h> |
47 | #include <sys/socket.h> | 48 | #include <sys/socket.h> |
@@ -107,10 +108,15 @@ static int channel_max_fd = 0; | |||
107 | * a corrupt remote server from accessing arbitrary TCP/IP ports on our local | 108 | * a corrupt remote server from accessing arbitrary TCP/IP ports on our local |
108 | * network (which might be behind a firewall). | 109 | * network (which might be behind a firewall). |
109 | */ | 110 | */ |
111 | /* XXX: streamlocal wants a path instead of host:port */ | ||
112 | /* Overload host_to_connect; we could just make this match Forward */ | ||
113 | /* XXX - can we use listen_host instead of listen_path? */ | ||
110 | typedef struct { | 114 | typedef struct { |
111 | char *host_to_connect; /* Connect to 'host'. */ | 115 | char *host_to_connect; /* Connect to 'host'. */ |
112 | u_short port_to_connect; /* Connect to 'port'. */ | 116 | int port_to_connect; /* Connect to 'port'. */ |
113 | u_short listen_port; /* Remote side should listen port number. */ | 117 | char *listen_host; /* Remote side should listen address. */ |
118 | char *listen_path; /* Remote side should listen path. */ | ||
119 | int listen_port; /* Remote side should listen port. */ | ||
114 | } ForwardPermission; | 120 | } ForwardPermission; |
115 | 121 | ||
116 | /* List of all permitted host/port pairs to connect by the user. */ | 122 | /* List of all permitted host/port pairs to connect by the user. */ |
@@ -473,6 +479,8 @@ channel_stop_listening(void) | |||
473 | case SSH_CHANNEL_PORT_LISTENER: | 479 | case SSH_CHANNEL_PORT_LISTENER: |
474 | case SSH_CHANNEL_RPORT_LISTENER: | 480 | case SSH_CHANNEL_RPORT_LISTENER: |
475 | case SSH_CHANNEL_X11_LISTENER: | 481 | case SSH_CHANNEL_X11_LISTENER: |
482 | case SSH_CHANNEL_UNIX_LISTENER: | ||
483 | case SSH_CHANNEL_RUNIX_LISTENER: | ||
476 | channel_close_fd(&c->sock); | 484 | channel_close_fd(&c->sock); |
477 | channel_free(c); | 485 | channel_free(c); |
478 | break; | 486 | break; |
@@ -535,6 +543,8 @@ channel_still_open(void) | |||
535 | case SSH_CHANNEL_CONNECTING: | 543 | case SSH_CHANNEL_CONNECTING: |
536 | case SSH_CHANNEL_ZOMBIE: | 544 | case SSH_CHANNEL_ZOMBIE: |
537 | case SSH_CHANNEL_ABANDONED: | 545 | case SSH_CHANNEL_ABANDONED: |
546 | case SSH_CHANNEL_UNIX_LISTENER: | ||
547 | case SSH_CHANNEL_RUNIX_LISTENER: | ||
538 | continue; | 548 | continue; |
539 | case SSH_CHANNEL_LARVAL: | 549 | case SSH_CHANNEL_LARVAL: |
540 | if (!compat20) | 550 | if (!compat20) |
@@ -581,6 +591,8 @@ channel_find_open(void) | |||
581 | case SSH_CHANNEL_CONNECTING: | 591 | case SSH_CHANNEL_CONNECTING: |
582 | case SSH_CHANNEL_ZOMBIE: | 592 | case SSH_CHANNEL_ZOMBIE: |
583 | case SSH_CHANNEL_ABANDONED: | 593 | case SSH_CHANNEL_ABANDONED: |
594 | case SSH_CHANNEL_UNIX_LISTENER: | ||
595 | case SSH_CHANNEL_RUNIX_LISTENER: | ||
584 | continue; | 596 | continue; |
585 | case SSH_CHANNEL_LARVAL: | 597 | case SSH_CHANNEL_LARVAL: |
586 | case SSH_CHANNEL_AUTH_SOCKET: | 598 | case SSH_CHANNEL_AUTH_SOCKET: |
@@ -631,6 +643,8 @@ channel_open_message(void) | |||
631 | case SSH_CHANNEL_ABANDONED: | 643 | case SSH_CHANNEL_ABANDONED: |
632 | case SSH_CHANNEL_MUX_CLIENT: | 644 | case SSH_CHANNEL_MUX_CLIENT: |
633 | case SSH_CHANNEL_MUX_LISTENER: | 645 | case SSH_CHANNEL_MUX_LISTENER: |
646 | case SSH_CHANNEL_UNIX_LISTENER: | ||
647 | case SSH_CHANNEL_RUNIX_LISTENER: | ||
634 | continue; | 648 | continue; |
635 | case SSH_CHANNEL_LARVAL: | 649 | case SSH_CHANNEL_LARVAL: |
636 | case SSH_CHANNEL_OPENING: | 650 | case SSH_CHANNEL_OPENING: |
@@ -1386,7 +1400,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1386 | static void | 1400 | static void |
1387 | port_open_helper(Channel *c, char *rtype) | 1401 | port_open_helper(Channel *c, char *rtype) |
1388 | { | 1402 | { |
1389 | int direct; | ||
1390 | char buf[1024]; | 1403 | char buf[1024]; |
1391 | char *local_ipaddr = get_local_ipaddr(c->sock); | 1404 | char *local_ipaddr = get_local_ipaddr(c->sock); |
1392 | int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1); | 1405 | int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1); |
@@ -1400,8 +1413,6 @@ port_open_helper(Channel *c, char *rtype) | |||
1400 | remote_port = 65535; | 1413 | remote_port = 65535; |
1401 | } | 1414 | } |
1402 | 1415 | ||
1403 | direct = (strcmp(rtype, "direct-tcpip") == 0); | ||
1404 | |||
1405 | snprintf(buf, sizeof buf, | 1416 | snprintf(buf, sizeof buf, |
1406 | "%s: listening port %d for %.100s port %d, " | 1417 | "%s: listening port %d for %.100s port %d, " |
1407 | "connect from %.200s port %d to %.100s port %d", | 1418 | "connect from %.200s port %d to %.100s port %d", |
@@ -1417,18 +1428,29 @@ port_open_helper(Channel *c, char *rtype) | |||
1417 | packet_put_int(c->self); | 1428 | packet_put_int(c->self); |
1418 | packet_put_int(c->local_window_max); | 1429 | packet_put_int(c->local_window_max); |
1419 | packet_put_int(c->local_maxpacket); | 1430 | packet_put_int(c->local_maxpacket); |
1420 | if (direct) { | 1431 | if (strcmp(rtype, "direct-tcpip") == 0) { |
1421 | /* target host, port */ | 1432 | /* target host, port */ |
1422 | packet_put_cstring(c->path); | 1433 | packet_put_cstring(c->path); |
1423 | packet_put_int(c->host_port); | 1434 | packet_put_int(c->host_port); |
1435 | } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { | ||
1436 | /* target path */ | ||
1437 | packet_put_cstring(c->path); | ||
1438 | } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { | ||
1439 | /* listen path */ | ||
1440 | packet_put_cstring(c->path); | ||
1424 | } else { | 1441 | } else { |
1425 | /* listen address, port */ | 1442 | /* listen address, port */ |
1426 | packet_put_cstring(c->path); | 1443 | packet_put_cstring(c->path); |
1427 | packet_put_int(local_port); | 1444 | packet_put_int(local_port); |
1428 | } | 1445 | } |
1429 | /* originator host and port */ | 1446 | if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { |
1430 | packet_put_cstring(remote_ipaddr); | 1447 | /* reserved for future owner/mode info */ |
1431 | packet_put_int((u_int)remote_port); | 1448 | packet_put_cstring(""); |
1449 | } else { | ||
1450 | /* originator host and port */ | ||
1451 | packet_put_cstring(remote_ipaddr); | ||
1452 | packet_put_int((u_int)remote_port); | ||
1453 | } | ||
1432 | packet_send(); | 1454 | packet_send(); |
1433 | } else { | 1455 | } else { |
1434 | packet_start(SSH_MSG_PORT_OPEN); | 1456 | packet_start(SSH_MSG_PORT_OPEN); |
@@ -1478,14 +1500,18 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1478 | if (c->type == SSH_CHANNEL_RPORT_LISTENER) { | 1500 | if (c->type == SSH_CHANNEL_RPORT_LISTENER) { |
1479 | nextstate = SSH_CHANNEL_OPENING; | 1501 | nextstate = SSH_CHANNEL_OPENING; |
1480 | rtype = "forwarded-tcpip"; | 1502 | rtype = "forwarded-tcpip"; |
1503 | } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { | ||
1504 | nextstate = SSH_CHANNEL_OPENING; | ||
1505 | rtype = "forwarded-streamlocal@openssh.com"; | ||
1506 | } else if (c->host_port == PORT_STREAMLOCAL) { | ||
1507 | nextstate = SSH_CHANNEL_OPENING; | ||
1508 | rtype = "direct-streamlocal@openssh.com"; | ||
1509 | } else if (c->host_port == 0) { | ||
1510 | nextstate = SSH_CHANNEL_DYNAMIC; | ||
1511 | rtype = "dynamic-tcpip"; | ||
1481 | } else { | 1512 | } else { |
1482 | if (c->host_port == 0) { | 1513 | nextstate = SSH_CHANNEL_OPENING; |
1483 | nextstate = SSH_CHANNEL_DYNAMIC; | 1514 | rtype = "direct-tcpip"; |
1484 | rtype = "dynamic-tcpip"; | ||
1485 | } else { | ||
1486 | nextstate = SSH_CHANNEL_OPENING; | ||
1487 | rtype = "direct-tcpip"; | ||
1488 | } | ||
1489 | } | 1515 | } |
1490 | 1516 | ||
1491 | addrlen = sizeof(addr); | 1517 | addrlen = sizeof(addr); |
@@ -1498,7 +1524,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1498 | c->notbefore = monotime() + 1; | 1524 | c->notbefore = monotime() + 1; |
1499 | return; | 1525 | return; |
1500 | } | 1526 | } |
1501 | set_nodelay(newsock); | 1527 | if (c->host_port != PORT_STREAMLOCAL) |
1528 | set_nodelay(newsock); | ||
1502 | nc = channel_new(rtype, nextstate, newsock, newsock, -1, | 1529 | nc = channel_new(rtype, nextstate, newsock, newsock, -1, |
1503 | c->local_window_max, c->local_maxpacket, 0, rtype, 1); | 1530 | c->local_window_max, c->local_maxpacket, 0, rtype, 1); |
1504 | nc->listening_port = c->listening_port; | 1531 | nc->listening_port = c->listening_port; |
@@ -1987,6 +2014,8 @@ channel_handler_init_20(void) | |||
1987 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; | 2014 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; |
1988 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | 2015 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; |
1989 | channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; | 2016 | channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; |
2017 | channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; | ||
2018 | channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; | ||
1990 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | 2019 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; |
1991 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | 2020 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; |
1992 | channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; | 2021 | channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; |
@@ -1997,6 +2026,8 @@ channel_handler_init_20(void) | |||
1997 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; | 2026 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; |
1998 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | 2027 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; |
1999 | channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; | 2028 | channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; |
2029 | channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; | ||
2030 | channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; | ||
2000 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | 2031 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; |
2001 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | 2032 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; |
2002 | channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; | 2033 | channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; |
@@ -2315,7 +2346,7 @@ void | |||
2315 | channel_input_data(int type, u_int32_t seq, void *ctxt) | 2346 | channel_input_data(int type, u_int32_t seq, void *ctxt) |
2316 | { | 2347 | { |
2317 | int id; | 2348 | int id; |
2318 | char *data; | 2349 | const u_char *data; |
2319 | u_int data_len, win_len; | 2350 | u_int data_len, win_len; |
2320 | Channel *c; | 2351 | Channel *c; |
2321 | 2352 | ||
@@ -2637,7 +2668,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt) | |||
2637 | originator_string = xstrdup("unknown (remote did not supply name)"); | 2668 | originator_string = xstrdup("unknown (remote did not supply name)"); |
2638 | } | 2669 | } |
2639 | packet_check_eom(); | 2670 | packet_check_eom(); |
2640 | c = channel_connect_to(host, host_port, | 2671 | c = channel_connect_to_port(host, host_port, |
2641 | "connected socket", originator_string); | 2672 | "connected socket", originator_string); |
2642 | free(originator_string); | 2673 | free(originator_string); |
2643 | free(host); | 2674 | free(host); |
@@ -2700,23 +2731,24 @@ channel_set_af(int af) | |||
2700 | * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR | 2731 | * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR |
2701 | * "" (empty string), "*" -> wildcard v4/v6 | 2732 | * "" (empty string), "*" -> wildcard v4/v6 |
2702 | * "localhost" -> loopback v4/v6 | 2733 | * "localhost" -> loopback v4/v6 |
2734 | * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set | ||
2703 | */ | 2735 | */ |
2704 | static const char * | 2736 | static const char * |
2705 | channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, | 2737 | channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, |
2706 | int is_client, int gateway_ports) | 2738 | int is_client, struct ForwardOptions *fwd_opts) |
2707 | { | 2739 | { |
2708 | const char *addr = NULL; | 2740 | const char *addr = NULL; |
2709 | int wildcard = 0; | 2741 | int wildcard = 0; |
2710 | 2742 | ||
2711 | if (listen_addr == NULL) { | 2743 | if (listen_addr == NULL) { |
2712 | /* No address specified: default to gateway_ports setting */ | 2744 | /* No address specified: default to gateway_ports setting */ |
2713 | if (gateway_ports) | 2745 | if (fwd_opts->gateway_ports) |
2714 | wildcard = 1; | 2746 | wildcard = 1; |
2715 | } else if (gateway_ports || is_client) { | 2747 | } else if (fwd_opts->gateway_ports || is_client) { |
2716 | if (((datafellows & SSH_OLD_FORWARD_ADDR) && | 2748 | if (((datafellows & SSH_OLD_FORWARD_ADDR) && |
2717 | strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || | 2749 | strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || |
2718 | *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || | 2750 | *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || |
2719 | (!is_client && gateway_ports == 1)) { | 2751 | (!is_client && fwd_opts->gateway_ports == 1)) { |
2720 | wildcard = 1; | 2752 | wildcard = 1; |
2721 | /* | 2753 | /* |
2722 | * Notify client if they requested a specific listen | 2754 | * Notify client if they requested a specific listen |
@@ -2729,9 +2761,20 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, | |||
2729 | "\"%s\" overridden by server " | 2761 | "\"%s\" overridden by server " |
2730 | "GatewayPorts", listen_addr); | 2762 | "GatewayPorts", listen_addr); |
2731 | } | 2763 | } |
2732 | } | 2764 | } else if (strcmp(listen_addr, "localhost") != 0 || |
2733 | else if (strcmp(listen_addr, "localhost") != 0) | 2765 | strcmp(listen_addr, "127.0.0.1") == 0 || |
2766 | strcmp(listen_addr, "::1") == 0) { | ||
2767 | /* Accept localhost address when GatewayPorts=yes */ | ||
2734 | addr = listen_addr; | 2768 | addr = listen_addr; |
2769 | } | ||
2770 | } else if (strcmp(listen_addr, "127.0.0.1") == 0 || | ||
2771 | strcmp(listen_addr, "::1") == 0) { | ||
2772 | /* | ||
2773 | * If a specific IPv4/IPv6 localhost address has been | ||
2774 | * requested then accept it even if gateway_ports is in | ||
2775 | * effect. This allows the client to prefer IPv4 or IPv6. | ||
2776 | */ | ||
2777 | addr = listen_addr; | ||
2735 | } | 2778 | } |
2736 | if (wildcardp != NULL) | 2779 | if (wildcardp != NULL) |
2737 | *wildcardp = wildcard; | 2780 | *wildcardp = wildcard; |
@@ -2739,9 +2782,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, | |||
2739 | } | 2782 | } |
2740 | 2783 | ||
2741 | static int | 2784 | static int |
2742 | channel_setup_fwd_listener(int type, const char *listen_addr, | 2785 | channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, |
2743 | u_short listen_port, int *allocated_listen_port, | 2786 | int *allocated_listen_port, struct ForwardOptions *fwd_opts) |
2744 | const char *host_to_connect, u_short port_to_connect, int gateway_ports) | ||
2745 | { | 2787 | { |
2746 | Channel *c; | 2788 | Channel *c; |
2747 | int sock, r, success = 0, wildcard = 0, is_client; | 2789 | int sock, r, success = 0, wildcard = 0, is_client; |
@@ -2751,7 +2793,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, | |||
2751 | in_port_t *lport_p; | 2793 | in_port_t *lport_p; |
2752 | 2794 | ||
2753 | host = (type == SSH_CHANNEL_RPORT_LISTENER) ? | 2795 | host = (type == SSH_CHANNEL_RPORT_LISTENER) ? |
2754 | listen_addr : host_to_connect; | 2796 | fwd->listen_host : fwd->connect_host; |
2755 | is_client = (type == SSH_CHANNEL_PORT_LISTENER); | 2797 | is_client = (type == SSH_CHANNEL_PORT_LISTENER); |
2756 | 2798 | ||
2757 | if (host == NULL) { | 2799 | if (host == NULL) { |
@@ -2764,9 +2806,9 @@ channel_setup_fwd_listener(int type, const char *listen_addr, | |||
2764 | } | 2806 | } |
2765 | 2807 | ||
2766 | /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ | 2808 | /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ |
2767 | addr = channel_fwd_bind_addr(listen_addr, &wildcard, | 2809 | addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard, |
2768 | is_client, gateway_ports); | 2810 | is_client, fwd_opts); |
2769 | debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", | 2811 | debug3("%s: type %d wildcard %d addr %s", __func__, |
2770 | type, wildcard, (addr == NULL) ? "NULL" : addr); | 2812 | type, wildcard, (addr == NULL) ? "NULL" : addr); |
2771 | 2813 | ||
2772 | /* | 2814 | /* |
@@ -2777,15 +2819,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr, | |||
2777 | hints.ai_family = IPv4or6; | 2819 | hints.ai_family = IPv4or6; |
2778 | hints.ai_flags = wildcard ? AI_PASSIVE : 0; | 2820 | hints.ai_flags = wildcard ? AI_PASSIVE : 0; |
2779 | hints.ai_socktype = SOCK_STREAM; | 2821 | hints.ai_socktype = SOCK_STREAM; |
2780 | snprintf(strport, sizeof strport, "%d", listen_port); | 2822 | snprintf(strport, sizeof strport, "%d", fwd->listen_port); |
2781 | if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { | 2823 | if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { |
2782 | if (addr == NULL) { | 2824 | if (addr == NULL) { |
2783 | /* This really shouldn't happen */ | 2825 | /* This really shouldn't happen */ |
2784 | packet_disconnect("getaddrinfo: fatal error: %s", | 2826 | packet_disconnect("getaddrinfo: fatal error: %s", |
2785 | ssh_gai_strerror(r)); | 2827 | ssh_gai_strerror(r)); |
2786 | } else { | 2828 | } else { |
2787 | error("channel_setup_fwd_listener: " | 2829 | error("%s: getaddrinfo(%.64s): %s", __func__, addr, |
2788 | "getaddrinfo(%.64s): %s", addr, | ||
2789 | ssh_gai_strerror(r)); | 2830 | ssh_gai_strerror(r)); |
2790 | } | 2831 | } |
2791 | return 0; | 2832 | return 0; |
@@ -2809,13 +2850,13 @@ channel_setup_fwd_listener(int type, const char *listen_addr, | |||
2809 | * If allocating a port for -R forwards, then use the | 2850 | * If allocating a port for -R forwards, then use the |
2810 | * same port for all address families. | 2851 | * same port for all address families. |
2811 | */ | 2852 | */ |
2812 | if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && | 2853 | if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && |
2813 | allocated_listen_port != NULL && *allocated_listen_port > 0) | 2854 | allocated_listen_port != NULL && *allocated_listen_port > 0) |
2814 | *lport_p = htons(*allocated_listen_port); | 2855 | *lport_p = htons(*allocated_listen_port); |
2815 | 2856 | ||
2816 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), | 2857 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), |
2817 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 2858 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { |
2818 | error("channel_setup_fwd_listener: getnameinfo failed"); | 2859 | error("%s: getnameinfo failed", __func__); |
2819 | continue; | 2860 | continue; |
2820 | } | 2861 | } |
2821 | /* Create a port to listen for the host. */ | 2862 | /* Create a port to listen for the host. */ |
@@ -2852,10 +2893,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr, | |||
2852 | } | 2893 | } |
2853 | 2894 | ||
2854 | /* | 2895 | /* |
2855 | * listen_port == 0 requests a dynamically allocated port - | 2896 | * fwd->listen_port == 0 requests a dynamically allocated port - |
2856 | * record what we got. | 2897 | * record what we got. |
2857 | */ | 2898 | */ |
2858 | if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && | 2899 | if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && |
2859 | allocated_listen_port != NULL && | 2900 | allocated_listen_port != NULL && |
2860 | *allocated_listen_port == 0) { | 2901 | *allocated_listen_port == 0) { |
2861 | *allocated_listen_port = get_sock_port(sock, 1); | 2902 | *allocated_listen_port = get_sock_port(sock, 1); |
@@ -2868,24 +2909,98 @@ channel_setup_fwd_listener(int type, const char *listen_addr, | |||
2868 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 2909 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
2869 | 0, "port listener", 1); | 2910 | 0, "port listener", 1); |
2870 | c->path = xstrdup(host); | 2911 | c->path = xstrdup(host); |
2871 | c->host_port = port_to_connect; | 2912 | c->host_port = fwd->connect_port; |
2872 | c->listening_addr = addr == NULL ? NULL : xstrdup(addr); | 2913 | c->listening_addr = addr == NULL ? NULL : xstrdup(addr); |
2873 | if (listen_port == 0 && allocated_listen_port != NULL && | 2914 | if (fwd->listen_port == 0 && allocated_listen_port != NULL && |
2874 | !(datafellows & SSH_BUG_DYNAMIC_RPORT)) | 2915 | !(datafellows & SSH_BUG_DYNAMIC_RPORT)) |
2875 | c->listening_port = *allocated_listen_port; | 2916 | c->listening_port = *allocated_listen_port; |
2876 | else | 2917 | else |
2877 | c->listening_port = listen_port; | 2918 | c->listening_port = fwd->listen_port; |
2878 | success = 1; | 2919 | success = 1; |
2879 | } | 2920 | } |
2880 | if (success == 0) | 2921 | if (success == 0) |
2881 | error("channel_setup_fwd_listener: cannot listen to port: %d", | 2922 | error("%s: cannot listen to port: %d", __func__, |
2882 | listen_port); | 2923 | fwd->listen_port); |
2883 | freeaddrinfo(aitop); | 2924 | freeaddrinfo(aitop); |
2884 | return success; | 2925 | return success; |
2885 | } | 2926 | } |
2886 | 2927 | ||
2887 | int | 2928 | static int |
2888 | channel_cancel_rport_listener(const char *host, u_short port) | 2929 | channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, |
2930 | struct ForwardOptions *fwd_opts) | ||
2931 | { | ||
2932 | struct sockaddr_un sunaddr; | ||
2933 | const char *path; | ||
2934 | Channel *c; | ||
2935 | int port, sock; | ||
2936 | mode_t omask; | ||
2937 | |||
2938 | switch (type) { | ||
2939 | case SSH_CHANNEL_UNIX_LISTENER: | ||
2940 | if (fwd->connect_path != NULL) { | ||
2941 | if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) { | ||
2942 | error("Local connecting path too long: %s", | ||
2943 | fwd->connect_path); | ||
2944 | return 0; | ||
2945 | } | ||
2946 | path = fwd->connect_path; | ||
2947 | port = PORT_STREAMLOCAL; | ||
2948 | } else { | ||
2949 | if (fwd->connect_host == NULL) { | ||
2950 | error("No forward host name."); | ||
2951 | return 0; | ||
2952 | } | ||
2953 | if (strlen(fwd->connect_host) >= NI_MAXHOST) { | ||
2954 | error("Forward host name too long."); | ||
2955 | return 0; | ||
2956 | } | ||
2957 | path = fwd->connect_host; | ||
2958 | port = fwd->connect_port; | ||
2959 | } | ||
2960 | break; | ||
2961 | case SSH_CHANNEL_RUNIX_LISTENER: | ||
2962 | path = fwd->listen_path; | ||
2963 | port = PORT_STREAMLOCAL; | ||
2964 | break; | ||
2965 | default: | ||
2966 | error("%s: unexpected channel type %d", __func__, type); | ||
2967 | return 0; | ||
2968 | } | ||
2969 | |||
2970 | if (fwd->listen_path == NULL) { | ||
2971 | error("No forward path name."); | ||
2972 | return 0; | ||
2973 | } | ||
2974 | if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) { | ||
2975 | error("Local listening path too long: %s", fwd->listen_path); | ||
2976 | return 0; | ||
2977 | } | ||
2978 | |||
2979 | debug3("%s: type %d path %s", __func__, type, fwd->listen_path); | ||
2980 | |||
2981 | /* Start a Unix domain listener. */ | ||
2982 | omask = umask(fwd_opts->streamlocal_bind_mask); | ||
2983 | sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG, | ||
2984 | fwd_opts->streamlocal_bind_unlink); | ||
2985 | umask(omask); | ||
2986 | if (sock < 0) | ||
2987 | return 0; | ||
2988 | |||
2989 | debug("Local forwarding listening on path %s.", fwd->listen_path); | ||
2990 | |||
2991 | /* Allocate a channel number for the socket. */ | ||
2992 | c = channel_new("unix listener", type, sock, sock, -1, | ||
2993 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | ||
2994 | 0, "unix listener", 1); | ||
2995 | c->path = xstrdup(path); | ||
2996 | c->host_port = port; | ||
2997 | c->listening_port = PORT_STREAMLOCAL; | ||
2998 | c->listening_addr = xstrdup(fwd->listen_path); | ||
2999 | return 1; | ||
3000 | } | ||
3001 | |||
3002 | static int | ||
3003 | channel_cancel_rport_listener_tcpip(const char *host, u_short port) | ||
2889 | { | 3004 | { |
2890 | u_int i; | 3005 | u_int i; |
2891 | int found = 0; | 3006 | int found = 0; |
@@ -2904,13 +3019,44 @@ channel_cancel_rport_listener(const char *host, u_short port) | |||
2904 | return (found); | 3019 | return (found); |
2905 | } | 3020 | } |
2906 | 3021 | ||
3022 | static int | ||
3023 | channel_cancel_rport_listener_streamlocal(const char *path) | ||
3024 | { | ||
3025 | u_int i; | ||
3026 | int found = 0; | ||
3027 | |||
3028 | for (i = 0; i < channels_alloc; i++) { | ||
3029 | Channel *c = channels[i]; | ||
3030 | if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER) | ||
3031 | continue; | ||
3032 | if (c->path == NULL) | ||
3033 | continue; | ||
3034 | if (strcmp(c->path, path) == 0) { | ||
3035 | debug2("%s: close channel %d", __func__, i); | ||
3036 | channel_free(c); | ||
3037 | found = 1; | ||
3038 | } | ||
3039 | } | ||
3040 | |||
3041 | return (found); | ||
3042 | } | ||
3043 | |||
2907 | int | 3044 | int |
2908 | channel_cancel_lport_listener(const char *lhost, u_short lport, | 3045 | channel_cancel_rport_listener(struct Forward *fwd) |
2909 | int cport, int gateway_ports) | 3046 | { |
3047 | if (fwd->listen_path != NULL) | ||
3048 | return channel_cancel_rport_listener_streamlocal(fwd->listen_path); | ||
3049 | else | ||
3050 | return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port); | ||
3051 | } | ||
3052 | |||
3053 | static int | ||
3054 | channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport, | ||
3055 | int cport, struct ForwardOptions *fwd_opts) | ||
2910 | { | 3056 | { |
2911 | u_int i; | 3057 | u_int i; |
2912 | int found = 0; | 3058 | int found = 0; |
2913 | const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports); | 3059 | const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); |
2914 | 3060 | ||
2915 | for (i = 0; i < channels_alloc; i++) { | 3061 | for (i = 0; i < channels_alloc; i++) { |
2916 | Channel *c = channels[i]; | 3062 | Channel *c = channels[i]; |
@@ -2939,24 +3085,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport, | |||
2939 | return (found); | 3085 | return (found); |
2940 | } | 3086 | } |
2941 | 3087 | ||
3088 | static int | ||
3089 | channel_cancel_lport_listener_streamlocal(const char *path) | ||
3090 | { | ||
3091 | u_int i; | ||
3092 | int found = 0; | ||
3093 | |||
3094 | if (path == NULL) { | ||
3095 | error("%s: no path specified.", __func__); | ||
3096 | return 0; | ||
3097 | } | ||
3098 | |||
3099 | for (i = 0; i < channels_alloc; i++) { | ||
3100 | Channel *c = channels[i]; | ||
3101 | if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER) | ||
3102 | continue; | ||
3103 | if (c->listening_addr == NULL) | ||
3104 | continue; | ||
3105 | if (strcmp(c->listening_addr, path) == 0) { | ||
3106 | debug2("%s: close channel %d", __func__, i); | ||
3107 | channel_free(c); | ||
3108 | found = 1; | ||
3109 | } | ||
3110 | } | ||
3111 | |||
3112 | return (found); | ||
3113 | } | ||
3114 | |||
3115 | int | ||
3116 | channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) | ||
3117 | { | ||
3118 | if (fwd->listen_path != NULL) | ||
3119 | return channel_cancel_lport_listener_streamlocal(fwd->listen_path); | ||
3120 | else | ||
3121 | return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts); | ||
3122 | } | ||
3123 | |||
2942 | /* protocol local port fwd, used by ssh (and sshd in v1) */ | 3124 | /* protocol local port fwd, used by ssh (and sshd in v1) */ |
2943 | int | 3125 | int |
2944 | channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, | 3126 | channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts) |
2945 | const char *host_to_connect, u_short port_to_connect, int gateway_ports) | ||
2946 | { | 3127 | { |
2947 | return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, | 3128 | if (fwd->listen_path != NULL) { |
2948 | listen_host, listen_port, NULL, host_to_connect, port_to_connect, | 3129 | return channel_setup_fwd_listener_streamlocal( |
2949 | gateway_ports); | 3130 | SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); |
3131 | } else { | ||
3132 | return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER, | ||
3133 | fwd, NULL, fwd_opts); | ||
3134 | } | ||
2950 | } | 3135 | } |
2951 | 3136 | ||
2952 | /* protocol v2 remote port fwd, used by sshd */ | 3137 | /* protocol v2 remote port fwd, used by sshd */ |
2953 | int | 3138 | int |
2954 | channel_setup_remote_fwd_listener(const char *listen_address, | 3139 | channel_setup_remote_fwd_listener(struct Forward *fwd, |
2955 | u_short listen_port, int *allocated_listen_port, int gateway_ports) | 3140 | int *allocated_listen_port, struct ForwardOptions *fwd_opts) |
2956 | { | 3141 | { |
2957 | return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, | 3142 | if (fwd->listen_path != NULL) { |
2958 | listen_address, listen_port, allocated_listen_port, | 3143 | return channel_setup_fwd_listener_streamlocal( |
2959 | NULL, 0, gateway_ports); | 3144 | SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); |
3145 | } else { | ||
3146 | return channel_setup_fwd_listener_tcpip( | ||
3147 | SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, | ||
3148 | fwd_opts); | ||
3149 | } | ||
2960 | } | 3150 | } |
2961 | 3151 | ||
2962 | /* | 3152 | /* |
@@ -2987,27 +3177,32 @@ channel_rfwd_bind_host(const char *listen_host) | |||
2987 | * channel_update_permitted_opens(). | 3177 | * channel_update_permitted_opens(). |
2988 | */ | 3178 | */ |
2989 | int | 3179 | int |
2990 | channel_request_remote_forwarding(const char *listen_host, u_short listen_port, | 3180 | channel_request_remote_forwarding(struct Forward *fwd) |
2991 | const char *host_to_connect, u_short port_to_connect) | ||
2992 | { | 3181 | { |
2993 | int type, success = 0, idx = -1; | 3182 | int type, success = 0, idx = -1; |
2994 | 3183 | ||
2995 | /* Send the forward request to the remote side. */ | 3184 | /* Send the forward request to the remote side. */ |
2996 | if (compat20) { | 3185 | if (compat20) { |
2997 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 3186 | packet_start(SSH2_MSG_GLOBAL_REQUEST); |
2998 | packet_put_cstring("tcpip-forward"); | 3187 | if (fwd->listen_path != NULL) { |
2999 | packet_put_char(1); /* boolean: want reply */ | 3188 | packet_put_cstring("streamlocal-forward@openssh.com"); |
3000 | packet_put_cstring(channel_rfwd_bind_host(listen_host)); | 3189 | packet_put_char(1); /* boolean: want reply */ |
3001 | packet_put_int(listen_port); | 3190 | packet_put_cstring(fwd->listen_path); |
3191 | } else { | ||
3192 | packet_put_cstring("tcpip-forward"); | ||
3193 | packet_put_char(1); /* boolean: want reply */ | ||
3194 | packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host)); | ||
3195 | packet_put_int(fwd->listen_port); | ||
3196 | } | ||
3002 | packet_send(); | 3197 | packet_send(); |
3003 | packet_write_wait(); | 3198 | packet_write_wait(); |
3004 | /* Assume that server accepts the request */ | 3199 | /* Assume that server accepts the request */ |
3005 | success = 1; | 3200 | success = 1; |
3006 | } else { | 3201 | } else if (fwd->listen_path == NULL) { |
3007 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); | 3202 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); |
3008 | packet_put_int(listen_port); | 3203 | packet_put_int(fwd->listen_port); |
3009 | packet_put_cstring(host_to_connect); | 3204 | packet_put_cstring(fwd->connect_host); |
3010 | packet_put_int(port_to_connect); | 3205 | packet_put_int(fwd->connect_port); |
3011 | packet_send(); | 3206 | packet_send(); |
3012 | packet_write_wait(); | 3207 | packet_write_wait(); |
3013 | 3208 | ||
@@ -3024,25 +3219,102 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port, | |||
3024 | packet_disconnect("Protocol error for port forward request:" | 3219 | packet_disconnect("Protocol error for port forward request:" |
3025 | "received packet type %d.", type); | 3220 | "received packet type %d.", type); |
3026 | } | 3221 | } |
3222 | } else { | ||
3223 | logit("Warning: Server does not support remote stream local forwarding."); | ||
3027 | } | 3224 | } |
3028 | if (success) { | 3225 | if (success) { |
3029 | /* Record that connection to this host/port is permitted. */ | 3226 | /* Record that connection to this host/port is permitted. */ |
3030 | permitted_opens = xrealloc(permitted_opens, | 3227 | permitted_opens = xrealloc(permitted_opens, |
3031 | num_permitted_opens + 1, sizeof(*permitted_opens)); | 3228 | num_permitted_opens + 1, sizeof(*permitted_opens)); |
3032 | idx = num_permitted_opens++; | 3229 | idx = num_permitted_opens++; |
3033 | permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); | 3230 | if (fwd->connect_path != NULL) { |
3034 | permitted_opens[idx].port_to_connect = port_to_connect; | 3231 | permitted_opens[idx].host_to_connect = |
3035 | permitted_opens[idx].listen_port = listen_port; | 3232 | xstrdup(fwd->connect_path); |
3233 | permitted_opens[idx].port_to_connect = | ||
3234 | PORT_STREAMLOCAL; | ||
3235 | } else { | ||
3236 | permitted_opens[idx].host_to_connect = | ||
3237 | xstrdup(fwd->connect_host); | ||
3238 | permitted_opens[idx].port_to_connect = | ||
3239 | fwd->connect_port; | ||
3240 | } | ||
3241 | if (fwd->listen_path != NULL) { | ||
3242 | permitted_opens[idx].listen_host = NULL; | ||
3243 | permitted_opens[idx].listen_path = | ||
3244 | xstrdup(fwd->listen_path); | ||
3245 | permitted_opens[idx].listen_port = PORT_STREAMLOCAL; | ||
3246 | } else { | ||
3247 | permitted_opens[idx].listen_host = | ||
3248 | fwd->listen_host ? xstrdup(fwd->listen_host) : NULL; | ||
3249 | permitted_opens[idx].listen_path = NULL; | ||
3250 | permitted_opens[idx].listen_port = fwd->listen_port; | ||
3251 | } | ||
3036 | } | 3252 | } |
3037 | return (idx); | 3253 | return (idx); |
3038 | } | 3254 | } |
3039 | 3255 | ||
3256 | static int | ||
3257 | open_match(ForwardPermission *allowed_open, const char *requestedhost, | ||
3258 | int requestedport) | ||
3259 | { | ||
3260 | if (allowed_open->host_to_connect == NULL) | ||
3261 | return 0; | ||
3262 | if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT && | ||
3263 | allowed_open->port_to_connect != requestedport) | ||
3264 | return 0; | ||
3265 | if (strcmp(allowed_open->host_to_connect, requestedhost) != 0) | ||
3266 | return 0; | ||
3267 | return 1; | ||
3268 | } | ||
3269 | |||
3270 | /* | ||
3271 | * Note that in the listen host/port case | ||
3272 | * we don't support FWD_PERMIT_ANY_PORT and | ||
3273 | * need to translate between the configured-host (listen_host) | ||
3274 | * and what we've sent to the remote server (channel_rfwd_bind_host) | ||
3275 | */ | ||
3276 | static int | ||
3277 | open_listen_match_tcpip(ForwardPermission *allowed_open, | ||
3278 | const char *requestedhost, u_short requestedport, int translate) | ||
3279 | { | ||
3280 | const char *allowed_host; | ||
3281 | |||
3282 | if (allowed_open->host_to_connect == NULL) | ||
3283 | return 0; | ||
3284 | if (allowed_open->listen_port != requestedport) | ||
3285 | return 0; | ||
3286 | if (!translate && allowed_open->listen_host == NULL && | ||
3287 | requestedhost == NULL) | ||
3288 | return 1; | ||
3289 | allowed_host = translate ? | ||
3290 | channel_rfwd_bind_host(allowed_open->listen_host) : | ||
3291 | allowed_open->listen_host; | ||
3292 | if (allowed_host == NULL || | ||
3293 | strcmp(allowed_host, requestedhost) != 0) | ||
3294 | return 0; | ||
3295 | return 1; | ||
3296 | } | ||
3297 | |||
3298 | static int | ||
3299 | open_listen_match_streamlocal(ForwardPermission *allowed_open, | ||
3300 | const char *requestedpath) | ||
3301 | { | ||
3302 | if (allowed_open->host_to_connect == NULL) | ||
3303 | return 0; | ||
3304 | if (allowed_open->listen_port != PORT_STREAMLOCAL) | ||
3305 | return 0; | ||
3306 | if (allowed_open->listen_path == NULL || | ||
3307 | strcmp(allowed_open->listen_path, requestedpath) != 0) | ||
3308 | return 0; | ||
3309 | return 1; | ||
3310 | } | ||
3311 | |||
3040 | /* | 3312 | /* |
3041 | * Request cancellation of remote forwarding of connection host:port from | 3313 | * Request cancellation of remote forwarding of connection host:port from |
3042 | * local side. | 3314 | * local side. |
3043 | */ | 3315 | */ |
3044 | int | 3316 | static int |
3045 | channel_request_rforward_cancel(const char *host, u_short port) | 3317 | channel_request_rforward_cancel_tcpip(const char *host, u_short port) |
3046 | { | 3318 | { |
3047 | int i; | 3319 | int i; |
3048 | 3320 | ||
@@ -3050,8 +3322,7 @@ channel_request_rforward_cancel(const char *host, u_short port) | |||
3050 | return -1; | 3322 | return -1; |
3051 | 3323 | ||
3052 | for (i = 0; i < num_permitted_opens; i++) { | 3324 | for (i = 0; i < num_permitted_opens; i++) { |
3053 | if (permitted_opens[i].host_to_connect != NULL && | 3325 | if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0)) |
3054 | permitted_opens[i].listen_port == port) | ||
3055 | break; | 3326 | break; |
3056 | } | 3327 | } |
3057 | if (i >= num_permitted_opens) { | 3328 | if (i >= num_permitted_opens) { |
@@ -3069,9 +3340,64 @@ channel_request_rforward_cancel(const char *host, u_short port) | |||
3069 | permitted_opens[i].port_to_connect = 0; | 3340 | permitted_opens[i].port_to_connect = 0; |
3070 | free(permitted_opens[i].host_to_connect); | 3341 | free(permitted_opens[i].host_to_connect); |
3071 | permitted_opens[i].host_to_connect = NULL; | 3342 | permitted_opens[i].host_to_connect = NULL; |
3343 | free(permitted_opens[i].listen_host); | ||
3344 | permitted_opens[i].listen_host = NULL; | ||
3345 | permitted_opens[i].listen_path = NULL; | ||
3346 | |||
3347 | return 0; | ||
3348 | } | ||
3349 | |||
3350 | /* | ||
3351 | * Request cancellation of remote forwarding of Unix domain socket | ||
3352 | * path from local side. | ||
3353 | */ | ||
3354 | static int | ||
3355 | channel_request_rforward_cancel_streamlocal(const char *path) | ||
3356 | { | ||
3357 | int i; | ||
3358 | |||
3359 | if (!compat20) | ||
3360 | return -1; | ||
3361 | |||
3362 | for (i = 0; i < num_permitted_opens; i++) { | ||
3363 | if (open_listen_match_streamlocal(&permitted_opens[i], path)) | ||
3364 | break; | ||
3365 | } | ||
3366 | if (i >= num_permitted_opens) { | ||
3367 | debug("%s: requested forward not found", __func__); | ||
3368 | return -1; | ||
3369 | } | ||
3370 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | ||
3371 | packet_put_cstring("cancel-streamlocal-forward@openssh.com"); | ||
3372 | packet_put_char(0); | ||
3373 | packet_put_cstring(path); | ||
3374 | packet_send(); | ||
3375 | |||
3376 | permitted_opens[i].listen_port = 0; | ||
3377 | permitted_opens[i].port_to_connect = 0; | ||
3378 | free(permitted_opens[i].host_to_connect); | ||
3379 | permitted_opens[i].host_to_connect = NULL; | ||
3380 | permitted_opens[i].listen_host = NULL; | ||
3381 | free(permitted_opens[i].listen_path); | ||
3382 | permitted_opens[i].listen_path = NULL; | ||
3072 | 3383 | ||
3073 | return 0; | 3384 | return 0; |
3074 | } | 3385 | } |
3386 | |||
3387 | /* | ||
3388 | * Request cancellation of remote forwarding of a connection from local side. | ||
3389 | */ | ||
3390 | int | ||
3391 | channel_request_rforward_cancel(struct Forward *fwd) | ||
3392 | { | ||
3393 | if (fwd->listen_path != NULL) { | ||
3394 | return (channel_request_rforward_cancel_streamlocal( | ||
3395 | fwd->listen_path)); | ||
3396 | } else { | ||
3397 | return (channel_request_rforward_cancel_tcpip(fwd->listen_host, | ||
3398 | fwd->listen_port ? fwd->listen_port : fwd->allocated_port)); | ||
3399 | } | ||
3400 | } | ||
3075 | 3401 | ||
3076 | /* | 3402 | /* |
3077 | * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates | 3403 | * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates |
@@ -3079,36 +3405,35 @@ channel_request_rforward_cancel(const char *host, u_short port) | |||
3079 | * message if there was an error). | 3405 | * message if there was an error). |
3080 | */ | 3406 | */ |
3081 | int | 3407 | int |
3082 | channel_input_port_forward_request(int is_root, int gateway_ports) | 3408 | channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts) |
3083 | { | 3409 | { |
3084 | u_short port, host_port; | ||
3085 | int success = 0; | 3410 | int success = 0; |
3086 | char *hostname; | 3411 | struct Forward fwd; |
3087 | 3412 | ||
3088 | /* Get arguments from the packet. */ | 3413 | /* Get arguments from the packet. */ |
3089 | port = packet_get_int(); | 3414 | memset(&fwd, 0, sizeof(fwd)); |
3090 | hostname = packet_get_string(NULL); | 3415 | fwd.listen_port = packet_get_int(); |
3091 | host_port = packet_get_int(); | 3416 | fwd.connect_host = packet_get_string(NULL); |
3417 | fwd.connect_port = packet_get_int(); | ||
3092 | 3418 | ||
3093 | #ifndef HAVE_CYGWIN | 3419 | #ifndef HAVE_CYGWIN |
3094 | /* | 3420 | /* |
3095 | * Check that an unprivileged user is not trying to forward a | 3421 | * Check that an unprivileged user is not trying to forward a |
3096 | * privileged port. | 3422 | * privileged port. |
3097 | */ | 3423 | */ |
3098 | if (port < IPPORT_RESERVED && !is_root) | 3424 | if (fwd.listen_port < IPPORT_RESERVED && !is_root) |
3099 | packet_disconnect( | 3425 | packet_disconnect( |
3100 | "Requested forwarding of port %d but user is not root.", | 3426 | "Requested forwarding of port %d but user is not root.", |
3101 | port); | 3427 | fwd.listen_port); |
3102 | if (host_port == 0) | 3428 | if (fwd.connect_port == 0) |
3103 | packet_disconnect("Dynamic forwarding denied."); | 3429 | packet_disconnect("Dynamic forwarding denied."); |
3104 | #endif | 3430 | #endif |
3105 | 3431 | ||
3106 | /* Initiate forwarding */ | 3432 | /* Initiate forwarding */ |
3107 | success = channel_setup_local_fwd_listener(NULL, port, hostname, | 3433 | success = channel_setup_local_fwd_listener(&fwd, fwd_opts); |
3108 | host_port, gateway_ports); | ||
3109 | 3434 | ||
3110 | /* Free the argument string. */ | 3435 | /* Free the argument string. */ |
3111 | free(hostname); | 3436 | free(fwd.connect_host); |
3112 | 3437 | ||
3113 | return (success ? 0 : -1); | 3438 | return (success ? 0 : -1); |
3114 | } | 3439 | } |
@@ -3134,6 +3459,9 @@ channel_add_permitted_opens(char *host, int port) | |||
3134 | num_permitted_opens + 1, sizeof(*permitted_opens)); | 3459 | num_permitted_opens + 1, sizeof(*permitted_opens)); |
3135 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); | 3460 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); |
3136 | permitted_opens[num_permitted_opens].port_to_connect = port; | 3461 | permitted_opens[num_permitted_opens].port_to_connect = port; |
3462 | permitted_opens[num_permitted_opens].listen_host = NULL; | ||
3463 | permitted_opens[num_permitted_opens].listen_path = NULL; | ||
3464 | permitted_opens[num_permitted_opens].listen_port = 0; | ||
3137 | num_permitted_opens++; | 3465 | num_permitted_opens++; |
3138 | 3466 | ||
3139 | all_opens_permitted = 0; | 3467 | all_opens_permitted = 0; |
@@ -3165,6 +3493,10 @@ channel_update_permitted_opens(int idx, int newport) | |||
3165 | permitted_opens[idx].port_to_connect = 0; | 3493 | permitted_opens[idx].port_to_connect = 0; |
3166 | free(permitted_opens[idx].host_to_connect); | 3494 | free(permitted_opens[idx].host_to_connect); |
3167 | permitted_opens[idx].host_to_connect = NULL; | 3495 | permitted_opens[idx].host_to_connect = NULL; |
3496 | free(permitted_opens[idx].listen_host); | ||
3497 | permitted_opens[idx].listen_host = NULL; | ||
3498 | free(permitted_opens[idx].listen_path); | ||
3499 | permitted_opens[idx].listen_path = NULL; | ||
3168 | } | 3500 | } |
3169 | } | 3501 | } |
3170 | 3502 | ||
@@ -3178,6 +3510,9 @@ channel_add_adm_permitted_opens(char *host, int port) | |||
3178 | permitted_adm_opens[num_adm_permitted_opens].host_to_connect | 3510 | permitted_adm_opens[num_adm_permitted_opens].host_to_connect |
3179 | = xstrdup(host); | 3511 | = xstrdup(host); |
3180 | permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; | 3512 | permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; |
3513 | permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL; | ||
3514 | permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL; | ||
3515 | permitted_adm_opens[num_adm_permitted_opens].listen_port = 0; | ||
3181 | return ++num_adm_permitted_opens; | 3516 | return ++num_adm_permitted_opens; |
3182 | } | 3517 | } |
3183 | 3518 | ||
@@ -3195,8 +3530,11 @@ channel_clear_permitted_opens(void) | |||
3195 | { | 3530 | { |
3196 | int i; | 3531 | int i; |
3197 | 3532 | ||
3198 | for (i = 0; i < num_permitted_opens; i++) | 3533 | for (i = 0; i < num_permitted_opens; i++) { |
3199 | free(permitted_opens[i].host_to_connect); | 3534 | free(permitted_opens[i].host_to_connect); |
3535 | free(permitted_opens[i].listen_host); | ||
3536 | free(permitted_opens[i].listen_path); | ||
3537 | } | ||
3200 | free(permitted_opens); | 3538 | free(permitted_opens); |
3201 | permitted_opens = NULL; | 3539 | permitted_opens = NULL; |
3202 | num_permitted_opens = 0; | 3540 | num_permitted_opens = 0; |
@@ -3207,8 +3545,11 @@ channel_clear_adm_permitted_opens(void) | |||
3207 | { | 3545 | { |
3208 | int i; | 3546 | int i; |
3209 | 3547 | ||
3210 | for (i = 0; i < num_adm_permitted_opens; i++) | 3548 | for (i = 0; i < num_adm_permitted_opens; i++) { |
3211 | free(permitted_adm_opens[i].host_to_connect); | 3549 | free(permitted_adm_opens[i].host_to_connect); |
3550 | free(permitted_adm_opens[i].listen_host); | ||
3551 | free(permitted_adm_opens[i].listen_path); | ||
3552 | } | ||
3212 | free(permitted_adm_opens); | 3553 | free(permitted_adm_opens); |
3213 | permitted_adm_opens = NULL; | 3554 | permitted_adm_opens = NULL; |
3214 | num_adm_permitted_opens = 0; | 3555 | num_adm_permitted_opens = 0; |
@@ -3246,30 +3587,32 @@ permitopen_port(const char *p) | |||
3246 | return -1; | 3587 | return -1; |
3247 | } | 3588 | } |
3248 | 3589 | ||
3249 | static int | ||
3250 | port_match(u_short allowedport, u_short requestedport) | ||
3251 | { | ||
3252 | if (allowedport == FWD_PERMIT_ANY_PORT || | ||
3253 | allowedport == requestedport) | ||
3254 | return 1; | ||
3255 | return 0; | ||
3256 | } | ||
3257 | |||
3258 | /* Try to start non-blocking connect to next host in cctx list */ | 3590 | /* Try to start non-blocking connect to next host in cctx list */ |
3259 | static int | 3591 | static int |
3260 | connect_next(struct channel_connect *cctx) | 3592 | connect_next(struct channel_connect *cctx) |
3261 | { | 3593 | { |
3262 | int sock, saved_errno; | 3594 | int sock, saved_errno; |
3263 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 3595 | struct sockaddr_un *sunaddr; |
3596 | char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))]; | ||
3264 | 3597 | ||
3265 | for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { | 3598 | for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { |
3266 | if (cctx->ai->ai_family != AF_INET && | 3599 | switch (cctx->ai->ai_family) { |
3267 | cctx->ai->ai_family != AF_INET6) | 3600 | case AF_UNIX: |
3268 | continue; | 3601 | /* unix:pathname instead of host:port */ |
3269 | if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, | 3602 | sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr; |
3270 | ntop, sizeof(ntop), strport, sizeof(strport), | 3603 | strlcpy(ntop, "unix", sizeof(ntop)); |
3271 | NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 3604 | strlcpy(strport, sunaddr->sun_path, sizeof(strport)); |
3272 | error("connect_next: getnameinfo failed"); | 3605 | break; |
3606 | case AF_INET: | ||
3607 | case AF_INET6: | ||
3608 | if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, | ||
3609 | ntop, sizeof(ntop), strport, sizeof(strport), | ||
3610 | NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | ||
3611 | error("connect_next: getnameinfo failed"); | ||
3612 | continue; | ||
3613 | } | ||
3614 | break; | ||
3615 | default: | ||
3273 | continue; | 3616 | continue; |
3274 | } | 3617 | } |
3275 | if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, | 3618 | if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, |
@@ -3292,10 +3635,11 @@ connect_next(struct channel_connect *cctx) | |||
3292 | errno = saved_errno; | 3635 | errno = saved_errno; |
3293 | continue; /* fail -- try next */ | 3636 | continue; /* fail -- try next */ |
3294 | } | 3637 | } |
3638 | if (cctx->ai->ai_family != AF_UNIX) | ||
3639 | set_nodelay(sock); | ||
3295 | debug("connect_next: host %.100s ([%.100s]:%s) " | 3640 | debug("connect_next: host %.100s ([%.100s]:%s) " |
3296 | "in progress, fd=%d", cctx->host, ntop, strport, sock); | 3641 | "in progress, fd=%d", cctx->host, ntop, strport, sock); |
3297 | cctx->ai = cctx->ai->ai_next; | 3642 | cctx->ai = cctx->ai->ai_next; |
3298 | set_nodelay(sock); | ||
3299 | return sock; | 3643 | return sock; |
3300 | } | 3644 | } |
3301 | return -1; | 3645 | return -1; |
@@ -3305,14 +3649,18 @@ static void | |||
3305 | channel_connect_ctx_free(struct channel_connect *cctx) | 3649 | channel_connect_ctx_free(struct channel_connect *cctx) |
3306 | { | 3650 | { |
3307 | free(cctx->host); | 3651 | free(cctx->host); |
3308 | if (cctx->aitop) | 3652 | if (cctx->aitop) { |
3309 | freeaddrinfo(cctx->aitop); | 3653 | if (cctx->aitop->ai_family == AF_UNIX) |
3654 | free(cctx->aitop); | ||
3655 | else | ||
3656 | freeaddrinfo(cctx->aitop); | ||
3657 | } | ||
3310 | memset(cctx, 0, sizeof(*cctx)); | 3658 | memset(cctx, 0, sizeof(*cctx)); |
3311 | } | 3659 | } |
3312 | 3660 | ||
3313 | /* Return CONNECTING channel to remote host, port */ | 3661 | /* Return CONNECTING channel to remote host:port or local socket path */ |
3314 | static Channel * | 3662 | static Channel * |
3315 | connect_to(const char *host, u_short port, char *ctype, char *rname) | 3663 | connect_to(const char *name, int port, char *ctype, char *rname) |
3316 | { | 3664 | { |
3317 | struct addrinfo hints; | 3665 | struct addrinfo hints; |
3318 | int gaierr; | 3666 | int gaierr; |
@@ -3322,23 +3670,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname) | |||
3322 | Channel *c; | 3670 | Channel *c; |
3323 | 3671 | ||
3324 | memset(&cctx, 0, sizeof(cctx)); | 3672 | memset(&cctx, 0, sizeof(cctx)); |
3325 | memset(&hints, 0, sizeof(hints)); | 3673 | |
3326 | hints.ai_family = IPv4or6; | 3674 | if (port == PORT_STREAMLOCAL) { |
3327 | hints.ai_socktype = SOCK_STREAM; | 3675 | struct sockaddr_un *sunaddr; |
3328 | snprintf(strport, sizeof strport, "%d", port); | 3676 | struct addrinfo *ai; |
3329 | if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) { | 3677 | |
3330 | error("connect_to %.100s: unknown host (%s)", host, | 3678 | if (strlen(name) > sizeof(sunaddr->sun_path)) { |
3331 | ssh_gai_strerror(gaierr)); | 3679 | error("%.100s: %.100s", name, strerror(ENAMETOOLONG)); |
3332 | return NULL; | 3680 | return (NULL); |
3681 | } | ||
3682 | |||
3683 | /* | ||
3684 | * Fake up a struct addrinfo for AF_UNIX connections. | ||
3685 | * channel_connect_ctx_free() must check ai_family | ||
3686 | * and use free() not freeaddirinfo() for AF_UNIX. | ||
3687 | */ | ||
3688 | ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr)); | ||
3689 | memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr)); | ||
3690 | ai->ai_addr = (struct sockaddr *)(ai + 1); | ||
3691 | ai->ai_addrlen = sizeof(*sunaddr); | ||
3692 | ai->ai_family = AF_UNIX; | ||
3693 | ai->ai_socktype = SOCK_STREAM; | ||
3694 | ai->ai_protocol = PF_UNSPEC; | ||
3695 | sunaddr = (struct sockaddr_un *)ai->ai_addr; | ||
3696 | sunaddr->sun_family = AF_UNIX; | ||
3697 | strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path)); | ||
3698 | cctx.aitop = ai; | ||
3699 | } else { | ||
3700 | memset(&hints, 0, sizeof(hints)); | ||
3701 | hints.ai_family = IPv4or6; | ||
3702 | hints.ai_socktype = SOCK_STREAM; | ||
3703 | snprintf(strport, sizeof strport, "%d", port); | ||
3704 | if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) { | ||
3705 | error("connect_to %.100s: unknown host (%s)", name, | ||
3706 | ssh_gai_strerror(gaierr)); | ||
3707 | return NULL; | ||
3708 | } | ||
3333 | } | 3709 | } |
3334 | 3710 | ||
3335 | cctx.host = xstrdup(host); | 3711 | cctx.host = xstrdup(name); |
3336 | cctx.port = port; | 3712 | cctx.port = port; |
3337 | cctx.ai = cctx.aitop; | 3713 | cctx.ai = cctx.aitop; |
3338 | 3714 | ||
3339 | if ((sock = connect_next(&cctx)) == -1) { | 3715 | if ((sock = connect_next(&cctx)) == -1) { |
3340 | error("connect to %.100s port %d failed: %s", | 3716 | error("connect to %.100s port %d failed: %s", |
3341 | host, port, strerror(errno)); | 3717 | name, port, strerror(errno)); |
3342 | channel_connect_ctx_free(&cctx); | 3718 | channel_connect_ctx_free(&cctx); |
3343 | return NULL; | 3719 | return NULL; |
3344 | } | 3720 | } |
@@ -3349,13 +3725,14 @@ connect_to(const char *host, u_short port, char *ctype, char *rname) | |||
3349 | } | 3725 | } |
3350 | 3726 | ||
3351 | Channel * | 3727 | Channel * |
3352 | channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) | 3728 | channel_connect_by_listen_address(const char *listen_host, |
3729 | u_short listen_port, char *ctype, char *rname) | ||
3353 | { | 3730 | { |
3354 | int i; | 3731 | int i; |
3355 | 3732 | ||
3356 | for (i = 0; i < num_permitted_opens; i++) { | 3733 | for (i = 0; i < num_permitted_opens; i++) { |
3357 | if (permitted_opens[i].host_to_connect != NULL && | 3734 | if (open_listen_match_tcpip(&permitted_opens[i], listen_host, |
3358 | port_match(permitted_opens[i].listen_port, listen_port)) { | 3735 | listen_port, 1)) { |
3359 | return connect_to( | 3736 | return connect_to( |
3360 | permitted_opens[i].host_to_connect, | 3737 | permitted_opens[i].host_to_connect, |
3361 | permitted_opens[i].port_to_connect, ctype, rname); | 3738 | permitted_opens[i].port_to_connect, ctype, rname); |
@@ -3366,29 +3743,45 @@ channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) | |||
3366 | return NULL; | 3743 | return NULL; |
3367 | } | 3744 | } |
3368 | 3745 | ||
3746 | Channel * | ||
3747 | channel_connect_by_listen_path(const char *path, char *ctype, char *rname) | ||
3748 | { | ||
3749 | int i; | ||
3750 | |||
3751 | for (i = 0; i < num_permitted_opens; i++) { | ||
3752 | if (open_listen_match_streamlocal(&permitted_opens[i], path)) { | ||
3753 | return connect_to( | ||
3754 | permitted_opens[i].host_to_connect, | ||
3755 | permitted_opens[i].port_to_connect, ctype, rname); | ||
3756 | } | ||
3757 | } | ||
3758 | error("WARNING: Server requests forwarding for unknown path %.100s", | ||
3759 | path); | ||
3760 | return NULL; | ||
3761 | } | ||
3762 | |||
3369 | /* Check if connecting to that port is permitted and connect. */ | 3763 | /* Check if connecting to that port is permitted and connect. */ |
3370 | Channel * | 3764 | Channel * |
3371 | channel_connect_to(const char *host, u_short port, char *ctype, char *rname) | 3765 | channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname) |
3372 | { | 3766 | { |
3373 | int i, permit, permit_adm = 1; | 3767 | int i, permit, permit_adm = 1; |
3374 | 3768 | ||
3375 | permit = all_opens_permitted; | 3769 | permit = all_opens_permitted; |
3376 | if (!permit) { | 3770 | if (!permit) { |
3377 | for (i = 0; i < num_permitted_opens; i++) | 3771 | for (i = 0; i < num_permitted_opens; i++) |
3378 | if (permitted_opens[i].host_to_connect != NULL && | 3772 | if (open_match(&permitted_opens[i], host, port)) { |
3379 | port_match(permitted_opens[i].port_to_connect, port) && | ||
3380 | strcmp(permitted_opens[i].host_to_connect, host) == 0) | ||
3381 | permit = 1; | 3773 | permit = 1; |
3774 | break; | ||
3775 | } | ||
3382 | } | 3776 | } |
3383 | 3777 | ||
3384 | if (num_adm_permitted_opens > 0) { | 3778 | if (num_adm_permitted_opens > 0) { |
3385 | permit_adm = 0; | 3779 | permit_adm = 0; |
3386 | for (i = 0; i < num_adm_permitted_opens; i++) | 3780 | for (i = 0; i < num_adm_permitted_opens; i++) |
3387 | if (permitted_adm_opens[i].host_to_connect != NULL && | 3781 | if (open_match(&permitted_adm_opens[i], host, port)) { |
3388 | port_match(permitted_adm_opens[i].port_to_connect, port) && | ||
3389 | strcmp(permitted_adm_opens[i].host_to_connect, host) | ||
3390 | == 0) | ||
3391 | permit_adm = 1; | 3782 | permit_adm = 1; |
3783 | break; | ||
3784 | } | ||
3392 | } | 3785 | } |
3393 | 3786 | ||
3394 | if (!permit || !permit_adm) { | 3787 | if (!permit || !permit_adm) { |
@@ -3399,6 +3792,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname) | |||
3399 | return connect_to(host, port, ctype, rname); | 3792 | return connect_to(host, port, ctype, rname); |
3400 | } | 3793 | } |
3401 | 3794 | ||
3795 | /* Check if connecting to that path is permitted and connect. */ | ||
3796 | Channel * | ||
3797 | channel_connect_to_path(const char *path, char *ctype, char *rname) | ||
3798 | { | ||
3799 | int i, permit, permit_adm = 1; | ||
3800 | |||
3801 | permit = all_opens_permitted; | ||
3802 | if (!permit) { | ||
3803 | for (i = 0; i < num_permitted_opens; i++) | ||
3804 | if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) { | ||
3805 | permit = 1; | ||
3806 | break; | ||
3807 | } | ||
3808 | } | ||
3809 | |||
3810 | if (num_adm_permitted_opens > 0) { | ||
3811 | permit_adm = 0; | ||
3812 | for (i = 0; i < num_adm_permitted_opens; i++) | ||
3813 | if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) { | ||
3814 | permit_adm = 1; | ||
3815 | break; | ||
3816 | } | ||
3817 | } | ||
3818 | |||
3819 | if (!permit || !permit_adm) { | ||
3820 | logit("Received request to connect to path %.100s, " | ||
3821 | "but the request was denied.", path); | ||
3822 | return NULL; | ||
3823 | } | ||
3824 | return connect_to(path, PORT_STREAMLOCAL, ctype, rname); | ||
3825 | } | ||
3826 | |||
3402 | void | 3827 | void |
3403 | channel_send_window_changes(void) | 3828 | channel_send_window_changes(void) |
3404 | { | 3829 | { |
diff --git a/channels.h b/channels.h index 4fab9d7c4..a000c98e5 100644 --- a/channels.h +++ b/channels.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.h,v 1.113 2013/06/07 15:37:52 dtucker Exp $ */ | 1 | /* $OpenBSD: channels.h,v 1.115 2014/07/15 15:54:14 millert Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -56,7 +56,9 @@ | |||
56 | #define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ | 56 | #define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ |
57 | #define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */ | 57 | #define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */ |
58 | #define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ | 58 | #define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ |
59 | #define SSH_CHANNEL_MAX_TYPE 18 | 59 | #define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ |
60 | #define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ | ||
61 | #define SSH_CHANNEL_MAX_TYPE 20 | ||
60 | 62 | ||
61 | #define CHANNEL_CANCEL_PORT_STATIC -1 | 63 | #define CHANNEL_CANCEL_PORT_STATIC -1 |
62 | 64 | ||
@@ -254,6 +256,8 @@ char *channel_open_message(void); | |||
254 | int channel_find_open(void); | 256 | int channel_find_open(void); |
255 | 257 | ||
256 | /* tcp forwarding */ | 258 | /* tcp forwarding */ |
259 | struct Forward; | ||
260 | struct ForwardOptions; | ||
257 | void channel_set_af(int af); | 261 | void channel_set_af(int af); |
258 | void channel_permit_all_opens(void); | 262 | void channel_permit_all_opens(void); |
259 | void channel_add_permitted_opens(char *, int); | 263 | void channel_add_permitted_opens(char *, int); |
@@ -263,18 +267,19 @@ void channel_update_permitted_opens(int, int); | |||
263 | void channel_clear_permitted_opens(void); | 267 | void channel_clear_permitted_opens(void); |
264 | void channel_clear_adm_permitted_opens(void); | 268 | void channel_clear_adm_permitted_opens(void); |
265 | void channel_print_adm_permitted_opens(void); | 269 | void channel_print_adm_permitted_opens(void); |
266 | int channel_input_port_forward_request(int, int); | 270 | int channel_input_port_forward_request(int, struct ForwardOptions *); |
267 | Channel *channel_connect_to(const char *, u_short, char *, char *); | 271 | Channel *channel_connect_to_port(const char *, u_short, char *, char *); |
272 | Channel *channel_connect_to_path(const char *, char *, char *); | ||
268 | Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); | 273 | Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); |
269 | Channel *channel_connect_by_listen_address(u_short, char *, char *); | 274 | Channel *channel_connect_by_listen_address(const char *, u_short, |
270 | int channel_request_remote_forwarding(const char *, u_short, | 275 | char *, char *); |
271 | const char *, u_short); | 276 | Channel *channel_connect_by_listen_path(const char *, char *, char *); |
272 | int channel_setup_local_fwd_listener(const char *, u_short, | 277 | int channel_request_remote_forwarding(struct Forward *); |
273 | const char *, u_short, int); | 278 | int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *); |
274 | int channel_request_rforward_cancel(const char *host, u_short port); | 279 | int channel_request_rforward_cancel(struct Forward *); |
275 | int channel_setup_remote_fwd_listener(const char *, u_short, int *, int); | 280 | int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *); |
276 | int channel_cancel_rport_listener(const char *, u_short); | 281 | int channel_cancel_rport_listener(struct Forward *); |
277 | int channel_cancel_lport_listener(const char *, u_short, int, int); | 282 | int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *); |
278 | int permitopen_port(const char *); | 283 | int permitopen_port(const char *); |
279 | 284 | ||
280 | /* x11 forwarding */ | 285 | /* x11 forwarding */ |
diff --git a/cipher-3des1.c b/cipher-3des1.c index b2823592b..2753f9a0e 100644 --- a/cipher-3des1.c +++ b/cipher-3des1.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher-3des1.c,v 1.10 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: cipher-3des1.c,v 1.11 2014/07/02 04:59:06 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2003 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2003 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -29,13 +29,11 @@ | |||
29 | 29 | ||
30 | #include <openssl/evp.h> | 30 | #include <openssl/evp.h> |
31 | 31 | ||
32 | #include <stdarg.h> | ||
33 | #include <string.h> | 32 | #include <string.h> |
34 | 33 | ||
35 | #include "xmalloc.h" | 34 | #include "xmalloc.h" |
36 | #include "log.h" | 35 | #include "log.h" |
37 | 36 | #include "ssherr.h" | |
38 | #include "openbsd-compat/openssl-compat.h" | ||
39 | 37 | ||
40 | /* | 38 | /* |
41 | * This is used by SSH1: | 39 | * This is used by SSH1: |
@@ -57,7 +55,7 @@ struct ssh1_3des_ctx | |||
57 | }; | 55 | }; |
58 | 56 | ||
59 | const EVP_CIPHER * evp_ssh1_3des(void); | 57 | const EVP_CIPHER * evp_ssh1_3des(void); |
60 | void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); | 58 | int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); |
61 | 59 | ||
62 | static int | 60 | static int |
63 | ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, | 61 | ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, |
@@ -67,11 +65,12 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, | |||
67 | u_char *k1, *k2, *k3; | 65 | u_char *k1, *k2, *k3; |
68 | 66 | ||
69 | if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { | 67 | if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { |
70 | c = xcalloc(1, sizeof(*c)); | 68 | if ((c = calloc(1, sizeof(*c))) == NULL) |
69 | return 0; | ||
71 | EVP_CIPHER_CTX_set_app_data(ctx, c); | 70 | EVP_CIPHER_CTX_set_app_data(ctx, c); |
72 | } | 71 | } |
73 | if (key == NULL) | 72 | if (key == NULL) |
74 | return (1); | 73 | return 1; |
75 | if (enc == -1) | 74 | if (enc == -1) |
76 | enc = ctx->encrypt; | 75 | enc = ctx->encrypt; |
77 | k1 = k2 = k3 = (u_char *) key; | 76 | k1 = k2 = k3 = (u_char *) key; |
@@ -85,44 +84,29 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, | |||
85 | EVP_CIPHER_CTX_init(&c->k1); | 84 | EVP_CIPHER_CTX_init(&c->k1); |
86 | EVP_CIPHER_CTX_init(&c->k2); | 85 | EVP_CIPHER_CTX_init(&c->k2); |
87 | EVP_CIPHER_CTX_init(&c->k3); | 86 | EVP_CIPHER_CTX_init(&c->k3); |
88 | #ifdef SSH_OLD_EVP | ||
89 | EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc); | ||
90 | EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc); | ||
91 | EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc); | ||
92 | #else | ||
93 | if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || | 87 | if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || |
94 | EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || | 88 | EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || |
95 | EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { | 89 | EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { |
96 | explicit_bzero(c, sizeof(*c)); | 90 | explicit_bzero(c, sizeof(*c)); |
97 | free(c); | 91 | free(c); |
98 | EVP_CIPHER_CTX_set_app_data(ctx, NULL); | 92 | EVP_CIPHER_CTX_set_app_data(ctx, NULL); |
99 | return (0); | 93 | return 0; |
100 | } | 94 | } |
101 | #endif | 95 | return 1; |
102 | return (1); | ||
103 | } | 96 | } |
104 | 97 | ||
105 | static int | 98 | static int |
106 | ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, | 99 | ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len) |
107 | LIBCRYPTO_EVP_INL_TYPE len) | ||
108 | { | 100 | { |
109 | struct ssh1_3des_ctx *c; | 101 | struct ssh1_3des_ctx *c; |
110 | 102 | ||
111 | if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { | 103 | if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) |
112 | error("ssh1_3des_cbc: no context"); | 104 | return 0; |
113 | return (0); | ||
114 | } | ||
115 | #ifdef SSH_OLD_EVP | ||
116 | EVP_Cipher(&c->k1, dest, (u_char *)src, len); | ||
117 | EVP_Cipher(&c->k2, dest, dest, len); | ||
118 | EVP_Cipher(&c->k3, dest, dest, len); | ||
119 | #else | ||
120 | if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || | 105 | if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || |
121 | EVP_Cipher(&c->k2, dest, dest, len) == 0 || | 106 | EVP_Cipher(&c->k2, dest, dest, len) == 0 || |
122 | EVP_Cipher(&c->k3, dest, dest, len) == 0) | 107 | EVP_Cipher(&c->k3, dest, dest, len) == 0) |
123 | return (0); | 108 | return 0; |
124 | #endif | 109 | return 1; |
125 | return (1); | ||
126 | } | 110 | } |
127 | 111 | ||
128 | static int | 112 | static int |
@@ -138,29 +122,28 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) | |||
138 | free(c); | 122 | free(c); |
139 | EVP_CIPHER_CTX_set_app_data(ctx, NULL); | 123 | EVP_CIPHER_CTX_set_app_data(ctx, NULL); |
140 | } | 124 | } |
141 | return (1); | 125 | return 1; |
142 | } | 126 | } |
143 | 127 | ||
144 | void | 128 | int |
145 | ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) | 129 | ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) |
146 | { | 130 | { |
147 | struct ssh1_3des_ctx *c; | 131 | struct ssh1_3des_ctx *c; |
148 | 132 | ||
149 | if (len != 24) | 133 | if (len != 24) |
150 | fatal("%s: bad 3des iv length: %d", __func__, len); | 134 | return SSH_ERR_INVALID_ARGUMENT; |
151 | if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) | 135 | if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) |
152 | fatal("%s: no 3des context", __func__); | 136 | return SSH_ERR_INTERNAL_ERROR; |
153 | if (doset) { | 137 | if (doset) { |
154 | debug3("%s: Installed 3DES IV", __func__); | ||
155 | memcpy(c->k1.iv, iv, 8); | 138 | memcpy(c->k1.iv, iv, 8); |
156 | memcpy(c->k2.iv, iv + 8, 8); | 139 | memcpy(c->k2.iv, iv + 8, 8); |
157 | memcpy(c->k3.iv, iv + 16, 8); | 140 | memcpy(c->k3.iv, iv + 16, 8); |
158 | } else { | 141 | } else { |
159 | debug3("%s: Copying 3DES IV", __func__); | ||
160 | memcpy(iv, c->k1.iv, 8); | 142 | memcpy(iv, c->k1.iv, 8); |
161 | memcpy(iv + 8, c->k2.iv, 8); | 143 | memcpy(iv + 8, c->k2.iv, 8); |
162 | memcpy(iv + 16, c->k3.iv, 8); | 144 | memcpy(iv + 16, c->k3.iv, 8); |
163 | } | 145 | } |
146 | return 0; | ||
164 | } | 147 | } |
165 | 148 | ||
166 | const EVP_CIPHER * | 149 | const EVP_CIPHER * |
@@ -176,8 +159,6 @@ evp_ssh1_3des(void) | |||
176 | ssh1_3des.init = ssh1_3des_init; | 159 | ssh1_3des.init = ssh1_3des_init; |
177 | ssh1_3des.cleanup = ssh1_3des_cleanup; | 160 | ssh1_3des.cleanup = ssh1_3des_cleanup; |
178 | ssh1_3des.do_cipher = ssh1_3des_cbc; | 161 | ssh1_3des.do_cipher = ssh1_3des_cbc; |
179 | #ifndef SSH_OLD_EVP | ||
180 | ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; | 162 | ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; |
181 | #endif | 163 | return &ssh1_3des; |
182 | return (&ssh1_3des); | ||
183 | } | 164 | } |
diff --git a/cipher-aesctr.c b/cipher-aesctr.c new file mode 100644 index 000000000..a4cf61e41 --- /dev/null +++ b/cipher-aesctr.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* $OpenBSD: cipher-aesctr.c,v 1.1 2014/04/29 15:39:33 markus Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2003 Markus Friedl <markus@openbsd.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <sys/types.h> | ||
19 | #include <string.h> | ||
20 | |||
21 | #include "cipher-aesctr.h" | ||
22 | |||
23 | /* | ||
24 | * increment counter 'ctr', | ||
25 | * the counter is of size 'len' bytes and stored in network-byte-order. | ||
26 | * (LSB at ctr[len-1], MSB at ctr[0]) | ||
27 | */ | ||
28 | static __inline__ void | ||
29 | aesctr_inc(u8 *ctr, u32 len) | ||
30 | { | ||
31 | ssize_t i; | ||
32 | |||
33 | #ifndef CONSTANT_TIME_INCREMENT | ||
34 | for (i = len - 1; i >= 0; i--) | ||
35 | if (++ctr[i]) /* continue on overflow */ | ||
36 | return; | ||
37 | #else | ||
38 | u8 x, add = 1; | ||
39 | |||
40 | for (i = len - 1; i >= 0; i--) { | ||
41 | ctr[i] += add; | ||
42 | /* constant time for: x = ctr[i] ? 1 : 0 */ | ||
43 | x = ctr[i]; | ||
44 | x = (x | (x >> 4)) & 0xf; | ||
45 | x = (x | (x >> 2)) & 0x3; | ||
46 | x = (x | (x >> 1)) & 0x1; | ||
47 | add *= (x^1); | ||
48 | } | ||
49 | #endif | ||
50 | } | ||
51 | |||
52 | void | ||
53 | aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits) | ||
54 | { | ||
55 | x->rounds = rijndaelKeySetupEnc(x->ek, k, kbits); | ||
56 | } | ||
57 | |||
58 | void | ||
59 | aesctr_ivsetup(aesctr_ctx *x,const u8 *iv) | ||
60 | { | ||
61 | memcpy(x->ctr, iv, AES_BLOCK_SIZE); | ||
62 | } | ||
63 | |||
64 | void | ||
65 | aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes) | ||
66 | { | ||
67 | u32 n = 0; | ||
68 | u8 buf[AES_BLOCK_SIZE]; | ||
69 | |||
70 | while ((bytes--) > 0) { | ||
71 | if (n == 0) { | ||
72 | rijndaelEncrypt(x->ek, x->rounds, x->ctr, buf); | ||
73 | aesctr_inc(x->ctr, AES_BLOCK_SIZE); | ||
74 | } | ||
75 | *(c++) = *(m++) ^ buf[n]; | ||
76 | n = (n + 1) % AES_BLOCK_SIZE; | ||
77 | } | ||
78 | } | ||
diff --git a/cipher-aesctr.h b/cipher-aesctr.h new file mode 100644 index 000000000..85d55bba2 --- /dev/null +++ b/cipher-aesctr.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* $OpenBSD: cipher-aesctr.h,v 1.1 2014/04/29 15:39:33 markus Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2014 Markus Friedl | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef OPENSSH_AESCTR_H | ||
19 | #define OPENSSH_AESCTR_H | ||
20 | |||
21 | #include "rijndael.h" | ||
22 | |||
23 | #define AES_BLOCK_SIZE 16 | ||
24 | |||
25 | typedef struct aesctr_ctx { | ||
26 | int rounds; /* keylen-dependent #rounds */ | ||
27 | u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ | ||
28 | u8 ctr[AES_BLOCK_SIZE]; /* counter */ | ||
29 | } aesctr_ctx; | ||
30 | |||
31 | void aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits); | ||
32 | void aesctr_ivsetup(aesctr_ctx *x,const u8 *iv); | ||
33 | void aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes); | ||
34 | |||
35 | #endif | ||
diff --git a/cipher-chachapoly.c b/cipher-chachapoly.c index 251b94ec8..8665b41a3 100644 --- a/cipher-chachapoly.c +++ b/cipher-chachapoly.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /* $OpenBSD: cipher-chachapoly.c,v 1.4 2014/01/31 16:39:19 tedu Exp $ */ | 17 | /* $OpenBSD: cipher-chachapoly.c,v 1.6 2014/07/03 12:42:16 jsing Exp $ */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | 20 | ||
@@ -24,16 +24,18 @@ | |||
24 | #include <stdio.h> /* needed for misc.h */ | 24 | #include <stdio.h> /* needed for misc.h */ |
25 | 25 | ||
26 | #include "log.h" | 26 | #include "log.h" |
27 | #include "misc.h" | 27 | #include "sshbuf.h" |
28 | #include "ssherr.h" | ||
28 | #include "cipher-chachapoly.h" | 29 | #include "cipher-chachapoly.h" |
29 | 30 | ||
30 | void chachapoly_init(struct chachapoly_ctx *ctx, | 31 | int chachapoly_init(struct chachapoly_ctx *ctx, |
31 | const u_char *key, u_int keylen) | 32 | const u_char *key, u_int keylen) |
32 | { | 33 | { |
33 | if (keylen != (32 + 32)) /* 2 x 256 bit keys */ | 34 | if (keylen != (32 + 32)) /* 2 x 256 bit keys */ |
34 | fatal("%s: invalid keylen %u", __func__, keylen); | 35 | return SSH_ERR_INVALID_ARGUMENT; |
35 | chacha_keysetup(&ctx->main_ctx, key, 256); | 36 | chacha_keysetup(&ctx->main_ctx, key, 256); |
36 | chacha_keysetup(&ctx->header_ctx, key + 32, 256); | 37 | chacha_keysetup(&ctx->header_ctx, key + 32, 256); |
38 | return 0; | ||
37 | } | 39 | } |
38 | 40 | ||
39 | /* | 41 | /* |
@@ -52,33 +54,37 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, | |||
52 | u_char seqbuf[8]; | 54 | u_char seqbuf[8]; |
53 | const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */ | 55 | const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */ |
54 | u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; | 56 | u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; |
55 | int r = -1; | 57 | int r = SSH_ERR_INTERNAL_ERROR; |
56 | 58 | ||
57 | /* | 59 | /* |
58 | * Run ChaCha20 once to generate the Poly1305 key. The IV is the | 60 | * Run ChaCha20 once to generate the Poly1305 key. The IV is the |
59 | * packet sequence number. | 61 | * packet sequence number. |
60 | */ | 62 | */ |
61 | memset(poly_key, 0, sizeof(poly_key)); | 63 | memset(poly_key, 0, sizeof(poly_key)); |
62 | put_u64(seqbuf, seqnr); | 64 | POKE_U64(seqbuf, seqnr); |
63 | chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL); | 65 | chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL); |
64 | chacha_encrypt_bytes(&ctx->main_ctx, | 66 | chacha_encrypt_bytes(&ctx->main_ctx, |
65 | poly_key, poly_key, sizeof(poly_key)); | 67 | poly_key, poly_key, sizeof(poly_key)); |
66 | /* Set Chacha's block counter to 1 */ | ||
67 | chacha_ivsetup(&ctx->main_ctx, seqbuf, one); | ||
68 | 68 | ||
69 | /* If decrypting, check tag before anything else */ | 69 | /* If decrypting, check tag before anything else */ |
70 | if (!do_encrypt) { | 70 | if (!do_encrypt) { |
71 | const u_char *tag = src + aadlen + len; | 71 | const u_char *tag = src + aadlen + len; |
72 | 72 | ||
73 | poly1305_auth(expected_tag, src, aadlen + len, poly_key); | 73 | poly1305_auth(expected_tag, src, aadlen + len, poly_key); |
74 | if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) | 74 | if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) { |
75 | r = SSH_ERR_MAC_INVALID; | ||
75 | goto out; | 76 | goto out; |
77 | } | ||
76 | } | 78 | } |
79 | |||
77 | /* Crypt additional data */ | 80 | /* Crypt additional data */ |
78 | if (aadlen) { | 81 | if (aadlen) { |
79 | chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); | 82 | chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); |
80 | chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen); | 83 | chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen); |
81 | } | 84 | } |
85 | |||
86 | /* Set Chacha's block counter to 1 */ | ||
87 | chacha_ivsetup(&ctx->main_ctx, seqbuf, one); | ||
82 | chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen, | 88 | chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen, |
83 | dest + aadlen, len); | 89 | dest + aadlen, len); |
84 | 90 | ||
@@ -88,7 +94,6 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, | |||
88 | poly_key); | 94 | poly_key); |
89 | } | 95 | } |
90 | r = 0; | 96 | r = 0; |
91 | |||
92 | out: | 97 | out: |
93 | explicit_bzero(expected_tag, sizeof(expected_tag)); | 98 | explicit_bzero(expected_tag, sizeof(expected_tag)); |
94 | explicit_bzero(seqbuf, sizeof(seqbuf)); | 99 | explicit_bzero(seqbuf, sizeof(seqbuf)); |
@@ -104,11 +109,11 @@ chachapoly_get_length(struct chachapoly_ctx *ctx, | |||
104 | u_char buf[4], seqbuf[8]; | 109 | u_char buf[4], seqbuf[8]; |
105 | 110 | ||
106 | if (len < 4) | 111 | if (len < 4) |
107 | return -1; /* Insufficient length */ | 112 | return SSH_ERR_MESSAGE_INCOMPLETE; |
108 | put_u64(seqbuf, seqnr); | 113 | POKE_U64(seqbuf, seqnr); |
109 | chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); | 114 | chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); |
110 | chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4); | 115 | chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4); |
111 | *plenp = get_u32(buf); | 116 | *plenp = PEEK_U32(buf); |
112 | return 0; | 117 | return 0; |
113 | } | 118 | } |
114 | 119 | ||
diff --git a/cipher-chachapoly.h b/cipher-chachapoly.h index 1628693b2..b7072be7d 100644 --- a/cipher-chachapoly.h +++ b/cipher-chachapoly.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher-chachapoly.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ | 1 | /* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) Damien Miller 2013 <djm@mindrot.org> | 4 | * Copyright (c) Damien Miller 2013 <djm@mindrot.org> |
@@ -28,7 +28,7 @@ struct chachapoly_ctx { | |||
28 | struct chacha_ctx main_ctx, header_ctx; | 28 | struct chacha_ctx main_ctx, header_ctx; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | void chachapoly_init(struct chachapoly_ctx *cpctx, | 31 | int chachapoly_init(struct chachapoly_ctx *cpctx, |
32 | const u_char *key, u_int keylen) | 32 | const u_char *key, u_int keylen) |
33 | __attribute__((__bounded__(__buffer__, 2, 3))); | 33 | __attribute__((__bounded__(__buffer__, 2, 3))); |
34 | int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, | 34 | int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher.c,v 1.97 2014/02/07 06:55:54 djm Exp $ */ | 1 | /* $OpenBSD: cipher.c,v 1.99 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -43,21 +43,21 @@ | |||
43 | #include <stdarg.h> | 43 | #include <stdarg.h> |
44 | #include <stdio.h> | 44 | #include <stdio.h> |
45 | 45 | ||
46 | #include "xmalloc.h" | ||
47 | #include "log.h" | ||
48 | #include "misc.h" | ||
49 | #include "cipher.h" | 46 | #include "cipher.h" |
50 | #include "buffer.h" | 47 | #include "misc.h" |
48 | #include "sshbuf.h" | ||
49 | #include "ssherr.h" | ||
51 | #include "digest.h" | 50 | #include "digest.h" |
52 | 51 | ||
53 | /* compatibility with old or broken OpenSSL versions */ | ||
54 | #include "openbsd-compat/openssl-compat.h" | 52 | #include "openbsd-compat/openssl-compat.h" |
55 | 53 | ||
54 | #ifdef WITH_SSH1 | ||
56 | extern const EVP_CIPHER *evp_ssh1_bf(void); | 55 | extern const EVP_CIPHER *evp_ssh1_bf(void); |
57 | extern const EVP_CIPHER *evp_ssh1_3des(void); | 56 | extern const EVP_CIPHER *evp_ssh1_3des(void); |
58 | extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); | 57 | extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); |
58 | #endif | ||
59 | 59 | ||
60 | struct Cipher { | 60 | struct sshcipher { |
61 | char *name; | 61 | char *name; |
62 | int number; /* for ssh1 only */ | 62 | int number; /* for ssh1 only */ |
63 | u_int block_size; | 63 | u_int block_size; |
@@ -68,15 +68,23 @@ struct Cipher { | |||
68 | u_int flags; | 68 | u_int flags; |
69 | #define CFLAG_CBC (1<<0) | 69 | #define CFLAG_CBC (1<<0) |
70 | #define CFLAG_CHACHAPOLY (1<<1) | 70 | #define CFLAG_CHACHAPOLY (1<<1) |
71 | #define CFLAG_AESCTR (1<<2) | ||
72 | #define CFLAG_NONE (1<<3) | ||
73 | #ifdef WITH_OPENSSL | ||
71 | const EVP_CIPHER *(*evptype)(void); | 74 | const EVP_CIPHER *(*evptype)(void); |
75 | #else | ||
76 | void *ignored; | ||
77 | #endif | ||
72 | }; | 78 | }; |
73 | 79 | ||
74 | static const struct Cipher ciphers[] = { | 80 | static const struct sshcipher ciphers[] = { |
75 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, | 81 | #ifdef WITH_SSH1 |
76 | { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, | 82 | { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, |
77 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, | 83 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, |
78 | { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, | 84 | { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, |
79 | 85 | #endif /* WITH_SSH1 */ | |
86 | #ifdef WITH_OPENSSL | ||
87 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, | ||
80 | { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, | 88 | { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, |
81 | { "blowfish-cbc", | 89 | { "blowfish-cbc", |
82 | SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, | 90 | SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, |
@@ -93,26 +101,33 @@ static const struct Cipher ciphers[] = { | |||
93 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, | 101 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, |
94 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, | 102 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, |
95 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, | 103 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, |
96 | #ifdef OPENSSL_HAVE_EVPGCM | 104 | # ifdef OPENSSL_HAVE_EVPGCM |
97 | { "aes128-gcm@openssh.com", | 105 | { "aes128-gcm@openssh.com", |
98 | SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, | 106 | SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, |
99 | { "aes256-gcm@openssh.com", | 107 | { "aes256-gcm@openssh.com", |
100 | SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, | 108 | SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, |
101 | #endif | 109 | # endif /* OPENSSL_HAVE_EVPGCM */ |
110 | #else /* WITH_OPENSSL */ | ||
111 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL }, | ||
112 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL }, | ||
113 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL }, | ||
114 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL }, | ||
115 | #endif /* WITH_OPENSSL */ | ||
102 | { "chacha20-poly1305@openssh.com", | 116 | { "chacha20-poly1305@openssh.com", |
103 | SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, | 117 | SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, |
118 | |||
104 | { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } | 119 | { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } |
105 | }; | 120 | }; |
106 | 121 | ||
107 | /*--*/ | 122 | /*--*/ |
108 | 123 | ||
109 | /* Returns a list of supported ciphers separated by the specified char. */ | 124 | /* Returns a comma-separated list of supported ciphers. */ |
110 | char * | 125 | char * |
111 | cipher_alg_list(char sep, int auth_only) | 126 | cipher_alg_list(char sep, int auth_only) |
112 | { | 127 | { |
113 | char *ret = NULL; | 128 | char *tmp, *ret = NULL; |
114 | size_t nlen, rlen = 0; | 129 | size_t nlen, rlen = 0; |
115 | const Cipher *c; | 130 | const struct sshcipher *c; |
116 | 131 | ||
117 | for (c = ciphers; c->name != NULL; c++) { | 132 | for (c = ciphers; c->name != NULL; c++) { |
118 | if (c->number != SSH_CIPHER_SSH2) | 133 | if (c->number != SSH_CIPHER_SSH2) |
@@ -122,7 +137,11 @@ cipher_alg_list(char sep, int auth_only) | |||
122 | if (ret != NULL) | 137 | if (ret != NULL) |
123 | ret[rlen++] = sep; | 138 | ret[rlen++] = sep; |
124 | nlen = strlen(c->name); | 139 | nlen = strlen(c->name); |
125 | ret = xrealloc(ret, 1, rlen + nlen + 2); | 140 | if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { |
141 | free(ret); | ||
142 | return NULL; | ||
143 | } | ||
144 | ret = tmp; | ||
126 | memcpy(ret + rlen, c->name, nlen + 1); | 145 | memcpy(ret + rlen, c->name, nlen + 1); |
127 | rlen += nlen; | 146 | rlen += nlen; |
128 | } | 147 | } |
@@ -130,19 +149,19 @@ cipher_alg_list(char sep, int auth_only) | |||
130 | } | 149 | } |
131 | 150 | ||
132 | u_int | 151 | u_int |
133 | cipher_blocksize(const Cipher *c) | 152 | cipher_blocksize(const struct sshcipher *c) |
134 | { | 153 | { |
135 | return (c->block_size); | 154 | return (c->block_size); |
136 | } | 155 | } |
137 | 156 | ||
138 | u_int | 157 | u_int |
139 | cipher_keylen(const Cipher *c) | 158 | cipher_keylen(const struct sshcipher *c) |
140 | { | 159 | { |
141 | return (c->key_len); | 160 | return (c->key_len); |
142 | } | 161 | } |
143 | 162 | ||
144 | u_int | 163 | u_int |
145 | cipher_seclen(const Cipher *c) | 164 | cipher_seclen(const struct sshcipher *c) |
146 | { | 165 | { |
147 | if (strcmp("3des-cbc", c->name) == 0) | 166 | if (strcmp("3des-cbc", c->name) == 0) |
148 | return 14; | 167 | return 14; |
@@ -150,13 +169,13 @@ cipher_seclen(const Cipher *c) | |||
150 | } | 169 | } |
151 | 170 | ||
152 | u_int | 171 | u_int |
153 | cipher_authlen(const Cipher *c) | 172 | cipher_authlen(const struct sshcipher *c) |
154 | { | 173 | { |
155 | return (c->auth_len); | 174 | return (c->auth_len); |
156 | } | 175 | } |
157 | 176 | ||
158 | u_int | 177 | u_int |
159 | cipher_ivlen(const Cipher *c) | 178 | cipher_ivlen(const struct sshcipher *c) |
160 | { | 179 | { |
161 | /* | 180 | /* |
162 | * Default is cipher block size, except for chacha20+poly1305 that | 181 | * Default is cipher block size, except for chacha20+poly1305 that |
@@ -167,13 +186,13 @@ cipher_ivlen(const Cipher *c) | |||
167 | } | 186 | } |
168 | 187 | ||
169 | u_int | 188 | u_int |
170 | cipher_get_number(const Cipher *c) | 189 | cipher_get_number(const struct sshcipher *c) |
171 | { | 190 | { |
172 | return (c->number); | 191 | return (c->number); |
173 | } | 192 | } |
174 | 193 | ||
175 | u_int | 194 | u_int |
176 | cipher_is_cbc(const Cipher *c) | 195 | cipher_is_cbc(const struct sshcipher *c) |
177 | { | 196 | { |
178 | return (c->flags & CFLAG_CBC) != 0; | 197 | return (c->flags & CFLAG_CBC) != 0; |
179 | } | 198 | } |
@@ -190,20 +209,20 @@ cipher_mask_ssh1(int client) | |||
190 | return mask; | 209 | return mask; |
191 | } | 210 | } |
192 | 211 | ||
193 | const Cipher * | 212 | const struct sshcipher * |
194 | cipher_by_name(const char *name) | 213 | cipher_by_name(const char *name) |
195 | { | 214 | { |
196 | const Cipher *c; | 215 | const struct sshcipher *c; |
197 | for (c = ciphers; c->name != NULL; c++) | 216 | for (c = ciphers; c->name != NULL; c++) |
198 | if (strcmp(c->name, name) == 0) | 217 | if (strcmp(c->name, name) == 0) |
199 | return c; | 218 | return c; |
200 | return NULL; | 219 | return NULL; |
201 | } | 220 | } |
202 | 221 | ||
203 | const Cipher * | 222 | const struct sshcipher * |
204 | cipher_by_number(int id) | 223 | cipher_by_number(int id) |
205 | { | 224 | { |
206 | const Cipher *c; | 225 | const struct sshcipher *c; |
207 | for (c = ciphers; c->name != NULL; c++) | 226 | for (c = ciphers; c->name != NULL; c++) |
208 | if (c->number == id) | 227 | if (c->number == id) |
209 | return c; | 228 | return c; |
@@ -214,23 +233,22 @@ cipher_by_number(int id) | |||
214 | int | 233 | int |
215 | ciphers_valid(const char *names) | 234 | ciphers_valid(const char *names) |
216 | { | 235 | { |
217 | const Cipher *c; | 236 | const struct sshcipher *c; |
218 | char *cipher_list, *cp; | 237 | char *cipher_list, *cp; |
219 | char *p; | 238 | char *p; |
220 | 239 | ||
221 | if (names == NULL || strcmp(names, "") == 0) | 240 | if (names == NULL || strcmp(names, "") == 0) |
222 | return 0; | 241 | return 0; |
223 | cipher_list = cp = xstrdup(names); | 242 | if ((cipher_list = cp = strdup(names)) == NULL) |
243 | return 0; | ||
224 | for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; | 244 | for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; |
225 | (p = strsep(&cp, CIPHER_SEP))) { | 245 | (p = strsep(&cp, CIPHER_SEP))) { |
226 | c = cipher_by_name(p); | 246 | c = cipher_by_name(p); |
227 | if (c == NULL || c->number != SSH_CIPHER_SSH2) { | 247 | if (c == NULL || c->number != SSH_CIPHER_SSH2) { |
228 | debug("bad cipher %s [%s]", p, names); | ||
229 | free(cipher_list); | 248 | free(cipher_list); |
230 | return 0; | 249 | return 0; |
231 | } | 250 | } |
232 | } | 251 | } |
233 | debug3("ciphers ok: [%s]", names); | ||
234 | free(cipher_list); | 252 | free(cipher_list); |
235 | return 1; | 253 | return 1; |
236 | } | 254 | } |
@@ -243,7 +261,7 @@ ciphers_valid(const char *names) | |||
243 | int | 261 | int |
244 | cipher_number(const char *name) | 262 | cipher_number(const char *name) |
245 | { | 263 | { |
246 | const Cipher *c; | 264 | const struct sshcipher *c; |
247 | if (name == NULL) | 265 | if (name == NULL) |
248 | return -1; | 266 | return -1; |
249 | for (c = ciphers; c->name != NULL; c++) | 267 | for (c = ciphers; c->name != NULL; c++) |
@@ -255,90 +273,104 @@ cipher_number(const char *name) | |||
255 | char * | 273 | char * |
256 | cipher_name(int id) | 274 | cipher_name(int id) |
257 | { | 275 | { |
258 | const Cipher *c = cipher_by_number(id); | 276 | const struct sshcipher *c = cipher_by_number(id); |
259 | return (c==NULL) ? "<unknown>" : c->name; | 277 | return (c==NULL) ? "<unknown>" : c->name; |
260 | } | 278 | } |
261 | 279 | ||
262 | void | 280 | const char * |
263 | cipher_init(CipherContext *cc, const Cipher *cipher, | 281 | cipher_warning_message(const struct sshcipher_ctx *cc) |
282 | { | ||
283 | if (cc == NULL || cc->cipher == NULL) | ||
284 | return NULL; | ||
285 | if (cc->cipher->number == SSH_CIPHER_DES) | ||
286 | return "use of DES is strongly discouraged due to " | ||
287 | "cryptographic weaknesses"; | ||
288 | return NULL; | ||
289 | } | ||
290 | |||
291 | int | ||
292 | cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher, | ||
264 | const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, | 293 | const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, |
265 | int do_encrypt) | 294 | int do_encrypt) |
266 | { | 295 | { |
267 | static int dowarn = 1; | 296 | #ifdef WITH_OPENSSL |
268 | #ifdef SSH_OLD_EVP | 297 | int ret = SSH_ERR_INTERNAL_ERROR; |
269 | EVP_CIPHER *type; | ||
270 | #else | ||
271 | const EVP_CIPHER *type; | 298 | const EVP_CIPHER *type; |
272 | int klen; | 299 | int klen; |
273 | #endif | ||
274 | u_char *junk, *discard; | 300 | u_char *junk, *discard; |
275 | 301 | ||
276 | if (cipher->number == SSH_CIPHER_DES) { | 302 | if (cipher->number == SSH_CIPHER_DES) { |
277 | if (dowarn) { | ||
278 | error("Warning: use of DES is strongly discouraged " | ||
279 | "due to cryptographic weaknesses"); | ||
280 | dowarn = 0; | ||
281 | } | ||
282 | if (keylen > 8) | 303 | if (keylen > 8) |
283 | keylen = 8; | 304 | keylen = 8; |
284 | } | 305 | } |
306 | #endif | ||
285 | cc->plaintext = (cipher->number == SSH_CIPHER_NONE); | 307 | cc->plaintext = (cipher->number == SSH_CIPHER_NONE); |
286 | cc->encrypt = do_encrypt; | 308 | cc->encrypt = do_encrypt; |
287 | 309 | ||
288 | if (keylen < cipher->key_len) | 310 | if (keylen < cipher->key_len || |
289 | fatal("cipher_init: key length %d is insufficient for %s.", | 311 | (iv != NULL && ivlen < cipher_ivlen(cipher))) |
290 | keylen, cipher->name); | 312 | return SSH_ERR_INVALID_ARGUMENT; |
291 | if (iv != NULL && ivlen < cipher_ivlen(cipher)) | ||
292 | fatal("cipher_init: iv length %d is insufficient for %s.", | ||
293 | ivlen, cipher->name); | ||
294 | cc->cipher = cipher; | ||
295 | 313 | ||
314 | cc->cipher = cipher; | ||
296 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { | 315 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { |
297 | chachapoly_init(&cc->cp_ctx, key, keylen); | 316 | return chachapoly_init(&cc->cp_ctx, key, keylen); |
298 | return; | ||
299 | } | 317 | } |
300 | type = (*cipher->evptype)(); | 318 | #ifndef WITH_OPENSSL |
301 | EVP_CIPHER_CTX_init(&cc->evp); | 319 | if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { |
302 | #ifdef SSH_OLD_EVP | 320 | aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); |
303 | if (type->key_len > 0 && type->key_len != keylen) { | 321 | aesctr_ivsetup(&cc->ac_ctx, iv); |
304 | debug("cipher_init: set keylen (%d -> %d)", | 322 | return 0; |
305 | type->key_len, keylen); | ||
306 | type->key_len = keylen; | ||
307 | } | 323 | } |
308 | EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, | 324 | if ((cc->cipher->flags & CFLAG_NONE) != 0) |
309 | (do_encrypt == CIPHER_ENCRYPT)); | 325 | return 0; |
326 | return SSH_ERR_INVALID_ARGUMENT; | ||
310 | #else | 327 | #else |
328 | type = (*cipher->evptype)(); | ||
329 | EVP_CIPHER_CTX_init(&cc->evp); | ||
311 | if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, | 330 | if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, |
312 | (do_encrypt == CIPHER_ENCRYPT)) == 0) | 331 | (do_encrypt == CIPHER_ENCRYPT)) == 0) { |
313 | fatal("cipher_init: EVP_CipherInit failed for %s", | 332 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
314 | cipher->name); | 333 | goto bad; |
334 | } | ||
315 | if (cipher_authlen(cipher) && | 335 | if (cipher_authlen(cipher) && |
316 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, | 336 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, |
317 | -1, (u_char *)iv)) | 337 | -1, (u_char *)iv)) { |
318 | fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s", | 338 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
319 | cipher->name); | 339 | goto bad; |
340 | } | ||
320 | klen = EVP_CIPHER_CTX_key_length(&cc->evp); | 341 | klen = EVP_CIPHER_CTX_key_length(&cc->evp); |
321 | if (klen > 0 && keylen != (u_int)klen) { | 342 | if (klen > 0 && keylen != (u_int)klen) { |
322 | debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); | 343 | if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) { |
323 | if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) | 344 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
324 | fatal("cipher_init: set keylen failed (%d -> %d)", | 345 | goto bad; |
325 | klen, keylen); | 346 | } |
347 | } | ||
348 | if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { | ||
349 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
350 | goto bad; | ||
326 | } | 351 | } |
327 | if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) | ||
328 | fatal("cipher_init: EVP_CipherInit: set key failed for %s", | ||
329 | cipher->name); | ||
330 | #endif | ||
331 | 352 | ||
332 | if (cipher->discard_len > 0) { | 353 | if (cipher->discard_len > 0) { |
333 | junk = xmalloc(cipher->discard_len); | 354 | if ((junk = malloc(cipher->discard_len)) == NULL || |
334 | discard = xmalloc(cipher->discard_len); | 355 | (discard = malloc(cipher->discard_len)) == NULL) { |
335 | if (EVP_Cipher(&cc->evp, discard, junk, | 356 | if (junk != NULL) |
336 | cipher->discard_len) == 0) | 357 | free(junk); |
337 | fatal("evp_crypt: EVP_Cipher failed during discard"); | 358 | ret = SSH_ERR_ALLOC_FAIL; |
359 | goto bad; | ||
360 | } | ||
361 | ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len); | ||
338 | explicit_bzero(discard, cipher->discard_len); | 362 | explicit_bzero(discard, cipher->discard_len); |
339 | free(junk); | 363 | free(junk); |
340 | free(discard); | 364 | free(discard); |
365 | if (ret != 1) { | ||
366 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
367 | bad: | ||
368 | EVP_CIPHER_CTX_cleanup(&cc->evp); | ||
369 | return ret; | ||
370 | } | ||
341 | } | 371 | } |
372 | #endif | ||
373 | return 0; | ||
342 | } | 374 | } |
343 | 375 | ||
344 | /* | 376 | /* |
@@ -350,204 +382,244 @@ cipher_init(CipherContext *cc, const Cipher *cipher, | |||
350 | * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. | 382 | * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. |
351 | * This tag is written on encryption and verified on decryption. | 383 | * This tag is written on encryption and verified on decryption. |
352 | * Both 'aadlen' and 'authlen' can be set to 0. | 384 | * Both 'aadlen' and 'authlen' can be set to 0. |
353 | * cipher_crypt() returns 0 on success and -1 if the decryption integrity | ||
354 | * check fails. | ||
355 | */ | 385 | */ |
356 | int | 386 | int |
357 | cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src, | 387 | cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, |
358 | u_int len, u_int aadlen, u_int authlen) | 388 | const u_char *src, u_int len, u_int aadlen, u_int authlen) |
359 | { | 389 | { |
360 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 390 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { |
361 | return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, | 391 | return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, |
362 | aadlen, authlen, cc->encrypt); | 392 | len, aadlen, authlen, cc->encrypt); |
393 | } | ||
394 | #ifndef WITH_OPENSSL | ||
395 | if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { | ||
396 | if (aadlen) | ||
397 | memcpy(dest, src, aadlen); | ||
398 | aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, | ||
399 | dest + aadlen, len); | ||
400 | return 0; | ||
401 | } | ||
402 | if ((cc->cipher->flags & CFLAG_NONE) != 0) { | ||
403 | memcpy(dest, src, aadlen + len); | ||
404 | return 0; | ||
405 | } | ||
406 | return SSH_ERR_INVALID_ARGUMENT; | ||
407 | #else | ||
363 | if (authlen) { | 408 | if (authlen) { |
364 | u_char lastiv[1]; | 409 | u_char lastiv[1]; |
365 | 410 | ||
366 | if (authlen != cipher_authlen(cc->cipher)) | 411 | if (authlen != cipher_authlen(cc->cipher)) |
367 | fatal("%s: authlen mismatch %d", __func__, authlen); | 412 | return SSH_ERR_INVALID_ARGUMENT; |
368 | /* increment IV */ | 413 | /* increment IV */ |
369 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, | 414 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, |
370 | 1, lastiv)) | 415 | 1, lastiv)) |
371 | fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); | 416 | return SSH_ERR_LIBCRYPTO_ERROR; |
372 | /* set tag on decyption */ | 417 | /* set tag on decyption */ |
373 | if (!cc->encrypt && | 418 | if (!cc->encrypt && |
374 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, | 419 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, |
375 | authlen, (u_char *)src + aadlen + len)) | 420 | authlen, (u_char *)src + aadlen + len)) |
376 | fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); | 421 | return SSH_ERR_LIBCRYPTO_ERROR; |
377 | } | 422 | } |
378 | if (aadlen) { | 423 | if (aadlen) { |
379 | if (authlen && | 424 | if (authlen && |
380 | EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) | 425 | EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) |
381 | fatal("%s: EVP_Cipher(aad) failed", __func__); | 426 | return SSH_ERR_LIBCRYPTO_ERROR; |
382 | memcpy(dest, src, aadlen); | 427 | memcpy(dest, src, aadlen); |
383 | } | 428 | } |
384 | if (len % cc->cipher->block_size) | 429 | if (len % cc->cipher->block_size) |
385 | fatal("%s: bad plaintext length %d", __func__, len); | 430 | return SSH_ERR_INVALID_ARGUMENT; |
386 | if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, | 431 | if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, |
387 | len) < 0) | 432 | len) < 0) |
388 | fatal("%s: EVP_Cipher failed", __func__); | 433 | return SSH_ERR_LIBCRYPTO_ERROR; |
389 | if (authlen) { | 434 | if (authlen) { |
390 | /* compute tag (on encrypt) or verify tag (on decrypt) */ | 435 | /* compute tag (on encrypt) or verify tag (on decrypt) */ |
391 | if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) { | 436 | if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) |
392 | if (cc->encrypt) | 437 | return cc->encrypt ? |
393 | fatal("%s: EVP_Cipher(final) failed", __func__); | 438 | SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID; |
394 | else | ||
395 | return -1; | ||
396 | } | ||
397 | if (cc->encrypt && | 439 | if (cc->encrypt && |
398 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, | 440 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, |
399 | authlen, dest + aadlen + len)) | 441 | authlen, dest + aadlen + len)) |
400 | fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); | 442 | return SSH_ERR_LIBCRYPTO_ERROR; |
401 | } | 443 | } |
402 | return 0; | 444 | return 0; |
445 | #endif | ||
403 | } | 446 | } |
404 | 447 | ||
405 | /* Extract the packet length, including any decryption necessary beforehand */ | 448 | /* Extract the packet length, including any decryption necessary beforehand */ |
406 | int | 449 | int |
407 | cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr, | 450 | cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, |
408 | const u_char *cp, u_int len) | 451 | const u_char *cp, u_int len) |
409 | { | 452 | { |
410 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 453 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
411 | return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, | 454 | return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, |
412 | cp, len); | 455 | cp, len); |
413 | if (len < 4) | 456 | if (len < 4) |
414 | return -1; | 457 | return SSH_ERR_MESSAGE_INCOMPLETE; |
415 | *plenp = get_u32(cp); | 458 | *plenp = get_u32(cp); |
416 | return 0; | 459 | return 0; |
417 | } | 460 | } |
418 | 461 | ||
419 | void | 462 | int |
420 | cipher_cleanup(CipherContext *cc) | 463 | cipher_cleanup(struct sshcipher_ctx *cc) |
421 | { | 464 | { |
465 | if (cc == NULL || cc->cipher == NULL) | ||
466 | return 0; | ||
422 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 467 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
423 | explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); | 468 | explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); |
469 | else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) | ||
470 | explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); | ||
471 | #ifdef WITH_OPENSSL | ||
424 | else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) | 472 | else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) |
425 | error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); | 473 | return SSH_ERR_LIBCRYPTO_ERROR; |
474 | #endif | ||
475 | return 0; | ||
426 | } | 476 | } |
427 | 477 | ||
428 | /* | 478 | /* |
429 | * Selects the cipher, and keys if by computing the MD5 checksum of the | 479 | * Selects the cipher, and keys if by computing the MD5 checksum of the |
430 | * passphrase and using the resulting 16 bytes as the key. | 480 | * passphrase and using the resulting 16 bytes as the key. |
431 | */ | 481 | */ |
432 | 482 | int | |
433 | void | 483 | cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher, |
434 | cipher_set_key_string(CipherContext *cc, const Cipher *cipher, | ||
435 | const char *passphrase, int do_encrypt) | 484 | const char *passphrase, int do_encrypt) |
436 | { | 485 | { |
437 | u_char digest[16]; | 486 | u_char digest[16]; |
487 | int r = SSH_ERR_INTERNAL_ERROR; | ||
438 | 488 | ||
439 | if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), | 489 | if ((r = ssh_digest_memory(SSH_DIGEST_MD5, |
440 | digest, sizeof(digest)) < 0) | 490 | passphrase, strlen(passphrase), |
441 | fatal("%s: md5 failed", __func__); | 491 | digest, sizeof(digest))) != 0) |
442 | 492 | goto out; | |
443 | cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); | ||
444 | 493 | ||
494 | r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); | ||
495 | out: | ||
445 | explicit_bzero(digest, sizeof(digest)); | 496 | explicit_bzero(digest, sizeof(digest)); |
497 | return r; | ||
446 | } | 498 | } |
447 | 499 | ||
448 | /* | 500 | /* |
449 | * Exports an IV from the CipherContext required to export the key | 501 | * Exports an IV from the sshcipher_ctx required to export the key |
450 | * state back from the unprivileged child to the privileged parent | 502 | * state back from the unprivileged child to the privileged parent |
451 | * process. | 503 | * process. |
452 | */ | 504 | */ |
453 | |||
454 | int | 505 | int |
455 | cipher_get_keyiv_len(const CipherContext *cc) | 506 | cipher_get_keyiv_len(const struct sshcipher_ctx *cc) |
456 | { | 507 | { |
457 | const Cipher *c = cc->cipher; | 508 | const struct sshcipher *c = cc->cipher; |
458 | int ivlen; | 509 | int ivlen = 0; |
459 | 510 | ||
460 | if (c->number == SSH_CIPHER_3DES) | 511 | if (c->number == SSH_CIPHER_3DES) |
461 | ivlen = 24; | 512 | ivlen = 24; |
462 | else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 513 | else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
463 | ivlen = 0; | 514 | ivlen = 0; |
515 | #ifdef WITH_OPENSSL | ||
464 | else | 516 | else |
465 | ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); | 517 | ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); |
518 | #endif /* WITH_OPENSSL */ | ||
466 | return (ivlen); | 519 | return (ivlen); |
467 | } | 520 | } |
468 | 521 | ||
469 | void | 522 | int |
470 | cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) | 523 | cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) |
471 | { | 524 | { |
472 | const Cipher *c = cc->cipher; | 525 | const struct sshcipher *c = cc->cipher; |
473 | int evplen; | 526 | #ifdef WITH_OPENSSL |
527 | int evplen; | ||
528 | #endif | ||
474 | 529 | ||
475 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { | 530 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { |
476 | if (len != 0) | 531 | if (len != 0) |
477 | fatal("%s: wrong iv length %d != %d", __func__, len, 0); | 532 | return SSH_ERR_INVALID_ARGUMENT; |
478 | return; | 533 | return 0; |
479 | } | 534 | } |
535 | if ((cc->cipher->flags & CFLAG_NONE) != 0) | ||
536 | return 0; | ||
480 | 537 | ||
481 | switch (c->number) { | 538 | switch (c->number) { |
539 | #ifdef WITH_OPENSSL | ||
482 | case SSH_CIPHER_SSH2: | 540 | case SSH_CIPHER_SSH2: |
483 | case SSH_CIPHER_DES: | 541 | case SSH_CIPHER_DES: |
484 | case SSH_CIPHER_BLOWFISH: | 542 | case SSH_CIPHER_BLOWFISH: |
485 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); | 543 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); |
486 | if (evplen <= 0) | 544 | if (evplen == 0) |
487 | return; | 545 | return 0; |
546 | else if (evplen < 0) | ||
547 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
488 | if ((u_int)evplen != len) | 548 | if ((u_int)evplen != len) |
489 | fatal("%s: wrong iv length %d != %d", __func__, | 549 | return SSH_ERR_INVALID_ARGUMENT; |
490 | evplen, len); | ||
491 | #ifdef USE_BUILTIN_RIJNDAEL | ||
492 | if (c->evptype == evp_rijndael) | ||
493 | ssh_rijndael_iv(&cc->evp, 0, iv, len); | ||
494 | else | ||
495 | #endif | ||
496 | #ifndef OPENSSL_HAVE_EVPCTR | 550 | #ifndef OPENSSL_HAVE_EVPCTR |
497 | if (c->evptype == evp_aes_128_ctr) | 551 | if (c->evptype == evp_aes_128_ctr) |
498 | ssh_aes_ctr_iv(&cc->evp, 0, iv, len); | 552 | ssh_aes_ctr_iv(&cc->evp, 0, iv, len); |
499 | else | 553 | else |
500 | #endif | 554 | #endif |
501 | memcpy(iv, cc->evp.iv, len); | 555 | if (cipher_authlen(c)) { |
556 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, | ||
557 | len, iv)) | ||
558 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
559 | } else | ||
560 | memcpy(iv, cc->evp.iv, len); | ||
502 | break; | 561 | break; |
562 | #endif | ||
563 | #ifdef WITH_SSH1 | ||
503 | case SSH_CIPHER_3DES: | 564 | case SSH_CIPHER_3DES: |
504 | ssh1_3des_iv(&cc->evp, 0, iv, 24); | 565 | return ssh1_3des_iv(&cc->evp, 0, iv, 24); |
505 | break; | 566 | #endif |
506 | default: | 567 | default: |
507 | fatal("%s: bad cipher %d", __func__, c->number); | 568 | return SSH_ERR_INVALID_ARGUMENT; |
508 | } | 569 | } |
570 | return 0; | ||
509 | } | 571 | } |
510 | 572 | ||
511 | void | 573 | int |
512 | cipher_set_keyiv(CipherContext *cc, u_char *iv) | 574 | cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) |
513 | { | 575 | { |
514 | const Cipher *c = cc->cipher; | 576 | const struct sshcipher *c = cc->cipher; |
515 | int evplen = 0; | 577 | #ifdef WITH_OPENSSL |
578 | int evplen = 0; | ||
579 | #endif | ||
516 | 580 | ||
517 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 581 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
518 | return; | 582 | return 0; |
583 | if ((cc->cipher->flags & CFLAG_NONE) != 0) | ||
584 | return 0; | ||
519 | 585 | ||
520 | switch (c->number) { | 586 | switch (c->number) { |
587 | #ifdef WITH_OPENSSL | ||
521 | case SSH_CIPHER_SSH2: | 588 | case SSH_CIPHER_SSH2: |
522 | case SSH_CIPHER_DES: | 589 | case SSH_CIPHER_DES: |
523 | case SSH_CIPHER_BLOWFISH: | 590 | case SSH_CIPHER_BLOWFISH: |
524 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); | 591 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); |
525 | if (evplen == 0) | 592 | if (evplen <= 0) |
526 | return; | 593 | return SSH_ERR_LIBCRYPTO_ERROR; |
527 | #ifdef USE_BUILTIN_RIJNDAEL | 594 | if (cipher_authlen(c)) { |
528 | if (c->evptype == evp_rijndael) | 595 | /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ |
529 | ssh_rijndael_iv(&cc->evp, 1, iv, evplen); | 596 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, |
530 | else | 597 | EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) |
531 | #endif | 598 | return SSH_ERR_LIBCRYPTO_ERROR; |
532 | #ifndef OPENSSL_HAVE_EVPCTR | 599 | } else |
533 | if (c->evptype == evp_aes_128_ctr) | 600 | memcpy(cc->evp.iv, iv, evplen); |
534 | ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen); | ||
535 | else | ||
536 | #endif | ||
537 | memcpy(cc->evp.iv, iv, evplen); | ||
538 | break; | 601 | break; |
602 | #endif | ||
603 | #ifdef WITH_SSH1 | ||
539 | case SSH_CIPHER_3DES: | 604 | case SSH_CIPHER_3DES: |
540 | ssh1_3des_iv(&cc->evp, 1, iv, 24); | 605 | return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24); |
541 | break; | 606 | #endif |
542 | default: | 607 | default: |
543 | fatal("%s: bad cipher %d", __func__, c->number); | 608 | return SSH_ERR_INVALID_ARGUMENT; |
544 | } | 609 | } |
610 | return 0; | ||
545 | } | 611 | } |
546 | 612 | ||
613 | #ifdef WITH_OPENSSL | ||
614 | #define EVP_X_STATE(evp) (evp).cipher_data | ||
615 | #define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size | ||
616 | #endif | ||
617 | |||
547 | int | 618 | int |
548 | cipher_get_keycontext(const CipherContext *cc, u_char *dat) | 619 | cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat) |
549 | { | 620 | { |
550 | const Cipher *c = cc->cipher; | 621 | #ifdef WITH_OPENSSL |
622 | const struct sshcipher *c = cc->cipher; | ||
551 | int plen = 0; | 623 | int plen = 0; |
552 | 624 | ||
553 | if (c->evptype == EVP_rc4) { | 625 | if (c->evptype == EVP_rc4) { |
@@ -557,16 +629,21 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat) | |||
557 | memcpy(dat, EVP_X_STATE(cc->evp), plen); | 629 | memcpy(dat, EVP_X_STATE(cc->evp), plen); |
558 | } | 630 | } |
559 | return (plen); | 631 | return (plen); |
632 | #else | ||
633 | return 0; | ||
634 | #endif | ||
560 | } | 635 | } |
561 | 636 | ||
562 | void | 637 | void |
563 | cipher_set_keycontext(CipherContext *cc, u_char *dat) | 638 | cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat) |
564 | { | 639 | { |
565 | const Cipher *c = cc->cipher; | 640 | #ifdef WITH_OPENSSL |
641 | const struct sshcipher *c = cc->cipher; | ||
566 | int plen; | 642 | int plen; |
567 | 643 | ||
568 | if (c->evptype == EVP_rc4) { | 644 | if (c->evptype == EVP_rc4) { |
569 | plen = EVP_X_STATE_LEN(cc->evp); | 645 | plen = EVP_X_STATE_LEN(cc->evp); |
570 | memcpy(EVP_X_STATE(cc->evp), dat, plen); | 646 | memcpy(EVP_X_STATE(cc->evp), dat, plen); |
571 | } | 647 | } |
648 | #endif | ||
572 | } | 649 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher.h,v 1.44 2014/01/25 10:12:50 dtucker Exp $ */ | 1 | /* $OpenBSD: cipher.h,v 1.46 2014/06/24 01:13:21 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -37,8 +37,10 @@ | |||
37 | #ifndef CIPHER_H | 37 | #ifndef CIPHER_H |
38 | #define CIPHER_H | 38 | #define CIPHER_H |
39 | 39 | ||
40 | #include <sys/types.h> | ||
40 | #include <openssl/evp.h> | 41 | #include <openssl/evp.h> |
41 | #include "cipher-chachapoly.h" | 42 | #include "cipher-chachapoly.h" |
43 | #include "cipher-aesctr.h" | ||
42 | 44 | ||
43 | /* | 45 | /* |
44 | * Cipher types for SSH-1. New types can be added, but old types should not | 46 | * Cipher types for SSH-1. New types can be added, but old types should not |
@@ -60,44 +62,47 @@ | |||
60 | #define CIPHER_ENCRYPT 1 | 62 | #define CIPHER_ENCRYPT 1 |
61 | #define CIPHER_DECRYPT 0 | 63 | #define CIPHER_DECRYPT 0 |
62 | 64 | ||
63 | typedef struct Cipher Cipher; | 65 | struct sshcipher; |
64 | typedef struct CipherContext CipherContext; | 66 | struct sshcipher_ctx { |
65 | |||
66 | struct Cipher; | ||
67 | struct CipherContext { | ||
68 | int plaintext; | 67 | int plaintext; |
69 | int encrypt; | 68 | int encrypt; |
70 | EVP_CIPHER_CTX evp; | 69 | EVP_CIPHER_CTX evp; |
71 | struct chachapoly_ctx cp_ctx; /* XXX union with evp? */ | 70 | struct chachapoly_ctx cp_ctx; /* XXX union with evp? */ |
72 | const Cipher *cipher; | 71 | struct aesctr_ctx ac_ctx; /* XXX union with evp? */ |
72 | const struct sshcipher *cipher; | ||
73 | }; | 73 | }; |
74 | 74 | ||
75 | typedef struct sshcipher Cipher ; | ||
76 | typedef struct sshcipher_ctx CipherContext ; | ||
77 | |||
75 | u_int cipher_mask_ssh1(int); | 78 | u_int cipher_mask_ssh1(int); |
76 | const Cipher *cipher_by_name(const char *); | 79 | const struct sshcipher *cipher_by_name(const char *); |
77 | const Cipher *cipher_by_number(int); | 80 | const struct sshcipher *cipher_by_number(int); |
78 | int cipher_number(const char *); | 81 | int cipher_number(const char *); |
79 | char *cipher_name(int); | 82 | char *cipher_name(int); |
80 | int ciphers_valid(const char *); | 83 | int ciphers_valid(const char *); |
81 | char *cipher_alg_list(char, int); | 84 | char *cipher_alg_list(char, int); |
82 | void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, | 85 | int cipher_init(struct sshcipher_ctx *, const struct sshcipher *, |
83 | const u_char *, u_int, int); | 86 | const u_char *, u_int, const u_char *, u_int, int); |
84 | int cipher_crypt(CipherContext *, u_int, u_char *, const u_char *, | 87 | const char* cipher_warning_message(const struct sshcipher_ctx *); |
88 | int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *, | ||
85 | u_int, u_int, u_int); | 89 | u_int, u_int, u_int); |
86 | int cipher_get_length(CipherContext *, u_int *, u_int, | 90 | int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int, |
87 | const u_char *, u_int); | 91 | const u_char *, u_int); |
88 | void cipher_cleanup(CipherContext *); | 92 | int cipher_cleanup(struct sshcipher_ctx *); |
89 | void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); | 93 | int cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *, |
90 | u_int cipher_blocksize(const Cipher *); | 94 | const char *, int); |
91 | u_int cipher_keylen(const Cipher *); | 95 | u_int cipher_blocksize(const struct sshcipher *); |
92 | u_int cipher_seclen(const Cipher *); | 96 | u_int cipher_keylen(const struct sshcipher *); |
93 | u_int cipher_authlen(const Cipher *); | 97 | u_int cipher_seclen(const struct sshcipher *); |
94 | u_int cipher_ivlen(const Cipher *); | 98 | u_int cipher_authlen(const struct sshcipher *); |
95 | u_int cipher_is_cbc(const Cipher *); | 99 | u_int cipher_ivlen(const struct sshcipher *); |
100 | u_int cipher_is_cbc(const struct sshcipher *); | ||
96 | 101 | ||
97 | u_int cipher_get_number(const Cipher *); | 102 | u_int cipher_get_number(const struct sshcipher *); |
98 | void cipher_get_keyiv(CipherContext *, u_char *, u_int); | 103 | int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int); |
99 | void cipher_set_keyiv(CipherContext *, u_char *); | 104 | int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *); |
100 | int cipher_get_keyiv_len(const CipherContext *); | 105 | int cipher_get_keyiv_len(const struct sshcipher_ctx *); |
101 | int cipher_get_keycontext(const CipherContext *, u_char *); | 106 | int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *); |
102 | void cipher_set_keycontext(CipherContext *, u_char *); | 107 | void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *); |
103 | #endif /* CIPHER_H */ | 108 | #endif /* CIPHER_H */ |
diff --git a/clientloop.c b/clientloop.c index 4bc5b57d2..0180774bb 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.258 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.261 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -100,13 +100,13 @@ | |||
100 | #include "cipher.h" | 100 | #include "cipher.h" |
101 | #include "kex.h" | 101 | #include "kex.h" |
102 | #include "log.h" | 102 | #include "log.h" |
103 | #include "misc.h" | ||
103 | #include "readconf.h" | 104 | #include "readconf.h" |
104 | #include "clientloop.h" | 105 | #include "clientloop.h" |
105 | #include "sshconnect.h" | 106 | #include "sshconnect.h" |
106 | #include "authfd.h" | 107 | #include "authfd.h" |
107 | #include "atomicio.h" | 108 | #include "atomicio.h" |
108 | #include "sshpty.h" | 109 | #include "sshpty.h" |
109 | #include "misc.h" | ||
110 | #include "match.h" | 110 | #include "match.h" |
111 | #include "msg.h" | 111 | #include "msg.h" |
112 | #include "roaming.h" | 112 | #include "roaming.h" |
@@ -880,13 +880,11 @@ static void | |||
880 | process_cmdline(void) | 880 | process_cmdline(void) |
881 | { | 881 | { |
882 | void (*handler)(int); | 882 | void (*handler)(int); |
883 | char *s, *cmd, *cancel_host; | 883 | char *s, *cmd; |
884 | int delete = 0, local = 0, remote = 0, dynamic = 0; | 884 | int ok, delete = 0, local = 0, remote = 0, dynamic = 0; |
885 | int cancel_port, ok; | 885 | struct Forward fwd; |
886 | Forward fwd; | ||
887 | 886 | ||
888 | memset(&fwd, 0, sizeof(fwd)); | 887 | memset(&fwd, 0, sizeof(fwd)); |
889 | fwd.listen_host = fwd.connect_host = NULL; | ||
890 | 888 | ||
891 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 889 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
892 | handler = signal(SIGINT, SIG_IGN); | 890 | handler = signal(SIGINT, SIG_IGN); |
@@ -952,29 +950,20 @@ process_cmdline(void) | |||
952 | 950 | ||
953 | /* XXX update list of forwards in options */ | 951 | /* XXX update list of forwards in options */ |
954 | if (delete) { | 952 | if (delete) { |
955 | cancel_port = 0; | 953 | /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */ |
956 | cancel_host = hpdelim(&s); /* may be NULL */ | 954 | if (!parse_forward(&fwd, s, 1, 0)) { |
957 | if (s != NULL) { | 955 | logit("Bad forwarding close specification."); |
958 | cancel_port = a2port(s); | ||
959 | cancel_host = cleanhostname(cancel_host); | ||
960 | } else { | ||
961 | cancel_port = a2port(cancel_host); | ||
962 | cancel_host = NULL; | ||
963 | } | ||
964 | if (cancel_port <= 0) { | ||
965 | logit("Bad forwarding close port"); | ||
966 | goto out; | 956 | goto out; |
967 | } | 957 | } |
968 | if (remote) | 958 | if (remote) |
969 | ok = channel_request_rforward_cancel(cancel_host, | 959 | ok = channel_request_rforward_cancel(&fwd) == 0; |
970 | cancel_port) == 0; | ||
971 | else if (dynamic) | 960 | else if (dynamic) |
972 | ok = channel_cancel_lport_listener(cancel_host, | 961 | ok = channel_cancel_lport_listener(&fwd, |
973 | cancel_port, 0, options.gateway_ports) > 0; | 962 | 0, &options.fwd_opts) > 0; |
974 | else | 963 | else |
975 | ok = channel_cancel_lport_listener(cancel_host, | 964 | ok = channel_cancel_lport_listener(&fwd, |
976 | cancel_port, CHANNEL_CANCEL_PORT_STATIC, | 965 | CHANNEL_CANCEL_PORT_STATIC, |
977 | options.gateway_ports) > 0; | 966 | &options.fwd_opts) > 0; |
978 | if (!ok) { | 967 | if (!ok) { |
979 | logit("Unkown port forwarding."); | 968 | logit("Unkown port forwarding."); |
980 | goto out; | 969 | goto out; |
@@ -986,16 +975,13 @@ process_cmdline(void) | |||
986 | goto out; | 975 | goto out; |
987 | } | 976 | } |
988 | if (local || dynamic) { | 977 | if (local || dynamic) { |
989 | if (!channel_setup_local_fwd_listener(fwd.listen_host, | 978 | if (!channel_setup_local_fwd_listener(&fwd, |
990 | fwd.listen_port, fwd.connect_host, | 979 | &options.fwd_opts)) { |
991 | fwd.connect_port, options.gateway_ports)) { | ||
992 | logit("Port forwarding failed."); | 980 | logit("Port forwarding failed."); |
993 | goto out; | 981 | goto out; |
994 | } | 982 | } |
995 | } else { | 983 | } else { |
996 | if (channel_request_remote_forwarding(fwd.listen_host, | 984 | if (channel_request_remote_forwarding(&fwd) < 0) { |
997 | fwd.listen_port, fwd.connect_host, | ||
998 | fwd.connect_port) < 0) { | ||
999 | logit("Port forwarding failed."); | 985 | logit("Port forwarding failed."); |
1000 | goto out; | 986 | goto out; |
1001 | } | 987 | } |
@@ -1008,7 +994,9 @@ out: | |||
1008 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 994 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1009 | free(cmd); | 995 | free(cmd); |
1010 | free(fwd.listen_host); | 996 | free(fwd.listen_host); |
997 | free(fwd.listen_path); | ||
1011 | free(fwd.connect_host); | 998 | free(fwd.connect_host); |
999 | free(fwd.connect_path); | ||
1012 | } | 1000 | } |
1013 | 1001 | ||
1014 | /* reasons to suppress output of an escape command in help output */ | 1002 | /* reasons to suppress output of an escape command in help output */ |
@@ -1865,11 +1853,10 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) | |||
1865 | originator_port = packet_get_int(); | 1853 | originator_port = packet_get_int(); |
1866 | packet_check_eom(); | 1854 | packet_check_eom(); |
1867 | 1855 | ||
1868 | debug("client_request_forwarded_tcpip: listen %s port %d, " | 1856 | debug("%s: listen %s port %d, originator %s port %d", __func__, |
1869 | "originator %s port %d", listen_address, listen_port, | 1857 | listen_address, listen_port, originator_address, originator_port); |
1870 | originator_address, originator_port); | ||
1871 | 1858 | ||
1872 | c = channel_connect_by_listen_address(listen_port, | 1859 | c = channel_connect_by_listen_address(listen_address, listen_port, |
1873 | "forwarded-tcpip", originator_address); | 1860 | "forwarded-tcpip", originator_address); |
1874 | 1861 | ||
1875 | free(originator_address); | 1862 | free(originator_address); |
@@ -1878,6 +1865,27 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) | |||
1878 | } | 1865 | } |
1879 | 1866 | ||
1880 | static Channel * | 1867 | static Channel * |
1868 | client_request_forwarded_streamlocal(const char *request_type, int rchan) | ||
1869 | { | ||
1870 | Channel *c = NULL; | ||
1871 | char *listen_path; | ||
1872 | |||
1873 | /* Get the remote path. */ | ||
1874 | listen_path = packet_get_string(NULL); | ||
1875 | /* XXX: Skip reserved field for now. */ | ||
1876 | if (packet_get_string_ptr(NULL) == NULL) | ||
1877 | fatal("%s: packet_get_string_ptr failed", __func__); | ||
1878 | packet_check_eom(); | ||
1879 | |||
1880 | debug("%s: %s", __func__, listen_path); | ||
1881 | |||
1882 | c = channel_connect_by_listen_path(listen_path, | ||
1883 | "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); | ||
1884 | free(listen_path); | ||
1885 | return c; | ||
1886 | } | ||
1887 | |||
1888 | static Channel * | ||
1881 | client_request_x11(const char *request_type, int rchan) | 1889 | client_request_x11(const char *request_type, int rchan) |
1882 | { | 1890 | { |
1883 | Channel *c = NULL; | 1891 | Channel *c = NULL; |
@@ -2004,6 +2012,8 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
2004 | 2012 | ||
2005 | if (strcmp(ctype, "forwarded-tcpip") == 0) { | 2013 | if (strcmp(ctype, "forwarded-tcpip") == 0) { |
2006 | c = client_request_forwarded_tcpip(ctype, rchan); | 2014 | c = client_request_forwarded_tcpip(ctype, rchan); |
2015 | } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { | ||
2016 | c = client_request_forwarded_streamlocal(ctype, rchan); | ||
2007 | } else if (strcmp(ctype, "x11") == 0) { | 2017 | } else if (strcmp(ctype, "x11") == 0) { |
2008 | c = client_request_x11(ctype, rchan); | 2018 | c = client_request_x11(ctype, rchan); |
2009 | } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { | 2019 | } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { |
@@ -2074,7 +2084,7 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) | |||
2074 | } | 2084 | } |
2075 | packet_check_eom(); | 2085 | packet_check_eom(); |
2076 | } | 2086 | } |
2077 | if (reply && c != NULL) { | 2087 | if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { |
2078 | packet_start(success ? | 2088 | packet_start(success ? |
2079 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); | 2089 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); |
2080 | packet_put_int(c->remote_id); | 2090 | packet_put_int(c->remote_id); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: compat.c,v 1.82 2013/12/30 23:52:27 djm Exp $ */ | 1 | /* $OpenBSD: compat.c,v 1.85 2014/04/20 02:49:32 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: compat.h,v 1.44 2013/12/30 23:52:27 djm Exp $ */ | 1 | /* $OpenBSD: compat.h,v 1.45 2014/04/18 23:52:25 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. |
diff --git a/config.h.in b/config.h.in index 6bc422c3e..a9a8b7ae3 100644 --- a/config.h.in +++ b/config.h.in | |||
@@ -420,6 +420,9 @@ | |||
420 | /* Define to 1 if you have the `EVP_MD_CTX_init' function. */ | 420 | /* Define to 1 if you have the `EVP_MD_CTX_init' function. */ |
421 | #undef HAVE_EVP_MD_CTX_INIT | 421 | #undef HAVE_EVP_MD_CTX_INIT |
422 | 422 | ||
423 | /* Define to 1 if you have the `EVP_ripemd160' function. */ | ||
424 | #undef HAVE_EVP_RIPEMD160 | ||
425 | |||
423 | /* Define to 1 if you have the `EVP_sha256' function. */ | 426 | /* Define to 1 if you have the `EVP_sha256' function. */ |
424 | #undef HAVE_EVP_SHA256 | 427 | #undef HAVE_EVP_SHA256 |
425 | 428 | ||
@@ -768,6 +771,9 @@ | |||
768 | /* Define to 1 if you have the <memory.h> header file. */ | 771 | /* Define to 1 if you have the <memory.h> header file. */ |
769 | #undef HAVE_MEMORY_H | 772 | #undef HAVE_MEMORY_H |
770 | 773 | ||
774 | /* Define to 1 if you have the `memset_s' function. */ | ||
775 | #undef HAVE_MEMSET_S | ||
776 | |||
771 | /* Define to 1 if you have the `mkdtemp' function. */ | 777 | /* Define to 1 if you have the `mkdtemp' function. */ |
772 | #undef HAVE_MKDTEMP | 778 | #undef HAVE_MKDTEMP |
773 | 779 | ||
@@ -1324,9 +1330,6 @@ | |||
1324 | /* Define if va_copy exists */ | 1330 | /* Define if va_copy exists */ |
1325 | #undef HAVE_VA_COPY | 1331 | #undef HAVE_VA_COPY |
1326 | 1332 | ||
1327 | /* Define to 1 if you have the `vhangup' function. */ | ||
1328 | #undef HAVE_VHANGUP | ||
1329 | |||
1330 | /* Define to 1 if you have the <vis.h> header file. */ | 1333 | /* Define to 1 if you have the <vis.h> header file. */ |
1331 | #undef HAVE_VIS_H | 1334 | #undef HAVE_VIS_H |
1332 | 1335 | ||
@@ -1387,9 +1390,6 @@ | |||
1387 | /* Define if pututxline updates lastlog too */ | 1390 | /* Define if pututxline updates lastlog too */ |
1388 | #undef LASTLOG_WRITE_PUTUTXLINE | 1391 | #undef LASTLOG_WRITE_PUTUTXLINE |
1389 | 1392 | ||
1390 | /* Define if you want TCP Wrappers support */ | ||
1391 | #undef LIBWRAP | ||
1392 | |||
1393 | /* Define to whatever link() returns for "not supported" if it doesn't return | 1393 | /* Define to whatever link() returns for "not supported" if it doesn't return |
1394 | EOPNOTSUPP. */ | 1394 | EOPNOTSUPP. */ |
1395 | #undef LINK_OPNOTSUPP_ERRNO | 1395 | #undef LINK_OPNOTSUPP_ERRNO |
@@ -1668,9 +1668,15 @@ | |||
1668 | /* Define if you want IRIX project management */ | 1668 | /* Define if you want IRIX project management */ |
1669 | #undef WITH_IRIX_PROJECT | 1669 | #undef WITH_IRIX_PROJECT |
1670 | 1670 | ||
1671 | /* use libcrypto for cryptography */ | ||
1672 | #undef WITH_OPENSSL | ||
1673 | |||
1671 | /* Define if you want SELinux support. */ | 1674 | /* Define if you want SELinux support. */ |
1672 | #undef WITH_SELINUX | 1675 | #undef WITH_SELINUX |
1673 | 1676 | ||
1677 | /* include SSH protocol version 1 support */ | ||
1678 | #undef WITH_SSH1 | ||
1679 | |||
1674 | /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most | 1680 | /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most |
1675 | significant byte first (like Motorola and SPARC, unlike Intel). */ | 1681 | significant byte first (like Motorola and SPARC, unlike Intel). */ |
1676 | #if defined AC_APPLE_UNIVERSAL_BUILD | 1682 | #if defined AC_APPLE_UNIVERSAL_BUILD |
@@ -1,5 +1,5 @@ | |||
1 | #! /bin/sh | 1 | #! /bin/sh |
2 | # From configure.ac Revision: 1.571 . | 2 | # From configure.ac Revision: 1.583 . |
3 | # Guess values for system-dependent variables and create Makefiles. | 3 | # Guess values for system-dependent variables and create Makefiles. |
4 | # Generated by GNU Autoconf 2.68 for OpenSSH Portable. | 4 | # Generated by GNU Autoconf 2.68 for OpenSSH Portable. |
5 | # | 5 | # |
@@ -725,7 +725,6 @@ with_osfsia | |||
725 | with_zlib | 725 | with_zlib |
726 | with_zlib_version_check | 726 | with_zlib_version_check |
727 | with_skey | 727 | with_skey |
728 | with_tcp_wrappers | ||
729 | with_ldns | 728 | with_ldns |
730 | with_libedit | 729 | with_libedit |
731 | with_audit | 730 | with_audit |
@@ -1418,7 +1417,6 @@ Optional Packages: | |||
1418 | --with-zlib=PATH Use zlib in PATH | 1417 | --with-zlib=PATH Use zlib in PATH |
1419 | --without-zlib-version-check Disable zlib version check | 1418 | --without-zlib-version-check Disable zlib version check |
1420 | --with-skey[=PATH] Enable S/Key support (optionally in PATH) | 1419 | --with-skey[=PATH] Enable S/Key support (optionally in PATH) |
1421 | --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH) | ||
1422 | --with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH) | 1420 | --with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH) |
1423 | --with-libedit[=PATH] Enable libedit support for sftp | 1421 | --with-libedit[=PATH] Enable libedit support for sftp |
1424 | --with-audit=module Enable audit support (modules=debug,bsm,linux) | 1422 | --with-audit=module Enable audit support (modules=debug,bsm,linux) |
@@ -9765,84 +9763,6 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |||
9765 | fi | 9763 | fi |
9766 | 9764 | ||
9767 | 9765 | ||
9768 | # Check whether user wants TCP wrappers support | ||
9769 | TCPW_MSG="no" | ||
9770 | |||
9771 | # Check whether --with-tcp-wrappers was given. | ||
9772 | if test "${with_tcp_wrappers+set}" = set; then : | ||
9773 | withval=$with_tcp_wrappers; | ||
9774 | if test "x$withval" != "xno" ; then | ||
9775 | saved_LIBS="$LIBS" | ||
9776 | saved_LDFLAGS="$LDFLAGS" | ||
9777 | saved_CPPFLAGS="$CPPFLAGS" | ||
9778 | if test -n "${withval}" && \ | ||
9779 | test "x${withval}" != "xyes"; then | ||
9780 | if test -d "${withval}/lib"; then | ||
9781 | if test -n "${need_dash_r}"; then | ||
9782 | LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" | ||
9783 | else | ||
9784 | LDFLAGS="-L${withval}/lib ${LDFLAGS}" | ||
9785 | fi | ||
9786 | else | ||
9787 | if test -n "${need_dash_r}"; then | ||
9788 | LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" | ||
9789 | else | ||
9790 | LDFLAGS="-L${withval} ${LDFLAGS}" | ||
9791 | fi | ||
9792 | fi | ||
9793 | if test -d "${withval}/include"; then | ||
9794 | CPPFLAGS="-I${withval}/include ${CPPFLAGS}" | ||
9795 | else | ||
9796 | CPPFLAGS="-I${withval} ${CPPFLAGS}" | ||
9797 | fi | ||
9798 | fi | ||
9799 | LIBS="-lwrap $LIBS" | ||
9800 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libwrap" >&5 | ||
9801 | $as_echo_n "checking for libwrap... " >&6; } | ||
9802 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | ||
9803 | /* end confdefs.h. */ | ||
9804 | |||
9805 | #include <sys/types.h> | ||
9806 | #include <sys/socket.h> | ||
9807 | #include <netinet/in.h> | ||
9808 | #include <tcpd.h> | ||
9809 | int deny_severity = 0, allow_severity = 0; | ||
9810 | |||
9811 | int | ||
9812 | main () | ||
9813 | { | ||
9814 | |||
9815 | hosts_access(0); | ||
9816 | |||
9817 | ; | ||
9818 | return 0; | ||
9819 | } | ||
9820 | _ACEOF | ||
9821 | if ac_fn_c_try_link "$LINENO"; then : | ||
9822 | |||
9823 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | ||
9824 | $as_echo "yes" >&6; } | ||
9825 | |||
9826 | $as_echo "#define LIBWRAP 1" >>confdefs.h | ||
9827 | |||
9828 | SSHDLIBS="$SSHDLIBS -lwrap" | ||
9829 | TCPW_MSG="yes" | ||
9830 | |||
9831 | else | ||
9832 | |||
9833 | as_fn_error $? "*** libwrap missing" "$LINENO" 5 | ||
9834 | |||
9835 | |||
9836 | fi | ||
9837 | rm -f core conftest.err conftest.$ac_objext \ | ||
9838 | conftest$ac_exeext conftest.$ac_ext | ||
9839 | LIBS="$saved_LIBS" | ||
9840 | fi | ||
9841 | |||
9842 | |||
9843 | fi | ||
9844 | |||
9845 | |||
9846 | # Check whether user wants to use ldns | 9766 | # Check whether user wants to use ldns |
9847 | LDNS_MSG="no" | 9767 | LDNS_MSG="no" |
9848 | 9768 | ||
@@ -10407,10 +10327,6 @@ for ac_func in \ | |||
10407 | Blowfish_expandstate \ | 10327 | Blowfish_expandstate \ |
10408 | Blowfish_expand0state \ | 10328 | Blowfish_expand0state \ |
10409 | Blowfish_stream2word \ | 10329 | Blowfish_stream2word \ |
10410 | arc4random \ | ||
10411 | arc4random_buf \ | ||
10412 | arc4random_stir \ | ||
10413 | arc4random_uniform \ | ||
10414 | asprintf \ | 10330 | asprintf \ |
10415 | b64_ntop \ | 10331 | b64_ntop \ |
10416 | __b64_ntop \ | 10332 | __b64_ntop \ |
@@ -10454,6 +10370,7 @@ for ac_func in \ | |||
10454 | mblen \ | 10370 | mblen \ |
10455 | md5_crypt \ | 10371 | md5_crypt \ |
10456 | memmove \ | 10372 | memmove \ |
10373 | memset_s \ | ||
10457 | mkdtemp \ | 10374 | mkdtemp \ |
10458 | mmap \ | 10375 | mmap \ |
10459 | ngetaddrinfo \ | 10376 | ngetaddrinfo \ |
@@ -10512,7 +10429,6 @@ for ac_func in \ | |||
10512 | user_from_uid \ | 10429 | user_from_uid \ |
10513 | usleep \ | 10430 | usleep \ |
10514 | vasprintf \ | 10431 | vasprintf \ |
10515 | vhangup \ | ||
10516 | vsnprintf \ | 10432 | vsnprintf \ |
10517 | waitpid \ | 10433 | waitpid \ |
10518 | 10434 | ||
@@ -11328,11 +11244,9 @@ fi | |||
11328 | 11244 | ||
11329 | fi | 11245 | fi |
11330 | 11246 | ||
11331 | # If we don't have a working asprintf, then we strongly depend on vsnprintf | 11247 | # We depend on vsnprintf returning the right thing on overflow: the |
11332 | # returning the right thing on overflow: the number of characters it tried to | 11248 | # number of characters it tried to create (as per SUSv3) |
11333 | # create (as per SUSv3) | 11249 | if test "x$ac_cv_func_vsnprintf" = "xyes" ; then |
11334 | if test "x$ac_cv_func_asprintf" != "xyes" && \ | ||
11335 | test "x$ac_cv_func_vsnprintf" = "xyes" ; then | ||
11336 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5 | 11250 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5 |
11337 | $as_echo_n "checking whether vsnprintf returns correct values on overflow... " >&6; } | 11251 | $as_echo_n "checking whether vsnprintf returns correct values on overflow... " >&6; } |
11338 | if test "$cross_compiling" = yes; then : | 11252 | if test "$cross_compiling" = yes; then : |
@@ -11347,10 +11261,14 @@ else | |||
11347 | #include <stdio.h> | 11261 | #include <stdio.h> |
11348 | #include <stdarg.h> | 11262 | #include <stdarg.h> |
11349 | 11263 | ||
11350 | int x_snprintf(char *str,size_t count,const char *fmt,...) | 11264 | int x_snprintf(char *str, size_t count, const char *fmt, ...) |
11351 | { | 11265 | { |
11352 | size_t ret; va_list ap; | 11266 | size_t ret; |
11353 | va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); | 11267 | va_list ap; |
11268 | |||
11269 | va_start(ap, fmt); | ||
11270 | ret = vsnprintf(str, count, fmt, ap); | ||
11271 | va_end(ap); | ||
11354 | return ret; | 11272 | return ret; |
11355 | } | 11273 | } |
11356 | 11274 | ||
@@ -11358,8 +11276,12 @@ int | |||
11358 | main () | 11276 | main () |
11359 | { | 11277 | { |
11360 | 11278 | ||
11361 | char x[1]; | 11279 | char x[1]; |
11362 | exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1); | 11280 | if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) |
11281 | return 1; | ||
11282 | if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) | ||
11283 | return 1; | ||
11284 | return 0; | ||
11363 | 11285 | ||
11364 | ; | 11286 | ; |
11365 | return 0; | 11287 | return 0; |
@@ -11956,7 +11878,7 @@ main () | |||
11956 | if(fd == NULL) | 11878 | if(fd == NULL) |
11957 | exit(1); | 11879 | exit(1); |
11958 | 11880 | ||
11959 | if ((rc = fprintf(fd ,"%x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) | 11881 | if ((rc = fprintf(fd ,"%08x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) |
11960 | exit(1); | 11882 | exit(1); |
11961 | 11883 | ||
11962 | exit(0); | 11884 | exit(0); |
@@ -12013,7 +11935,8 @@ main () | |||
12013 | if(fd == NULL) | 11935 | if(fd == NULL) |
12014 | exit(1); | 11936 | exit(1); |
12015 | 11937 | ||
12016 | if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0) | 11938 | if ((rc = fprintf(fd ,"%08x (%s)\n", SSLeay(), |
11939 | SSLeay_version(SSLEAY_VERSION))) <0) | ||
12017 | exit(1); | 11940 | exit(1); |
12018 | 11941 | ||
12019 | exit(0); | 11942 | exit(0); |
@@ -12025,6 +11948,13 @@ _ACEOF | |||
12025 | if ac_fn_c_try_run "$LINENO"; then : | 11948 | if ac_fn_c_try_run "$LINENO"; then : |
12026 | 11949 | ||
12027 | ssl_library_ver=`cat conftest.ssllibver` | 11950 | ssl_library_ver=`cat conftest.ssllibver` |
11951 | # Check version is supported. | ||
11952 | case "$ssl_library_ver" in | ||
11953 | 0090[0-7]*|009080[0-5]*) | ||
11954 | as_fn_error $? "OpenSSL >= 0.9.8f required" "$LINENO" 5 | ||
11955 | ;; | ||
11956 | *) ;; | ||
11957 | esac | ||
12028 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5 | 11958 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5 |
12029 | $as_echo "$ssl_library_ver" >&6; } | 11959 | $as_echo "$ssl_library_ver" >&6; } |
12030 | 11960 | ||
@@ -12040,6 +11970,18 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ | |||
12040 | fi | 11970 | fi |
12041 | 11971 | ||
12042 | 11972 | ||
11973 | # XXX make --without-openssl work | ||
11974 | |||
11975 | cat >>confdefs.h <<_ACEOF | ||
11976 | #define WITH_OPENSSL 1 | ||
11977 | _ACEOF | ||
11978 | |||
11979 | |||
11980 | cat >>confdefs.h <<_ACEOF | ||
11981 | #define WITH_SSH1 1 | ||
11982 | _ACEOF | ||
11983 | |||
11984 | |||
12043 | 11985 | ||
12044 | # Check whether --with-openssl-header-check was given. | 11986 | # Check whether --with-openssl-header-check was given. |
12045 | if test "${with_openssl_header_check+set}" = set; then : | 11987 | if test "${with_openssl_header_check+set}" = set; then : |
@@ -12573,6 +12515,25 @@ else | |||
12573 | fi | 12515 | fi |
12574 | done | 12516 | done |
12575 | 12517 | ||
12518 | # Search for RIPE-MD support in OpenSSL | ||
12519 | for ac_func in EVP_ripemd160 | ||
12520 | do : | ||
12521 | ac_fn_c_check_func "$LINENO" "EVP_ripemd160" "ac_cv_func_EVP_ripemd160" | ||
12522 | if test "x$ac_cv_func_EVP_ripemd160" = xyes; then : | ||
12523 | cat >>confdefs.h <<_ACEOF | ||
12524 | #define HAVE_EVP_RIPEMD160 1 | ||
12525 | _ACEOF | ||
12526 | |||
12527 | else | ||
12528 | unsupported_algorithms="$unsupported_algorithms \ | ||
12529 | hmac-ripemd160 | ||
12530 | hmac-ripemd160@openssh.com | ||
12531 | hmac-ripemd160-etm@openssh.com" | ||
12532 | |||
12533 | |||
12534 | fi | ||
12535 | done | ||
12536 | |||
12576 | 12537 | ||
12577 | # Check complete ECC support in OpenSSL | 12538 | # Check complete ECC support in OpenSSL |
12578 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5 | 12539 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5 |
@@ -12773,6 +12734,24 @@ fi | |||
12773 | 12734 | ||
12774 | 12735 | ||
12775 | 12736 | ||
12737 | for ac_func in \ | ||
12738 | arc4random \ | ||
12739 | arc4random_buf \ | ||
12740 | arc4random_stir \ | ||
12741 | arc4random_uniform \ | ||
12742 | |||
12743 | do : | ||
12744 | as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` | ||
12745 | ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" | ||
12746 | if eval test \"x\$"$as_ac_var"\" = x"yes"; then : | ||
12747 | cat >>confdefs.h <<_ACEOF | ||
12748 | #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 | ||
12749 | _ACEOF | ||
12750 | |||
12751 | fi | ||
12752 | done | ||
12753 | |||
12754 | |||
12776 | saved_LIBS="$LIBS" | 12755 | saved_LIBS="$LIBS" |
12777 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5 | 12756 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5 |
12778 | $as_echo_n "checking for ia_openinfo in -liaf... " >&6; } | 12757 | $as_echo_n "checking for ia_openinfo in -liaf... " >&6; } |
@@ -13182,7 +13161,14 @@ fi | |||
13182 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | 13161 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext |
13183 | fi | 13162 | fi |
13184 | 13163 | ||
13185 | SSH_PRIVSEP_USER=sshd | 13164 | case "$host" in |
13165 | *-*-cygwin*) | ||
13166 | SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER | ||
13167 | ;; | ||
13168 | *) | ||
13169 | SSH_PRIVSEP_USER=sshd | ||
13170 | ;; | ||
13171 | esac | ||
13186 | 13172 | ||
13187 | # Check whether --with-privsep-user was given. | 13173 | # Check whether --with-privsep-user was given. |
13188 | if test "${with_privsep_user+set}" = set; then : | 13174 | if test "${with_privsep_user+set}" = set; then : |
@@ -13195,11 +13181,19 @@ if test "${with_privsep_user+set}" = set; then : | |||
13195 | 13181 | ||
13196 | fi | 13182 | fi |
13197 | 13183 | ||
13184 | if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then | ||
13185 | |||
13186 | cat >>confdefs.h <<_ACEOF | ||
13187 | #define SSH_PRIVSEP_USER CYGWIN_SSH_PRIVSEP_USER | ||
13188 | _ACEOF | ||
13189 | |||
13190 | else | ||
13198 | 13191 | ||
13199 | cat >>confdefs.h <<_ACEOF | 13192 | cat >>confdefs.h <<_ACEOF |
13200 | #define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER" | 13193 | #define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER" |
13201 | _ACEOF | 13194 | _ACEOF |
13202 | 13195 | ||
13196 | fi | ||
13203 | 13197 | ||
13204 | 13198 | ||
13205 | if test "x$have_linux_no_new_privs" = "x1" ; then | 13199 | if test "x$have_linux_no_new_privs" = "x1" ; then |
@@ -19872,7 +19866,6 @@ echo " KerberosV support: $KRB5_MSG" | |||
19872 | echo " SELinux support: $SELINUX_MSG" | 19866 | echo " SELinux support: $SELINUX_MSG" |
19873 | echo " Smartcard support: $SCARD_MSG" | 19867 | echo " Smartcard support: $SCARD_MSG" |
19874 | echo " S/KEY support: $SKEY_MSG" | 19868 | echo " S/KEY support: $SKEY_MSG" |
19875 | echo " TCP Wrappers support: $TCPW_MSG" | ||
19876 | echo " MD5 password support: $MD5_MSG" | 19869 | echo " MD5 password support: $MD5_MSG" |
19877 | echo " libedit support: $LIBEDIT_MSG" | 19870 | echo " libedit support: $LIBEDIT_MSG" |
19878 | echo " Solaris process contract support: $SPC_MSG" | 19871 | echo " Solaris process contract support: $SPC_MSG" |
diff --git a/configure.ac b/configure.ac index 86692714b..f5c65c5a4 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: configure.ac,v 1.571 2014/02/21 17:09:34 tim Exp $ | 1 | # $Id: configure.ac,v 1.583 2014/08/26 20:32:01 djm Exp $ |
2 | # | 2 | # |
3 | # Copyright (c) 1999-2004 Damien Miller | 3 | # Copyright (c) 1999-2004 Damien Miller |
4 | # | 4 | # |
@@ -15,7 +15,7 @@ | |||
15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | 16 | ||
17 | AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) | 17 | AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) |
18 | AC_REVISION($Revision: 1.571 $) | 18 | AC_REVISION($Revision: 1.583 $) |
19 | AC_CONFIG_SRCDIR([ssh.c]) | 19 | AC_CONFIG_SRCDIR([ssh.c]) |
20 | AC_LANG([C]) | 20 | AC_LANG([C]) |
21 | 21 | ||
@@ -1655,10 +1655,6 @@ AC_CHECK_FUNCS([ \ | |||
1655 | Blowfish_expandstate \ | 1655 | Blowfish_expandstate \ |
1656 | Blowfish_expand0state \ | 1656 | Blowfish_expand0state \ |
1657 | Blowfish_stream2word \ | 1657 | Blowfish_stream2word \ |
1658 | arc4random \ | ||
1659 | arc4random_buf \ | ||
1660 | arc4random_stir \ | ||
1661 | arc4random_uniform \ | ||
1662 | asprintf \ | 1658 | asprintf \ |
1663 | b64_ntop \ | 1659 | b64_ntop \ |
1664 | __b64_ntop \ | 1660 | __b64_ntop \ |
@@ -1702,6 +1698,7 @@ AC_CHECK_FUNCS([ \ | |||
1702 | mblen \ | 1698 | mblen \ |
1703 | md5_crypt \ | 1699 | md5_crypt \ |
1704 | memmove \ | 1700 | memmove \ |
1701 | memset_s \ | ||
1705 | mkdtemp \ | 1702 | mkdtemp \ |
1706 | mmap \ | 1703 | mmap \ |
1707 | ngetaddrinfo \ | 1704 | ngetaddrinfo \ |
@@ -1760,7 +1757,6 @@ AC_CHECK_FUNCS([ \ | |||
1760 | user_from_uid \ | 1757 | user_from_uid \ |
1761 | usleep \ | 1758 | usleep \ |
1762 | vasprintf \ | 1759 | vasprintf \ |
1763 | vhangup \ | ||
1764 | vsnprintf \ | 1760 | vsnprintf \ |
1765 | waitpid \ | 1761 | waitpid \ |
1766 | ]) | 1762 | ]) |
@@ -1972,11 +1968,9 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then | |||
1972 | ) | 1968 | ) |
1973 | fi | 1969 | fi |
1974 | 1970 | ||
1975 | # If we don't have a working asprintf, then we strongly depend on vsnprintf | 1971 | # We depend on vsnprintf returning the right thing on overflow: the |
1976 | # returning the right thing on overflow: the number of characters it tried to | 1972 | # number of characters it tried to create (as per SUSv3) |
1977 | # create (as per SUSv3) | 1973 | if test "x$ac_cv_func_vsnprintf" = "xyes" ; then |
1978 | if test "x$ac_cv_func_asprintf" != "xyes" && \ | ||
1979 | test "x$ac_cv_func_vsnprintf" = "xyes" ; then | ||
1980 | AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow]) | 1974 | AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow]) |
1981 | AC_RUN_IFELSE( | 1975 | AC_RUN_IFELSE( |
1982 | [AC_LANG_PROGRAM([[ | 1976 | [AC_LANG_PROGRAM([[ |
@@ -1984,15 +1978,23 @@ if test "x$ac_cv_func_asprintf" != "xyes" && \ | |||
1984 | #include <stdio.h> | 1978 | #include <stdio.h> |
1985 | #include <stdarg.h> | 1979 | #include <stdarg.h> |
1986 | 1980 | ||
1987 | int x_snprintf(char *str,size_t count,const char *fmt,...) | 1981 | int x_snprintf(char *str, size_t count, const char *fmt, ...) |
1988 | { | 1982 | { |
1989 | size_t ret; va_list ap; | 1983 | size_t ret; |
1990 | va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); | 1984 | va_list ap; |
1985 | |||
1986 | va_start(ap, fmt); | ||
1987 | ret = vsnprintf(str, count, fmt, ap); | ||
1988 | va_end(ap); | ||
1991 | return ret; | 1989 | return ret; |
1992 | } | 1990 | } |
1993 | ]], [[ | 1991 | ]], [[ |
1994 | char x[1]; | 1992 | char x[1]; |
1995 | exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1); | 1993 | if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) |
1994 | return 1; | ||
1995 | if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) | ||
1996 | return 1; | ||
1997 | return 0; | ||
1996 | ]])], | 1998 | ]])], |
1997 | [AC_MSG_RESULT([yes])], | 1999 | [AC_MSG_RESULT([yes])], |
1998 | [ | 2000 | [ |
@@ -2328,7 +2330,7 @@ AC_RUN_IFELSE( | |||
2328 | if(fd == NULL) | 2330 | if(fd == NULL) |
2329 | exit(1); | 2331 | exit(1); |
2330 | 2332 | ||
2331 | if ((rc = fprintf(fd ,"%x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) | 2333 | if ((rc = fprintf(fd ,"%08x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) |
2332 | exit(1); | 2334 | exit(1); |
2333 | 2335 | ||
2334 | exit(0); | 2336 | exit(0); |
@@ -2363,13 +2365,21 @@ AC_RUN_IFELSE( | |||
2363 | if(fd == NULL) | 2365 | if(fd == NULL) |
2364 | exit(1); | 2366 | exit(1); |
2365 | 2367 | ||
2366 | if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0) | 2368 | if ((rc = fprintf(fd ,"%08x (%s)\n", SSLeay(), |
2369 | SSLeay_version(SSLEAY_VERSION))) <0) | ||
2367 | exit(1); | 2370 | exit(1); |
2368 | 2371 | ||
2369 | exit(0); | 2372 | exit(0); |
2370 | ]])], | 2373 | ]])], |
2371 | [ | 2374 | [ |
2372 | ssl_library_ver=`cat conftest.ssllibver` | 2375 | ssl_library_ver=`cat conftest.ssllibver` |
2376 | # Check version is supported. | ||
2377 | case "$ssl_library_ver" in | ||
2378 | 0090[[0-7]]*|009080[[0-5]]*) | ||
2379 | AC_MSG_ERROR([OpenSSL >= 0.9.8f required]) | ||
2380 | ;; | ||
2381 | *) ;; | ||
2382 | esac | ||
2373 | AC_MSG_RESULT([$ssl_library_ver]) | 2383 | AC_MSG_RESULT([$ssl_library_ver]) |
2374 | ], | 2384 | ], |
2375 | [ | 2385 | [ |
@@ -2381,6 +2391,10 @@ AC_RUN_IFELSE( | |||
2381 | ] | 2391 | ] |
2382 | ) | 2392 | ) |
2383 | 2393 | ||
2394 | # XXX make --without-openssl work | ||
2395 | AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography]) | ||
2396 | AC_DEFINE_UNQUOTED([WITH_SSH1], [1], [include SSH protocol version 1 support]) | ||
2397 | |||
2384 | AC_ARG_WITH([openssl-header-check], | 2398 | AC_ARG_WITH([openssl-header-check], |
2385 | [ --without-openssl-header-check Disable OpenSSL version consistency check], | 2399 | [ --without-openssl-header-check Disable OpenSSL version consistency check], |
2386 | [ if test "x$withval" = "xno" ; then | 2400 | [ if test "x$withval" = "xno" ; then |
@@ -2589,6 +2603,14 @@ AC_CHECK_FUNCS([SHA256_Update EVP_sha256], , | |||
2589 | hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com" | 2603 | hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com" |
2590 | ] | 2604 | ] |
2591 | ) | 2605 | ) |
2606 | # Search for RIPE-MD support in OpenSSL | ||
2607 | AC_CHECK_FUNCS([EVP_ripemd160], , | ||
2608 | [unsupported_algorithms="$unsupported_algorithms \ | ||
2609 | hmac-ripemd160 | ||
2610 | hmac-ripemd160@openssh.com | ||
2611 | hmac-ripemd160-etm@openssh.com" | ||
2612 | ] | ||
2613 | ) | ||
2592 | 2614 | ||
2593 | # Check complete ECC support in OpenSSL | 2615 | # Check complete ECC support in OpenSSL |
2594 | AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) | 2616 | AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) |
@@ -2709,6 +2731,13 @@ fi | |||
2709 | AC_SUBST([TEST_SSH_ECC]) | 2731 | AC_SUBST([TEST_SSH_ECC]) |
2710 | AC_SUBST([COMMENT_OUT_ECC]) | 2732 | AC_SUBST([COMMENT_OUT_ECC]) |
2711 | 2733 | ||
2734 | AC_CHECK_FUNCS([ \ | ||
2735 | arc4random \ | ||
2736 | arc4random_buf \ | ||
2737 | arc4random_stir \ | ||
2738 | arc4random_uniform \ | ||
2739 | ]) | ||
2740 | |||
2712 | saved_LIBS="$LIBS" | 2741 | saved_LIBS="$LIBS" |
2713 | AC_CHECK_LIB([iaf], [ia_openinfo], [ | 2742 | AC_CHECK_LIB([iaf], [ia_openinfo], [ |
2714 | LIBS="$LIBS -liaf" | 2743 | LIBS="$LIBS -liaf" |
@@ -2892,7 +2921,14 @@ if test "x$PAM_MSG" = "xyes" ; then | |||
2892 | ]) | 2921 | ]) |
2893 | fi | 2922 | fi |
2894 | 2923 | ||
2895 | SSH_PRIVSEP_USER=sshd | 2924 | case "$host" in |
2925 | *-*-cygwin*) | ||
2926 | SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER | ||
2927 | ;; | ||
2928 | *) | ||
2929 | SSH_PRIVSEP_USER=sshd | ||
2930 | ;; | ||
2931 | esac | ||
2896 | AC_ARG_WITH([privsep-user], | 2932 | AC_ARG_WITH([privsep-user], |
2897 | [ --with-privsep-user=user Specify non-privileged user for privilege separation], | 2933 | [ --with-privsep-user=user Specify non-privileged user for privilege separation], |
2898 | [ | 2934 | [ |
@@ -2902,8 +2938,13 @@ AC_ARG_WITH([privsep-user], | |||
2902 | fi | 2938 | fi |
2903 | ] | 2939 | ] |
2904 | ) | 2940 | ) |
2905 | AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"], | 2941 | if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then |
2906 | [non-privileged user for privilege separation]) | 2942 | AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], [CYGWIN_SSH_PRIVSEP_USER], |
2943 | [Cygwin function to fetch non-privileged user for privilege separation]) | ||
2944 | else | ||
2945 | AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"], | ||
2946 | [non-privileged user for privilege separation]) | ||
2947 | fi | ||
2907 | AC_SUBST([SSH_PRIVSEP_USER]) | 2948 | AC_SUBST([SSH_PRIVSEP_USER]) |
2908 | 2949 | ||
2909 | if test "x$have_linux_no_new_privs" = "x1" ; then | 2950 | if test "x$have_linux_no_new_privs" = "x1" ; then |
diff --git a/consolekit.c b/consolekit.c index f1039e652..0266f06a2 100644 --- a/consolekit.c +++ b/consolekit.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include "hostfile.h" | 53 | #include "hostfile.h" |
54 | #include "auth.h" | 54 | #include "auth.h" |
55 | #include "log.h" | 55 | #include "log.h" |
56 | #include "misc.h" | ||
56 | #include "servconf.h" | 57 | #include "servconf.h" |
57 | #include "canohost.h" | 58 | #include "canohost.h" |
58 | #include "session.h" | 59 | #include "session.h" |
diff --git a/contrib/caldera/openssh.spec b/contrib/caldera/openssh.spec index 0061fe933..0011b4dea 100644 --- a/contrib/caldera/openssh.spec +++ b/contrib/caldera/openssh.spec | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | #old cvs stuff. please update before use. may be deprecated. | 17 | #old cvs stuff. please update before use. may be deprecated. |
18 | %define use_stable 1 | 18 | %define use_stable 1 |
19 | %define version 6.6p1 | 19 | %define version 6.7p1 |
20 | %if %{use_stable} | 20 | %if %{use_stable} |
21 | %define cvs %{nil} | 21 | %define cvs %{nil} |
22 | %define release 1 | 22 | %define release 1 |
@@ -178,7 +178,6 @@ by Jim Knoble <jmknoble@pobox.com>. | |||
178 | CFLAGS="$RPM_OPT_FLAGS" \ | 178 | CFLAGS="$RPM_OPT_FLAGS" \ |
179 | %configure \ | 179 | %configure \ |
180 | --with-pam \ | 180 | --with-pam \ |
181 | --with-tcp-wrappers \ | ||
182 | --with-privsep-path=%{_var}/empty/sshd \ | 181 | --with-privsep-path=%{_var}/empty/sshd \ |
183 | #leave this line for easy edits. | 182 | #leave this line for easy edits. |
184 | 183 | ||
@@ -363,4 +362,4 @@ fi | |||
363 | * Mon Jan 01 1998 ... | 362 | * Mon Jan 01 1998 ... |
364 | Template Version: 1.31 | 363 | Template Version: 1.31 |
365 | 364 | ||
366 | $Id: openssh.spec,v 1.83 2014/02/27 23:03:55 djm Exp $ | 365 | $Id: openssh.spec,v 1.85 2014/08/19 01:36:08 djm Exp $ |
diff --git a/contrib/cygwin/README b/contrib/cygwin/README index 2562b6186..1396d99cd 100644 --- a/contrib/cygwin/README +++ b/contrib/cygwin/README | |||
@@ -69,7 +69,7 @@ Building OpenSSH | |||
69 | Building from source is easy. Just unpack the source archive, cd to that | 69 | Building from source is easy. Just unpack the source archive, cd to that |
70 | directory, and call cygport: | 70 | directory, and call cygport: |
71 | 71 | ||
72 | cygport openssh.cygport almostall | 72 | cygport openssh.cygport all |
73 | 73 | ||
74 | You must have installed the following packages to be able to build OpenSSH | 74 | You must have installed the following packages to be able to build OpenSSH |
75 | with the aforementioned cygport script: | 75 | with the aforementioned cygport script: |
@@ -77,7 +77,6 @@ with the aforementioned cygport script: | |||
77 | zlib | 77 | zlib |
78 | crypt | 78 | crypt |
79 | openssl-devel | 79 | openssl-devel |
80 | libwrap-devel | ||
81 | libedit-devel | 80 | libedit-devel |
82 | libkrb5-devel | 81 | libkrb5-devel |
83 | 82 | ||
diff --git a/contrib/cygwin/ssh-host-config b/contrib/cygwin/ssh-host-config index 05efd3b3b..a7ea3e0d2 100644 --- a/contrib/cygwin/ssh-host-config +++ b/contrib/cygwin/ssh-host-config | |||
@@ -34,9 +34,9 @@ declare -a csih_required_commands=( | |||
34 | /usr/bin/mv coreutils | 34 | /usr/bin/mv coreutils |
35 | /usr/bin/rm coreutils | 35 | /usr/bin/rm coreutils |
36 | /usr/bin/cygpath cygwin | 36 | /usr/bin/cygpath cygwin |
37 | /usr/bin/mkpasswd cygwin | ||
37 | /usr/bin/mount cygwin | 38 | /usr/bin/mount cygwin |
38 | /usr/bin/ps cygwin | 39 | /usr/bin/ps cygwin |
39 | /usr/bin/setfacl cygwin | ||
40 | /usr/bin/umount cygwin | 40 | /usr/bin/umount cygwin |
41 | /usr/bin/cmp diffutils | 41 | /usr/bin/cmp diffutils |
42 | /usr/bin/grep grep | 42 | /usr/bin/grep grep |
@@ -59,8 +59,9 @@ PREFIX=/usr | |||
59 | SYSCONFDIR=/etc | 59 | SYSCONFDIR=/etc |
60 | LOCALSTATEDIR=/var | 60 | LOCALSTATEDIR=/var |
61 | 61 | ||
62 | sshd_config_configured=no | ||
62 | port_number=22 | 63 | port_number=22 |
63 | privsep_configured=no | 64 | strictmodes=yes |
64 | privsep_used=yes | 65 | privsep_used=yes |
65 | cygwin_value="" | 66 | cygwin_value="" |
66 | user_account= | 67 | user_account= |
@@ -89,28 +90,8 @@ update_services_file() { | |||
89 | # Depends on the above mount | 90 | # Depends on the above mount |
90 | _wservices=`cygpath -w "${_services}"` | 91 | _wservices=`cygpath -w "${_services}"` |
91 | 92 | ||
92 | # Remove sshd 22/port from services | ||
93 | if [ `/usr/bin/grep -q 'sshd[ \t][ \t]*22' "${_services}"; echo $?` -eq 0 ] | ||
94 | then | ||
95 | /usr/bin/grep -v 'sshd[ \t][ \t]*22' "${_services}" > "${_serv_tmp}" | ||
96 | if [ -f "${_serv_tmp}" ] | ||
97 | then | ||
98 | if /usr/bin/mv "${_serv_tmp}" "${_services}" | ||
99 | then | ||
100 | csih_inform "Removing sshd from ${_wservices}" | ||
101 | else | ||
102 | csih_warning "Removing sshd from ${_wservices} failed!" | ||
103 | let ++ret | ||
104 | fi | ||
105 | /usr/bin/rm -f "${_serv_tmp}" | ||
106 | else | ||
107 | csih_warning "Removing sshd from ${_wservices} failed!" | ||
108 | let ++ret | ||
109 | fi | ||
110 | fi | ||
111 | |||
112 | # Add ssh 22/tcp and ssh 22/udp to services | 93 | # Add ssh 22/tcp and ssh 22/udp to services |
113 | if [ `/usr/bin/grep -q 'ssh[ \t][ \t]*22' "${_services}"; echo $?` -ne 0 ] | 94 | if [ `/usr/bin/grep -q 'ssh[[:space:]][[:space:]]*22' "${_services}"; echo $?` -ne 0 ] |
114 | then | 95 | then |
115 | if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh 22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh 22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}" | 96 | if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh 22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh 22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}" |
116 | then | 97 | then |
@@ -132,17 +113,45 @@ update_services_file() { | |||
132 | } # --- End of update_services_file --- # | 113 | } # --- End of update_services_file --- # |
133 | 114 | ||
134 | # ====================================================================== | 115 | # ====================================================================== |
116 | # Routine: sshd_strictmodes | ||
117 | # MODIFIES: strictmodes | ||
118 | # ====================================================================== | ||
119 | sshd_strictmodes() { | ||
120 | if [ "${sshd_config_configured}" != "yes" ] | ||
121 | then | ||
122 | echo | ||
123 | csih_inform "StrictModes is set to 'yes' by default." | ||
124 | csih_inform "This is the recommended setting, but it requires that the POSIX" | ||
125 | csih_inform "permissions of the user's home directory, the user's .ssh" | ||
126 | csih_inform "directory, and the user's ssh key files are tight so that" | ||
127 | csih_inform "only the user has write permissions." | ||
128 | csih_inform "On the other hand, StrictModes don't work well with default" | ||
129 | csih_inform "Windows permissions of a home directory mounted with the" | ||
130 | csih_inform "'noacl' option, and they don't work at all if the home" | ||
131 | csih_inform "directory is on a FAT or FAT32 partition." | ||
132 | if ! csih_request "Should StrictModes be used?" | ||
133 | then | ||
134 | strictmodes=no | ||
135 | fi | ||
136 | fi | ||
137 | return 0 | ||
138 | } | ||
139 | |||
140 | # ====================================================================== | ||
135 | # Routine: sshd_privsep | 141 | # Routine: sshd_privsep |
136 | # MODIFIES: privsep_configured privsep_used | 142 | # MODIFIES: privsep_used |
137 | # ====================================================================== | 143 | # ====================================================================== |
138 | sshd_privsep() { | 144 | sshd_privsep() { |
139 | local sshdconfig_tmp | ||
140 | local ret=0 | 145 | local ret=0 |
141 | 146 | ||
142 | if [ "${privsep_configured}" != "yes" ] | 147 | if [ "${sshd_config_configured}" != "yes" ] |
143 | then | 148 | then |
144 | csih_inform "Privilege separation is set to yes by default since OpenSSH 3.3." | 149 | echo |
145 | csih_inform "However, this requires a non-privileged account called 'sshd'." | 150 | csih_inform "Privilege separation is set to 'sandbox' by default since" |
151 | csih_inform "OpenSSH 6.1. This is unsupported by Cygwin and has to be set" | ||
152 | csih_inform "to 'yes' or 'no'." | ||
153 | csih_inform "However, using privilege separation requires a non-privileged account" | ||
154 | csih_inform "called 'sshd'." | ||
146 | csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep." | 155 | csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep." |
147 | if csih_request "Should privilege separation be used?" | 156 | if csih_request "Should privilege separation be used?" |
148 | then | 157 | then |
@@ -159,36 +168,53 @@ sshd_privsep() { | |||
159 | privsep_used=no | 168 | privsep_used=no |
160 | fi | 169 | fi |
161 | fi | 170 | fi |
171 | return $ret | ||
172 | } # --- End of sshd_privsep --- # | ||
162 | 173 | ||
163 | # Create default sshd_config from skeleton files in /etc/defaults/etc or | 174 | # ====================================================================== |
164 | # modify to add the missing privsep configuration option | 175 | # Routine: sshd_config_tweak |
165 | if /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1 | 176 | # ====================================================================== |
177 | sshd_config_tweak() { | ||
178 | local ret=0 | ||
179 | |||
180 | # Modify sshd_config | ||
181 | csih_inform "Updating ${SYSCONFDIR}/sshd_config file" | ||
182 | if [ "${port_number}" -ne 22 ] | ||
166 | then | 183 | then |
167 | csih_inform "Updating ${SYSCONFDIR}/sshd_config file" | 184 | /usr/bin/sed -i -e "s/^#\?[[:space:]]*Port[[:space:]].*/Port ${port_number}/" \ |
168 | sshdconfig_tmp=${SYSCONFDIR}/sshd_config.$$ | 185 | ${SYSCONFDIR}/sshd_config |
169 | /usr/bin/sed -e "s/^#UsePrivilegeSeparation yes/UsePrivilegeSeparation ${privsep_used}/ | 186 | if [ $? -ne 0 ] |
170 | s/^#Port 22/Port ${port_number}/ | ||
171 | s/^#StrictModes yes/StrictModes no/" \ | ||
172 | < ${SYSCONFDIR}/sshd_config \ | ||
173 | > "${sshdconfig_tmp}" | ||
174 | if ! /usr/bin/mv "${sshdconfig_tmp}" ${SYSCONFDIR}/sshd_config | ||
175 | then | 187 | then |
176 | csih_warning "Setting privilege separation to 'yes' failed!" | 188 | csih_warning "Setting listening port to ${port_number} failed!" |
177 | csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" | 189 | csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" |
178 | let ++ret | 190 | let ++ret |
191 | fi | ||
192 | fi | ||
193 | if [ "${strictmodes}" = "no" ] | ||
194 | then | ||
195 | /usr/bin/sed -i -e "s/^#\?[[:space:]]*StrictModes[[:space:]].*/StrictModes no/" \ | ||
196 | ${SYSCONFDIR}/sshd_config | ||
197 | if [ $? -ne 0 ] | ||
198 | then | ||
199 | csih_warning "Setting StrictModes to 'no' failed!" | ||
200 | csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" | ||
201 | let ++ret | ||
179 | fi | 202 | fi |
180 | elif [ "${privsep_configured}" != "yes" ] | 203 | fi |
204 | if [ "${sshd_config_configured}" != "yes" ] | ||
181 | then | 205 | then |
182 | echo >> ${SYSCONFDIR}/sshd_config | 206 | /usr/bin/sed -i -e " |
183 | if ! echo "UsePrivilegeSeparation ${privsep_used}" >> ${SYSCONFDIR}/sshd_config | 207 | s/^#\?UsePrivilegeSeparation .*/UsePrivilegeSeparation ${privsep_used}/" \ |
208 | ${SYSCONFDIR}/sshd_config | ||
209 | if [ $? -ne 0 ] | ||
184 | then | 210 | then |
185 | csih_warning "Setting privilege separation to 'yes' failed!" | 211 | csih_warning "Setting privilege separation failed!" |
186 | csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" | 212 | csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" |
187 | let ++ret | 213 | let ++ret |
188 | fi | 214 | fi |
189 | fi | 215 | fi |
190 | return $ret | 216 | return $ret |
191 | } # --- End of sshd_privsep --- # | 217 | } # --- End of sshd_config_tweak --- # |
192 | 218 | ||
193 | # ====================================================================== | 219 | # ====================================================================== |
194 | # Routine: update_inetd_conf | 220 | # Routine: update_inetd_conf |
@@ -207,11 +233,11 @@ update_inetd_conf() { | |||
207 | # we have inetutils-1.5 inetd.d support | 233 | # we have inetutils-1.5 inetd.d support |
208 | if [ -f "${_inetcnf}" ] | 234 | if [ -f "${_inetcnf}" ] |
209 | then | 235 | then |
210 | /usr/bin/grep -q '^[ \t]*ssh' "${_inetcnf}" && _with_comment=0 | 236 | /usr/bin/grep -q '^[[:space:]]*ssh' "${_inetcnf}" && _with_comment=0 |
211 | 237 | ||
212 | # check for sshd OR ssh in top-level inetd.conf file, and remove | 238 | # check for sshd OR ssh in top-level inetd.conf file, and remove |
213 | # will be replaced by a file in inetd.d/ | 239 | # will be replaced by a file in inetd.d/ |
214 | if [ `/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -eq 0 ] | 240 | if [ $(/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?) -eq 0 ] |
215 | then | 241 | then |
216 | /usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}" | 242 | /usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}" |
217 | if [ -f "${_inetcnf_tmp}" ] | 243 | if [ -f "${_inetcnf_tmp}" ] |
@@ -236,9 +262,9 @@ update_inetd_conf() { | |||
236 | then | 262 | then |
237 | if [ "${_with_comment}" -eq 0 ] | 263 | if [ "${_with_comment}" -eq 0 ] |
238 | then | 264 | then |
239 | /usr/bin/sed -e 's/@COMMENT@[ \t]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" | 265 | /usr/bin/sed -e 's/@COMMENT@[[:space:]]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" |
240 | else | 266 | else |
241 | /usr/bin/sed -e 's/@COMMENT@[ \t]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" | 267 | /usr/bin/sed -e 's/@COMMENT@[[:space:]]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" |
242 | fi | 268 | fi |
243 | if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}" | 269 | if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}" |
244 | then | 270 | then |
@@ -251,13 +277,13 @@ update_inetd_conf() { | |||
251 | 277 | ||
252 | elif [ -f "${_inetcnf}" ] | 278 | elif [ -f "${_inetcnf}" ] |
253 | then | 279 | then |
254 | /usr/bin/grep -q '^[ \t]*sshd' "${_inetcnf}" && _with_comment=0 | 280 | /usr/bin/grep -q '^[[:space:]]*sshd' "${_inetcnf}" && _with_comment=0 |
255 | 281 | ||
256 | # check for sshd in top-level inetd.conf file, and remove | 282 | # check for sshd in top-level inetd.conf file, and remove |
257 | # will be replaced by a file in inetd.d/ | 283 | # will be replaced by a file in inetd.d/ |
258 | if [ `/usr/bin/grep -q '^[# \t]*sshd' "${_inetcnf}"; echo $?` -eq 0 ] | 284 | if [ `/usr/bin/grep -q '^#\?[[:space:]]*sshd' "${_inetcnf}"; echo $?` -eq 0 ] |
259 | then | 285 | then |
260 | /usr/bin/grep -v '^[# \t]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}" | 286 | /usr/bin/grep -v '^#\?[[:space:]]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}" |
261 | if [ -f "${_inetcnf_tmp}" ] | 287 | if [ -f "${_inetcnf_tmp}" ] |
262 | then | 288 | then |
263 | if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}" | 289 | if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}" |
@@ -305,17 +331,26 @@ check_service_files_ownership() { | |||
305 | 331 | ||
306 | if [ -z "${run_service_as}" ] | 332 | if [ -z "${run_service_as}" ] |
307 | then | 333 | then |
308 | accnt_name=$(/usr/bin/cygrunsrv -VQ sshd | /usr/bin/sed -ne 's/^Account *: *//gp') | 334 | accnt_name=$(/usr/bin/cygrunsrv -VQ sshd | |
335 | /usr/bin/sed -ne 's/^Account *: *//gp') | ||
309 | if [ "${accnt_name}" = "LocalSystem" ] | 336 | if [ "${accnt_name}" = "LocalSystem" ] |
310 | then | 337 | then |
311 | # Convert "LocalSystem" to "SYSTEM" as is the correct account name | 338 | # Convert "LocalSystem" to "SYSTEM" as is the correct account name |
312 | accnt_name="SYSTEM:" | 339 | run_service_as="SYSTEM" |
313 | elif [[ "${accnt_name}" =~ ^\.\\ ]] | 340 | else |
314 | then | 341 | dom="${accnt_name%%\\*}" |
315 | # Convert "." domain to local machine name | 342 | accnt_name="${accnt_name#*\\}" |
316 | accnt_name="U-${COMPUTERNAME}${accnt_name#.}," | 343 | if [ "${dom}" = '.' ] |
344 | then | ||
345 | # Check local account | ||
346 | run_service_as=$(/usr/bin/mkpasswd -l -u "${accnt_name}" | | ||
347 | /usr/bin/awk -F: '{print $1;}') | ||
348 | else | ||
349 | # Check domain | ||
350 | run_service_as=$(/usr/bin/mkpasswd -d "${dom}" -u "${accnt_name}" | | ||
351 | /usr/bin/awk -F: '{print $1;}') | ||
352 | fi | ||
317 | fi | 353 | fi |
318 | run_service_as=$(/usr/bin/grep -Fi "${accnt_name}" /etc/passwd | /usr/bin/awk -F: '{print $1;}') | ||
319 | if [ -z "${run_service_as}" ] | 354 | if [ -z "${run_service_as}" ] |
320 | then | 355 | then |
321 | csih_warning "Couldn't determine name of user running sshd service from /etc/passwd!" | 356 | csih_warning "Couldn't determine name of user running sshd service from /etc/passwd!" |
@@ -615,32 +650,6 @@ echo | |||
615 | 650 | ||
616 | warning_cnt=0 | 651 | warning_cnt=0 |
617 | 652 | ||
618 | # Check for ${SYSCONFDIR} directory | ||
619 | csih_make_dir "${SYSCONFDIR}" "Cannot create global configuration files." | ||
620 | if ! /usr/bin/chmod 775 "${SYSCONFDIR}" >/dev/null 2>&1 | ||
621 | then | ||
622 | csih_warning "Can't set permissions on ${SYSCONFDIR}!" | ||
623 | let ++warning_cnt | ||
624 | fi | ||
625 | if ! /usr/bin/setfacl -m u:system:rwx "${SYSCONFDIR}" >/dev/null 2>&1 | ||
626 | then | ||
627 | csih_warning "Can't set extended permissions on ${SYSCONFDIR}!" | ||
628 | let ++warning_cnt | ||
629 | fi | ||
630 | |||
631 | # Check for /var/log directory | ||
632 | csih_make_dir "${LOCALSTATEDIR}/log" "Cannot create log directory." | ||
633 | if ! /usr/bin/chmod 775 "${LOCALSTATEDIR}/log" >/dev/null 2>&1 | ||
634 | then | ||
635 | csih_warning "Can't set permissions on ${LOCALSTATEDIR}/log!" | ||
636 | let ++warning_cnt | ||
637 | fi | ||
638 | if ! /usr/bin/setfacl -m u:system:rwx "${LOCALSTATEDIR}/log" >/dev/null 2>&1 | ||
639 | then | ||
640 | csih_warning "Can't set extended permissions on ${LOCALSTATEDIR}/log!" | ||
641 | let ++warning_cnt | ||
642 | fi | ||
643 | |||
644 | # Create /var/log/lastlog if not already exists | 653 | # Create /var/log/lastlog if not already exists |
645 | if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ] | 654 | if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ] |
646 | then | 655 | then |
@@ -665,13 +674,9 @@ then | |||
665 | csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!" | 674 | csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!" |
666 | let ++warning_cnt | 675 | let ++warning_cnt |
667 | fi | 676 | fi |
668 | if ! /usr/bin/setfacl -m u:system:rwx "${LOCALSTATEDIR}/empty" >/dev/null 2>&1 | ||
669 | then | ||
670 | csih_warning "Can't set extended permissions on ${LOCALSTATEDIR}/empty!" | ||
671 | let ++warning_cnt | ||
672 | fi | ||
673 | 677 | ||
674 | # generate missing host keys | 678 | # generate missing host keys |
679 | csih_inform "Generating missing SSH host keys" | ||
675 | /usr/bin/ssh-keygen -A || let warning_cnt+=$? | 680 | /usr/bin/ssh-keygen -A || let warning_cnt+=$? |
676 | 681 | ||
677 | # handle ssh_config | 682 | # handle ssh_config |
@@ -690,10 +695,11 @@ fi | |||
690 | csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt | 695 | csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt |
691 | if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1 | 696 | if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1 |
692 | then | 697 | then |
693 | /usr/bin/grep -q UsePrivilegeSeparation ${SYSCONFDIR}/sshd_config && privsep_configured=yes | 698 | sshd_config_configured=yes |
694 | fi | 699 | fi |
700 | sshd_strictmodes || let warning_cnt+=$? | ||
695 | sshd_privsep || let warning_cnt+=$? | 701 | sshd_privsep || let warning_cnt+=$? |
696 | 702 | sshd_config_tweak || let warning_cnt+=$? | |
697 | update_services_file || let warning_cnt+=$? | 703 | update_services_file || let warning_cnt+=$? |
698 | update_inetd_conf || let warning_cnt+=$? | 704 | update_inetd_conf || let warning_cnt+=$? |
699 | install_service || let warning_cnt+=$? | 705 | install_service || let warning_cnt+=$? |
diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec index 96401c6ee..9bdce1e3c 100644 --- a/contrib/redhat/openssh.spec +++ b/contrib/redhat/openssh.spec | |||
@@ -1,4 +1,4 @@ | |||
1 | %define ver 6.6p1 | 1 | %define ver 6.7p1 |
2 | %define rel 1 | 2 | %define rel 1 |
3 | 3 | ||
4 | # OpenSSH privilege separation requires a user & group ID | 4 | # OpenSSH privilege separation requires a user & group ID |
@@ -86,7 +86,7 @@ PreReq: initscripts >= 5.00 | |||
86 | %else | 86 | %else |
87 | Requires: initscripts >= 5.20 | 87 | Requires: initscripts >= 5.20 |
88 | %endif | 88 | %endif |
89 | BuildRequires: perl, openssl-devel, tcp_wrappers | 89 | BuildRequires: perl, openssl-devel |
90 | BuildRequires: /bin/login | 90 | BuildRequires: /bin/login |
91 | %if ! %{build6x} | 91 | %if ! %{build6x} |
92 | BuildPreReq: glibc-devel, pam | 92 | BuildPreReq: glibc-devel, pam |
@@ -192,7 +192,6 @@ echo K5DIR=$K5DIR | |||
192 | --sysconfdir=%{_sysconfdir}/ssh \ | 192 | --sysconfdir=%{_sysconfdir}/ssh \ |
193 | --libexecdir=%{_libexecdir}/openssh \ | 193 | --libexecdir=%{_libexecdir}/openssh \ |
194 | --datadir=%{_datadir}/openssh \ | 194 | --datadir=%{_datadir}/openssh \ |
195 | --with-tcp-wrappers \ | ||
196 | --with-rsh=%{_bindir}/rsh \ | 195 | --with-rsh=%{_bindir}/rsh \ |
197 | --with-default-path=/usr/local/bin:/bin:/usr/bin \ | 196 | --with-default-path=/usr/local/bin:/bin:/usr/bin \ |
198 | --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ | 197 | --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ |
diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec index 0515d6d7c..f87674317 100644 --- a/contrib/suse/openssh.spec +++ b/contrib/suse/openssh.spec | |||
@@ -13,7 +13,7 @@ | |||
13 | 13 | ||
14 | Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation | 14 | Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation |
15 | Name: openssh | 15 | Name: openssh |
16 | Version: 6.6p1 | 16 | Version: 6.7p1 |
17 | URL: http://www.openssh.com/ | 17 | URL: http://www.openssh.com/ |
18 | Release: 1 | 18 | Release: 1 |
19 | Source0: openssh-%{version}.tar.gz | 19 | Source0: openssh-%{version}.tar.gz |
@@ -28,11 +28,9 @@ Provides: ssh | |||
28 | # (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.) | 28 | # (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.) |
29 | # building prerequisites -- stuff for | 29 | # building prerequisites -- stuff for |
30 | # OpenSSL (openssl-devel), | 30 | # OpenSSL (openssl-devel), |
31 | # TCP Wrappers (tcpd-devel), | ||
32 | # and Gnome (glibdev, gtkdev, and gnlibsd) | 31 | # and Gnome (glibdev, gtkdev, and gnlibsd) |
33 | # | 32 | # |
34 | BuildPrereq: openssl | 33 | BuildPrereq: openssl |
35 | BuildPrereq: tcpd-devel | ||
36 | BuildPrereq: zlib-devel | 34 | BuildPrereq: zlib-devel |
37 | #BuildPrereq: glibdev | 35 | #BuildPrereq: glibdev |
38 | #BuildPrereq: gtkdev | 36 | #BuildPrereq: gtkdev |
@@ -140,7 +138,6 @@ CFLAGS="$RPM_OPT_FLAGS" \ | |||
140 | --mandir=%{_mandir} \ | 138 | --mandir=%{_mandir} \ |
141 | --with-privsep-path=/var/lib/empty \ | 139 | --with-privsep-path=/var/lib/empty \ |
142 | --with-pam \ | 140 | --with-pam \ |
143 | --with-tcp-wrappers \ | ||
144 | --libexecdir=%{_libdir}/ssh | 141 | --libexecdir=%{_libdir}/ssh |
145 | make | 142 | make |
146 | 143 | ||
diff --git a/debian/.git-dpm b/debian/.git-dpm index e15bf4ebd..c10ac230e 100644 --- a/debian/.git-dpm +++ b/debian/.git-dpm | |||
@@ -1,7 +1,7 @@ | |||
1 | # see git-dpm(1) from git-dpm package | 1 | # see git-dpm(1) from git-dpm package |
2 | 02883061577ec43ff8d0e8f0cf486bc5131db507 | 2 | 762c062828f5a8f6ed189ed6e44ad38fd92f8b36 |
3 | 02883061577ec43ff8d0e8f0cf486bc5131db507 | 3 | 762c062828f5a8f6ed189ed6e44ad38fd92f8b36 |
4 | 796ba4fd011b5d0d9d78d592ba2f30fc9d5ed2e7 | 4 | 487bdb3a5ef6075887b830ccb8a0b14f6da78e93 |
5 | 487bdb3a5ef6075887b830ccb8a0b14f6da78e93 | 5 | 487bdb3a5ef6075887b830ccb8a0b14f6da78e93 |
6 | openssh_6.7p1.orig.tar.gz | 6 | openssh_6.7p1.orig.tar.gz |
7 | 14e5fbed710ade334d65925e080d1aaeb9c85bf6 | 7 | 14e5fbed710ade334d65925e080d1aaeb9c85bf6 |
diff --git a/debian/changelog b/debian/changelog index 0cf20dc14..e89bee3b7 100644 --- a/debian/changelog +++ b/debian/changelog | |||
@@ -1,5 +1,46 @@ | |||
1 | openssh (1:6.6p1-9) UNRELEASED; urgency=medium | 1 | openssh (1:6.7p1-1) UNRELEASED; urgency=medium |
2 | 2 | ||
3 | * New upstream release (http://www.openssh.com/txt/release-6.7): | ||
4 | - sshd(8): The default set of ciphers and MACs has been altered to | ||
5 | remove unsafe algorithms. In particular, CBC ciphers and arcfour* are | ||
6 | disabled by default. The full set of algorithms remains available if | ||
7 | configured explicitly via the Ciphers and MACs sshd_config options. | ||
8 | - ssh(1), sshd(8): Add support for Unix domain socket forwarding. A | ||
9 | remote TCP port may be forwarded to a local Unix domain socket and | ||
10 | vice versa or both ends may be a Unix domain socket (closes: #236718). | ||
11 | - ssh(1), ssh-keygen(1): Add support for SSHFP DNS records for ED25519 | ||
12 | key types. | ||
13 | - sftp(1): Allow resumption of interrupted uploads. | ||
14 | - ssh(1): When rekeying, skip file/DNS lookups of the hostkey if it is | ||
15 | the same as the one sent during initial key exchange. | ||
16 | - sshd(8): Allow explicit ::1 and 127.0.0.1 forwarding bind addresses | ||
17 | when GatewayPorts=no; allows client to choose address family. | ||
18 | - sshd(8): Add a sshd_config PermitUserRC option to control whether | ||
19 | ~/.ssh/rc is executed, mirroring the no-user-rc authorized_keys | ||
20 | option. | ||
21 | - ssh(1): Add a %C escape sequence for LocalCommand and ControlPath that | ||
22 | expands to a unique identifer based on a hash of the tuple of (local | ||
23 | host, remote user, hostname, port). Helps avoid exceeding miserly | ||
24 | pathname limits for Unix domain sockets in multiplexing control paths. | ||
25 | - sshd(8): Make the "Too many authentication failures" message include | ||
26 | the user, source address, port and protocol in a format similar to the | ||
27 | authentication success / failure messages. | ||
28 | - Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC when it is | ||
29 | available. It considers time spent suspended, thereby ensuring | ||
30 | timeouts (e.g. for expiring agent keys) fire correctly (closes: | ||
31 | #734553). | ||
32 | - Use prctl() to prevent sftp-server from accessing | ||
33 | /proc/self/{mem,maps}. | ||
34 | * Restore TCP wrappers support, removed upstream in 6.7. It is true that | ||
35 | dropping this reduces preauth attack surface in sshd. On the other | ||
36 | hand, this support seems to be quite widely used, and abruptly dropping | ||
37 | it (from the perspective of users who don't read openssh-unix-dev) could | ||
38 | easily cause more serious problems in practice. It's not entirely clear | ||
39 | what the right long-term answer for Debian is, but it at least probably | ||
40 | doesn't involve dropping this feature shortly before a freeze. | ||
41 | * Replace patch to disable OpenSSL version check with an updated version | ||
42 | of Kurt Roeckx's patch from #732940 to just avoid checking the status | ||
43 | field. | ||
3 | * Build-depend on a new enough dpkg-dev for dpkg-buildflags, rather than | 44 | * Build-depend on a new enough dpkg-dev for dpkg-buildflags, rather than |
4 | simply a new enough dpkg. | 45 | simply a new enough dpkg. |
5 | * Simplify debian/rules using /usr/share/dpkg/buildflags.mk. | 46 | * Simplify debian/rules using /usr/share/dpkg/buildflags.mk. |
diff --git a/debian/patches/auth-log-verbosity.patch b/debian/patches/auth-log-verbosity.patch index 8d26d7b6f..84a14cfb8 100644 --- a/debian/patches/auth-log-verbosity.patch +++ b/debian/patches/auth-log-verbosity.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 283322f493ee7dc75511f6cf9e9b88e536de0874 Mon Sep 17 00:00:00 2001 | 1 | From 1ecd5db58295874d8b9a7ce98fe1880ab08fbcaf Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:02 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:02 +0000 |
4 | Subject: Quieten logs when multiple from= restrictions are used | 4 | Subject: Quieten logs when multiple from= restrictions are used |
@@ -16,7 +16,7 @@ Patch-Name: auth-log-verbosity.patch | |||
16 | 4 files changed, 32 insertions(+), 9 deletions(-) | 16 | 4 files changed, 32 insertions(+), 9 deletions(-) |
17 | 17 | ||
18 | diff --git a/auth-options.c b/auth-options.c | 18 | diff --git a/auth-options.c b/auth-options.c |
19 | index fa209ea..df61330 100644 | 19 | index f3d9c9d..d4d22d7 100644 |
20 | --- a/auth-options.c | 20 | --- a/auth-options.c |
21 | +++ b/auth-options.c | 21 | +++ b/auth-options.c |
22 | @@ -54,9 +54,20 @@ int forced_tun_device = -1; | 22 | @@ -54,9 +54,20 @@ int forced_tun_device = -1; |
@@ -58,7 +58,7 @@ index fa209ea..df61330 100644 | |||
58 | auth_debug_add("Your host '%.200s' is not " | 58 | auth_debug_add("Your host '%.200s' is not " |
59 | "permitted to use this key for login.", | 59 | "permitted to use this key for login.", |
60 | remote_host); | 60 | remote_host); |
61 | @@ -510,11 +524,14 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, | 61 | @@ -511,11 +525,14 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, |
62 | break; | 62 | break; |
63 | case 0: | 63 | case 0: |
64 | /* no match */ | 64 | /* no match */ |
@@ -91,10 +91,10 @@ index 7455c94..a3f0a02 100644 | |||
91 | void auth_clear_options(void); | 91 | void auth_clear_options(void); |
92 | int auth_cert_options(Key *, struct passwd *); | 92 | int auth_cert_options(Key *, struct passwd *); |
93 | diff --git a/auth-rsa.c b/auth-rsa.c | 93 | diff --git a/auth-rsa.c b/auth-rsa.c |
94 | index 5dad6c3..260ce2f 100644 | 94 | index e9f4ede..5d7bdcb 100644 |
95 | --- a/auth-rsa.c | 95 | --- a/auth-rsa.c |
96 | +++ b/auth-rsa.c | 96 | +++ b/auth-rsa.c |
97 | @@ -178,6 +178,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, | 97 | @@ -179,6 +179,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, |
98 | if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL) | 98 | if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL) |
99 | return 0; | 99 | return 0; |
100 | 100 | ||
@@ -104,10 +104,10 @@ index 5dad6c3..260ce2f 100644 | |||
104 | * Go though the accepted keys, looking for the current key. If | 104 | * Go though the accepted keys, looking for the current key. If |
105 | * found, perform a challenge-response dialog to verify that the | 105 | * found, perform a challenge-response dialog to verify that the |
106 | diff --git a/auth2-pubkey.c b/auth2-pubkey.c | 106 | diff --git a/auth2-pubkey.c b/auth2-pubkey.c |
107 | index 0fd27bb..7c56927 100644 | 107 | index f3ca965..f78b046 100644 |
108 | --- a/auth2-pubkey.c | 108 | --- a/auth2-pubkey.c |
109 | +++ b/auth2-pubkey.c | 109 | +++ b/auth2-pubkey.c |
110 | @@ -263,6 +263,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert) | 110 | @@ -263,6 +263,7 @@ match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert) |
111 | restore_uid(); | 111 | restore_uid(); |
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
diff --git a/debian/patches/authorized-keys-man-symlink.patch b/debian/patches/authorized-keys-man-symlink.patch index 74bfb46e6..6afb0420b 100644 --- a/debian/patches/authorized-keys-man-symlink.patch +++ b/debian/patches/authorized-keys-man-symlink.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 71448da5ce75ba50bcb10dbbd3b8c7633f633e8f Mon Sep 17 00:00:00 2001 | 1 | From 19b0441502c07401dd6d418f8f81cc7f1a44ccb1 Mon Sep 17 00:00:00 2001 |
2 | From: Tomas Pospisek <tpo_deb@sourcepole.ch> | 2 | From: Tomas Pospisek <tpo_deb@sourcepole.ch> |
3 | Date: Sun, 9 Feb 2014 16:10:07 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:07 +0000 |
4 | Subject: Install authorized_keys(5) as a symlink to sshd(8) | 4 | Subject: Install authorized_keys(5) as a symlink to sshd(8) |
@@ -13,10 +13,10 @@ Patch-Name: authorized-keys-man-symlink.patch | |||
13 | 1 file changed, 1 insertion(+) | 13 | 1 file changed, 1 insertion(+) |
14 | 14 | ||
15 | diff --git a/Makefile.in b/Makefile.in | 15 | diff --git a/Makefile.in b/Makefile.in |
16 | index 3d96c05..feee0b2 100644 | 16 | index c4cb8ea..a4402e9 100644 |
17 | --- a/Makefile.in | 17 | --- a/Makefile.in |
18 | +++ b/Makefile.in | 18 | +++ b/Makefile.in |
19 | @@ -287,6 +287,7 @@ install-files: | 19 | @@ -309,6 +309,7 @@ install-files: |
20 | $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 | 20 | $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 |
21 | $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 | 21 | $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 |
22 | $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 | 22 | $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 |
diff --git a/debian/patches/consolekit.patch b/debian/patches/consolekit.patch index e3ff4d7e4..e50c77f62 100644 --- a/debian/patches/consolekit.patch +++ b/debian/patches/consolekit.patch | |||
@@ -1,33 +1,33 @@ | |||
1 | From 7a26d16efb4ee303c8d66ee82caf9d0686f4a074 Mon Sep 17 00:00:00 2001 | 1 | From f51fe0c55e54c12db952624e980d18f39c41e581 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@ubuntu.com> | 2 | From: Colin Watson <cjwatson@ubuntu.com> |
3 | Date: Sun, 9 Feb 2014 16:09:57 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:57 +0000 |
4 | Subject: Add support for registering ConsoleKit sessions on login | 4 | Subject: Add support for registering ConsoleKit sessions on login |
5 | 5 | ||
6 | Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1450 | 6 | Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1450 |
7 | Last-Updated: 2014-03-20 | 7 | Last-Updated: 2014-10-07 |
8 | 8 | ||
9 | Patch-Name: consolekit.patch | 9 | Patch-Name: consolekit.patch |
10 | --- | 10 | --- |
11 | Makefile.in | 3 +- | 11 | Makefile.in | 3 +- |
12 | configure | 132 +++++++++++++++++++++++++++++++ | 12 | configure | 132 +++++++++++++++++++++++++++++++ |
13 | configure.ac | 25 ++++++ | 13 | configure.ac | 25 ++++++ |
14 | consolekit.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 14 | consolekit.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
15 | consolekit.h | 24 ++++++ | 15 | consolekit.h | 24 ++++++ |
16 | monitor.c | 42 ++++++++++ | 16 | monitor.c | 42 ++++++++++ |
17 | monitor.h | 2 + | 17 | monitor.h | 2 + |
18 | monitor_wrap.c | 30 ++++++++ | 18 | monitor_wrap.c | 30 +++++++ |
19 | monitor_wrap.h | 4 + | 19 | monitor_wrap.h | 4 + |
20 | session.c | 13 ++++ | 20 | session.c | 13 ++++ |
21 | session.h | 6 ++ | 21 | session.h | 6 ++ |
22 | 11 files changed, 520 insertions(+), 1 deletion(-) | 22 | 11 files changed, 521 insertions(+), 1 deletion(-) |
23 | create mode 100644 consolekit.c | 23 | create mode 100644 consolekit.c |
24 | create mode 100644 consolekit.h | 24 | create mode 100644 consolekit.h |
25 | 25 | ||
26 | diff --git a/Makefile.in b/Makefile.in | 26 | diff --git a/Makefile.in b/Makefile.in |
27 | index ee1d2c3..3d96c05 100644 | 27 | index 086d8dd..c4cb8ea 100644 |
28 | --- a/Makefile.in | 28 | --- a/Makefile.in |
29 | +++ b/Makefile.in | 29 | +++ b/Makefile.in |
30 | @@ -97,7 +97,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ | 30 | @@ -107,7 +107,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ |
31 | sftp-server.o sftp-common.o \ | 31 | sftp-server.o sftp-common.o \ |
32 | roaming_common.o roaming_serv.o \ | 32 | roaming_common.o roaming_serv.o \ |
33 | sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ | 33 | sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ |
@@ -38,10 +38,10 @@ index ee1d2c3..3d96c05 100644 | |||
38 | MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out | 38 | MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out |
39 | MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 | 39 | MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 |
40 | diff --git a/configure b/configure | 40 | diff --git a/configure b/configure |
41 | index b6b5b6d..e2f12cd 100755 | 41 | index ea5f200..7be478a 100755 |
42 | --- a/configure | 42 | --- a/configure |
43 | +++ b/configure | 43 | +++ b/configure |
44 | @@ -740,6 +740,7 @@ with_privsep_user | 44 | @@ -739,6 +739,7 @@ with_privsep_user |
45 | with_sandbox | 45 | with_sandbox |
46 | with_selinux | 46 | with_selinux |
47 | with_kerberos5 | 47 | with_kerberos5 |
@@ -49,7 +49,7 @@ index b6b5b6d..e2f12cd 100755 | |||
49 | with_privsep_path | 49 | with_privsep_path |
50 | with_xauth | 50 | with_xauth |
51 | enable_strip | 51 | enable_strip |
52 | @@ -1432,6 +1433,7 @@ Optional Packages: | 52 | @@ -1430,6 +1431,7 @@ Optional Packages: |
53 | --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, capsicum) | 53 | --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, capsicum) |
54 | --with-selinux Enable SELinux support | 54 | --with-selinux Enable SELinux support |
55 | --with-kerberos5=PATH Enable Kerberos 5 support | 55 | --with-kerberos5=PATH Enable Kerberos 5 support |
@@ -57,7 +57,7 @@ index b6b5b6d..e2f12cd 100755 | |||
57 | --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty) | 57 | --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty) |
58 | --with-xauth=PATH Specify path to xauth program | 58 | --with-xauth=PATH Specify path to xauth program |
59 | --with-maildir=/path/to/mail Specify your system mail directory | 59 | --with-maildir=/path/to/mail Specify your system mail directory |
60 | @@ -17217,6 +17219,135 @@ fi | 60 | @@ -17211,6 +17213,135 @@ fi |
61 | 61 | ||
62 | 62 | ||
63 | 63 | ||
@@ -193,7 +193,7 @@ index b6b5b6d..e2f12cd 100755 | |||
193 | # Looking for programs, paths and files | 193 | # Looking for programs, paths and files |
194 | 194 | ||
195 | PRIVSEP_PATH=/var/empty | 195 | PRIVSEP_PATH=/var/empty |
196 | @@ -19746,6 +19877,7 @@ echo " MD5 password support: $MD5_MSG" | 196 | @@ -19739,6 +19870,7 @@ echo " MD5 password support: $MD5_MSG" |
197 | echo " libedit support: $LIBEDIT_MSG" | 197 | echo " libedit support: $LIBEDIT_MSG" |
198 | echo " Solaris process contract support: $SPC_MSG" | 198 | echo " Solaris process contract support: $SPC_MSG" |
199 | echo " Solaris project support: $SP_MSG" | 199 | echo " Solaris project support: $SP_MSG" |
@@ -202,10 +202,10 @@ index b6b5b6d..e2f12cd 100755 | |||
202 | echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" | 202 | echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" |
203 | echo " BSD Auth support: $BSD_AUTH_MSG" | 203 | echo " BSD Auth support: $BSD_AUTH_MSG" |
204 | diff --git a/configure.ac b/configure.ac | 204 | diff --git a/configure.ac b/configure.ac |
205 | index d235fb0..8669271 100644 | 205 | index 7f160f1..f5c65c5 100644 |
206 | --- a/configure.ac | 206 | --- a/configure.ac |
207 | +++ b/configure.ac | 207 | +++ b/configure.ac |
208 | @@ -4072,6 +4072,30 @@ AC_ARG_WITH([kerberos5], | 208 | @@ -4113,6 +4113,30 @@ AC_ARG_WITH([kerberos5], |
209 | AC_SUBST([GSSLIBS]) | 209 | AC_SUBST([GSSLIBS]) |
210 | AC_SUBST([K5LIBS]) | 210 | AC_SUBST([K5LIBS]) |
211 | 211 | ||
@@ -236,7 +236,7 @@ index d235fb0..8669271 100644 | |||
236 | # Looking for programs, paths and files | 236 | # Looking for programs, paths and files |
237 | 237 | ||
238 | PRIVSEP_PATH=/var/empty | 238 | PRIVSEP_PATH=/var/empty |
239 | @@ -4873,6 +4897,7 @@ echo " MD5 password support: $MD5_MSG" | 239 | @@ -4914,6 +4938,7 @@ echo " MD5 password support: $MD5_MSG" |
240 | echo " libedit support: $LIBEDIT_MSG" | 240 | echo " libedit support: $LIBEDIT_MSG" |
241 | echo " Solaris process contract support: $SPC_MSG" | 241 | echo " Solaris process contract support: $SPC_MSG" |
242 | echo " Solaris project support: $SP_MSG" | 242 | echo " Solaris project support: $SP_MSG" |
@@ -246,10 +246,10 @@ index d235fb0..8669271 100644 | |||
246 | echo " BSD Auth support: $BSD_AUTH_MSG" | 246 | echo " BSD Auth support: $BSD_AUTH_MSG" |
247 | diff --git a/consolekit.c b/consolekit.c | 247 | diff --git a/consolekit.c b/consolekit.c |
248 | new file mode 100644 | 248 | new file mode 100644 |
249 | index 0000000..f1039e6 | 249 | index 0000000..0266f06 |
250 | --- /dev/null | 250 | --- /dev/null |
251 | +++ b/consolekit.c | 251 | +++ b/consolekit.c |
252 | @@ -0,0 +1,240 @@ | 252 | @@ -0,0 +1,241 @@ |
253 | +/* | 253 | +/* |
254 | + * Copyright (c) 2008 Colin Watson. All rights reserved. | 254 | + * Copyright (c) 2008 Colin Watson. All rights reserved. |
255 | + * | 255 | + * |
@@ -305,6 +305,7 @@ index 0000000..f1039e6 | |||
305 | +#include "hostfile.h" | 305 | +#include "hostfile.h" |
306 | +#include "auth.h" | 306 | +#include "auth.h" |
307 | +#include "log.h" | 307 | +#include "log.h" |
308 | +#include "misc.h" | ||
308 | +#include "servconf.h" | 309 | +#include "servconf.h" |
309 | +#include "canohost.h" | 310 | +#include "canohost.h" |
310 | +#include "session.h" | 311 | +#include "session.h" |
@@ -521,10 +522,10 @@ index 0000000..8ce3716 | |||
521 | + | 522 | + |
522 | +#endif /* USE_CONSOLEKIT */ | 523 | +#endif /* USE_CONSOLEKIT */ |
523 | diff --git a/monitor.c b/monitor.c | 524 | diff --git a/monitor.c b/monitor.c |
524 | index 11eac63..7c105e6 100644 | 525 | index 94b194d..cc15ce4 100644 |
525 | --- a/monitor.c | 526 | --- a/monitor.c |
526 | +++ b/monitor.c | 527 | +++ b/monitor.c |
527 | @@ -97,6 +97,9 @@ | 528 | @@ -100,6 +100,9 @@ |
528 | #include "ssh2.h" | 529 | #include "ssh2.h" |
529 | #include "roaming.h" | 530 | #include "roaming.h" |
530 | #include "authfd.h" | 531 | #include "authfd.h" |
@@ -534,7 +535,7 @@ index 11eac63..7c105e6 100644 | |||
534 | 535 | ||
535 | #ifdef GSSAPI | 536 | #ifdef GSSAPI |
536 | static Gssctxt *gsscontext = NULL; | 537 | static Gssctxt *gsscontext = NULL; |
537 | @@ -187,6 +190,10 @@ int mm_answer_audit_command(int, Buffer *); | 538 | @@ -190,6 +193,10 @@ int mm_answer_audit_command(int, Buffer *); |
538 | 539 | ||
539 | static int monitor_read_log(struct monitor *); | 540 | static int monitor_read_log(struct monitor *); |
540 | 541 | ||
@@ -543,9 +544,9 @@ index 11eac63..7c105e6 100644 | |||
543 | +#endif | 544 | +#endif |
544 | + | 545 | + |
545 | static Authctxt *authctxt; | 546 | static Authctxt *authctxt; |
546 | static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ | ||
547 | 547 | ||
548 | @@ -272,6 +279,9 @@ struct mon_table mon_dispatch_postauth20[] = { | 548 | #ifdef WITH_SSH1 |
549 | @@ -282,6 +289,9 @@ struct mon_table mon_dispatch_postauth20[] = { | ||
549 | {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, | 550 | {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, |
550 | {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, | 551 | {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, |
551 | #endif | 552 | #endif |
@@ -555,17 +556,17 @@ index 11eac63..7c105e6 100644 | |||
555 | {0, 0, NULL} | 556 | {0, 0, NULL} |
556 | }; | 557 | }; |
557 | 558 | ||
558 | @@ -314,6 +324,9 @@ struct mon_table mon_dispatch_postauth15[] = { | 559 | @@ -327,6 +337,9 @@ struct mon_table mon_dispatch_postauth15[] = { |
559 | {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, | 560 | {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, |
560 | {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, | 561 | {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, |
561 | #endif | 562 | #endif |
562 | +#ifdef USE_CONSOLEKIT | 563 | +#ifdef USE_CONSOLEKIT |
563 | + {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register}, | 564 | + {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register}, |
564 | +#endif | 565 | +#endif |
566 | #endif /* WITH_SSH1 */ | ||
565 | {0, 0, NULL} | 567 | {0, 0, NULL} |
566 | }; | 568 | }; |
567 | 569 | @@ -509,6 +522,9 @@ monitor_child_postauth(struct monitor *pmonitor) | |
568 | @@ -492,6 +505,9 @@ monitor_child_postauth(struct monitor *pmonitor) | ||
569 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); | 570 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); |
570 | monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); | 571 | monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); |
571 | } | 572 | } |
@@ -575,7 +576,7 @@ index 11eac63..7c105e6 100644 | |||
575 | 576 | ||
576 | for (;;) | 577 | for (;;) |
577 | monitor_read(pmonitor, mon_dispatch, NULL); | 578 | monitor_read(pmonitor, mon_dispatch, NULL); |
578 | @@ -2269,3 +2285,29 @@ mm_answer_gss_updatecreds(int socket, Buffer *m) { | 579 | @@ -2296,3 +2312,29 @@ mm_answer_gss_updatecreds(int socket, Buffer *m) { |
579 | 580 | ||
580 | #endif /* GSSAPI */ | 581 | #endif /* GSSAPI */ |
581 | 582 | ||
@@ -619,10 +620,10 @@ index 4d5e8fa..10ba59e 100644 | |||
619 | 620 | ||
620 | struct mm_master; | 621 | struct mm_master; |
621 | diff --git a/monitor_wrap.c b/monitor_wrap.c | 622 | diff --git a/monitor_wrap.c b/monitor_wrap.c |
622 | index f75dc9d..a8fb07b 100644 | 623 | index 6dc890a..4c57d4d 100644 |
623 | --- a/monitor_wrap.c | 624 | --- a/monitor_wrap.c |
624 | +++ b/monitor_wrap.c | 625 | +++ b/monitor_wrap.c |
625 | @@ -1353,3 +1353,33 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) | 626 | @@ -1363,3 +1363,33 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) |
626 | 627 | ||
627 | #endif /* GSSAPI */ | 628 | #endif /* GSSAPI */ |
628 | 629 | ||
@@ -670,10 +671,10 @@ index 9c2ee49..00e93fe 100644 | |||
670 | + | 671 | + |
671 | #endif /* _MM_WRAP_H_ */ | 672 | #endif /* _MM_WRAP_H_ */ |
672 | diff --git a/session.c b/session.c | 673 | diff --git a/session.c b/session.c |
673 | index 6848df4..9d43fc3 100644 | 674 | index 6f389ac..6250c20 100644 |
674 | --- a/session.c | 675 | --- a/session.c |
675 | +++ b/session.c | 676 | +++ b/session.c |
676 | @@ -92,6 +92,7 @@ | 677 | @@ -93,6 +93,7 @@ |
677 | #include "kex.h" | 678 | #include "kex.h" |
678 | #include "monitor_wrap.h" | 679 | #include "monitor_wrap.h" |
679 | #include "sftp.h" | 680 | #include "sftp.h" |
@@ -681,7 +682,7 @@ index 6848df4..9d43fc3 100644 | |||
681 | 682 | ||
682 | #if defined(KRB5) && defined(USE_AFS) | 683 | #if defined(KRB5) && defined(USE_AFS) |
683 | #include <kafs.h> | 684 | #include <kafs.h> |
684 | @@ -1160,6 +1161,9 @@ do_setup_env(Session *s, const char *shell) | 685 | @@ -1143,6 +1144,9 @@ do_setup_env(Session *s, const char *shell) |
685 | #if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN) | 686 | #if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN) |
686 | char *path = NULL; | 687 | char *path = NULL; |
687 | #endif | 688 | #endif |
@@ -691,7 +692,7 @@ index 6848df4..9d43fc3 100644 | |||
691 | 692 | ||
692 | /* Initialize the environment. */ | 693 | /* Initialize the environment. */ |
693 | envsize = 100; | 694 | envsize = 100; |
694 | @@ -1304,6 +1308,11 @@ do_setup_env(Session *s, const char *shell) | 695 | @@ -1287,6 +1291,11 @@ do_setup_env(Session *s, const char *shell) |
695 | child_set_env(&env, &envsize, "KRB5CCNAME", | 696 | child_set_env(&env, &envsize, "KRB5CCNAME", |
696 | s->authctxt->krb5_ccname); | 697 | s->authctxt->krb5_ccname); |
697 | #endif | 698 | #endif |
@@ -703,7 +704,7 @@ index 6848df4..9d43fc3 100644 | |||
703 | #ifdef USE_PAM | 704 | #ifdef USE_PAM |
704 | /* | 705 | /* |
705 | * Pull in any environment variables that may have | 706 | * Pull in any environment variables that may have |
706 | @@ -2353,6 +2362,10 @@ session_pty_cleanup2(Session *s) | 707 | @@ -2350,6 +2359,10 @@ session_pty_cleanup2(Session *s) |
707 | 708 | ||
708 | debug("session_pty_cleanup: session %d release %s", s->self, s->tty); | 709 | debug("session_pty_cleanup: session %d release %s", s->self, s->tty); |
709 | 710 | ||
diff --git a/debian/patches/curve25519-sha256-bignum-encoding.patch b/debian/patches/curve25519-sha256-bignum-encoding.patch deleted file mode 100644 index ccb66048d..000000000 --- a/debian/patches/curve25519-sha256-bignum-encoding.patch +++ /dev/null | |||
@@ -1,161 +0,0 @@ | |||
1 | From 02883061577ec43ff8d0e8f0cf486bc5131db507 Mon Sep 17 00:00:00 2001 | ||
2 | From: Damien Miller <djm@mindrot.org> | ||
3 | Date: Sun, 20 Apr 2014 13:47:45 +1000 | ||
4 | Subject: bad bignum encoding for curve25519-sha256@libssh.org | ||
5 | |||
6 | Hi, | ||
7 | |||
8 | So I screwed up when writing the support for the curve25519 KEX method | ||
9 | that doesn't depend on OpenSSL's BIGNUM type - a bug in my code left | ||
10 | leading zero bytes where they should have been skipped. The impact of | ||
11 | this is that OpenSSH 6.5 and 6.6 will fail during key exchange with a | ||
12 | peer that implements curve25519-sha256@libssh.org properly about 0.2% | ||
13 | of the time (one in every 512ish connections). | ||
14 | |||
15 | We've fixed this for OpenSSH 6.7 by avoiding the curve25519-sha256 | ||
16 | key exchange for previous versions, but I'd recommend distributors | ||
17 | of OpenSSH apply this patch so the affected code doesn't become | ||
18 | too entrenched in LTS releases. | ||
19 | |||
20 | The patch fixes the bug and makes OpenSSH identify itself as 6.6.1 so as | ||
21 | to distinguish itself from the incorrect versions so the compatibility | ||
22 | code to disable the affected KEX isn't activated. | ||
23 | |||
24 | I've committed this on the 6.6 branch too. | ||
25 | |||
26 | Apologies for the hassle. | ||
27 | |||
28 | -d | ||
29 | |||
30 | Origin: upstream, https://lists.mindrot.org/pipermail/openssh-unix-dev/2014-April/032494.html | ||
31 | Forwarded: not-needed | ||
32 | Last-Update: 2014-04-21 | ||
33 | |||
34 | Patch-Name: curve25519-sha256-bignum-encoding.patch | ||
35 | --- | ||
36 | bufaux.c | 5 ++++- | ||
37 | compat.c | 17 ++++++++++++++++- | ||
38 | compat.h | 2 ++ | ||
39 | sshconnect2.c | 2 ++ | ||
40 | sshd.c | 3 +++ | ||
41 | version.h | 2 +- | ||
42 | 6 files changed, 28 insertions(+), 3 deletions(-) | ||
43 | |||
44 | diff --git a/bufaux.c b/bufaux.c | ||
45 | index e24b5fc..f6a6f2a 100644 | ||
46 | --- a/bufaux.c | ||
47 | +++ b/bufaux.c | ||
48 | @@ -1,4 +1,4 @@ | ||
49 | -/* $OpenBSD: bufaux.c,v 1.56 2014/02/02 03:44:31 djm Exp $ */ | ||
50 | +/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */ | ||
51 | /* | ||
52 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | ||
53 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
54 | @@ -372,6 +372,9 @@ buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) | ||
55 | |||
56 | if (l > 8 * 1024) | ||
57 | fatal("%s: length %u too long", __func__, l); | ||
58 | + /* Skip leading zero bytes */ | ||
59 | + for (; l > 0 && *s == 0; l--, s++) | ||
60 | + ; | ||
61 | p = buf = xmalloc(l + 1); | ||
62 | /* | ||
63 | * If most significant bit is set then prepend a zero byte to | ||
64 | diff --git a/compat.c b/compat.c | ||
65 | index 9d9fabe..2709dc5 100644 | ||
66 | --- a/compat.c | ||
67 | +++ b/compat.c | ||
68 | @@ -95,6 +95,9 @@ compat_datafellows(const char *version) | ||
69 | { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, | ||
70 | { "OpenSSH_4*", 0 }, | ||
71 | { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT}, | ||
72 | + { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH}, | ||
73 | + { "OpenSSH_6.5*," | ||
74 | + "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD}, | ||
75 | { "OpenSSH*", SSH_NEW_OPENSSH }, | ||
76 | { "*MindTerm*", 0 }, | ||
77 | { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| | ||
78 | @@ -251,7 +254,6 @@ compat_cipher_proposal(char *cipher_prop) | ||
79 | return cipher_prop; | ||
80 | } | ||
81 | |||
82 | - | ||
83 | char * | ||
84 | compat_pkalg_proposal(char *pkalg_prop) | ||
85 | { | ||
86 | @@ -265,3 +267,16 @@ compat_pkalg_proposal(char *pkalg_prop) | ||
87 | return pkalg_prop; | ||
88 | } | ||
89 | |||
90 | +char * | ||
91 | +compat_kex_proposal(char *kex_prop) | ||
92 | +{ | ||
93 | + if (!(datafellows & SSH_BUG_CURVE25519PAD)) | ||
94 | + return kex_prop; | ||
95 | + debug2("%s: original KEX proposal: %s", __func__, kex_prop); | ||
96 | + kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org"); | ||
97 | + debug2("%s: compat KEX proposal: %s", __func__, kex_prop); | ||
98 | + if (*kex_prop == '\0') | ||
99 | + fatal("No supported key exchange algorithms found"); | ||
100 | + return kex_prop; | ||
101 | +} | ||
102 | + | ||
103 | diff --git a/compat.h b/compat.h | ||
104 | index b174fa1..a6c3f3d 100644 | ||
105 | --- a/compat.h | ||
106 | +++ b/compat.h | ||
107 | @@ -59,6 +59,7 @@ | ||
108 | #define SSH_BUG_RFWD_ADDR 0x02000000 | ||
109 | #define SSH_NEW_OPENSSH 0x04000000 | ||
110 | #define SSH_BUG_DYNAMIC_RPORT 0x08000000 | ||
111 | +#define SSH_BUG_CURVE25519PAD 0x10000000 | ||
112 | |||
113 | void enable_compat13(void); | ||
114 | void enable_compat20(void); | ||
115 | @@ -66,6 +67,7 @@ void compat_datafellows(const char *); | ||
116 | int proto_spec(const char *); | ||
117 | char *compat_cipher_proposal(char *); | ||
118 | char *compat_pkalg_proposal(char *); | ||
119 | +char *compat_kex_proposal(char *); | ||
120 | |||
121 | extern int compat13; | ||
122 | extern int compat20; | ||
123 | diff --git a/sshconnect2.c b/sshconnect2.c | ||
124 | index 66cb035..1a4e551 100644 | ||
125 | --- a/sshconnect2.c | ||
126 | +++ b/sshconnect2.c | ||
127 | @@ -220,6 +220,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | ||
128 | } | ||
129 | if (options.kex_algorithms != NULL) | ||
130 | myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; | ||
131 | + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( | ||
132 | + myproposal[PROPOSAL_KEX_ALGS]); | ||
133 | |||
134 | #ifdef GSSAPI | ||
135 | /* If we've got GSSAPI algorithms, then we also support the | ||
136 | diff --git a/sshd.c b/sshd.c | ||
137 | index 0964491..fe78d7b 100644 | ||
138 | --- a/sshd.c | ||
139 | +++ b/sshd.c | ||
140 | @@ -2534,6 +2534,9 @@ do_ssh2_kex(void) | ||
141 | if (options.kex_algorithms != NULL) | ||
142 | myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; | ||
143 | |||
144 | + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( | ||
145 | + myproposal[PROPOSAL_KEX_ALGS]); | ||
146 | + | ||
147 | if (options.rekey_limit || options.rekey_interval) | ||
148 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, | ||
149 | (time_t)options.rekey_interval); | ||
150 | diff --git a/version.h b/version.h | ||
151 | index a97c337..0659576 100644 | ||
152 | --- a/version.h | ||
153 | +++ b/version.h | ||
154 | @@ -1,6 +1,6 @@ | ||
155 | /* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */ | ||
156 | |||
157 | -#define SSH_VERSION "OpenSSH_6.6" | ||
158 | +#define SSH_VERSION "OpenSSH_6.6.1" | ||
159 | |||
160 | #define SSH_PORTABLE "p1" | ||
161 | #define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE | ||
diff --git a/debian/patches/debian-banner.patch b/debian/patches/debian-banner.patch index 49219cf93..ab64cbed5 100644 --- a/debian/patches/debian-banner.patch +++ b/debian/patches/debian-banner.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 9fcad888f4dbf0ecc0c7e87b6ef0f8d88d7ac3ec Mon Sep 17 00:00:00 2001 | 1 | From 114c8a8fb488cbe39507edb75c51198a4b9e8b24 Mon Sep 17 00:00:00 2001 |
2 | From: Kees Cook <kees@debian.org> | 2 | From: Kees Cook <kees@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:06 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:06 +0000 |
4 | Subject: Add DebianBanner server configuration option | 4 | Subject: Add DebianBanner server configuration option |
@@ -8,7 +8,7 @@ initial protocol handshake, for those scared by package-versioning.patch. | |||
8 | 8 | ||
9 | Bug-Debian: http://bugs.debian.org/562048 | 9 | Bug-Debian: http://bugs.debian.org/562048 |
10 | Forwarded: not-needed | 10 | Forwarded: not-needed |
11 | Last-Update: 2013-09-14 | 11 | Last-Update: 2014-10-07 |
12 | 12 | ||
13 | Patch-Name: debian-banner.patch | 13 | Patch-Name: debian-banner.patch |
14 | --- | 14 | --- |
@@ -19,10 +19,10 @@ Patch-Name: debian-banner.patch | |||
19 | 4 files changed, 18 insertions(+), 1 deletion(-) | 19 | 4 files changed, 18 insertions(+), 1 deletion(-) |
20 | 20 | ||
21 | diff --git a/servconf.c b/servconf.c | 21 | diff --git a/servconf.c b/servconf.c |
22 | index 90de888..37fd2de 100644 | 22 | index a252487..6c7741a 100644 |
23 | --- a/servconf.c | 23 | --- a/servconf.c |
24 | +++ b/servconf.c | 24 | +++ b/servconf.c |
25 | @@ -156,6 +156,7 @@ initialize_server_options(ServerOptions *options) | 25 | @@ -160,6 +160,7 @@ initialize_server_options(ServerOptions *options) |
26 | options->ip_qos_interactive = -1; | 26 | options->ip_qos_interactive = -1; |
27 | options->ip_qos_bulk = -1; | 27 | options->ip_qos_bulk = -1; |
28 | options->version_addendum = NULL; | 28 | options->version_addendum = NULL; |
@@ -30,34 +30,34 @@ index 90de888..37fd2de 100644 | |||
30 | } | 30 | } |
31 | 31 | ||
32 | void | 32 | void |
33 | @@ -309,6 +310,8 @@ fill_default_server_options(ServerOptions *options) | 33 | @@ -321,6 +322,8 @@ fill_default_server_options(ServerOptions *options) |
34 | options->ip_qos_bulk = IPTOS_THROUGHPUT; | 34 | options->fwd_opts.streamlocal_bind_mask = 0177; |
35 | if (options->version_addendum == NULL) | 35 | if (options->fwd_opts.streamlocal_bind_unlink == -1) |
36 | options->version_addendum = xstrdup(""); | 36 | options->fwd_opts.streamlocal_bind_unlink = 0; |
37 | + if (options->debian_banner == -1) | 37 | + if (options->debian_banner == -1) |
38 | + options->debian_banner = 1; | 38 | + options->debian_banner = 1; |
39 | /* Turn privilege separation on by default */ | 39 | /* Turn privilege separation on by default */ |
40 | if (use_privsep == -1) | 40 | if (use_privsep == -1) |
41 | use_privsep = PRIVSEP_NOSANDBOX; | 41 | use_privsep = PRIVSEP_NOSANDBOX; |
42 | @@ -359,6 +362,7 @@ typedef enum { | 42 | @@ -373,6 +376,7 @@ typedef enum { |
43 | sKexAlgorithms, sIPQoS, sVersionAddendum, | 43 | sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, |
44 | sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, | 44 | sStreamLocalBindMask, sStreamLocalBindUnlink, |
45 | sAuthenticationMethods, sHostKeyAgent, | 45 | sAllowStreamLocalForwarding, |
46 | + sDebianBanner, | 46 | + sDebianBanner, |
47 | sDeprecated, sUnsupported | 47 | sDeprecated, sUnsupported |
48 | } ServerOpCodes; | 48 | } ServerOpCodes; |
49 | 49 | ||
50 | @@ -496,6 +500,7 @@ static struct { | 50 | @@ -514,6 +518,7 @@ static struct { |
51 | { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, | 51 | { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, |
52 | { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, | 52 | { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, |
53 | { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, | 53 | { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, |
54 | + { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, | 54 | + { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, |
55 | { NULL, sBadOption, 0 } | 55 | { NULL, sBadOption, 0 } |
56 | }; | 56 | }; |
57 | 57 | ||
58 | @@ -1654,6 +1659,10 @@ process_server_config_line(ServerOptions *options, char *line, | 58 | @@ -1697,6 +1702,10 @@ process_server_config_line(ServerOptions *options, char *line, |
59 | } | 59 | intptr = &options->fwd_opts.streamlocal_bind_unlink; |
60 | return 0; | 60 | goto parse_flag; |
61 | 61 | ||
62 | + case sDebianBanner: | 62 | + case sDebianBanner: |
63 | + intptr = &options->debian_banner; | 63 | + intptr = &options->debian_banner; |
@@ -67,10 +67,10 @@ index 90de888..37fd2de 100644 | |||
67 | logit("%s line %d: Deprecated option %s", | 67 | logit("%s line %d: Deprecated option %s", |
68 | filename, linenum, arg); | 68 | filename, linenum, arg); |
69 | diff --git a/servconf.h b/servconf.h | 69 | diff --git a/servconf.h b/servconf.h |
70 | index c922eb5..dcd1c2a 100644 | 70 | index f8265a8..fa48804 100644 |
71 | --- a/servconf.h | 71 | --- a/servconf.h |
72 | +++ b/servconf.h | 72 | +++ b/servconf.h |
73 | @@ -186,6 +186,8 @@ typedef struct { | 73 | @@ -188,6 +188,8 @@ typedef struct { |
74 | 74 | ||
75 | u_int num_auth_methods; | 75 | u_int num_auth_methods; |
76 | char *auth_methods[MAX_AUTH_METHODS]; | 76 | char *auth_methods[MAX_AUTH_METHODS]; |
@@ -80,10 +80,10 @@ index c922eb5..dcd1c2a 100644 | |||
80 | 80 | ||
81 | /* Information about the incoming connection as used by Match */ | 81 | /* Information about the incoming connection as used by Match */ |
82 | diff --git a/sshd.c b/sshd.c | 82 | diff --git a/sshd.c b/sshd.c |
83 | index af9b8f1..665c0b9 100644 | 83 | index 1710e71..87331c1 100644 |
84 | --- a/sshd.c | 84 | --- a/sshd.c |
85 | +++ b/sshd.c | 85 | +++ b/sshd.c |
86 | @@ -440,7 +440,8 @@ sshd_exchange_identification(int sock_in, int sock_out) | 86 | @@ -443,7 +443,8 @@ sshd_exchange_identification(int sock_in, int sock_out) |
87 | } | 87 | } |
88 | 88 | ||
89 | xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", | 89 | xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", |
@@ -94,10 +94,10 @@ index af9b8f1..665c0b9 100644 | |||
94 | options.version_addendum, newline); | 94 | options.version_addendum, newline); |
95 | 95 | ||
96 | diff --git a/sshd_config.5 b/sshd_config.5 | 96 | diff --git a/sshd_config.5 b/sshd_config.5 |
97 | index 2164d58..8f078f6 100644 | 97 | index 2843048..58997d3 100644 |
98 | --- a/sshd_config.5 | 98 | --- a/sshd_config.5 |
99 | +++ b/sshd_config.5 | 99 | +++ b/sshd_config.5 |
100 | @@ -413,6 +413,11 @@ or | 100 | @@ -447,6 +447,11 @@ or |
101 | .Dq no . | 101 | .Dq no . |
102 | The default is | 102 | The default is |
103 | .Dq delayed . | 103 | .Dq delayed . |
diff --git a/debian/patches/debian-config.patch b/debian/patches/debian-config.patch index 9ada04a10..661d30ca8 100644 --- a/debian/patches/debian-config.patch +++ b/debian/patches/debian-config.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From df5c8d109fb3d9ec16a487107a44300ed3006849 Mon Sep 17 00:00:00 2001 | 1 | From 762c062828f5a8f6ed189ed6e44ad38fd92f8b36 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:18 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:18 +0000 |
4 | Subject: Various Debian-specific configuration changes | 4 | Subject: Various Debian-specific configuration changes |
@@ -34,10 +34,10 @@ Patch-Name: debian-config.patch | |||
34 | 5 files changed, 51 insertions(+), 3 deletions(-) | 34 | 5 files changed, 51 insertions(+), 3 deletions(-) |
35 | 35 | ||
36 | diff --git a/readconf.c b/readconf.c | 36 | diff --git a/readconf.c b/readconf.c |
37 | index 32c4b42..5429fc2 100644 | 37 | index 0648867..29338b6 100644 |
38 | --- a/readconf.c | 38 | --- a/readconf.c |
39 | +++ b/readconf.c | 39 | +++ b/readconf.c |
40 | @@ -1640,7 +1640,7 @@ fill_default_options(Options * options) | 40 | @@ -1681,7 +1681,7 @@ fill_default_options(Options * options) |
41 | if (options->forward_x11 == -1) | 41 | if (options->forward_x11 == -1) |
42 | options->forward_x11 = 0; | 42 | options->forward_x11 = 0; |
43 | if (options->forward_x11_trusted == -1) | 43 | if (options->forward_x11_trusted == -1) |
@@ -71,7 +71,7 @@ index 228e5ab..c9386aa 100644 | |||
71 | + GSSAPIAuthentication yes | 71 | + GSSAPIAuthentication yes |
72 | + GSSAPIDelegateCredentials no | 72 | + GSSAPIDelegateCredentials no |
73 | diff --git a/ssh_config.5 b/ssh_config.5 | 73 | diff --git a/ssh_config.5 b/ssh_config.5 |
74 | index 1d500e9..22e6372 100644 | 74 | index a1005ba..da3c177 100644 |
75 | --- a/ssh_config.5 | 75 | --- a/ssh_config.5 |
76 | +++ b/ssh_config.5 | 76 | +++ b/ssh_config.5 |
77 | @@ -71,6 +71,22 @@ Since the first obtained value for each parameter is used, more | 77 | @@ -71,6 +71,22 @@ Since the first obtained value for each parameter is used, more |
@@ -97,7 +97,7 @@ index 1d500e9..22e6372 100644 | |||
97 | The configuration file has the following format: | 97 | The configuration file has the following format: |
98 | .Pp | 98 | .Pp |
99 | Empty lines and lines starting with | 99 | Empty lines and lines starting with |
100 | @@ -654,7 +670,8 @@ token used for the session will be set to expire after 20 minutes. | 100 | @@ -673,7 +689,8 @@ token used for the session will be set to expire after 20 minutes. |
101 | Remote clients will be refused access after this time. | 101 | Remote clients will be refused access after this time. |
102 | .Pp | 102 | .Pp |
103 | The default is | 103 | The default is |
@@ -120,7 +120,7 @@ index d9b8594..4db32f5 100644 | |||
120 | #StrictModes yes | 120 | #StrictModes yes |
121 | #MaxAuthTries 6 | 121 | #MaxAuthTries 6 |
122 | diff --git a/sshd_config.5 b/sshd_config.5 | 122 | diff --git a/sshd_config.5 b/sshd_config.5 |
123 | index 908e0bb..90fd3f4 100644 | 123 | index 7396b23..7aa7b47 100644 |
124 | --- a/sshd_config.5 | 124 | --- a/sshd_config.5 |
125 | +++ b/sshd_config.5 | 125 | +++ b/sshd_config.5 |
126 | @@ -57,6 +57,31 @@ Arguments may optionally be enclosed in double quotes | 126 | @@ -57,6 +57,31 @@ Arguments may optionally be enclosed in double quotes |
diff --git a/debian/patches/dnssec-sshfp.patch b/debian/patches/dnssec-sshfp.patch index bc89c50fc..0212ea841 100644 --- a/debian/patches/dnssec-sshfp.patch +++ b/debian/patches/dnssec-sshfp.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 912129ba92bea401d8cdeadc7aa7084fbf7625a1 Mon Sep 17 00:00:00 2001 | 1 | From 4ac9937c1d9f1901ab0694114d76e59a138aae96 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:01 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:01 +0000 |
4 | Subject: Force use of DNSSEC even if "options edns0" isn't in resolv.conf | 4 | Subject: Force use of DNSSEC even if "options edns0" isn't in resolv.conf |
@@ -18,10 +18,10 @@ Patch-Name: dnssec-sshfp.patch | |||
18 | 3 files changed, 21 insertions(+), 6 deletions(-) | 18 | 3 files changed, 21 insertions(+), 6 deletions(-) |
19 | 19 | ||
20 | diff --git a/dns.c b/dns.c | 20 | diff --git a/dns.c b/dns.c |
21 | index 630b97a..478c3d9 100644 | 21 | index c4d073c..e5872c1 100644 |
22 | --- a/dns.c | 22 | --- a/dns.c |
23 | +++ b/dns.c | 23 | +++ b/dns.c |
24 | @@ -196,6 +196,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, | 24 | @@ -203,6 +203,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, |
25 | { | 25 | { |
26 | u_int counter; | 26 | u_int counter; |
27 | int result; | 27 | int result; |
@@ -29,7 +29,7 @@ index 630b97a..478c3d9 100644 | |||
29 | struct rrsetinfo *fingerprints = NULL; | 29 | struct rrsetinfo *fingerprints = NULL; |
30 | 30 | ||
31 | u_int8_t hostkey_algorithm; | 31 | u_int8_t hostkey_algorithm; |
32 | @@ -219,8 +220,19 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, | 32 | @@ -226,8 +227,19 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, |
33 | return -1; | 33 | return -1; |
34 | } | 34 | } |
35 | 35 | ||
diff --git a/debian/patches/doc-hash-tab-completion.patch b/debian/patches/doc-hash-tab-completion.patch index 16c40b05f..8e6cfa575 100644 --- a/debian/patches/doc-hash-tab-completion.patch +++ b/debian/patches/doc-hash-tab-completion.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 1d108ef62050b4368e24e1efada16ec88c177fb8 Mon Sep 17 00:00:00 2001 | 1 | From 2fd0b3814e27d584efa6df92845a7354e7c2de6c Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:11 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:11 +0000 |
4 | Subject: Document that HashKnownHosts may break tab-completion | 4 | Subject: Document that HashKnownHosts may break tab-completion |
@@ -13,10 +13,10 @@ Patch-Name: doc-hash-tab-completion.patch | |||
13 | 1 file changed, 3 insertions(+) | 13 | 1 file changed, 3 insertions(+) |
14 | 14 | ||
15 | diff --git a/ssh_config.5 b/ssh_config.5 | 15 | diff --git a/ssh_config.5 b/ssh_config.5 |
16 | index 4bf7cbb..1d500e9 100644 | 16 | index d68b45a..a1005ba 100644 |
17 | --- a/ssh_config.5 | 17 | --- a/ssh_config.5 |
18 | +++ b/ssh_config.5 | 18 | +++ b/ssh_config.5 |
19 | @@ -740,6 +740,9 @@ Note that existing names and addresses in known hosts files | 19 | @@ -759,6 +759,9 @@ Note that existing names and addresses in known hosts files |
20 | will not be converted automatically, | 20 | will not be converted automatically, |
21 | but may be manually hashed using | 21 | but may be manually hashed using |
22 | .Xr ssh-keygen 1 . | 22 | .Xr ssh-keygen 1 . |
diff --git a/debian/patches/doc-upstart.patch b/debian/patches/doc-upstart.patch index da8fc7ed4..c1ce1bcae 100644 --- a/debian/patches/doc-upstart.patch +++ b/debian/patches/doc-upstart.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 111de26347496af3f6ed04849fd29bc4bf1c2cea Mon Sep 17 00:00:00 2001 | 1 | From 252e76b3ad6e83a798e479a2beba5be7000ff85e Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@ubuntu.com> | 2 | From: Colin Watson <cjwatson@ubuntu.com> |
3 | Date: Sun, 9 Feb 2014 16:10:12 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:12 +0000 |
4 | Subject: Refer to ssh's Upstart job as well as its init script | 4 | Subject: Refer to ssh's Upstart job as well as its init script |
@@ -12,10 +12,10 @@ Patch-Name: doc-upstart.patch | |||
12 | 1 file changed, 4 insertions(+), 1 deletion(-) | 12 | 1 file changed, 4 insertions(+), 1 deletion(-) |
13 | 13 | ||
14 | diff --git a/sshd.8 b/sshd.8 | 14 | diff --git a/sshd.8 b/sshd.8 |
15 | index b016e90..cba168a 100644 | 15 | index 3538208..f8f9eac 100644 |
16 | --- a/sshd.8 | 16 | --- a/sshd.8 |
17 | +++ b/sshd.8 | 17 | +++ b/sshd.8 |
18 | @@ -70,7 +70,10 @@ over an insecure network. | 18 | @@ -67,7 +67,10 @@ over an insecure network. |
19 | .Nm | 19 | .Nm |
20 | listens for connections from clients. | 20 | listens for connections from clients. |
21 | It is normally started at boot from | 21 | It is normally started at boot from |
diff --git a/debian/patches/gnome-ssh-askpass2-icon.patch b/debian/patches/gnome-ssh-askpass2-icon.patch index dab518f65..84fe03acc 100644 --- a/debian/patches/gnome-ssh-askpass2-icon.patch +++ b/debian/patches/gnome-ssh-askpass2-icon.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From b7df8fdb32f3d33b70ff8733cb0c39417e367534 Mon Sep 17 00:00:00 2001 | 1 | From 1195b028cb9f402633cfdcae6ec34bf63b4ab771 Mon Sep 17 00:00:00 2001 |
2 | From: Vincent Untz <vuntz@ubuntu.com> | 2 | From: Vincent Untz <vuntz@ubuntu.com> |
3 | Date: Sun, 9 Feb 2014 16:10:16 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:16 +0000 |
4 | Subject: Give the ssh-askpass-gnome window a default icon | 4 | Subject: Give the ssh-askpass-gnome window a default icon |
diff --git a/debian/patches/gssapi.patch b/debian/patches/gssapi.patch index d8439bf03..e8cbc1083 100644 --- a/debian/patches/gssapi.patch +++ b/debian/patches/gssapi.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 9dfcd1a0e691c1cad34b168e27b3ed31ab6986cd Mon Sep 17 00:00:00 2001 | 1 | From 1c1b6fa17982eb622e2c4e8f4a279f2113f57413 Mon Sep 17 00:00:00 2001 |
2 | From: Simon Wilkinson <simon@sxw.org.uk> | 2 | From: Simon Wilkinson <simon@sxw.org.uk> |
3 | Date: Sun, 9 Feb 2014 16:09:48 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:48 +0000 |
4 | Subject: GSSAPI key exchange support | 4 | Subject: GSSAPI key exchange support |
@@ -17,7 +17,7 @@ have it merged into the main openssh package rather than having separate | |||
17 | security history. | 17 | security history. |
18 | 18 | ||
19 | Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242 | 19 | Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242 |
20 | Last-Updated: 2014-03-19 | 20 | Last-Updated: 2014-10-07 |
21 | 21 | ||
22 | Patch-Name: gssapi.patch | 22 | Patch-Name: gssapi.patch |
23 | --- | 23 | --- |
@@ -36,9 +36,7 @@ Patch-Name: gssapi.patch | |||
36 | kex.c | 16 +++ | 36 | kex.c | 16 +++ |
37 | kex.h | 14 +++ | 37 | kex.h | 14 +++ |
38 | kexgssc.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 38 | kexgssc.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
39 | kexgsss.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++ | 39 | kexgsss.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++ |
40 | key.c | 3 +- | ||
41 | key.h | 1 + | ||
42 | monitor.c | 108 +++++++++++++++++- | 40 | monitor.c | 108 +++++++++++++++++- |
43 | monitor.h | 3 + | 41 | monitor.h | 3 + |
44 | monitor_wrap.c | 47 +++++++- | 42 | monitor_wrap.c | 47 +++++++- |
@@ -54,7 +52,9 @@ Patch-Name: gssapi.patch | |||
54 | sshd.c | 110 ++++++++++++++++++ | 52 | sshd.c | 110 ++++++++++++++++++ |
55 | sshd_config | 2 + | 53 | sshd_config | 2 + |
56 | sshd_config.5 | 28 +++++ | 54 | sshd_config.5 | 28 +++++ |
57 | 33 files changed, 2051 insertions(+), 59 deletions(-) | 55 | sshkey.c | 3 +- |
56 | sshkey.h | 1 + | ||
57 | 33 files changed, 2052 insertions(+), 59 deletions(-) | ||
58 | create mode 100644 ChangeLog.gssapi | 58 | create mode 100644 ChangeLog.gssapi |
59 | create mode 100644 kexgssc.c | 59 | create mode 100644 kexgssc.c |
60 | create mode 100644 kexgsss.c | 60 | create mode 100644 kexgsss.c |
@@ -179,10 +179,10 @@ index 0000000..f117a33 | |||
179 | + (from jbasney AT ncsa.uiuc.edu) | 179 | + (from jbasney AT ncsa.uiuc.edu) |
180 | + <gssapi-with-mic support is Bugzilla #1008> | 180 | + <gssapi-with-mic support is Bugzilla #1008> |
181 | diff --git a/Makefile.in b/Makefile.in | 181 | diff --git a/Makefile.in b/Makefile.in |
182 | index 28a8ec4..ee1d2c3 100644 | 182 | index 06be3d5..086d8dd 100644 |
183 | --- a/Makefile.in | 183 | --- a/Makefile.in |
184 | +++ b/Makefile.in | 184 | +++ b/Makefile.in |
185 | @@ -72,6 +72,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ | 185 | @@ -82,6 +82,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ |
186 | atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ | 186 | atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ |
187 | monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ | 187 | monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ |
188 | kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ | 188 | kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ |
@@ -190,7 +190,7 @@ index 28a8ec4..ee1d2c3 100644 | |||
190 | msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ | 190 | msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ |
191 | ssh-pkcs11.o krl.o smult_curve25519_ref.o \ | 191 | ssh-pkcs11.o krl.o smult_curve25519_ref.o \ |
192 | kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ | 192 | kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ |
193 | @@ -91,7 +92,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ | 193 | @@ -101,7 +102,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ |
194 | auth2-none.o auth2-passwd.o auth2-pubkey.o \ | 194 | auth2-none.o auth2-passwd.o auth2-pubkey.o \ |
195 | monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ | 195 | monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ |
196 | kexc25519s.o auth-krb5.o \ | 196 | kexc25519s.o auth-krb5.o \ |
@@ -200,10 +200,10 @@ index 28a8ec4..ee1d2c3 100644 | |||
200 | sftp-server.o sftp-common.o \ | 200 | sftp-server.o sftp-common.o \ |
201 | roaming_common.o roaming_serv.o \ | 201 | roaming_common.o roaming_serv.o \ |
202 | diff --git a/auth-krb5.c b/auth-krb5.c | 202 | diff --git a/auth-krb5.c b/auth-krb5.c |
203 | index 6c62bdf..69a1a53 100644 | 203 | index 0089b18..ec47869 100644 |
204 | --- a/auth-krb5.c | 204 | --- a/auth-krb5.c |
205 | +++ b/auth-krb5.c | 205 | +++ b/auth-krb5.c |
206 | @@ -182,8 +182,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password) | 206 | @@ -183,8 +183,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password) |
207 | 207 | ||
208 | len = strlen(authctxt->krb5_ticket_file) + 6; | 208 | len = strlen(authctxt->krb5_ticket_file) + 6; |
209 | authctxt->krb5_ccname = xmalloc(len); | 209 | authctxt->krb5_ccname = xmalloc(len); |
@@ -217,7 +217,7 @@ index 6c62bdf..69a1a53 100644 | |||
217 | 217 | ||
218 | #ifdef USE_PAM | 218 | #ifdef USE_PAM |
219 | if (options.use_pam) | 219 | if (options.use_pam) |
220 | @@ -240,15 +245,22 @@ krb5_cleanup_proc(Authctxt *authctxt) | 220 | @@ -241,15 +246,22 @@ krb5_cleanup_proc(Authctxt *authctxt) |
221 | #ifndef HEIMDAL | 221 | #ifndef HEIMDAL |
222 | krb5_error_code | 222 | krb5_error_code |
223 | ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { | 223 | ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { |
@@ -242,7 +242,7 @@ index 6c62bdf..69a1a53 100644 | |||
242 | old_umask = umask(0177); | 242 | old_umask = umask(0177); |
243 | tmpfd = mkstemp(ccname + strlen("FILE:")); | 243 | tmpfd = mkstemp(ccname + strlen("FILE:")); |
244 | oerrno = errno; | 244 | oerrno = errno; |
245 | @@ -265,6 +277,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { | 245 | @@ -266,6 +278,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { |
246 | return oerrno; | 246 | return oerrno; |
247 | } | 247 | } |
248 | close(tmpfd); | 248 | close(tmpfd); |
@@ -251,7 +251,7 @@ index 6c62bdf..69a1a53 100644 | |||
251 | return (krb5_cc_resolve(ctx, ccname, ccache)); | 251 | return (krb5_cc_resolve(ctx, ccname, ccache)); |
252 | } | 252 | } |
253 | diff --git a/auth2-gss.c b/auth2-gss.c | 253 | diff --git a/auth2-gss.c b/auth2-gss.c |
254 | index c28a705..3ff2d72 100644 | 254 | index 447f896..284f364 100644 |
255 | --- a/auth2-gss.c | 255 | --- a/auth2-gss.c |
256 | +++ b/auth2-gss.c | 256 | +++ b/auth2-gss.c |
257 | @@ -1,7 +1,7 @@ | 257 | @@ -1,7 +1,7 @@ |
@@ -263,7 +263,7 @@ index c28a705..3ff2d72 100644 | |||
263 | * | 263 | * |
264 | * Redistribution and use in source and binary forms, with or without | 264 | * Redistribution and use in source and binary forms, with or without |
265 | * modification, are permitted provided that the following conditions | 265 | * modification, are permitted provided that the following conditions |
266 | @@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); | 266 | @@ -53,6 +53,40 @@ static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); |
267 | static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); | 267 | static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); |
268 | static void input_gssapi_errtok(int, u_int32_t, void *); | 268 | static void input_gssapi_errtok(int, u_int32_t, void *); |
269 | 269 | ||
@@ -304,7 +304,7 @@ index c28a705..3ff2d72 100644 | |||
304 | /* | 304 | /* |
305 | * We only support those mechanisms that we know about (ie ones that we know | 305 | * We only support those mechanisms that we know about (ie ones that we know |
306 | * how to check local user kuserok and the like) | 306 | * how to check local user kuserok and the like) |
307 | @@ -235,7 +269,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) | 307 | @@ -236,7 +270,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) |
308 | 308 | ||
309 | packet_check_eom(); | 309 | packet_check_eom(); |
310 | 310 | ||
@@ -314,7 +314,7 @@ index c28a705..3ff2d72 100644 | |||
314 | 314 | ||
315 | authctxt->postponed = 0; | 315 | authctxt->postponed = 0; |
316 | dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); | 316 | dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); |
317 | @@ -270,7 +305,8 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) | 317 | @@ -271,7 +306,8 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) |
318 | gssbuf.length = buffer_len(&b); | 318 | gssbuf.length = buffer_len(&b); |
319 | 319 | ||
320 | if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) | 320 | if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) |
@@ -324,7 +324,7 @@ index c28a705..3ff2d72 100644 | |||
324 | else | 324 | else |
325 | logit("GSSAPI MIC check failed"); | 325 | logit("GSSAPI MIC check failed"); |
326 | 326 | ||
327 | @@ -285,6 +321,12 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) | 327 | @@ -286,6 +322,12 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) |
328 | userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); | 328 | userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); |
329 | } | 329 | } |
330 | 330 | ||
@@ -338,10 +338,10 @@ index c28a705..3ff2d72 100644 | |||
338 | "gssapi-with-mic", | 338 | "gssapi-with-mic", |
339 | userauth_gssapi, | 339 | userauth_gssapi, |
340 | diff --git a/auth2.c b/auth2.c | 340 | diff --git a/auth2.c b/auth2.c |
341 | index a5490c0..fbe3e1b 100644 | 341 | index d9b440a..2f0d565 100644 |
342 | --- a/auth2.c | 342 | --- a/auth2.c |
343 | +++ b/auth2.c | 343 | +++ b/auth2.c |
344 | @@ -69,6 +69,7 @@ extern Authmethod method_passwd; | 344 | @@ -70,6 +70,7 @@ extern Authmethod method_passwd; |
345 | extern Authmethod method_kbdint; | 345 | extern Authmethod method_kbdint; |
346 | extern Authmethod method_hostbased; | 346 | extern Authmethod method_hostbased; |
347 | #ifdef GSSAPI | 347 | #ifdef GSSAPI |
@@ -349,7 +349,7 @@ index a5490c0..fbe3e1b 100644 | |||
349 | extern Authmethod method_gssapi; | 349 | extern Authmethod method_gssapi; |
350 | #endif | 350 | #endif |
351 | 351 | ||
352 | @@ -76,6 +77,7 @@ Authmethod *authmethods[] = { | 352 | @@ -77,6 +78,7 @@ Authmethod *authmethods[] = { |
353 | &method_none, | 353 | &method_none, |
354 | &method_pubkey, | 354 | &method_pubkey, |
355 | #ifdef GSSAPI | 355 | #ifdef GSSAPI |
@@ -358,7 +358,7 @@ index a5490c0..fbe3e1b 100644 | |||
358 | #endif | 358 | #endif |
359 | &method_passwd, | 359 | &method_passwd, |
360 | diff --git a/clientloop.c b/clientloop.c | 360 | diff --git a/clientloop.c b/clientloop.c |
361 | index 59ad3a2..6d8cd7d 100644 | 361 | index 397c965..f9175e3 100644 |
362 | --- a/clientloop.c | 362 | --- a/clientloop.c |
363 | +++ b/clientloop.c | 363 | +++ b/clientloop.c |
364 | @@ -111,6 +111,10 @@ | 364 | @@ -111,6 +111,10 @@ |
@@ -372,7 +372,7 @@ index 59ad3a2..6d8cd7d 100644 | |||
372 | /* import options */ | 372 | /* import options */ |
373 | extern Options options; | 373 | extern Options options; |
374 | 374 | ||
375 | @@ -1608,6 +1612,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | 375 | @@ -1596,6 +1600,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) |
376 | /* Do channel operations unless rekeying in progress. */ | 376 | /* Do channel operations unless rekeying in progress. */ |
377 | if (!rekeying) { | 377 | if (!rekeying) { |
378 | channel_after_select(readset, writeset); | 378 | channel_after_select(readset, writeset); |
@@ -389,7 +389,7 @@ index 59ad3a2..6d8cd7d 100644 | |||
389 | debug("need rekeying"); | 389 | debug("need rekeying"); |
390 | xxx_kex->done = 0; | 390 | xxx_kex->done = 0; |
391 | diff --git a/config.h.in b/config.h.in | 391 | diff --git a/config.h.in b/config.h.in |
392 | index 0401ad1..6bc422c 100644 | 392 | index 16d6206..a9a8b7a 100644 |
393 | --- a/config.h.in | 393 | --- a/config.h.in |
394 | +++ b/config.h.in | 394 | +++ b/config.h.in |
395 | @@ -1622,6 +1622,9 @@ | 395 | @@ -1622,6 +1622,9 @@ |
@@ -413,10 +413,10 @@ index 0401ad1..6bc422c 100644 | |||
413 | #undef USE_SOLARIS_PROCESS_CONTRACTS | 413 | #undef USE_SOLARIS_PROCESS_CONTRACTS |
414 | 414 | ||
415 | diff --git a/configure b/configure | 415 | diff --git a/configure b/configure |
416 | index d690393..b6b5b6d 100755 | 416 | index 6815388..ea5f200 100755 |
417 | --- a/configure | 417 | --- a/configure |
418 | +++ b/configure | 418 | +++ b/configure |
419 | @@ -7170,6 +7170,63 @@ $as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h | 419 | @@ -7168,6 +7168,63 @@ $as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h |
420 | 420 | ||
421 | $as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h | 421 | $as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h |
422 | 422 | ||
@@ -481,7 +481,7 @@ index d690393..b6b5b6d 100755 | |||
481 | ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default" | 481 | ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default" |
482 | if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then : | 482 | if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then : |
483 | diff --git a/configure.ac b/configure.ac | 483 | diff --git a/configure.ac b/configure.ac |
484 | index 7c6ce08..d235fb0 100644 | 484 | index 67c4486..90e81e1 100644 |
485 | --- a/configure.ac | 485 | --- a/configure.ac |
486 | +++ b/configure.ac | 486 | +++ b/configure.ac |
487 | @@ -584,6 +584,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) | 487 | @@ -584,6 +584,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) |
@@ -866,7 +866,7 @@ index b39281b..1e569ad 100644 | |||
866 | + | 866 | + |
867 | #endif /* GSSAPI */ | 867 | #endif /* GSSAPI */ |
868 | diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c | 868 | diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c |
869 | index 759fa10..e678a27 100644 | 869 | index 795992d..fd8b371 100644 |
870 | --- a/gss-serv-krb5.c | 870 | --- a/gss-serv-krb5.c |
871 | +++ b/gss-serv-krb5.c | 871 | +++ b/gss-serv-krb5.c |
872 | @@ -1,7 +1,7 @@ | 872 | @@ -1,7 +1,7 @@ |
@@ -878,7 +878,7 @@ index 759fa10..e678a27 100644 | |||
878 | * | 878 | * |
879 | * Redistribution and use in source and binary forms, with or without | 879 | * Redistribution and use in source and binary forms, with or without |
880 | * modification, are permitted provided that the following conditions | 880 | * modification, are permitted provided that the following conditions |
881 | @@ -120,8 +120,8 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) | 881 | @@ -121,8 +121,8 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) |
882 | krb5_error_code problem; | 882 | krb5_error_code problem; |
883 | krb5_principal princ; | 883 | krb5_principal princ; |
884 | OM_uint32 maj_status, min_status; | 884 | OM_uint32 maj_status, min_status; |
@@ -888,7 +888,7 @@ index 759fa10..e678a27 100644 | |||
888 | 888 | ||
889 | if (client->creds == NULL) { | 889 | if (client->creds == NULL) { |
890 | debug("No credentials stored"); | 890 | debug("No credentials stored"); |
891 | @@ -180,11 +180,16 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) | 891 | @@ -181,11 +181,16 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) |
892 | return; | 892 | return; |
893 | } | 893 | } |
894 | 894 | ||
@@ -909,7 +909,7 @@ index 759fa10..e678a27 100644 | |||
909 | 909 | ||
910 | #ifdef USE_PAM | 910 | #ifdef USE_PAM |
911 | if (options.use_pam) | 911 | if (options.use_pam) |
912 | @@ -196,6 +201,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) | 912 | @@ -197,6 +202,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) |
913 | return; | 913 | return; |
914 | } | 914 | } |
915 | 915 | ||
@@ -981,7 +981,7 @@ index 759fa10..e678a27 100644 | |||
981 | ssh_gssapi_mech gssapi_kerberos_mech = { | 981 | ssh_gssapi_mech gssapi_kerberos_mech = { |
982 | "toWM5Slw5Ew8Mqkay+al2g==", | 982 | "toWM5Slw5Ew8Mqkay+al2g==", |
983 | "Kerberos", | 983 | "Kerberos", |
984 | @@ -203,7 +273,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { | 984 | @@ -204,7 +274,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { |
985 | NULL, | 985 | NULL, |
986 | &ssh_gssapi_krb5_userok, | 986 | &ssh_gssapi_krb5_userok, |
987 | NULL, | 987 | NULL, |
@@ -992,11 +992,11 @@ index 759fa10..e678a27 100644 | |||
992 | 992 | ||
993 | #endif /* KRB5 */ | 993 | #endif /* KRB5 */ |
994 | diff --git a/gss-serv.c b/gss-serv.c | 994 | diff --git a/gss-serv.c b/gss-serv.c |
995 | index e61b37b..c33463b 100644 | 995 | index 5c59924..50fa438 100644 |
996 | --- a/gss-serv.c | 996 | --- a/gss-serv.c |
997 | +++ b/gss-serv.c | 997 | +++ b/gss-serv.c |
998 | @@ -1,7 +1,7 @@ | 998 | @@ -1,7 +1,7 @@ |
999 | /* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */ | 999 | /* $OpenBSD: gss-serv.c,v 1.27 2014/07/03 03:34:09 djm Exp $ */ |
1000 | 1000 | ||
1001 | /* | 1001 | /* |
1002 | - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. | 1002 | - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. |
@@ -1029,7 +1029,7 @@ index e61b37b..c33463b 100644 | |||
1029 | #ifdef KRB5 | 1029 | #ifdef KRB5 |
1030 | extern ssh_gssapi_mech gssapi_kerberos_mech; | 1030 | extern ssh_gssapi_mech gssapi_kerberos_mech; |
1031 | @@ -100,25 +106,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) | 1031 | @@ -100,25 +106,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) |
1032 | char lname[MAXHOSTNAMELEN]; | 1032 | char lname[NI_MAXHOST]; |
1033 | gss_OID_set oidset; | 1033 | gss_OID_set oidset; |
1034 | 1034 | ||
1035 | - gss_create_empty_oid_set(&status, &oidset); | 1035 | - gss_create_empty_oid_set(&status, &oidset); |
@@ -1038,11 +1038,11 @@ index e61b37b..c33463b 100644 | |||
1038 | + gss_create_empty_oid_set(&status, &oidset); | 1038 | + gss_create_empty_oid_set(&status, &oidset); |
1039 | + gss_add_oid_set_member(&status, ctx->oid, &oidset); | 1039 | + gss_add_oid_set_member(&status, ctx->oid, &oidset); |
1040 | 1040 | ||
1041 | - if (gethostname(lname, MAXHOSTNAMELEN)) { | 1041 | - if (gethostname(lname, sizeof(lname))) { |
1042 | - gss_release_oid_set(&status, &oidset); | 1042 | - gss_release_oid_set(&status, &oidset); |
1043 | - return (-1); | 1043 | - return (-1); |
1044 | - } | 1044 | - } |
1045 | + if (gethostname(lname, MAXHOSTNAMELEN)) { | 1045 | + if (gethostname(lname, sizeof(lname))) { |
1046 | + gss_release_oid_set(&status, &oidset); | 1046 | + gss_release_oid_set(&status, &oidset); |
1047 | + return (-1); | 1047 | + return (-1); |
1048 | + } | 1048 | + } |
@@ -1310,10 +1310,10 @@ index e61b37b..c33463b 100644 | |||
1310 | 1310 | ||
1311 | #endif | 1311 | #endif |
1312 | diff --git a/kex.c b/kex.c | 1312 | diff --git a/kex.c b/kex.c |
1313 | index 74e2b86..d114ee3 100644 | 1313 | index a173e70..891852b 100644 |
1314 | --- a/kex.c | 1314 | --- a/kex.c |
1315 | +++ b/kex.c | 1315 | +++ b/kex.c |
1316 | @@ -51,6 +51,10 @@ | 1316 | @@ -53,6 +53,10 @@ |
1317 | #include "roaming.h" | 1317 | #include "roaming.h" |
1318 | #include "digest.h" | 1318 | #include "digest.h" |
1319 | 1319 | ||
@@ -1324,8 +1324,8 @@ index 74e2b86..d114ee3 100644 | |||
1324 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L | 1324 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L |
1325 | # if defined(HAVE_EVP_SHA256) | 1325 | # if defined(HAVE_EVP_SHA256) |
1326 | # define evp_ssh_sha256 EVP_sha256 | 1326 | # define evp_ssh_sha256 EVP_sha256 |
1327 | @@ -92,6 +96,14 @@ static const struct kexalg kexalgs[] = { | 1327 | @@ -96,6 +100,14 @@ static const struct kexalg kexalgs[] = { |
1328 | #endif | 1328 | #endif /* HAVE_EVP_SHA256 */ |
1329 | { NULL, -1, -1, -1}, | 1329 | { NULL, -1, -1, -1}, |
1330 | }; | 1330 | }; |
1331 | +static const struct kexalg kexalg_prefixes[] = { | 1331 | +static const struct kexalg kexalg_prefixes[] = { |
@@ -1339,7 +1339,7 @@ index 74e2b86..d114ee3 100644 | |||
1339 | 1339 | ||
1340 | char * | 1340 | char * |
1341 | kex_alg_list(char sep) | 1341 | kex_alg_list(char sep) |
1342 | @@ -120,6 +132,10 @@ kex_alg_by_name(const char *name) | 1342 | @@ -124,6 +136,10 @@ kex_alg_by_name(const char *name) |
1343 | if (strcmp(k->name, name) == 0) | 1343 | if (strcmp(k->name, name) == 0) |
1344 | return k; | 1344 | return k; |
1345 | } | 1345 | } |
@@ -1351,7 +1351,7 @@ index 74e2b86..d114ee3 100644 | |||
1351 | } | 1351 | } |
1352 | 1352 | ||
1353 | diff --git a/kex.h b/kex.h | 1353 | diff --git a/kex.h b/kex.h |
1354 | index c85680e..ea698c4 100644 | 1354 | index 4c40ec8..c179a4d 100644 |
1355 | --- a/kex.h | 1355 | --- a/kex.h |
1356 | +++ b/kex.h | 1356 | +++ b/kex.h |
1357 | @@ -76,6 +76,9 @@ enum kex_exchange { | 1357 | @@ -76,6 +76,9 @@ enum kex_exchange { |
@@ -1729,10 +1729,10 @@ index 0000000..92a31c5 | |||
1729 | +#endif /* GSSAPI */ | 1729 | +#endif /* GSSAPI */ |
1730 | diff --git a/kexgsss.c b/kexgsss.c | 1730 | diff --git a/kexgsss.c b/kexgsss.c |
1731 | new file mode 100644 | 1731 | new file mode 100644 |
1732 | index 0000000..8095259 | 1732 | index 0000000..6a0ece8 |
1733 | --- /dev/null | 1733 | --- /dev/null |
1734 | +++ b/kexgsss.c | 1734 | +++ b/kexgsss.c |
1735 | @@ -0,0 +1,289 @@ | 1735 | @@ -0,0 +1,290 @@ |
1736 | +/* | 1736 | +/* |
1737 | + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. | 1737 | + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. |
1738 | + * | 1738 | + * |
@@ -1777,6 +1777,7 @@ index 0000000..8095259 | |||
1777 | +#include "dh.h" | 1777 | +#include "dh.h" |
1778 | +#include "ssh-gss.h" | 1778 | +#include "ssh-gss.h" |
1779 | +#include "monitor_wrap.h" | 1779 | +#include "monitor_wrap.h" |
1780 | +#include "misc.h" | ||
1780 | +#include "servconf.h" | 1781 | +#include "servconf.h" |
1781 | + | 1782 | + |
1782 | +extern ServerOptions options; | 1783 | +extern ServerOptions options; |
@@ -2022,44 +2023,11 @@ index 0000000..8095259 | |||
2022 | + ssh_gssapi_rekey_creds(); | 2023 | + ssh_gssapi_rekey_creds(); |
2023 | +} | 2024 | +} |
2024 | +#endif /* GSSAPI */ | 2025 | +#endif /* GSSAPI */ |
2025 | diff --git a/key.c b/key.c | ||
2026 | index 168e1b7..3d640e7 100644 | ||
2027 | --- a/key.c | ||
2028 | +++ b/key.c | ||
2029 | @@ -985,6 +985,7 @@ static const struct keytype keytypes[] = { | ||
2030 | KEY_DSA_CERT_V00, 0, 1 }, | ||
2031 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", | ||
2032 | KEY_ED25519_CERT, 0, 1 }, | ||
2033 | + { "null", "null", KEY_NULL, 0, 0 }, | ||
2034 | { NULL, NULL, -1, -1, 0 } | ||
2035 | }; | ||
2036 | |||
2037 | @@ -1063,7 +1064,7 @@ key_alg_list(int certs_only, int plain_only) | ||
2038 | const struct keytype *kt; | ||
2039 | |||
2040 | for (kt = keytypes; kt->type != -1; kt++) { | ||
2041 | - if (kt->name == NULL) | ||
2042 | + if (kt->name == NULL || kt->type == KEY_NULL) | ||
2043 | continue; | ||
2044 | if ((certs_only && !kt->cert) || (plain_only && kt->cert)) | ||
2045 | continue; | ||
2046 | diff --git a/key.h b/key.h | ||
2047 | index d8ad13d..c8aeba2 100644 | ||
2048 | --- a/key.h | ||
2049 | +++ b/key.h | ||
2050 | @@ -46,6 +46,7 @@ enum types { | ||
2051 | KEY_ED25519_CERT, | ||
2052 | KEY_RSA_CERT_V00, | ||
2053 | KEY_DSA_CERT_V00, | ||
2054 | + KEY_NULL, | ||
2055 | KEY_UNSPEC | ||
2056 | }; | ||
2057 | enum fp_type { | ||
2058 | diff --git a/monitor.c b/monitor.c | 2026 | diff --git a/monitor.c b/monitor.c |
2059 | index 531c4f9..2918814 100644 | 2027 | index dbe29f1..b0896ef 100644 |
2060 | --- a/monitor.c | 2028 | --- a/monitor.c |
2061 | +++ b/monitor.c | 2029 | +++ b/monitor.c |
2062 | @@ -175,6 +175,8 @@ int mm_answer_gss_setup_ctx(int, Buffer *); | 2030 | @@ -178,6 +178,8 @@ int mm_answer_gss_setup_ctx(int, Buffer *); |
2063 | int mm_answer_gss_accept_ctx(int, Buffer *); | 2031 | int mm_answer_gss_accept_ctx(int, Buffer *); |
2064 | int mm_answer_gss_userok(int, Buffer *); | 2032 | int mm_answer_gss_userok(int, Buffer *); |
2065 | int mm_answer_gss_checkmic(int, Buffer *); | 2033 | int mm_answer_gss_checkmic(int, Buffer *); |
@@ -2068,7 +2036,7 @@ index 531c4f9..2918814 100644 | |||
2068 | #endif | 2036 | #endif |
2069 | 2037 | ||
2070 | #ifdef SSH_AUDIT_EVENTS | 2038 | #ifdef SSH_AUDIT_EVENTS |
2071 | @@ -247,11 +249,18 @@ struct mon_table mon_dispatch_proto20[] = { | 2039 | @@ -255,11 +257,18 @@ struct mon_table mon_dispatch_proto20[] = { |
2072 | {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, | 2040 | {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, |
2073 | {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, | 2041 | {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, |
2074 | {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, | 2042 | {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, |
@@ -2084,10 +2052,10 @@ index 531c4f9..2918814 100644 | |||
2084 | + {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, | 2052 | + {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, |
2085 | + {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, | 2053 | + {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, |
2086 | +#endif | 2054 | +#endif |
2055 | #ifdef WITH_OPENSSL | ||
2087 | {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, | 2056 | {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, |
2088 | {MONITOR_REQ_SIGN, 0, mm_answer_sign}, | 2057 | #endif |
2089 | {MONITOR_REQ_PTY, 0, mm_answer_pty}, | 2058 | @@ -374,6 +383,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) |
2090 | @@ -360,6 +369,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | ||
2091 | /* Permit requests for moduli and signatures */ | 2059 | /* Permit requests for moduli and signatures */ |
2092 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); | 2060 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); |
2093 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); | 2061 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
@@ -2098,7 +2066,7 @@ index 531c4f9..2918814 100644 | |||
2098 | } else { | 2066 | } else { |
2099 | mon_dispatch = mon_dispatch_proto15; | 2067 | mon_dispatch = mon_dispatch_proto15; |
2100 | 2068 | ||
2101 | @@ -465,6 +478,10 @@ monitor_child_postauth(struct monitor *pmonitor) | 2069 | @@ -482,6 +495,10 @@ monitor_child_postauth(struct monitor *pmonitor) |
2102 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); | 2070 | monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); |
2103 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); | 2071 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
2104 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); | 2072 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); |
@@ -2109,9 +2077,9 @@ index 531c4f9..2918814 100644 | |||
2109 | } else { | 2077 | } else { |
2110 | mon_dispatch = mon_dispatch_postauth15; | 2078 | mon_dispatch = mon_dispatch_postauth15; |
2111 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); | 2079 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); |
2112 | @@ -1834,6 +1851,13 @@ mm_get_kex(Buffer *m) | 2080 | @@ -1861,6 +1878,13 @@ mm_get_kex(Buffer *m) |
2113 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | ||
2114 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 2081 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
2082 | #endif | ||
2115 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 2083 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
2116 | +#ifdef GSSAPI | 2084 | +#ifdef GSSAPI |
2117 | + if (options.gss_keyex) { | 2085 | + if (options.gss_keyex) { |
@@ -2123,7 +2091,7 @@ index 531c4f9..2918814 100644 | |||
2123 | kex->server = 1; | 2091 | kex->server = 1; |
2124 | kex->hostkey_type = buffer_get_int(m); | 2092 | kex->hostkey_type = buffer_get_int(m); |
2125 | kex->kex_type = buffer_get_int(m); | 2093 | kex->kex_type = buffer_get_int(m); |
2126 | @@ -2041,6 +2065,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m) | 2094 | @@ -2068,6 +2092,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m) |
2127 | OM_uint32 major; | 2095 | OM_uint32 major; |
2128 | u_int len; | 2096 | u_int len; |
2129 | 2097 | ||
@@ -2133,7 +2101,7 @@ index 531c4f9..2918814 100644 | |||
2133 | goid.elements = buffer_get_string(m, &len); | 2101 | goid.elements = buffer_get_string(m, &len); |
2134 | goid.length = len; | 2102 | goid.length = len; |
2135 | 2103 | ||
2136 | @@ -2068,6 +2095,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) | 2104 | @@ -2095,6 +2122,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) |
2137 | OM_uint32 flags = 0; /* GSI needs this */ | 2105 | OM_uint32 flags = 0; /* GSI needs this */ |
2138 | u_int len; | 2106 | u_int len; |
2139 | 2107 | ||
@@ -2143,7 +2111,7 @@ index 531c4f9..2918814 100644 | |||
2143 | in.value = buffer_get_string(m, &len); | 2111 | in.value = buffer_get_string(m, &len); |
2144 | in.length = len; | 2112 | in.length = len; |
2145 | major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); | 2113 | major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); |
2146 | @@ -2085,6 +2115,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) | 2114 | @@ -2112,6 +2142,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) |
2147 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); | 2115 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); |
2148 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); | 2116 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); |
2149 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); | 2117 | monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); |
@@ -2151,7 +2119,7 @@ index 531c4f9..2918814 100644 | |||
2151 | } | 2119 | } |
2152 | return (0); | 2120 | return (0); |
2153 | } | 2121 | } |
2154 | @@ -2096,6 +2127,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m) | 2122 | @@ -2123,6 +2154,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m) |
2155 | OM_uint32 ret; | 2123 | OM_uint32 ret; |
2156 | u_int len; | 2124 | u_int len; |
2157 | 2125 | ||
@@ -2161,7 +2129,7 @@ index 531c4f9..2918814 100644 | |||
2161 | gssbuf.value = buffer_get_string(m, &len); | 2129 | gssbuf.value = buffer_get_string(m, &len); |
2162 | gssbuf.length = len; | 2130 | gssbuf.length = len; |
2163 | mic.value = buffer_get_string(m, &len); | 2131 | mic.value = buffer_get_string(m, &len); |
2164 | @@ -2122,7 +2156,11 @@ mm_answer_gss_userok(int sock, Buffer *m) | 2132 | @@ -2149,7 +2183,11 @@ mm_answer_gss_userok(int sock, Buffer *m) |
2165 | { | 2133 | { |
2166 | int authenticated; | 2134 | int authenticated; |
2167 | 2135 | ||
@@ -2174,7 +2142,7 @@ index 531c4f9..2918814 100644 | |||
2174 | 2142 | ||
2175 | buffer_clear(m); | 2143 | buffer_clear(m); |
2176 | buffer_put_int(m, authenticated); | 2144 | buffer_put_int(m, authenticated); |
2177 | @@ -2135,5 +2173,73 @@ mm_answer_gss_userok(int sock, Buffer *m) | 2145 | @@ -2162,5 +2200,73 @@ mm_answer_gss_userok(int sock, Buffer *m) |
2178 | /* Monitor loop will terminate if authenticated */ | 2146 | /* Monitor loop will terminate if authenticated */ |
2179 | return (authenticated); | 2147 | return (authenticated); |
2180 | } | 2148 | } |
@@ -2263,10 +2231,10 @@ index 5bc41b5..7f32b0c 100644 | |||
2263 | 2231 | ||
2264 | struct mm_master; | 2232 | struct mm_master; |
2265 | diff --git a/monitor_wrap.c b/monitor_wrap.c | 2233 | diff --git a/monitor_wrap.c b/monitor_wrap.c |
2266 | index 1a47e41..60b987d 100644 | 2234 | index 45dc169..e476f0d 100644 |
2267 | --- a/monitor_wrap.c | 2235 | --- a/monitor_wrap.c |
2268 | +++ b/monitor_wrap.c | 2236 | +++ b/monitor_wrap.c |
2269 | @@ -1271,7 +1271,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) | 2237 | @@ -1281,7 +1281,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) |
2270 | } | 2238 | } |
2271 | 2239 | ||
2272 | int | 2240 | int |
@@ -2275,7 +2243,7 @@ index 1a47e41..60b987d 100644 | |||
2275 | { | 2243 | { |
2276 | Buffer m; | 2244 | Buffer m; |
2277 | int authenticated = 0; | 2245 | int authenticated = 0; |
2278 | @@ -1288,5 +1288,50 @@ mm_ssh_gssapi_userok(char *user) | 2246 | @@ -1298,5 +1298,50 @@ mm_ssh_gssapi_userok(char *user) |
2279 | debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); | 2247 | debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); |
2280 | return (authenticated); | 2248 | return (authenticated); |
2281 | } | 2249 | } |
@@ -2343,10 +2311,10 @@ index 18c2501..a4e9d24 100644 | |||
2343 | 2311 | ||
2344 | #ifdef USE_PAM | 2312 | #ifdef USE_PAM |
2345 | diff --git a/readconf.c b/readconf.c | 2313 | diff --git a/readconf.c b/readconf.c |
2346 | index dc884c9..7613ff2 100644 | 2314 | index 7948ce1..9127e93 100644 |
2347 | --- a/readconf.c | 2315 | --- a/readconf.c |
2348 | +++ b/readconf.c | 2316 | +++ b/readconf.c |
2349 | @@ -141,6 +141,8 @@ typedef enum { | 2317 | @@ -142,6 +142,8 @@ typedef enum { |
2350 | oClearAllForwardings, oNoHostAuthenticationForLocalhost, | 2318 | oClearAllForwardings, oNoHostAuthenticationForLocalhost, |
2351 | oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, | 2319 | oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, |
2352 | oAddressFamily, oGssAuthentication, oGssDelegateCreds, | 2320 | oAddressFamily, oGssAuthentication, oGssDelegateCreds, |
@@ -2355,7 +2323,7 @@ index dc884c9..7613ff2 100644 | |||
2355 | oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, | 2323 | oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, |
2356 | oSendEnv, oControlPath, oControlMaster, oControlPersist, | 2324 | oSendEnv, oControlPath, oControlMaster, oControlPersist, |
2357 | oHashKnownHosts, | 2325 | oHashKnownHosts, |
2358 | @@ -183,10 +185,19 @@ static struct { | 2326 | @@ -185,10 +187,19 @@ static struct { |
2359 | { "afstokenpassing", oUnsupported }, | 2327 | { "afstokenpassing", oUnsupported }, |
2360 | #if defined(GSSAPI) | 2328 | #if defined(GSSAPI) |
2361 | { "gssapiauthentication", oGssAuthentication }, | 2329 | { "gssapiauthentication", oGssAuthentication }, |
@@ -2375,7 +2343,7 @@ index dc884c9..7613ff2 100644 | |||
2375 | #endif | 2343 | #endif |
2376 | { "fallbacktorsh", oDeprecated }, | 2344 | { "fallbacktorsh", oDeprecated }, |
2377 | { "usersh", oDeprecated }, | 2345 | { "usersh", oDeprecated }, |
2378 | @@ -841,10 +852,30 @@ parse_time: | 2346 | @@ -865,10 +876,30 @@ parse_time: |
2379 | intptr = &options->gss_authentication; | 2347 | intptr = &options->gss_authentication; |
2380 | goto parse_flag; | 2348 | goto parse_flag; |
2381 | 2349 | ||
@@ -2406,7 +2374,7 @@ index dc884c9..7613ff2 100644 | |||
2406 | case oBatchMode: | 2374 | case oBatchMode: |
2407 | intptr = &options->batch_mode; | 2375 | intptr = &options->batch_mode; |
2408 | goto parse_flag; | 2376 | goto parse_flag; |
2409 | @@ -1497,7 +1528,12 @@ initialize_options(Options * options) | 2377 | @@ -1538,7 +1569,12 @@ initialize_options(Options * options) |
2410 | options->pubkey_authentication = -1; | 2378 | options->pubkey_authentication = -1; |
2411 | options->challenge_response_authentication = -1; | 2379 | options->challenge_response_authentication = -1; |
2412 | options->gss_authentication = -1; | 2380 | options->gss_authentication = -1; |
@@ -2419,7 +2387,7 @@ index dc884c9..7613ff2 100644 | |||
2419 | options->password_authentication = -1; | 2387 | options->password_authentication = -1; |
2420 | options->kbd_interactive_authentication = -1; | 2388 | options->kbd_interactive_authentication = -1; |
2421 | options->kbd_interactive_devices = NULL; | 2389 | options->kbd_interactive_devices = NULL; |
2422 | @@ -1616,8 +1652,14 @@ fill_default_options(Options * options) | 2390 | @@ -1661,8 +1697,14 @@ fill_default_options(Options * options) |
2423 | options->challenge_response_authentication = 1; | 2391 | options->challenge_response_authentication = 1; |
2424 | if (options->gss_authentication == -1) | 2392 | if (options->gss_authentication == -1) |
2425 | options->gss_authentication = 0; | 2393 | options->gss_authentication = 0; |
@@ -2435,10 +2403,10 @@ index dc884c9..7613ff2 100644 | |||
2435 | options->password_authentication = 1; | 2403 | options->password_authentication = 1; |
2436 | if (options->kbd_interactive_authentication == -1) | 2404 | if (options->kbd_interactive_authentication == -1) |
2437 | diff --git a/readconf.h b/readconf.h | 2405 | diff --git a/readconf.h b/readconf.h |
2438 | index 75e3f8f..5cc97f0 100644 | 2406 | index 0b9cb77..0e29889 100644 |
2439 | --- a/readconf.h | 2407 | --- a/readconf.h |
2440 | +++ b/readconf.h | 2408 | +++ b/readconf.h |
2441 | @@ -54,7 +54,12 @@ typedef struct { | 2409 | @@ -45,7 +45,12 @@ typedef struct { |
2442 | int challenge_response_authentication; | 2410 | int challenge_response_authentication; |
2443 | /* Try S/Key or TIS, authentication. */ | 2411 | /* Try S/Key or TIS, authentication. */ |
2444 | int gss_authentication; /* Try GSS authentication */ | 2412 | int gss_authentication; /* Try GSS authentication */ |
@@ -2452,10 +2420,10 @@ index 75e3f8f..5cc97f0 100644 | |||
2452 | * authentication. */ | 2420 | * authentication. */ |
2453 | int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ | 2421 | int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ |
2454 | diff --git a/servconf.c b/servconf.c | 2422 | diff --git a/servconf.c b/servconf.c |
2455 | index 7ba65d5..0083cf8 100644 | 2423 | index b7f3294..cb3c831 100644 |
2456 | --- a/servconf.c | 2424 | --- a/servconf.c |
2457 | +++ b/servconf.c | 2425 | +++ b/servconf.c |
2458 | @@ -108,7 +108,10 @@ initialize_server_options(ServerOptions *options) | 2426 | @@ -109,7 +109,10 @@ initialize_server_options(ServerOptions *options) |
2459 | options->kerberos_ticket_cleanup = -1; | 2427 | options->kerberos_ticket_cleanup = -1; |
2460 | options->kerberos_get_afs_token = -1; | 2428 | options->kerberos_get_afs_token = -1; |
2461 | options->gss_authentication=-1; | 2429 | options->gss_authentication=-1; |
@@ -2466,7 +2434,7 @@ index 7ba65d5..0083cf8 100644 | |||
2466 | options->password_authentication = -1; | 2434 | options->password_authentication = -1; |
2467 | options->kbd_interactive_authentication = -1; | 2435 | options->kbd_interactive_authentication = -1; |
2468 | options->challenge_response_authentication = -1; | 2436 | options->challenge_response_authentication = -1; |
2469 | @@ -244,8 +247,14 @@ fill_default_server_options(ServerOptions *options) | 2437 | @@ -250,8 +253,14 @@ fill_default_server_options(ServerOptions *options) |
2470 | options->kerberos_get_afs_token = 0; | 2438 | options->kerberos_get_afs_token = 0; |
2471 | if (options->gss_authentication == -1) | 2439 | if (options->gss_authentication == -1) |
2472 | options->gss_authentication = 0; | 2440 | options->gss_authentication = 0; |
@@ -2481,7 +2449,7 @@ index 7ba65d5..0083cf8 100644 | |||
2481 | if (options->password_authentication == -1) | 2449 | if (options->password_authentication == -1) |
2482 | options->password_authentication = 1; | 2450 | options->password_authentication = 1; |
2483 | if (options->kbd_interactive_authentication == -1) | 2451 | if (options->kbd_interactive_authentication == -1) |
2484 | @@ -340,7 +349,9 @@ typedef enum { | 2452 | @@ -352,7 +361,9 @@ typedef enum { |
2485 | sBanner, sUseDNS, sHostbasedAuthentication, | 2453 | sBanner, sUseDNS, sHostbasedAuthentication, |
2486 | sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, | 2454 | sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, |
2487 | sClientAliveCountMax, sAuthorizedKeysFile, | 2455 | sClientAliveCountMax, sAuthorizedKeysFile, |
@@ -2492,7 +2460,7 @@ index 7ba65d5..0083cf8 100644 | |||
2492 | sMatch, sPermitOpen, sForceCommand, sChrootDirectory, | 2460 | sMatch, sPermitOpen, sForceCommand, sChrootDirectory, |
2493 | sUsePrivilegeSeparation, sAllowAgentForwarding, | 2461 | sUsePrivilegeSeparation, sAllowAgentForwarding, |
2494 | sHostCertificate, | 2462 | sHostCertificate, |
2495 | @@ -407,10 +418,20 @@ static struct { | 2463 | @@ -421,10 +432,20 @@ static struct { |
2496 | #ifdef GSSAPI | 2464 | #ifdef GSSAPI |
2497 | { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, | 2465 | { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, |
2498 | { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, | 2466 | { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, |
@@ -2513,7 +2481,7 @@ index 7ba65d5..0083cf8 100644 | |||
2513 | { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, | 2481 | { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, |
2514 | { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, | 2482 | { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, |
2515 | { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, | 2483 | { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, |
2516 | @@ -1086,10 +1107,22 @@ process_server_config_line(ServerOptions *options, char *line, | 2484 | @@ -1104,10 +1125,22 @@ process_server_config_line(ServerOptions *options, char *line, |
2517 | intptr = &options->gss_authentication; | 2485 | intptr = &options->gss_authentication; |
2518 | goto parse_flag; | 2486 | goto parse_flag; |
2519 | 2487 | ||
@@ -2536,7 +2504,7 @@ index 7ba65d5..0083cf8 100644 | |||
2536 | case sPasswordAuthentication: | 2504 | case sPasswordAuthentication: |
2537 | intptr = &options->password_authentication; | 2505 | intptr = &options->password_authentication; |
2538 | goto parse_flag; | 2506 | goto parse_flag; |
2539 | @@ -1995,7 +2028,10 @@ dump_config(ServerOptions *o) | 2507 | @@ -2042,7 +2075,10 @@ dump_config(ServerOptions *o) |
2540 | #endif | 2508 | #endif |
2541 | #ifdef GSSAPI | 2509 | #ifdef GSSAPI |
2542 | dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); | 2510 | dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); |
@@ -2548,10 +2516,10 @@ index 7ba65d5..0083cf8 100644 | |||
2548 | dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); | 2516 | dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); |
2549 | dump_cfg_fmtint(sKbdInteractiveAuthentication, | 2517 | dump_cfg_fmtint(sKbdInteractiveAuthentication, |
2550 | diff --git a/servconf.h b/servconf.h | 2518 | diff --git a/servconf.h b/servconf.h |
2551 | index 752d1c5..c922eb5 100644 | 2519 | index 766db3a..f8265a8 100644 |
2552 | --- a/servconf.h | 2520 | --- a/servconf.h |
2553 | +++ b/servconf.h | 2521 | +++ b/servconf.h |
2554 | @@ -112,7 +112,10 @@ typedef struct { | 2522 | @@ -113,7 +113,10 @@ typedef struct { |
2555 | int kerberos_get_afs_token; /* If true, try to get AFS token if | 2523 | int kerberos_get_afs_token; /* If true, try to get AFS token if |
2556 | * authenticated with Kerberos. */ | 2524 | * authenticated with Kerberos. */ |
2557 | int gss_authentication; /* If true, permit GSSAPI authentication */ | 2525 | int gss_authentication; /* If true, permit GSSAPI authentication */ |
@@ -2679,10 +2647,10 @@ index 03a228f..228e5ab 100644 | |||
2679 | # CheckHostIP yes | 2647 | # CheckHostIP yes |
2680 | # AddressFamily any | 2648 | # AddressFamily any |
2681 | diff --git a/ssh_config.5 b/ssh_config.5 | 2649 | diff --git a/ssh_config.5 b/ssh_config.5 |
2682 | index b580392..e7accd6 100644 | 2650 | index f9ede7a..e6649ac 100644 |
2683 | --- a/ssh_config.5 | 2651 | --- a/ssh_config.5 |
2684 | +++ b/ssh_config.5 | 2652 | +++ b/ssh_config.5 |
2685 | @@ -682,11 +682,43 @@ Specifies whether user authentication based on GSSAPI is allowed. | 2653 | @@ -701,11 +701,43 @@ Specifies whether user authentication based on GSSAPI is allowed. |
2686 | The default is | 2654 | The default is |
2687 | .Dq no . | 2655 | .Dq no . |
2688 | Note that this option applies to protocol version 2 only. | 2656 | Note that this option applies to protocol version 2 only. |
@@ -2728,11 +2696,11 @@ index b580392..e7accd6 100644 | |||
2728 | Indicates that | 2696 | Indicates that |
2729 | .Xr ssh 1 | 2697 | .Xr ssh 1 |
2730 | diff --git a/sshconnect2.c b/sshconnect2.c | 2698 | diff --git a/sshconnect2.c b/sshconnect2.c |
2731 | index 7f4ff41..66cb035 100644 | 2699 | index 68f7f4f..7b478f1 100644 |
2732 | --- a/sshconnect2.c | 2700 | --- a/sshconnect2.c |
2733 | +++ b/sshconnect2.c | 2701 | +++ b/sshconnect2.c |
2734 | @@ -158,9 +158,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | 2702 | @@ -159,9 +159,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) |
2735 | { | 2703 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; |
2736 | Kex *kex; | 2704 | Kex *kex; |
2737 | 2705 | ||
2738 | +#ifdef GSSAPI | 2706 | +#ifdef GSSAPI |
@@ -2766,9 +2734,9 @@ index 7f4ff41..66cb035 100644 | |||
2766 | if (options.ciphers == (char *)-1) { | 2734 | if (options.ciphers == (char *)-1) { |
2767 | logit("No valid ciphers for protocol version 2 given, using defaults."); | 2735 | logit("No valid ciphers for protocol version 2 given, using defaults."); |
2768 | options.ciphers = NULL; | 2736 | options.ciphers = NULL; |
2769 | @@ -196,6 +221,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | 2737 | @@ -199,6 +224,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) |
2770 | if (options.kex_algorithms != NULL) | 2738 | myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( |
2771 | myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; | 2739 | myproposal[PROPOSAL_KEX_ALGS]); |
2772 | 2740 | ||
2773 | +#ifdef GSSAPI | 2741 | +#ifdef GSSAPI |
2774 | + /* If we've got GSSAPI algorithms, then we also support the | 2742 | + /* If we've got GSSAPI algorithms, then we also support the |
@@ -2784,9 +2752,9 @@ index 7f4ff41..66cb035 100644 | |||
2784 | if (options.rekey_limit || options.rekey_interval) | 2752 | if (options.rekey_limit || options.rekey_interval) |
2785 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, | 2753 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, |
2786 | (time_t)options.rekey_interval); | 2754 | (time_t)options.rekey_interval); |
2787 | @@ -208,10 +244,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | 2755 | @@ -213,10 +249,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) |
2788 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; | ||
2789 | kex->kex[KEX_ECDH_SHA2] = kexecdh_client; | 2756 | kex->kex[KEX_ECDH_SHA2] = kexecdh_client; |
2757 | #endif | ||
2790 | kex->kex[KEX_C25519_SHA256] = kexc25519_client; | 2758 | kex->kex[KEX_C25519_SHA256] = kexc25519_client; |
2791 | +#ifdef GSSAPI | 2759 | +#ifdef GSSAPI |
2792 | + if (options.gss_keyex) { | 2760 | + if (options.gss_keyex) { |
@@ -2815,7 +2783,7 @@ index 7f4ff41..66cb035 100644 | |||
2815 | xxx_kex = kex; | 2783 | xxx_kex = kex; |
2816 | 2784 | ||
2817 | dispatch_run(DISPATCH_BLOCK, &kex->done, kex); | 2785 | dispatch_run(DISPATCH_BLOCK, &kex->done, kex); |
2818 | @@ -301,6 +357,7 @@ void input_gssapi_token(int type, u_int32_t, void *); | 2786 | @@ -306,6 +362,7 @@ void input_gssapi_token(int type, u_int32_t, void *); |
2819 | void input_gssapi_hash(int type, u_int32_t, void *); | 2787 | void input_gssapi_hash(int type, u_int32_t, void *); |
2820 | void input_gssapi_error(int, u_int32_t, void *); | 2788 | void input_gssapi_error(int, u_int32_t, void *); |
2821 | void input_gssapi_errtok(int, u_int32_t, void *); | 2789 | void input_gssapi_errtok(int, u_int32_t, void *); |
@@ -2823,7 +2791,7 @@ index 7f4ff41..66cb035 100644 | |||
2823 | #endif | 2791 | #endif |
2824 | 2792 | ||
2825 | void userauth(Authctxt *, char *); | 2793 | void userauth(Authctxt *, char *); |
2826 | @@ -316,6 +373,11 @@ static char *authmethods_get(void); | 2794 | @@ -321,6 +378,11 @@ static char *authmethods_get(void); |
2827 | 2795 | ||
2828 | Authmethod authmethods[] = { | 2796 | Authmethod authmethods[] = { |
2829 | #ifdef GSSAPI | 2797 | #ifdef GSSAPI |
@@ -2835,7 +2803,7 @@ index 7f4ff41..66cb035 100644 | |||
2835 | {"gssapi-with-mic", | 2803 | {"gssapi-with-mic", |
2836 | userauth_gssapi, | 2804 | userauth_gssapi, |
2837 | NULL, | 2805 | NULL, |
2838 | @@ -612,19 +674,31 @@ userauth_gssapi(Authctxt *authctxt) | 2806 | @@ -617,19 +679,31 @@ userauth_gssapi(Authctxt *authctxt) |
2839 | static u_int mech = 0; | 2807 | static u_int mech = 0; |
2840 | OM_uint32 min; | 2808 | OM_uint32 min; |
2841 | int ok = 0; | 2809 | int ok = 0; |
@@ -2869,7 +2837,7 @@ index 7f4ff41..66cb035 100644 | |||
2869 | ok = 1; /* Mechanism works */ | 2837 | ok = 1; /* Mechanism works */ |
2870 | } else { | 2838 | } else { |
2871 | mech++; | 2839 | mech++; |
2872 | @@ -721,8 +795,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) | 2840 | @@ -726,8 +800,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) |
2873 | { | 2841 | { |
2874 | Authctxt *authctxt = ctxt; | 2842 | Authctxt *authctxt = ctxt; |
2875 | Gssctxt *gssctxt; | 2843 | Gssctxt *gssctxt; |
@@ -2880,7 +2848,7 @@ index 7f4ff41..66cb035 100644 | |||
2880 | 2848 | ||
2881 | if (authctxt == NULL) | 2849 | if (authctxt == NULL) |
2882 | fatal("input_gssapi_response: no authentication context"); | 2850 | fatal("input_gssapi_response: no authentication context"); |
2883 | @@ -831,6 +905,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt) | 2851 | @@ -836,6 +910,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt) |
2884 | free(msg); | 2852 | free(msg); |
2885 | free(lang); | 2853 | free(lang); |
2886 | } | 2854 | } |
@@ -2930,10 +2898,10 @@ index 7f4ff41..66cb035 100644 | |||
2930 | 2898 | ||
2931 | int | 2899 | int |
2932 | diff --git a/sshd.c b/sshd.c | 2900 | diff --git a/sshd.c b/sshd.c |
2933 | index 7523de9..d787fea 100644 | 2901 | index 481d001..e6706a8 100644 |
2934 | --- a/sshd.c | 2902 | --- a/sshd.c |
2935 | +++ b/sshd.c | 2903 | +++ b/sshd.c |
2936 | @@ -122,6 +122,10 @@ | 2904 | @@ -123,6 +123,10 @@ |
2937 | #include "ssh-sandbox.h" | 2905 | #include "ssh-sandbox.h" |
2938 | #include "version.h" | 2906 | #include "version.h" |
2939 | 2907 | ||
@@ -2941,10 +2909,10 @@ index 7523de9..d787fea 100644 | |||
2941 | +#include <Security/AuthSession.h> | 2909 | +#include <Security/AuthSession.h> |
2942 | +#endif | 2910 | +#endif |
2943 | + | 2911 | + |
2944 | #ifdef LIBWRAP | 2912 | #ifndef O_NOCTTY |
2945 | #include <tcpd.h> | 2913 | #define O_NOCTTY 0 |
2946 | #include <syslog.h> | 2914 | #endif |
2947 | @@ -1728,10 +1732,13 @@ main(int ac, char **av) | 2915 | @@ -1745,10 +1749,13 @@ main(int ac, char **av) |
2948 | logit("Disabling protocol version 1. Could not load host key"); | 2916 | logit("Disabling protocol version 1. Could not load host key"); |
2949 | options.protocol &= ~SSH_PROTO_1; | 2917 | options.protocol &= ~SSH_PROTO_1; |
2950 | } | 2918 | } |
@@ -2958,7 +2926,7 @@ index 7523de9..d787fea 100644 | |||
2958 | if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { | 2926 | if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { |
2959 | logit("sshd: no hostkeys available -- exiting."); | 2927 | logit("sshd: no hostkeys available -- exiting."); |
2960 | exit(1); | 2928 | exit(1); |
2961 | @@ -2058,6 +2065,60 @@ main(int ac, char **av) | 2929 | @@ -2060,6 +2067,60 @@ main(int ac, char **av) |
2962 | remote_ip, remote_port, | 2930 | remote_ip, remote_port, |
2963 | get_local_ipaddr(sock_in), get_local_port()); | 2931 | get_local_ipaddr(sock_in), get_local_port()); |
2964 | 2932 | ||
@@ -3019,7 +2987,7 @@ index 7523de9..d787fea 100644 | |||
3019 | /* | 2987 | /* |
3020 | * We don't want to listen forever unless the other side | 2988 | * We don't want to listen forever unless the other side |
3021 | * successfully authenticates itself. So we set up an alarm which is | 2989 | * successfully authenticates itself. So we set up an alarm which is |
3022 | @@ -2469,6 +2530,48 @@ do_ssh2_kex(void) | 2990 | @@ -2482,6 +2543,48 @@ do_ssh2_kex(void) |
3023 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( | 2991 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( |
3024 | list_hostkey_types()); | 2992 | list_hostkey_types()); |
3025 | 2993 | ||
@@ -3067,10 +3035,10 @@ index 7523de9..d787fea 100644 | |||
3067 | + | 3035 | + |
3068 | /* start key exchange */ | 3036 | /* start key exchange */ |
3069 | kex = kex_setup(myproposal); | 3037 | kex = kex_setup(myproposal); |
3070 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 3038 | #ifdef WITH_OPENSSL |
3071 | @@ -2477,6 +2580,13 @@ do_ssh2_kex(void) | 3039 | @@ -2492,6 +2595,13 @@ do_ssh2_kex(void) |
3072 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | ||
3073 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 3040 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
3041 | #endif | ||
3074 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 3042 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
3075 | +#ifdef GSSAPI | 3043 | +#ifdef GSSAPI |
3076 | + if (options.gss_keyex) { | 3044 | + if (options.gss_keyex) { |
@@ -3096,10 +3064,10 @@ index e9045bc..d9b8594 100644 | |||
3096 | # Set this to 'yes' to enable PAM authentication, account processing, | 3064 | # Set this to 'yes' to enable PAM authentication, account processing, |
3097 | # and session processing. If this is enabled, PAM authentication will | 3065 | # and session processing. If this is enabled, PAM authentication will |
3098 | diff --git a/sshd_config.5 b/sshd_config.5 | 3066 | diff --git a/sshd_config.5 b/sshd_config.5 |
3099 | index ce71efe..ceed88a 100644 | 3067 | index fd44abe..c8b43da 100644 |
3100 | --- a/sshd_config.5 | 3068 | --- a/sshd_config.5 |
3101 | +++ b/sshd_config.5 | 3069 | +++ b/sshd_config.5 |
3102 | @@ -493,12 +493,40 @@ Specifies whether user authentication based on GSSAPI is allowed. | 3070 | @@ -527,12 +527,40 @@ Specifies whether user authentication based on GSSAPI is allowed. |
3103 | The default is | 3071 | The default is |
3104 | .Dq no . | 3072 | .Dq no . |
3105 | Note that this option applies to protocol version 2 only. | 3073 | Note that this option applies to protocol version 2 only. |
@@ -3140,3 +3108,36 @@ index ce71efe..ceed88a 100644 | |||
3140 | .It Cm HostbasedAuthentication | 3108 | .It Cm HostbasedAuthentication |
3141 | Specifies whether rhosts or /etc/hosts.equiv authentication together | 3109 | Specifies whether rhosts or /etc/hosts.equiv authentication together |
3142 | with successful public key client host authentication is allowed | 3110 | with successful public key client host authentication is allowed |
3111 | diff --git a/sshkey.c b/sshkey.c | ||
3112 | index fdd0c8a..1a96eae 100644 | ||
3113 | --- a/sshkey.c | ||
3114 | +++ b/sshkey.c | ||
3115 | @@ -110,6 +110,7 @@ static const struct keytype keytypes[] = { | ||
3116 | { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", | ||
3117 | KEY_DSA_CERT_V00, 0, 1 }, | ||
3118 | #endif /* WITH_OPENSSL */ | ||
3119 | + { "null", "null", KEY_NULL, 0, 0 }, | ||
3120 | { NULL, NULL, -1, -1, 0 } | ||
3121 | }; | ||
3122 | |||
3123 | @@ -198,7 +199,7 @@ key_alg_list(int certs_only, int plain_only) | ||
3124 | const struct keytype *kt; | ||
3125 | |||
3126 | for (kt = keytypes; kt->type != -1; kt++) { | ||
3127 | - if (kt->name == NULL) | ||
3128 | + if (kt->name == NULL || kt->type == KEY_NULL) | ||
3129 | continue; | ||
3130 | if ((certs_only && !kt->cert) || (plain_only && kt->cert)) | ||
3131 | continue; | ||
3132 | diff --git a/sshkey.h b/sshkey.h | ||
3133 | index 450b30c..b573e7f 100644 | ||
3134 | --- a/sshkey.h | ||
3135 | +++ b/sshkey.h | ||
3136 | @@ -64,6 +64,7 @@ enum sshkey_types { | ||
3137 | KEY_ED25519_CERT, | ||
3138 | KEY_RSA_CERT_V00, | ||
3139 | KEY_DSA_CERT_V00, | ||
3140 | + KEY_NULL, | ||
3141 | KEY_UNSPEC | ||
3142 | }; | ||
3143 | |||
diff --git a/debian/patches/helpful-wait-terminate.patch b/debian/patches/helpful-wait-terminate.patch index e79f4990f..de43f2a80 100644 --- a/debian/patches/helpful-wait-terminate.patch +++ b/debian/patches/helpful-wait-terminate.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From ef912859a4300360164292abe47b5516c8ee4a13 Mon Sep 17 00:00:00 2001 | 1 | From aca34215fc0e85d6b49e04f0a3cd0db79732125e Mon Sep 17 00:00:00 2001 |
2 | From: Matthew Vernon <matthew@debian.org> | 2 | From: Matthew Vernon <matthew@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:09:56 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:56 +0000 |
4 | Subject: Mention ~& when waiting for forwarded connections to terminate | 4 | Subject: Mention ~& when waiting for forwarded connections to terminate |
@@ -12,7 +12,7 @@ Patch-Name: helpful-wait-terminate.patch | |||
12 | 1 file changed, 1 insertion(+), 1 deletion(-) | 12 | 1 file changed, 1 insertion(+), 1 deletion(-) |
13 | 13 | ||
14 | diff --git a/serverloop.c b/serverloop.c | 14 | diff --git a/serverloop.c b/serverloop.c |
15 | index 2f8e3a0..441d73b 100644 | 15 | index e92f9e2..813e5bf 100644 |
16 | --- a/serverloop.c | 16 | --- a/serverloop.c |
17 | +++ b/serverloop.c | 17 | +++ b/serverloop.c |
18 | @@ -687,7 +687,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | 18 | @@ -687,7 +687,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) |
diff --git a/debian/patches/keepalive-extensions.patch b/debian/patches/keepalive-extensions.patch index 680701f3d..15acabc0e 100644 --- a/debian/patches/keepalive-extensions.patch +++ b/debian/patches/keepalive-extensions.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 81540b7886fdc73c7be304706ea33d6d87b5fc81 Mon Sep 17 00:00:00 2001 | 1 | From bd3abc2f732da3a61e4158b915480808957a4357 Mon Sep 17 00:00:00 2001 |
2 | From: Richard Kettlewell <rjk@greenend.org.uk> | 2 | From: Richard Kettlewell <rjk@greenend.org.uk> |
3 | Date: Sun, 9 Feb 2014 16:09:52 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:52 +0000 |
4 | Subject: Various keepalive extensions | 4 | Subject: Various keepalive extensions |
@@ -16,7 +16,7 @@ keepalives. | |||
16 | Author: Ian Jackson <ian@chiark.greenend.org.uk> | 16 | Author: Ian Jackson <ian@chiark.greenend.org.uk> |
17 | Author: Matthew Vernon <matthew@debian.org> | 17 | Author: Matthew Vernon <matthew@debian.org> |
18 | Author: Colin Watson <cjwatson@debian.org> | 18 | Author: Colin Watson <cjwatson@debian.org> |
19 | Last-Update: 2013-09-14 | 19 | Last-Update: 2014-10-07 |
20 | 20 | ||
21 | Patch-Name: keepalive-extensions.patch | 21 | Patch-Name: keepalive-extensions.patch |
22 | --- | 22 | --- |
@@ -26,27 +26,27 @@ Patch-Name: keepalive-extensions.patch | |||
26 | 3 files changed, 34 insertions(+), 4 deletions(-) | 26 | 3 files changed, 34 insertions(+), 4 deletions(-) |
27 | 27 | ||
28 | diff --git a/readconf.c b/readconf.c | 28 | diff --git a/readconf.c b/readconf.c |
29 | index bcd8cad..6409937 100644 | 29 | index bc879eb..337818c 100644 |
30 | --- a/readconf.c | 30 | --- a/readconf.c |
31 | +++ b/readconf.c | 31 | +++ b/readconf.c |
32 | @@ -151,6 +151,7 @@ typedef enum { | 32 | @@ -153,6 +153,7 @@ typedef enum { |
33 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, | ||
34 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, | 33 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
35 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, | 34 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
35 | oStreamLocalBindMask, oStreamLocalBindUnlink, | ||
36 | + oProtocolKeepAlives, oSetupTimeOut, | 36 | + oProtocolKeepAlives, oSetupTimeOut, |
37 | oIgnoredUnknownOption, oDeprecated, oUnsupported | 37 | oIgnoredUnknownOption, oDeprecated, oUnsupported |
38 | } OpCodes; | 38 | } OpCodes; |
39 | 39 | ||
40 | @@ -274,6 +275,8 @@ static struct { | 40 | @@ -278,6 +279,8 @@ static struct { |
41 | { "canonicalizemaxdots", oCanonicalizeMaxDots }, | 41 | { "streamlocalbindmask", oStreamLocalBindMask }, |
42 | { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, | 42 | { "streamlocalbindunlink", oStreamLocalBindUnlink }, |
43 | { "ignoreunknown", oIgnoreUnknown }, | 43 | { "ignoreunknown", oIgnoreUnknown }, |
44 | + { "protocolkeepalives", oProtocolKeepAlives }, | 44 | + { "protocolkeepalives", oProtocolKeepAlives }, |
45 | + { "setuptimeout", oSetupTimeOut }, | 45 | + { "setuptimeout", oSetupTimeOut }, |
46 | 46 | ||
47 | { NULL, oBadOption } | 47 | { NULL, oBadOption } |
48 | }; | 48 | }; |
49 | @@ -1247,6 +1250,8 @@ parse_int: | 49 | @@ -1271,6 +1274,8 @@ parse_int: |
50 | goto parse_flag; | 50 | goto parse_flag; |
51 | 51 | ||
52 | case oServerAliveInterval: | 52 | case oServerAliveInterval: |
@@ -55,7 +55,7 @@ index bcd8cad..6409937 100644 | |||
55 | intptr = &options->server_alive_interval; | 55 | intptr = &options->server_alive_interval; |
56 | goto parse_time; | 56 | goto parse_time; |
57 | 57 | ||
58 | @@ -1746,8 +1751,13 @@ fill_default_options(Options * options) | 58 | @@ -1791,8 +1796,13 @@ fill_default_options(Options * options) |
59 | options->rekey_interval = 0; | 59 | options->rekey_interval = 0; |
60 | if (options->verify_host_key_dns == -1) | 60 | if (options->verify_host_key_dns == -1) |
61 | options->verify_host_key_dns = 0; | 61 | options->verify_host_key_dns = 0; |
@@ -72,7 +72,7 @@ index bcd8cad..6409937 100644 | |||
72 | options->server_alive_count_max = 3; | 72 | options->server_alive_count_max = 3; |
73 | if (options->control_master == -1) | 73 | if (options->control_master == -1) |
74 | diff --git a/ssh_config.5 b/ssh_config.5 | 74 | diff --git a/ssh_config.5 b/ssh_config.5 |
75 | index 473971e..3172fd4 100644 | 75 | index 01f1f7f..ea92ea8 100644 |
76 | --- a/ssh_config.5 | 76 | --- a/ssh_config.5 |
77 | +++ b/ssh_config.5 | 77 | +++ b/ssh_config.5 |
78 | @@ -205,8 +205,12 @@ Valid arguments are | 78 | @@ -205,8 +205,12 @@ Valid arguments are |
@@ -89,7 +89,7 @@ index 473971e..3172fd4 100644 | |||
89 | The argument must be | 89 | The argument must be |
90 | .Dq yes | 90 | .Dq yes |
91 | or | 91 | or |
92 | @@ -1305,8 +1309,15 @@ from the server, | 92 | @@ -1336,8 +1340,15 @@ from the server, |
93 | will send a message through the encrypted | 93 | will send a message through the encrypted |
94 | channel to request a response from the server. | 94 | channel to request a response from the server. |
95 | The default | 95 | The default |
@@ -103,10 +103,10 @@ index 473971e..3172fd4 100644 | |||
103 | +and | 103 | +and |
104 | +.Cm SetupTimeOut | 104 | +.Cm SetupTimeOut |
105 | +are Debian-specific compatibility aliases for this option. | 105 | +are Debian-specific compatibility aliases for this option. |
106 | .It Cm StrictHostKeyChecking | 106 | .It Cm StreamLocalBindMask |
107 | If this flag is set to | 107 | Sets the octal file creation mode mask |
108 | .Dq yes , | 108 | .Pq umask |
109 | @@ -1345,6 +1356,12 @@ Specifies whether the system should send TCP keepalive messages to the | 109 | @@ -1403,6 +1414,12 @@ Specifies whether the system should send TCP keepalive messages to the |
110 | other side. | 110 | other side. |
111 | If they are sent, death of the connection or crash of one | 111 | If they are sent, death of the connection or crash of one |
112 | of the machines will be properly noticed. | 112 | of the machines will be properly noticed. |
@@ -120,10 +120,10 @@ index 473971e..3172fd4 100644 | |||
120 | connections will die if the route is down temporarily, and some people | 120 | connections will die if the route is down temporarily, and some people |
121 | find it annoying. | 121 | find it annoying. |
122 | diff --git a/sshd_config.5 b/sshd_config.5 | 122 | diff --git a/sshd_config.5 b/sshd_config.5 |
123 | index ceed88a..2164d58 100644 | 123 | index c8b43da..2843048 100644 |
124 | --- a/sshd_config.5 | 124 | --- a/sshd_config.5 |
125 | +++ b/sshd_config.5 | 125 | +++ b/sshd_config.5 |
126 | @@ -1183,6 +1183,9 @@ This avoids infinitely hanging sessions. | 126 | @@ -1307,6 +1307,9 @@ This avoids infinitely hanging sessions. |
127 | .Pp | 127 | .Pp |
128 | To disable TCP keepalive messages, the value should be set to | 128 | To disable TCP keepalive messages, the value should be set to |
129 | .Dq no . | 129 | .Dq no . |
diff --git a/debian/patches/lintian-symlink-pickiness.patch b/debian/patches/lintian-symlink-pickiness.patch index 09e09ecf8..81b924e35 100644 --- a/debian/patches/lintian-symlink-pickiness.patch +++ b/debian/patches/lintian-symlink-pickiness.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From eb567100ef178f4395c95cc1f37b921e02c3dd5b Mon Sep 17 00:00:00 2001 | 1 | From 248d3bb8de371b55aaf3a8f544c15f3a25eb7339 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:08 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:08 +0000 |
4 | Subject: Fix picky lintian errors about slogin symlinks | 4 | Subject: Fix picky lintian errors about slogin symlinks |
@@ -15,10 +15,10 @@ Patch-Name: lintian-symlink-pickiness.patch | |||
15 | 1 file changed, 2 insertions(+), 2 deletions(-) | 15 | 1 file changed, 2 insertions(+), 2 deletions(-) |
16 | 16 | ||
17 | diff --git a/Makefile.in b/Makefile.in | 17 | diff --git a/Makefile.in b/Makefile.in |
18 | index feee0b2..7d192bb 100644 | 18 | index a4402e9..4eab574 100644 |
19 | --- a/Makefile.in | 19 | --- a/Makefile.in |
20 | +++ b/Makefile.in | 20 | +++ b/Makefile.in |
21 | @@ -293,9 +293,9 @@ install-files: | 21 | @@ -315,9 +315,9 @@ install-files: |
22 | $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 | 22 | $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 |
23 | $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 | 23 | $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 |
24 | -rm -f $(DESTDIR)$(bindir)/slogin | 24 | -rm -f $(DESTDIR)$(bindir)/slogin |
diff --git a/debian/patches/mention-ssh-keygen-on-keychange.patch b/debian/patches/mention-ssh-keygen-on-keychange.patch index e00b6c345..f90c7e2b1 100644 --- a/debian/patches/mention-ssh-keygen-on-keychange.patch +++ b/debian/patches/mention-ssh-keygen-on-keychange.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 8ab8f1465980856291f215c7b7184a4456398fb4 Mon Sep 17 00:00:00 2001 | 1 | From 064453886f4c3d8ac0b0c8d015ad614c8bce3b42 Mon Sep 17 00:00:00 2001 |
2 | From: Scott Moser <smoser@ubuntu.com> | 2 | From: Scott Moser <smoser@ubuntu.com> |
3 | Date: Sun, 9 Feb 2014 16:10:03 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:03 +0000 |
4 | Subject: Mention ssh-keygen in ssh fingerprint changed warning | 4 | Subject: Mention ssh-keygen in ssh fingerprint changed warning |
@@ -13,10 +13,10 @@ Patch-Name: mention-ssh-keygen-on-keychange.patch | |||
13 | 1 file changed, 6 insertions(+), 1 deletion(-) | 13 | 1 file changed, 6 insertions(+), 1 deletion(-) |
14 | 14 | ||
15 | diff --git a/sshconnect.c b/sshconnect.c | 15 | diff --git a/sshconnect.c b/sshconnect.c |
16 | index 9e02837..e0a5db9 100644 | 16 | index 26116d2..ab83d0c 100644 |
17 | --- a/sshconnect.c | 17 | --- a/sshconnect.c |
18 | +++ b/sshconnect.c | 18 | +++ b/sshconnect.c |
19 | @@ -1065,9 +1065,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, | 19 | @@ -1066,9 +1066,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, |
20 | error("%s. This could either mean that", key_msg); | 20 | error("%s. This could either mean that", key_msg); |
21 | error("DNS SPOOFING is happening or the IP address for the host"); | 21 | error("DNS SPOOFING is happening or the IP address for the host"); |
22 | error("and its host key have changed at the same time."); | 22 | error("and its host key have changed at the same time."); |
@@ -30,7 +30,7 @@ index 9e02837..e0a5db9 100644 | |||
30 | } | 30 | } |
31 | /* The host key has changed. */ | 31 | /* The host key has changed. */ |
32 | warn_changed_key(host_key); | 32 | warn_changed_key(host_key); |
33 | @@ -1075,6 +1078,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, | 33 | @@ -1076,6 +1079,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, |
34 | user_hostfiles[0]); | 34 | user_hostfiles[0]); |
35 | error("Offending %s key in %s:%lu", key_type(host_found->key), | 35 | error("Offending %s key in %s:%lu", key_type(host_found->key), |
36 | host_found->file, host_found->line); | 36 | host_found->file, host_found->line); |
diff --git a/debian/patches/no-openssl-version-check.patch b/debian/patches/no-openssl-version-check.patch deleted file mode 100644 index 56fa46aac..000000000 --- a/debian/patches/no-openssl-version-check.patch +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | From 20690ea4b33e8ff81fea287492270df3a7029777 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Hands <phil@hands.com> | ||
3 | Date: Sun, 9 Feb 2014 16:10:14 +0000 | ||
4 | Subject: Disable OpenSSL version check | ||
5 | |||
6 | OpenSSL's SONAME is sufficient nowadays. | ||
7 | |||
8 | Author: Colin Watson <cjwatson@debian.org> | ||
9 | Bug-Debian: http://bugs.debian.org/93581 | ||
10 | Bug-Debian: http://bugs.debian.org/664383 | ||
11 | Forwarded: not-needed | ||
12 | Last-Update: 2013-12-23 | ||
13 | |||
14 | Patch-Name: no-openssl-version-check.patch | ||
15 | --- | ||
16 | entropy.c | 12 ------------ | ||
17 | 1 file changed, 12 deletions(-) | ||
18 | |||
19 | diff --git a/entropy.c b/entropy.c | ||
20 | index 2d483b3..2aee2d9 100644 | ||
21 | --- a/entropy.c | ||
22 | +++ b/entropy.c | ||
23 | @@ -209,18 +209,6 @@ seed_rng(void) | ||
24 | #ifndef OPENSSL_PRNG_ONLY | ||
25 | unsigned char buf[RANDOM_SEED_SIZE]; | ||
26 | #endif | ||
27 | - /* | ||
28 | - * OpenSSL version numbers: MNNFFPPS: major minor fix patch status | ||
29 | - * We match major, minor, fix and status (not patch) for <1.0.0. | ||
30 | - * After that, we acceptable compatible fix versions (so we | ||
31 | - * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed | ||
32 | - * within a patch series. | ||
33 | - */ | ||
34 | - u_long version_mask = SSLeay() >= 0x1000000f ? ~0xffff0L : ~0xff0L; | ||
35 | - if (((SSLeay() ^ OPENSSL_VERSION_NUMBER) & version_mask) || | ||
36 | - (SSLeay() >> 12) < (OPENSSL_VERSION_NUMBER >> 12)) | ||
37 | - fatal("OpenSSL version mismatch. Built against %lx, you " | ||
38 | - "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); | ||
39 | |||
40 | #ifndef OPENSSL_PRNG_ONLY | ||
41 | if (RAND_status() == 1) { | ||
diff --git a/debian/patches/no-openssl-version-status.patch b/debian/patches/no-openssl-version-status.patch new file mode 100644 index 000000000..dfcef83b0 --- /dev/null +++ b/debian/patches/no-openssl-version-status.patch | |||
@@ -0,0 +1,62 @@ | |||
1 | From 37fd625165d0df302e441d9cad9bcc742378eef5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Kurt Roeckx <kurt@roeckx.be> | ||
3 | Date: Sun, 9 Feb 2014 16:10:14 +0000 | ||
4 | Subject: Don't check the status field of the OpenSSL version | ||
5 | |||
6 | There is no reason to check the version of OpenSSL (in Debian). If it's | ||
7 | not compatible the soname will change. OpenSSH seems to want to do a | ||
8 | check for the soname based on the version number, but wants to keep the | ||
9 | status of the release the same. Remove that check on the status since | ||
10 | it doesn't tell you anything about how compatible that version is. | ||
11 | |||
12 | Author: Colin Watson <cjwatson@debian.org> | ||
13 | Bug-Debian: https://bugs.debian.org/93581 | ||
14 | Bug-Debian: https://bugs.debian.org/664383 | ||
15 | Bug-Debian: https://bugs.debian.org/732940 | ||
16 | Forwarded: not-needed | ||
17 | Last-Update: 2014-10-07 | ||
18 | |||
19 | Patch-Name: no-openssl-version-status.patch | ||
20 | --- | ||
21 | openbsd-compat/openssl-compat.c | 6 +++--- | ||
22 | openbsd-compat/regress/opensslvertest.c | 1 + | ||
23 | 2 files changed, 4 insertions(+), 3 deletions(-) | ||
24 | |||
25 | diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c | ||
26 | index 36570e4..defd5fb 100644 | ||
27 | --- a/openbsd-compat/openssl-compat.c | ||
28 | +++ b/openbsd-compat/openssl-compat.c | ||
29 | @@ -34,7 +34,7 @@ | ||
30 | /* | ||
31 | * OpenSSL version numbers: MNNFFPPS: major minor fix patch status | ||
32 | * We match major, minor, fix and status (not patch) for <1.0.0. | ||
33 | - * After that, we acceptable compatible fix versions (so we | ||
34 | + * After that, we accept compatible fix and status versions (so we | ||
35 | * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed | ||
36 | * within a patch series. | ||
37 | */ | ||
38 | @@ -55,10 +55,10 @@ ssh_compatible_openssl(long headerver, long libver) | ||
39 | } | ||
40 | |||
41 | /* | ||
42 | - * For versions >= 1.0.0, major,minor,status must match and library | ||
43 | + * For versions >= 1.0.0, major,minor must match and library | ||
44 | * fix version must be equal to or newer than the header. | ||
45 | */ | ||
46 | - mask = 0xfff0000fL; /* major,minor,status */ | ||
47 | + mask = 0xfff00000L; /* major,minor */ | ||
48 | hfix = (headerver & 0x000ff000) >> 12; | ||
49 | lfix = (libver & 0x000ff000) >> 12; | ||
50 | if ( (headerver & mask) == (libver & mask) && lfix >= hfix) | ||
51 | diff --git a/openbsd-compat/regress/opensslvertest.c b/openbsd-compat/regress/opensslvertest.c | ||
52 | index 5d019b5..5847487 100644 | ||
53 | --- a/openbsd-compat/regress/opensslvertest.c | ||
54 | +++ b/openbsd-compat/regress/opensslvertest.c | ||
55 | @@ -35,6 +35,7 @@ struct version_test { | ||
56 | |||
57 | /* built with 1.0.1b release headers */ | ||
58 | { 0x1000101fL, 0x1000101fL, 1},/* exact match */ | ||
59 | + { 0x1000101fL, 0x10001010L, 1}, /* different status: ok */ | ||
60 | { 0x1000101fL, 0x1000102fL, 1}, /* newer library patch version: ok */ | ||
61 | { 0x1000101fL, 0x1000100fL, 1}, /* older library patch version: ok */ | ||
62 | { 0x1000101fL, 0x1000201fL, 1}, /* newer library fix version: ok */ | ||
diff --git a/debian/patches/openbsd-docs.patch b/debian/patches/openbsd-docs.patch index 9a34a4182..37ad675d4 100644 --- a/debian/patches/openbsd-docs.patch +++ b/debian/patches/openbsd-docs.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From ec9bfd62211fdf5a3004ef2045c2eb3baccfd375 Mon Sep 17 00:00:00 2001 | 1 | From 0b9407d3023938b02bccf7dd1874a871d0cc8eb5 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:09 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:09 +0000 |
4 | Subject: Adjust various OpenBSD-specific references in manual pages | 4 | Subject: Adjust various OpenBSD-specific references in manual pages |
@@ -10,7 +10,7 @@ No single bug reference for this patch, but history includes: | |||
10 | https://bugs.launchpad.net/bugs/456660 (ssl(8)) | 10 | https://bugs.launchpad.net/bugs/456660 (ssl(8)) |
11 | 11 | ||
12 | Forwarded: not-needed | 12 | Forwarded: not-needed |
13 | Last-Update: 2013-09-14 | 13 | Last-Update: 2014-10-07 |
14 | 14 | ||
15 | Patch-Name: openbsd-docs.patch | 15 | Patch-Name: openbsd-docs.patch |
16 | --- | 16 | --- |
@@ -44,7 +44,7 @@ index ef0de08..149846c 100644 | |||
44 | .Sh SEE ALSO | 44 | .Sh SEE ALSO |
45 | .Xr ssh-keygen 1 , | 45 | .Xr ssh-keygen 1 , |
46 | diff --git a/ssh-keygen.1 b/ssh-keygen.1 | 46 | diff --git a/ssh-keygen.1 b/ssh-keygen.1 |
47 | index 12e00d4..a71de74 100644 | 47 | index 723a016..79b948c 100644 |
48 | --- a/ssh-keygen.1 | 48 | --- a/ssh-keygen.1 |
49 | +++ b/ssh-keygen.1 | 49 | +++ b/ssh-keygen.1 |
50 | @@ -172,9 +172,7 @@ key in | 50 | @@ -172,9 +172,7 @@ key in |
@@ -88,10 +88,10 @@ index 12e00d4..a71de74 100644 | |||
88 | The file format is described in | 88 | The file format is described in |
89 | .Xr moduli 5 . | 89 | .Xr moduli 5 . |
90 | diff --git a/ssh.1 b/ssh.1 | 90 | diff --git a/ssh.1 b/ssh.1 |
91 | index ff5e6ac..67b4f44 100644 | 91 | index 7f6ab77..de178cd 100644 |
92 | --- a/ssh.1 | 92 | --- a/ssh.1 |
93 | +++ b/ssh.1 | 93 | +++ b/ssh.1 |
94 | @@ -763,6 +763,10 @@ Protocol 1 is restricted to using only RSA keys, | 94 | @@ -753,6 +753,10 @@ Protocol 1 is restricted to using only RSA keys, |
95 | but protocol 2 may use any. | 95 | but protocol 2 may use any. |
96 | The HISTORY section of | 96 | The HISTORY section of |
97 | .Xr ssl 8 | 97 | .Xr ssl 8 |
@@ -103,10 +103,10 @@ index ff5e6ac..67b4f44 100644 | |||
103 | .Pp | 103 | .Pp |
104 | The file | 104 | The file |
105 | diff --git a/sshd.8 b/sshd.8 | 105 | diff --git a/sshd.8 b/sshd.8 |
106 | index e6a900b..b016e90 100644 | 106 | index eaeac45..3538208 100644 |
107 | --- a/sshd.8 | 107 | --- a/sshd.8 |
108 | +++ b/sshd.8 | 108 | +++ b/sshd.8 |
109 | @@ -70,7 +70,7 @@ over an insecure network. | 109 | @@ -67,7 +67,7 @@ over an insecure network. |
110 | .Nm | 110 | .Nm |
111 | listens for connections from clients. | 111 | listens for connections from clients. |
112 | It is normally started at boot from | 112 | It is normally started at boot from |
@@ -133,14 +133,14 @@ index e6a900b..b016e90 100644 | |||
133 | .Xr sshd_config 5 , | 133 | .Xr sshd_config 5 , |
134 | .Xr inetd 8 , | 134 | .Xr inetd 8 , |
135 | diff --git a/sshd_config.5 b/sshd_config.5 | 135 | diff --git a/sshd_config.5 b/sshd_config.5 |
136 | index 8f078f6..908e0bb 100644 | 136 | index 58997d3..7396b23 100644 |
137 | --- a/sshd_config.5 | 137 | --- a/sshd_config.5 |
138 | +++ b/sshd_config.5 | 138 | +++ b/sshd_config.5 |
139 | @@ -283,8 +283,7 @@ This option is only available for protocol version 2. | 139 | @@ -303,8 +303,7 @@ This option is only available for protocol version 2. |
140 | By default, no banner is displayed. | 140 | By default, no banner is displayed. |
141 | .It Cm ChallengeResponseAuthentication | 141 | .It Cm ChallengeResponseAuthentication |
142 | Specifies whether challenge-response authentication is allowed (e.g. via | 142 | Specifies whether challenge-response authentication is allowed (e.g. via |
143 | -PAM or though authentication styles supported in | 143 | -PAM or through authentication styles supported in |
144 | -.Xr login.conf 5 ) | 144 | -.Xr login.conf 5 ) |
145 | +PAM). | 145 | +PAM). |
146 | The default is | 146 | The default is |
diff --git a/debian/patches/package-versioning.patch b/debian/patches/package-versioning.patch index c9c20d1c0..07a28af9a 100644 --- a/debian/patches/package-versioning.patch +++ b/debian/patches/package-versioning.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 6de70b95f5005447ae23532d4f3ee41a9338479f Mon Sep 17 00:00:00 2001 | 1 | From 8679c96f74ee7dbea6c15c764b036fbab7372740 Mon Sep 17 00:00:00 2001 |
2 | From: Matthew Vernon <matthew@debian.org> | 2 | From: Matthew Vernon <matthew@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:05 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:05 +0000 |
4 | Subject: Include the Debian version in our identification | 4 | Subject: Include the Debian version in our identification |
@@ -19,10 +19,10 @@ Patch-Name: package-versioning.patch | |||
19 | 3 files changed, 9 insertions(+), 4 deletions(-) | 19 | 3 files changed, 9 insertions(+), 4 deletions(-) |
20 | 20 | ||
21 | diff --git a/sshconnect.c b/sshconnect.c | 21 | diff --git a/sshconnect.c b/sshconnect.c |
22 | index e0a5db9..87c3770 100644 | 22 | index ab83d0c..563405e 100644 |
23 | --- a/sshconnect.c | 23 | --- a/sshconnect.c |
24 | +++ b/sshconnect.c | 24 | +++ b/sshconnect.c |
25 | @@ -520,10 +520,10 @@ send_client_banner(int connection_out, int minor1) | 25 | @@ -521,10 +521,10 @@ send_client_banner(int connection_out, int minor1) |
26 | /* Send our own protocol version identification. */ | 26 | /* Send our own protocol version identification. */ |
27 | if (compat20) { | 27 | if (compat20) { |
28 | xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", | 28 | xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", |
@@ -36,10 +36,10 @@ index e0a5db9..87c3770 100644 | |||
36 | if (roaming_atomicio(vwrite, connection_out, client_version_string, | 36 | if (roaming_atomicio(vwrite, connection_out, client_version_string, |
37 | strlen(client_version_string)) != strlen(client_version_string)) | 37 | strlen(client_version_string)) != strlen(client_version_string)) |
38 | diff --git a/sshd.c b/sshd.c | 38 | diff --git a/sshd.c b/sshd.c |
39 | index e343d90..af9b8f1 100644 | 39 | index 48a14dd..1710e71 100644 |
40 | --- a/sshd.c | 40 | --- a/sshd.c |
41 | +++ b/sshd.c | 41 | +++ b/sshd.c |
42 | @@ -440,7 +440,7 @@ sshd_exchange_identification(int sock_in, int sock_out) | 42 | @@ -443,7 +443,7 @@ sshd_exchange_identification(int sock_in, int sock_out) |
43 | } | 43 | } |
44 | 44 | ||
45 | xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", | 45 | xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", |
@@ -49,11 +49,11 @@ index e343d90..af9b8f1 100644 | |||
49 | options.version_addendum, newline); | 49 | options.version_addendum, newline); |
50 | 50 | ||
51 | diff --git a/version.h b/version.h | 51 | diff --git a/version.h b/version.h |
52 | index a1579ac..a97c337 100644 | 52 | index cc8a079..0fee7c3 100644 |
53 | --- a/version.h | 53 | --- a/version.h |
54 | +++ b/version.h | 54 | +++ b/version.h |
55 | @@ -3,4 +3,9 @@ | 55 | @@ -3,4 +3,9 @@ |
56 | #define SSH_VERSION "OpenSSH_6.6" | 56 | #define SSH_VERSION "OpenSSH_6.7" |
57 | 57 | ||
58 | #define SSH_PORTABLE "p1" | 58 | #define SSH_PORTABLE "p1" |
59 | -#define SSH_RELEASE SSH_VERSION SSH_PORTABLE | 59 | -#define SSH_RELEASE SSH_VERSION SSH_PORTABLE |
diff --git a/debian/patches/quieter-signals.patch b/debian/patches/quieter-signals.patch index 075b59823..6d9a2f9c0 100644 --- a/debian/patches/quieter-signals.patch +++ b/debian/patches/quieter-signals.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 9875e47079abff55f8d2c1e958e9d50de6eae7ec Mon Sep 17 00:00:00 2001 | 1 | From dc028c5992b4b14cca380b6ad2115fcc6907a8b7 Mon Sep 17 00:00:00 2001 |
2 | From: Peter Samuelson <peter@p12n.org> | 2 | From: Peter Samuelson <peter@p12n.org> |
3 | Date: Sun, 9 Feb 2014 16:09:55 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:55 +0000 |
4 | Subject: Reduce severity of "Killed by signal %d" | 4 | Subject: Reduce severity of "Killed by signal %d" |
@@ -22,10 +22,10 @@ Patch-Name: quieter-signals.patch | |||
22 | 1 file changed, 4 insertions(+), 2 deletions(-) | 22 | 1 file changed, 4 insertions(+), 2 deletions(-) |
23 | 23 | ||
24 | diff --git a/clientloop.c b/clientloop.c | 24 | diff --git a/clientloop.c b/clientloop.c |
25 | index 73a800c..4bc5b57 100644 | 25 | index 046ca8b..0180774 100644 |
26 | --- a/clientloop.c | 26 | --- a/clientloop.c |
27 | +++ b/clientloop.c | 27 | +++ b/clientloop.c |
28 | @@ -1717,8 +1717,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | 28 | @@ -1705,8 +1705,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) |
29 | exit_status = 0; | 29 | exit_status = 0; |
30 | } | 30 | } |
31 | 31 | ||
diff --git a/debian/patches/restore-tcp-wrappers.patch b/debian/patches/restore-tcp-wrappers.patch new file mode 100644 index 000000000..c590f52ce --- /dev/null +++ b/debian/patches/restore-tcp-wrappers.patch | |||
@@ -0,0 +1,172 @@ | |||
1 | From b25d6dd3b6b5a2cb93723586c56d6fa0277ea56a Mon Sep 17 00:00:00 2001 | ||
2 | From: Colin Watson <cjwatson@debian.org> | ||
3 | Date: Tue, 7 Oct 2014 13:22:41 +0100 | ||
4 | Subject: Restore TCP wrappers support | ||
5 | |||
6 | Support for TCP wrappers was dropped in OpenSSH 6.7. See this message | ||
7 | and thread: | ||
8 | |||
9 | https://lists.mindrot.org/pipermail/openssh-unix-dev/2014-April/032497.html | ||
10 | |||
11 | It is true that this reduces preauth attack surface in sshd. On the | ||
12 | other hand, this support seems to be quite widely used, and abruptly | ||
13 | dropping it (from the perspective of users who don't read | ||
14 | openssh-unix-dev) could easily cause more serious problems in practice. | ||
15 | |||
16 | It's not entirely clear what the right long-term answer for Debian is, | ||
17 | but it at least probably doesn't involve dropping this feature shortly | ||
18 | before a freeze. | ||
19 | |||
20 | Forwarded: not-needed | ||
21 | Last-Update: 2014-10-07 | ||
22 | |||
23 | Patch-Name: restore-tcp-wrappers.patch | ||
24 | --- | ||
25 | configure.ac | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
26 | sshd.8 | 7 +++++++ | ||
27 | sshd.c | 25 +++++++++++++++++++++++++ | ||
28 | 3 files changed, 89 insertions(+) | ||
29 | |||
30 | diff --git a/configure.ac b/configure.ac | ||
31 | index 90e81e1..7f160f1 100644 | ||
32 | --- a/configure.ac | ||
33 | +++ b/configure.ac | ||
34 | @@ -1404,6 +1404,62 @@ AC_ARG_WITH([skey], | ||
35 | ] | ||
36 | ) | ||
37 | |||
38 | +# Check whether user wants TCP wrappers support | ||
39 | +TCPW_MSG="no" | ||
40 | +AC_ARG_WITH([tcp-wrappers], | ||
41 | + [ --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)], | ||
42 | + [ | ||
43 | + if test "x$withval" != "xno" ; then | ||
44 | + saved_LIBS="$LIBS" | ||
45 | + saved_LDFLAGS="$LDFLAGS" | ||
46 | + saved_CPPFLAGS="$CPPFLAGS" | ||
47 | + if test -n "${withval}" && \ | ||
48 | + test "x${withval}" != "xyes"; then | ||
49 | + if test -d "${withval}/lib"; then | ||
50 | + if test -n "${need_dash_r}"; then | ||
51 | + LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" | ||
52 | + else | ||
53 | + LDFLAGS="-L${withval}/lib ${LDFLAGS}" | ||
54 | + fi | ||
55 | + else | ||
56 | + if test -n "${need_dash_r}"; then | ||
57 | + LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" | ||
58 | + else | ||
59 | + LDFLAGS="-L${withval} ${LDFLAGS}" | ||
60 | + fi | ||
61 | + fi | ||
62 | + if test -d "${withval}/include"; then | ||
63 | + CPPFLAGS="-I${withval}/include ${CPPFLAGS}" | ||
64 | + else | ||
65 | + CPPFLAGS="-I${withval} ${CPPFLAGS}" | ||
66 | + fi | ||
67 | + fi | ||
68 | + LIBS="-lwrap $LIBS" | ||
69 | + AC_MSG_CHECKING([for libwrap]) | ||
70 | + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ | ||
71 | +#include <sys/types.h> | ||
72 | +#include <sys/socket.h> | ||
73 | +#include <netinet/in.h> | ||
74 | +#include <tcpd.h> | ||
75 | +int deny_severity = 0, allow_severity = 0; | ||
76 | + ]], [[ | ||
77 | + hosts_access(0); | ||
78 | + ]])], [ | ||
79 | + AC_MSG_RESULT([yes]) | ||
80 | + AC_DEFINE([LIBWRAP], [1], | ||
81 | + [Define if you want | ||
82 | + TCP Wrappers support]) | ||
83 | + SSHDLIBS="$SSHDLIBS -lwrap" | ||
84 | + TCPW_MSG="yes" | ||
85 | + ], [ | ||
86 | + AC_MSG_ERROR([*** libwrap missing]) | ||
87 | + | ||
88 | + ]) | ||
89 | + LIBS="$saved_LIBS" | ||
90 | + fi | ||
91 | + ] | ||
92 | +) | ||
93 | + | ||
94 | # Check whether user wants to use ldns | ||
95 | LDNS_MSG="no" | ||
96 | AC_ARG_WITH(ldns, | ||
97 | @@ -4853,6 +4909,7 @@ echo " KerberosV support: $KRB5_MSG" | ||
98 | echo " SELinux support: $SELINUX_MSG" | ||
99 | echo " Smartcard support: $SCARD_MSG" | ||
100 | echo " S/KEY support: $SKEY_MSG" | ||
101 | +echo " TCP Wrappers support: $TCPW_MSG" | ||
102 | echo " MD5 password support: $MD5_MSG" | ||
103 | echo " libedit support: $LIBEDIT_MSG" | ||
104 | echo " Solaris process contract support: $SPC_MSG" | ||
105 | diff --git a/sshd.8 b/sshd.8 | ||
106 | index 01459d6..eaeac45 100644 | ||
107 | --- a/sshd.8 | ||
108 | +++ b/sshd.8 | ||
109 | @@ -851,6 +851,12 @@ the user's home directory becomes accessible. | ||
110 | This file should be writable only by the user, and need not be | ||
111 | readable by anyone else. | ||
112 | .Pp | ||
113 | +.It Pa /etc/hosts.allow | ||
114 | +.It Pa /etc/hosts.deny | ||
115 | +Access controls that should be enforced by tcp-wrappers are defined here. | ||
116 | +Further details are described in | ||
117 | +.Xr hosts_access 5 . | ||
118 | +.Pp | ||
119 | .It Pa /etc/hosts.equiv | ||
120 | This file is for host-based authentication (see | ||
121 | .Xr ssh 1 ) . | ||
122 | @@ -954,6 +960,7 @@ The content of this file is not sensitive; it can be world-readable. | ||
123 | .Xr ssh-keygen 1 , | ||
124 | .Xr ssh-keyscan 1 , | ||
125 | .Xr chroot 2 , | ||
126 | +.Xr hosts_access 5 , | ||
127 | .Xr login.conf 5 , | ||
128 | .Xr moduli 5 , | ||
129 | .Xr sshd_config 5 , | ||
130 | diff --git a/sshd.c b/sshd.c | ||
131 | index e6706a8..3a6be65 100644 | ||
132 | --- a/sshd.c | ||
133 | +++ b/sshd.c | ||
134 | @@ -127,6 +127,13 @@ | ||
135 | #include <Security/AuthSession.h> | ||
136 | #endif | ||
137 | |||
138 | +#ifdef LIBWRAP | ||
139 | +#include <tcpd.h> | ||
140 | +#include <syslog.h> | ||
141 | +int allow_severity; | ||
142 | +int deny_severity; | ||
143 | +#endif /* LIBWRAP */ | ||
144 | + | ||
145 | #ifndef O_NOCTTY | ||
146 | #define O_NOCTTY 0 | ||
147 | #endif | ||
148 | @@ -2061,6 +2068,24 @@ main(int ac, char **av) | ||
149 | #ifdef SSH_AUDIT_EVENTS | ||
150 | audit_connection_from(remote_ip, remote_port); | ||
151 | #endif | ||
152 | +#ifdef LIBWRAP | ||
153 | + allow_severity = options.log_facility|LOG_INFO; | ||
154 | + deny_severity = options.log_facility|LOG_WARNING; | ||
155 | + /* Check whether logins are denied from this host. */ | ||
156 | + if (packet_connection_is_on_socket()) { | ||
157 | + struct request_info req; | ||
158 | + | ||
159 | + request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); | ||
160 | + fromhost(&req); | ||
161 | + | ||
162 | + if (!hosts_access(&req)) { | ||
163 | + debug("Connection refused by tcp wrapper"); | ||
164 | + refuse(&req); | ||
165 | + /* NOTREACHED */ | ||
166 | + fatal("libwrap refuse returns"); | ||
167 | + } | ||
168 | + } | ||
169 | +#endif /* LIBWRAP */ | ||
170 | |||
171 | /* Log the connection. */ | ||
172 | verbose("Connection from %s port %d on %s port %d", | ||
diff --git a/debian/patches/scp-quoting.patch b/debian/patches/scp-quoting.patch index ff037a43a..ee006da93 100644 --- a/debian/patches/scp-quoting.patch +++ b/debian/patches/scp-quoting.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 8ab204ee192e655d5a8f4d599adb3d99eeabedc6 Mon Sep 17 00:00:00 2001 | 1 | From fd174c13c46191abdb33c0a45545573a8e06b061 Mon Sep 17 00:00:00 2001 |
2 | From: =?UTF-8?q?Nicolas=20Valc=C3=A1rcel?= <nvalcarcel@ubuntu.com> | 2 | From: =?UTF-8?q?Nicolas=20Valc=C3=A1rcel?= <nvalcarcel@ubuntu.com> |
3 | Date: Sun, 9 Feb 2014 16:09:59 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:59 +0000 |
4 | Subject: Adjust scp quoting in verbose mode | 4 | Subject: Adjust scp quoting in verbose mode |
@@ -17,7 +17,7 @@ Patch-Name: scp-quoting.patch | |||
17 | 1 file changed, 10 insertions(+), 2 deletions(-) | 17 | 1 file changed, 10 insertions(+), 2 deletions(-) |
18 | 18 | ||
19 | diff --git a/scp.c b/scp.c | 19 | diff --git a/scp.c b/scp.c |
20 | index 18d3b1d..0669d02 100644 | 20 | index 1ec3b70..a1b318b 100644 |
21 | --- a/scp.c | 21 | --- a/scp.c |
22 | +++ b/scp.c | 22 | +++ b/scp.c |
23 | @@ -189,8 +189,16 @@ do_local_cmd(arglist *a) | 23 | @@ -189,8 +189,16 @@ do_local_cmd(arglist *a) |
diff --git a/debian/patches/selinux-role.patch b/debian/patches/selinux-role.patch index e0ca12fb0..1fa0bf928 100644 --- a/debian/patches/selinux-role.patch +++ b/debian/patches/selinux-role.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From ae32d626ed3d15cfd7f432358b63c005961921df Mon Sep 17 00:00:00 2001 | 1 | From c9638aa44d787849cea1ae273f0908c6313fd19b Mon Sep 17 00:00:00 2001 |
2 | From: Manoj Srivastava <srivasta@debian.org> | 2 | From: Manoj Srivastava <srivasta@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:09:49 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:49 +0000 |
4 | Subject: Handle SELinux authorisation roles | 4 | Subject: Handle SELinux authorisation roles |
@@ -32,7 +32,7 @@ Patch-Name: selinux-role.patch | |||
32 | 16 files changed, 104 insertions(+), 31 deletions(-) | 32 | 16 files changed, 104 insertions(+), 31 deletions(-) |
33 | 33 | ||
34 | diff --git a/auth.h b/auth.h | 34 | diff --git a/auth.h b/auth.h |
35 | index 124e597..79e4ea5 100644 | 35 | index d081c94..f099e98 100644 |
36 | --- a/auth.h | 36 | --- a/auth.h |
37 | +++ b/auth.h | 37 | +++ b/auth.h |
38 | @@ -59,6 +59,7 @@ struct Authctxt { | 38 | @@ -59,6 +59,7 @@ struct Authctxt { |
@@ -44,10 +44,10 @@ index 124e597..79e4ea5 100644 | |||
44 | char *info; /* Extra info for next auth_log */ | 44 | char *info; /* Extra info for next auth_log */ |
45 | #ifdef BSD_AUTH | 45 | #ifdef BSD_AUTH |
46 | diff --git a/auth1.c b/auth1.c | 46 | diff --git a/auth1.c b/auth1.c |
47 | index 0f870b3..c707390 100644 | 47 | index 5038828..52b17db 100644 |
48 | --- a/auth1.c | 48 | --- a/auth1.c |
49 | +++ b/auth1.c | 49 | +++ b/auth1.c |
50 | @@ -380,7 +380,7 @@ void | 50 | @@ -381,7 +381,7 @@ void |
51 | do_authentication(Authctxt *authctxt) | 51 | do_authentication(Authctxt *authctxt) |
52 | { | 52 | { |
53 | u_int ulen; | 53 | u_int ulen; |
@@ -56,7 +56,7 @@ index 0f870b3..c707390 100644 | |||
56 | 56 | ||
57 | /* Get the name of the user that we wish to log in as. */ | 57 | /* Get the name of the user that we wish to log in as. */ |
58 | packet_read_expect(SSH_CMSG_USER); | 58 | packet_read_expect(SSH_CMSG_USER); |
59 | @@ -389,11 +389,17 @@ do_authentication(Authctxt *authctxt) | 59 | @@ -390,11 +390,17 @@ do_authentication(Authctxt *authctxt) |
60 | user = packet_get_cstring(&ulen); | 60 | user = packet_get_cstring(&ulen); |
61 | packet_check_eom(); | 61 | packet_check_eom(); |
62 | 62 | ||
@@ -75,10 +75,10 @@ index 0f870b3..c707390 100644 | |||
75 | /* Verify that the user is a valid user. */ | 75 | /* Verify that the user is a valid user. */ |
76 | if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) | 76 | if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) |
77 | diff --git a/auth2.c b/auth2.c | 77 | diff --git a/auth2.c b/auth2.c |
78 | index fbe3e1b..70f2925 100644 | 78 | index 2f0d565..fa1a588 100644 |
79 | --- a/auth2.c | 79 | --- a/auth2.c |
80 | +++ b/auth2.c | 80 | +++ b/auth2.c |
81 | @@ -216,7 +216,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) | 81 | @@ -217,7 +217,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) |
82 | { | 82 | { |
83 | Authctxt *authctxt = ctxt; | 83 | Authctxt *authctxt = ctxt; |
84 | Authmethod *m = NULL; | 84 | Authmethod *m = NULL; |
@@ -87,7 +87,7 @@ index fbe3e1b..70f2925 100644 | |||
87 | int authenticated = 0; | 87 | int authenticated = 0; |
88 | 88 | ||
89 | if (authctxt == NULL) | 89 | if (authctxt == NULL) |
90 | @@ -228,8 +228,13 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) | 90 | @@ -229,8 +229,13 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) |
91 | debug("userauth-request for user %s service %s method %s", user, service, method); | 91 | debug("userauth-request for user %s service %s method %s", user, service, method); |
92 | debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); | 92 | debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); |
93 | 93 | ||
@@ -101,7 +101,7 @@ index fbe3e1b..70f2925 100644 | |||
101 | 101 | ||
102 | if (authctxt->attempt++ == 0) { | 102 | if (authctxt->attempt++ == 0) { |
103 | /* setup auth context */ | 103 | /* setup auth context */ |
104 | @@ -253,8 +258,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) | 104 | @@ -254,8 +259,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) |
105 | use_privsep ? " [net]" : ""); | 105 | use_privsep ? " [net]" : ""); |
106 | authctxt->service = xstrdup(service); | 106 | authctxt->service = xstrdup(service); |
107 | authctxt->style = style ? xstrdup(style) : NULL; | 107 | authctxt->style = style ? xstrdup(style) : NULL; |
@@ -113,10 +113,10 @@ index fbe3e1b..70f2925 100644 | |||
113 | if (auth2_setup_methods_lists(authctxt) != 0) | 113 | if (auth2_setup_methods_lists(authctxt) != 0) |
114 | packet_disconnect("no authentication methods enabled"); | 114 | packet_disconnect("no authentication methods enabled"); |
115 | diff --git a/monitor.c b/monitor.c | 115 | diff --git a/monitor.c b/monitor.c |
116 | index 2918814..11eac63 100644 | 116 | index b0896ef..94b194d 100644 |
117 | --- a/monitor.c | 117 | --- a/monitor.c |
118 | +++ b/monitor.c | 118 | +++ b/monitor.c |
119 | @@ -145,6 +145,7 @@ int mm_answer_sign(int, Buffer *); | 119 | @@ -148,6 +148,7 @@ int mm_answer_sign(int, Buffer *); |
120 | int mm_answer_pwnamallow(int, Buffer *); | 120 | int mm_answer_pwnamallow(int, Buffer *); |
121 | int mm_answer_auth2_read_banner(int, Buffer *); | 121 | int mm_answer_auth2_read_banner(int, Buffer *); |
122 | int mm_answer_authserv(int, Buffer *); | 122 | int mm_answer_authserv(int, Buffer *); |
@@ -124,7 +124,7 @@ index 2918814..11eac63 100644 | |||
124 | int mm_answer_authpassword(int, Buffer *); | 124 | int mm_answer_authpassword(int, Buffer *); |
125 | int mm_answer_bsdauthquery(int, Buffer *); | 125 | int mm_answer_bsdauthquery(int, Buffer *); |
126 | int mm_answer_bsdauthrespond(int, Buffer *); | 126 | int mm_answer_bsdauthrespond(int, Buffer *); |
127 | @@ -221,6 +222,7 @@ struct mon_table mon_dispatch_proto20[] = { | 127 | @@ -229,6 +230,7 @@ struct mon_table mon_dispatch_proto20[] = { |
128 | {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, | 128 | {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, |
129 | {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, | 129 | {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, |
130 | {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, | 130 | {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, |
@@ -132,7 +132,7 @@ index 2918814..11eac63 100644 | |||
132 | {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, | 132 | {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, |
133 | {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, | 133 | {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, |
134 | #ifdef USE_PAM | 134 | #ifdef USE_PAM |
135 | @@ -822,6 +824,7 @@ mm_answer_pwnamallow(int sock, Buffer *m) | 135 | @@ -841,6 +843,7 @@ mm_answer_pwnamallow(int sock, Buffer *m) |
136 | else { | 136 | else { |
137 | /* Allow service/style information on the auth context */ | 137 | /* Allow service/style information on the auth context */ |
138 | monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); | 138 | monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); |
@@ -140,7 +140,7 @@ index 2918814..11eac63 100644 | |||
140 | monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); | 140 | monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); |
141 | } | 141 | } |
142 | #ifdef USE_PAM | 142 | #ifdef USE_PAM |
143 | @@ -852,14 +855,37 @@ mm_answer_authserv(int sock, Buffer *m) | 143 | @@ -871,14 +874,37 @@ mm_answer_authserv(int sock, Buffer *m) |
144 | 144 | ||
145 | authctxt->service = buffer_get_string(m, NULL); | 145 | authctxt->service = buffer_get_string(m, NULL); |
146 | authctxt->style = buffer_get_string(m, NULL); | 146 | authctxt->style = buffer_get_string(m, NULL); |
@@ -180,7 +180,7 @@ index 2918814..11eac63 100644 | |||
180 | return (0); | 180 | return (0); |
181 | } | 181 | } |
182 | 182 | ||
183 | @@ -1464,7 +1490,7 @@ mm_answer_pty(int sock, Buffer *m) | 183 | @@ -1485,7 +1511,7 @@ mm_answer_pty(int sock, Buffer *m) |
184 | res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); | 184 | res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); |
185 | if (res == 0) | 185 | if (res == 0) |
186 | goto error; | 186 | goto error; |
@@ -203,10 +203,10 @@ index 7f32b0c..4d5e8fa 100644 | |||
203 | 203 | ||
204 | struct mm_master; | 204 | struct mm_master; |
205 | diff --git a/monitor_wrap.c b/monitor_wrap.c | 205 | diff --git a/monitor_wrap.c b/monitor_wrap.c |
206 | index 60b987d..f75dc9d 100644 | 206 | index e476f0d..6dc890a 100644 |
207 | --- a/monitor_wrap.c | 207 | --- a/monitor_wrap.c |
208 | +++ b/monitor_wrap.c | 208 | +++ b/monitor_wrap.c |
209 | @@ -318,10 +318,10 @@ mm_auth2_read_banner(void) | 209 | @@ -324,10 +324,10 @@ mm_auth2_read_banner(void) |
210 | return (banner); | 210 | return (banner); |
211 | } | 211 | } |
212 | 212 | ||
@@ -219,7 +219,7 @@ index 60b987d..f75dc9d 100644 | |||
219 | { | 219 | { |
220 | Buffer m; | 220 | Buffer m; |
221 | 221 | ||
222 | @@ -330,12 +330,30 @@ mm_inform_authserv(char *service, char *style) | 222 | @@ -336,12 +336,30 @@ mm_inform_authserv(char *service, char *style) |
223 | buffer_init(&m); | 223 | buffer_init(&m); |
224 | buffer_put_cstring(&m, service); | 224 | buffer_put_cstring(&m, service); |
225 | buffer_put_cstring(&m, style ? style : ""); | 225 | buffer_put_cstring(&m, style ? style : ""); |
@@ -361,10 +361,10 @@ index e3d1004..80ce13a 100644 | |||
361 | void ssh_selinux_setfscreatecon(const char *); | 361 | void ssh_selinux_setfscreatecon(const char *); |
362 | #endif | 362 | #endif |
363 | diff --git a/platform.c b/platform.c | 363 | diff --git a/platform.c b/platform.c |
364 | index 30fc609..4aab9a9 100644 | 364 | index ee313da..f35ec39 100644 |
365 | --- a/platform.c | 365 | --- a/platform.c |
366 | +++ b/platform.c | 366 | +++ b/platform.c |
367 | @@ -142,7 +142,7 @@ platform_setusercontext(struct passwd *pw) | 367 | @@ -143,7 +143,7 @@ platform_setusercontext(struct passwd *pw) |
368 | * called if sshd is running as root. | 368 | * called if sshd is running as root. |
369 | */ | 369 | */ |
370 | void | 370 | void |
@@ -373,7 +373,7 @@ index 30fc609..4aab9a9 100644 | |||
373 | { | 373 | { |
374 | #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) | 374 | #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) |
375 | /* | 375 | /* |
376 | @@ -183,7 +183,7 @@ platform_setusercontext_post_groups(struct passwd *pw) | 376 | @@ -184,7 +184,7 @@ platform_setusercontext_post_groups(struct passwd *pw) |
377 | } | 377 | } |
378 | #endif /* HAVE_SETPCRED */ | 378 | #endif /* HAVE_SETPCRED */ |
379 | #ifdef WITH_SELINUX | 379 | #ifdef WITH_SELINUX |
@@ -396,10 +396,10 @@ index 1c7a45d..436ae7c 100644 | |||
396 | char *platform_krb5_get_principal_name(const char *); | 396 | char *platform_krb5_get_principal_name(const char *); |
397 | int platform_sys_dir_uid(uid_t); | 397 | int platform_sys_dir_uid(uid_t); |
398 | diff --git a/session.c b/session.c | 398 | diff --git a/session.c b/session.c |
399 | index 2bcf818..6848df4 100644 | 399 | index 3e96557..6f389ac 100644 |
400 | --- a/session.c | 400 | --- a/session.c |
401 | +++ b/session.c | 401 | +++ b/session.c |
402 | @@ -1502,7 +1502,7 @@ safely_chroot(const char *path, uid_t uid) | 402 | @@ -1486,7 +1486,7 @@ safely_chroot(const char *path, uid_t uid) |
403 | 403 | ||
404 | /* Set login name, uid, gid, and groups. */ | 404 | /* Set login name, uid, gid, and groups. */ |
405 | void | 405 | void |
@@ -407,8 +407,8 @@ index 2bcf818..6848df4 100644 | |||
407 | +do_setusercontext(struct passwd *pw, const char *role) | 407 | +do_setusercontext(struct passwd *pw, const char *role) |
408 | { | 408 | { |
409 | char *chroot_path, *tmp; | 409 | char *chroot_path, *tmp; |
410 | 410 | #ifdef USE_LIBIAF | |
411 | @@ -1530,7 +1530,7 @@ do_setusercontext(struct passwd *pw) | 411 | @@ -1517,7 +1517,7 @@ do_setusercontext(struct passwd *pw) |
412 | endgrent(); | 412 | endgrent(); |
413 | #endif | 413 | #endif |
414 | 414 | ||
@@ -417,7 +417,7 @@ index 2bcf818..6848df4 100644 | |||
417 | 417 | ||
418 | if (options.chroot_directory != NULL && | 418 | if (options.chroot_directory != NULL && |
419 | strcasecmp(options.chroot_directory, "none") != 0) { | 419 | strcasecmp(options.chroot_directory, "none") != 0) { |
420 | @@ -1679,7 +1679,7 @@ do_child(Session *s, const char *command) | 420 | @@ -1676,7 +1676,7 @@ do_child(Session *s, const char *command) |
421 | 421 | ||
422 | /* Force a password change */ | 422 | /* Force a password change */ |
423 | if (s->authctxt->force_pwchange) { | 423 | if (s->authctxt->force_pwchange) { |
@@ -426,7 +426,7 @@ index 2bcf818..6848df4 100644 | |||
426 | child_close_fds(); | 426 | child_close_fds(); |
427 | do_pwchange(s); | 427 | do_pwchange(s); |
428 | exit(1); | 428 | exit(1); |
429 | @@ -1706,7 +1706,7 @@ do_child(Session *s, const char *command) | 429 | @@ -1703,7 +1703,7 @@ do_child(Session *s, const char *command) |
430 | /* When PAM is enabled we rely on it to do the nologin check */ | 430 | /* When PAM is enabled we rely on it to do the nologin check */ |
431 | if (!options.use_pam) | 431 | if (!options.use_pam) |
432 | do_nologin(pw); | 432 | do_nologin(pw); |
@@ -435,7 +435,7 @@ index 2bcf818..6848df4 100644 | |||
435 | /* | 435 | /* |
436 | * PAM session modules in do_setusercontext may have | 436 | * PAM session modules in do_setusercontext may have |
437 | * generated messages, so if this in an interactive | 437 | * generated messages, so if this in an interactive |
438 | @@ -2117,7 +2117,7 @@ session_pty_req(Session *s) | 438 | @@ -2114,7 +2114,7 @@ session_pty_req(Session *s) |
439 | tty_parse_modes(s->ttyfd, &n_bytes); | 439 | tty_parse_modes(s->ttyfd, &n_bytes); |
440 | 440 | ||
441 | if (!use_privsep) | 441 | if (!use_privsep) |
@@ -458,10 +458,10 @@ index 6a2f35e..ef6593c 100644 | |||
458 | const char *value); | 458 | const char *value); |
459 | 459 | ||
460 | diff --git a/sshd.c b/sshd.c | 460 | diff --git a/sshd.c b/sshd.c |
461 | index d787fea..e343d90 100644 | 461 | index 3a6be65..48a14dd 100644 |
462 | --- a/sshd.c | 462 | --- a/sshd.c |
463 | +++ b/sshd.c | 463 | +++ b/sshd.c |
464 | @@ -769,7 +769,7 @@ privsep_postauth(Authctxt *authctxt) | 464 | @@ -772,7 +772,7 @@ privsep_postauth(Authctxt *authctxt) |
465 | explicit_bzero(rnd, sizeof(rnd)); | 465 | explicit_bzero(rnd, sizeof(rnd)); |
466 | 466 | ||
467 | /* Drop privileges */ | 467 | /* Drop privileges */ |
@@ -471,10 +471,10 @@ index d787fea..e343d90 100644 | |||
471 | skip: | 471 | skip: |
472 | /* It is safe now to apply the key state */ | 472 | /* It is safe now to apply the key state */ |
473 | diff --git a/sshpty.c b/sshpty.c | 473 | diff --git a/sshpty.c b/sshpty.c |
474 | index bbbc0fe..8cc26a2 100644 | 474 | index a2059b7..3512ec8 100644 |
475 | --- a/sshpty.c | 475 | --- a/sshpty.c |
476 | +++ b/sshpty.c | 476 | +++ b/sshpty.c |
477 | @@ -200,7 +200,7 @@ pty_change_window_size(int ptyfd, u_int row, u_int col, | 477 | @@ -187,7 +187,7 @@ pty_change_window_size(int ptyfd, u_int row, u_int col, |
478 | } | 478 | } |
479 | 479 | ||
480 | void | 480 | void |
@@ -483,7 +483,7 @@ index bbbc0fe..8cc26a2 100644 | |||
483 | { | 483 | { |
484 | struct group *grp; | 484 | struct group *grp; |
485 | gid_t gid; | 485 | gid_t gid; |
486 | @@ -227,7 +227,7 @@ pty_setowner(struct passwd *pw, const char *tty) | 486 | @@ -214,7 +214,7 @@ pty_setowner(struct passwd *pw, const char *tty) |
487 | strerror(errno)); | 487 | strerror(errno)); |
488 | 488 | ||
489 | #ifdef WITH_SELINUX | 489 | #ifdef WITH_SELINUX |
diff --git a/debian/patches/series b/debian/patches/series index c554b34ca..bbc7a5fb4 100644 --- a/debian/patches/series +++ b/debian/patches/series | |||
@@ -1,4 +1,5 @@ | |||
1 | gssapi.patch | 1 | gssapi.patch |
2 | restore-tcp-wrappers.patch | ||
2 | selinux-role.patch | 3 | selinux-role.patch |
3 | ssh-vulnkey-compat.patch | 4 | ssh-vulnkey-compat.patch |
4 | ssh1-keepalive.patch | 5 | ssh1-keepalive.patch |
@@ -22,9 +23,7 @@ ssh-argv0.patch | |||
22 | doc-hash-tab-completion.patch | 23 | doc-hash-tab-completion.patch |
23 | doc-upstart.patch | 24 | doc-upstart.patch |
24 | ssh-agent-setgid.patch | 25 | ssh-agent-setgid.patch |
25 | no-openssl-version-check.patch | 26 | no-openssl-version-status.patch |
26 | gnome-ssh-askpass2-icon.patch | 27 | gnome-ssh-askpass2-icon.patch |
27 | sigstop.patch | 28 | sigstop.patch |
28 | debian-config.patch | 29 | debian-config.patch |
29 | sshfp_with_server_cert_upstr | ||
30 | curve25519-sha256-bignum-encoding.patch | ||
diff --git a/debian/patches/shell-path.patch b/debian/patches/shell-path.patch index 48c16d2a2..07e20f03d 100644 --- a/debian/patches/shell-path.patch +++ b/debian/patches/shell-path.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 6103c29d855e82c098e88ee12f05a6eb41f659ce Mon Sep 17 00:00:00 2001 | 1 | From 66377fbb52584b41bd7f6f19116107fbbad41058 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:00 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:00 +0000 |
4 | Subject: Look for $SHELL on the path for ProxyCommand/LocalCommand | 4 | Subject: Look for $SHELL on the path for ProxyCommand/LocalCommand |
@@ -16,10 +16,10 @@ Patch-Name: shell-path.patch | |||
16 | 1 file changed, 2 insertions(+), 2 deletions(-) | 16 | 1 file changed, 2 insertions(+), 2 deletions(-) |
17 | 17 | ||
18 | diff --git a/sshconnect.c b/sshconnect.c | 18 | diff --git a/sshconnect.c b/sshconnect.c |
19 | index 573d7a8..9e02837 100644 | 19 | index ac09eae..26116d2 100644 |
20 | --- a/sshconnect.c | 20 | --- a/sshconnect.c |
21 | +++ b/sshconnect.c | 21 | +++ b/sshconnect.c |
22 | @@ -227,7 +227,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) | 22 | @@ -228,7 +228,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) |
23 | /* Execute the proxy command. Note that we gave up any | 23 | /* Execute the proxy command. Note that we gave up any |
24 | extra privileges above. */ | 24 | extra privileges above. */ |
25 | signal(SIGPIPE, SIG_DFL); | 25 | signal(SIGPIPE, SIG_DFL); |
@@ -28,7 +28,7 @@ index 573d7a8..9e02837 100644 | |||
28 | perror(argv[0]); | 28 | perror(argv[0]); |
29 | exit(1); | 29 | exit(1); |
30 | } | 30 | } |
31 | @@ -1387,7 +1387,7 @@ ssh_local_cmd(const char *args) | 31 | @@ -1416,7 +1416,7 @@ ssh_local_cmd(const char *args) |
32 | if (pid == 0) { | 32 | if (pid == 0) { |
33 | signal(SIGPIPE, SIG_DFL); | 33 | signal(SIGPIPE, SIG_DFL); |
34 | debug3("Executing %s -c \"%s\"", shell, args); | 34 | debug3("Executing %s -c \"%s\"", shell, args); |
diff --git a/debian/patches/sigstop.patch b/debian/patches/sigstop.patch index 6a15e0dc5..1eaa7758b 100644 --- a/debian/patches/sigstop.patch +++ b/debian/patches/sigstop.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From cfeaa0ba2ce2859573f7e980be09ef05511f56a2 Mon Sep 17 00:00:00 2001 | 1 | From 689f465c66059e527974c6d4ea8e95f04d5abab7 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:17 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:17 +0000 |
4 | Subject: Support synchronisation with service supervisor using SIGSTOP | 4 | Subject: Support synchronisation with service supervisor using SIGSTOP |
@@ -13,10 +13,10 @@ Patch-Name: sigstop.patch | |||
13 | 1 file changed, 10 insertions(+) | 13 | 1 file changed, 10 insertions(+) |
14 | 14 | ||
15 | diff --git a/sshd.c b/sshd.c | 15 | diff --git a/sshd.c b/sshd.c |
16 | index 665c0b9..0964491 100644 | 16 | index 87331c1..23d5a64 100644 |
17 | --- a/sshd.c | 17 | --- a/sshd.c |
18 | +++ b/sshd.c | 18 | +++ b/sshd.c |
19 | @@ -1931,6 +1931,16 @@ main(int ac, char **av) | 19 | @@ -1958,6 +1958,16 @@ main(int ac, char **av) |
20 | } | 20 | } |
21 | } | 21 | } |
22 | 22 | ||
diff --git a/debian/patches/ssh-agent-setgid.patch b/debian/patches/ssh-agent-setgid.patch index af23075b3..9c3ddc86e 100644 --- a/debian/patches/ssh-agent-setgid.patch +++ b/debian/patches/ssh-agent-setgid.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From d53483ab71ac2a9195c8f171da5a5dcf54ec16ec Mon Sep 17 00:00:00 2001 | 1 | From 78dd041bb6ad29ceb35f05b539b09ccf761eaee2 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:13 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:13 +0000 |
4 | Subject: Document consequences of ssh-agent being setgid in ssh-agent(1) | 4 | Subject: Document consequences of ssh-agent being setgid in ssh-agent(1) |
@@ -13,10 +13,10 @@ Patch-Name: ssh-agent-setgid.patch | |||
13 | 1 file changed, 15 insertions(+) | 13 | 1 file changed, 15 insertions(+) |
14 | 14 | ||
15 | diff --git a/ssh-agent.1 b/ssh-agent.1 | 15 | diff --git a/ssh-agent.1 b/ssh-agent.1 |
16 | index 281ecbd..38fd540 100644 | 16 | index a1e634f..f2c4080 100644 |
17 | --- a/ssh-agent.1 | 17 | --- a/ssh-agent.1 |
18 | +++ b/ssh-agent.1 | 18 | +++ b/ssh-agent.1 |
19 | @@ -183,6 +183,21 @@ environment variable holds the agent's process ID. | 19 | @@ -172,6 +172,21 @@ environment variable holds the agent's process ID. |
20 | .Pp | 20 | .Pp |
21 | The agent exits automatically when the command given on the command | 21 | The agent exits automatically when the command given on the command |
22 | line terminates. | 22 | line terminates. |
@@ -37,4 +37,4 @@ index 281ecbd..38fd540 100644 | |||
37 | +so in the program executed by ssh-agent. | 37 | +so in the program executed by ssh-agent. |
38 | .Sh FILES | 38 | .Sh FILES |
39 | .Bl -tag -width Ds | 39 | .Bl -tag -width Ds |
40 | .It Pa ~/.ssh/identity | 40 | .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt |
diff --git a/debian/patches/ssh-argv0.patch b/debian/patches/ssh-argv0.patch index d456facea..0ccf7c42b 100644 --- a/debian/patches/ssh-argv0.patch +++ b/debian/patches/ssh-argv0.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From d4ac61d918775f629eff9a389d0f7bb0f8426b48 Mon Sep 17 00:00:00 2001 | 1 | From cbd5cb03866f6df50c82d26588b73135d05bf245 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:10:10 +0000 | 3 | Date: Sun, 9 Feb 2014 16:10:10 +0000 |
4 | Subject: ssh(1): Refer to ssh-argv0(1) | 4 | Subject: ssh(1): Refer to ssh-argv0(1) |
@@ -18,10 +18,10 @@ Patch-Name: ssh-argv0.patch | |||
18 | 1 file changed, 1 insertion(+) | 18 | 1 file changed, 1 insertion(+) |
19 | 19 | ||
20 | diff --git a/ssh.1 b/ssh.1 | 20 | diff --git a/ssh.1 b/ssh.1 |
21 | index 67b4f44..9868025 100644 | 21 | index de178cd..2606b15 100644 |
22 | --- a/ssh.1 | 22 | --- a/ssh.1 |
23 | +++ b/ssh.1 | 23 | +++ b/ssh.1 |
24 | @@ -1468,6 +1468,7 @@ if an error occurred. | 24 | @@ -1458,6 +1458,7 @@ if an error occurred. |
25 | .Xr sftp 1 , | 25 | .Xr sftp 1 , |
26 | .Xr ssh-add 1 , | 26 | .Xr ssh-add 1 , |
27 | .Xr ssh-agent 1 , | 27 | .Xr ssh-agent 1 , |
diff --git a/debian/patches/ssh-vulnkey-compat.patch b/debian/patches/ssh-vulnkey-compat.patch index fa738b084..427ee6be1 100644 --- a/debian/patches/ssh-vulnkey-compat.patch +++ b/debian/patches/ssh-vulnkey-compat.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From d422205e757aaf23e8e0e787f842ef37f6a170a2 Mon Sep 17 00:00:00 2001 | 1 | From e6836d7c98c75d3252de56c2f3ea07e12c817e00 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@ubuntu.com> | 2 | From: Colin Watson <cjwatson@ubuntu.com> |
3 | Date: Sun, 9 Feb 2014 16:09:50 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:50 +0000 |
4 | Subject: Accept obsolete ssh-vulnkey configuration options | 4 | Subject: Accept obsolete ssh-vulnkey configuration options |
@@ -17,10 +17,10 @@ Patch-Name: ssh-vulnkey-compat.patch | |||
17 | 2 files changed, 2 insertions(+) | 17 | 2 files changed, 2 insertions(+) |
18 | 18 | ||
19 | diff --git a/readconf.c b/readconf.c | 19 | diff --git a/readconf.c b/readconf.c |
20 | index 7613ff2..bcd8cad 100644 | 20 | index 9127e93..bc879eb 100644 |
21 | --- a/readconf.c | 21 | --- a/readconf.c |
22 | +++ b/readconf.c | 22 | +++ b/readconf.c |
23 | @@ -172,6 +172,7 @@ static struct { | 23 | @@ -174,6 +174,7 @@ static struct { |
24 | { "passwordauthentication", oPasswordAuthentication }, | 24 | { "passwordauthentication", oPasswordAuthentication }, |
25 | { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, | 25 | { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, |
26 | { "kbdinteractivedevices", oKbdInteractiveDevices }, | 26 | { "kbdinteractivedevices", oKbdInteractiveDevices }, |
@@ -29,10 +29,10 @@ index 7613ff2..bcd8cad 100644 | |||
29 | { "pubkeyauthentication", oPubkeyAuthentication }, | 29 | { "pubkeyauthentication", oPubkeyAuthentication }, |
30 | { "dsaauthentication", oPubkeyAuthentication }, /* alias */ | 30 | { "dsaauthentication", oPubkeyAuthentication }, /* alias */ |
31 | diff --git a/servconf.c b/servconf.c | 31 | diff --git a/servconf.c b/servconf.c |
32 | index 0083cf8..90de888 100644 | 32 | index cb3c831..a252487 100644 |
33 | --- a/servconf.c | 33 | --- a/servconf.c |
34 | +++ b/servconf.c | 34 | +++ b/servconf.c |
35 | @@ -448,6 +448,7 @@ static struct { | 35 | @@ -462,6 +462,7 @@ static struct { |
36 | { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, | 36 | { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, |
37 | { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, | 37 | { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, |
38 | { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, | 38 | { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, |
diff --git a/debian/patches/ssh1-keepalive.patch b/debian/patches/ssh1-keepalive.patch index ded7c122a..2e5fa306d 100644 --- a/debian/patches/ssh1-keepalive.patch +++ b/debian/patches/ssh1-keepalive.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 789d58ed3df120c7b80d07fb2d259c216194a29c Mon Sep 17 00:00:00 2001 | 1 | From cbbc8577950b93090171c7394bcdeb68b7c3cd0c Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:09:51 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:51 +0000 |
4 | Subject: Partial server keep-alive implementation for SSH1 | 4 | Subject: Partial server keep-alive implementation for SSH1 |
@@ -13,7 +13,7 @@ Patch-Name: ssh1-keepalive.patch | |||
13 | 2 files changed, 19 insertions(+), 11 deletions(-) | 13 | 2 files changed, 19 insertions(+), 11 deletions(-) |
14 | 14 | ||
15 | diff --git a/clientloop.c b/clientloop.c | 15 | diff --git a/clientloop.c b/clientloop.c |
16 | index 6d8cd7d..73a800c 100644 | 16 | index f9175e3..046ca8b 100644 |
17 | --- a/clientloop.c | 17 | --- a/clientloop.c |
18 | +++ b/clientloop.c | 18 | +++ b/clientloop.c |
19 | @@ -563,16 +563,21 @@ client_global_request_reply(int type, u_int32_t seq, void *ctxt) | 19 | @@ -563,16 +563,21 @@ client_global_request_reply(int type, u_int32_t seq, void *ctxt) |
@@ -57,10 +57,10 @@ index 6d8cd7d..73a800c 100644 | |||
57 | server_alive_time = now + options.server_alive_interval; | 57 | server_alive_time = now + options.server_alive_interval; |
58 | } | 58 | } |
59 | diff --git a/ssh_config.5 b/ssh_config.5 | 59 | diff --git a/ssh_config.5 b/ssh_config.5 |
60 | index e7accd6..473971e 100644 | 60 | index e6649ac..01f1f7f 100644 |
61 | --- a/ssh_config.5 | 61 | --- a/ssh_config.5 |
62 | +++ b/ssh_config.5 | 62 | +++ b/ssh_config.5 |
63 | @@ -1294,7 +1294,10 @@ If, for example, | 63 | @@ -1325,7 +1325,10 @@ If, for example, |
64 | .Cm ServerAliveCountMax | 64 | .Cm ServerAliveCountMax |
65 | is left at the default, if the server becomes unresponsive, | 65 | is left at the default, if the server becomes unresponsive, |
66 | ssh will disconnect after approximately 45 seconds. | 66 | ssh will disconnect after approximately 45 seconds. |
diff --git a/debian/patches/sshfp_with_server_cert_upstr b/debian/patches/sshfp_with_server_cert_upstr deleted file mode 100644 index b453081c5..000000000 --- a/debian/patches/sshfp_with_server_cert_upstr +++ /dev/null | |||
@@ -1,83 +0,0 @@ | |||
1 | From 08a63152deb5deda168aaef870bdb9f56425acb3 Mon Sep 17 00:00:00 2001 | ||
2 | From: Matthew Vernon <mcv21@cam.ac.uk> | ||
3 | Date: Wed, 26 Mar 2014 15:32:23 +0000 | ||
4 | Subject: Attempt SSHFP lookup even if server presents a certificate | ||
5 | |||
6 | If an ssh server presents a certificate to the client, then the client | ||
7 | does not check the DNS for SSHFP records. This means that a malicious | ||
8 | server can essentially disable DNS-host-key-checking, which means the | ||
9 | client will fall back to asking the user (who will just say "yes" to | ||
10 | the fingerprint, sadly). | ||
11 | |||
12 | This patch is by Damien Miller (of openssh upstream). It's simpler | ||
13 | than the patch by Mark Wooding which I applied yesterday; a copy is | ||
14 | taken of the proffered key/cert, the key extracted from the cert (if | ||
15 | necessary), and then the DNS consulted. | ||
16 | |||
17 | Signed-off-by: Matthew Vernon <matthew@debian.org> | ||
18 | Bug-Debian: http://bugs.debian.org/742513 | ||
19 | Patch-Name: sshfp_with_server_cert_upstr | ||
20 | --- | ||
21 | sshconnect.c | 42 ++++++++++++++++++++++++++---------------- | ||
22 | 1 file changed, 26 insertions(+), 16 deletions(-) | ||
23 | |||
24 | diff --git a/sshconnect.c b/sshconnect.c | ||
25 | index 87c3770..324f5e0 100644 | ||
26 | --- a/sshconnect.c | ||
27 | +++ b/sshconnect.c | ||
28 | @@ -1224,29 +1224,39 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | ||
29 | { | ||
30 | int flags = 0; | ||
31 | char *fp; | ||
32 | + Key *plain = NULL; | ||
33 | |||
34 | fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); | ||
35 | debug("Server host key: %s %s", key_type(host_key), fp); | ||
36 | free(fp); | ||
37 | |||
38 | - /* XXX certs are not yet supported for DNS */ | ||
39 | - if (!key_is_cert(host_key) && options.verify_host_key_dns && | ||
40 | - verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) { | ||
41 | - if (flags & DNS_VERIFY_FOUND) { | ||
42 | - | ||
43 | - if (options.verify_host_key_dns == 1 && | ||
44 | - flags & DNS_VERIFY_MATCH && | ||
45 | - flags & DNS_VERIFY_SECURE) | ||
46 | - return 0; | ||
47 | - | ||
48 | - if (flags & DNS_VERIFY_MATCH) { | ||
49 | - matching_host_key_dns = 1; | ||
50 | - } else { | ||
51 | - warn_changed_key(host_key); | ||
52 | - error("Update the SSHFP RR in DNS with the new " | ||
53 | - "host key to get rid of this message."); | ||
54 | + if (options.verify_host_key_dns) { | ||
55 | + /* | ||
56 | + * XXX certs are not yet supported for DNS, so downgrade | ||
57 | + * them and try the plain key. | ||
58 | + */ | ||
59 | + plain = key_from_private(host_key); | ||
60 | + if (key_is_cert(plain)) | ||
61 | + key_drop_cert(plain); | ||
62 | + if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { | ||
63 | + if (flags & DNS_VERIFY_FOUND) { | ||
64 | + if (options.verify_host_key_dns == 1 && | ||
65 | + flags & DNS_VERIFY_MATCH && | ||
66 | + flags & DNS_VERIFY_SECURE) { | ||
67 | + key_free(plain); | ||
68 | + return 0; | ||
69 | + } | ||
70 | + if (flags & DNS_VERIFY_MATCH) { | ||
71 | + matching_host_key_dns = 1; | ||
72 | + } else { | ||
73 | + warn_changed_key(plain); | ||
74 | + error("Update the SSHFP RR in DNS " | ||
75 | + "with the new host key to get rid " | ||
76 | + "of this message."); | ||
77 | + } | ||
78 | } | ||
79 | } | ||
80 | + key_free(plain); | ||
81 | } | ||
82 | |||
83 | return check_host_key(host, hostaddr, options.port, host_key, RDRW, | ||
diff --git a/debian/patches/syslog-level-silent.patch b/debian/patches/syslog-level-silent.patch index 7cbd3a7e3..bfc236927 100644 --- a/debian/patches/syslog-level-silent.patch +++ b/debian/patches/syslog-level-silent.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From b8ed36cdf2dbebc01e52e83eece4bb1d78607e84 Mon Sep 17 00:00:00 2001 | 1 | From 69f7c00e04d1baa01a9038eeb764cfed0830fb19 Mon Sep 17 00:00:00 2001 |
2 | From: Jonathan David Amery <jdamery@ysolde.ucam.org> | 2 | From: Jonathan David Amery <jdamery@ysolde.ucam.org> |
3 | Date: Sun, 9 Feb 2014 16:09:54 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:54 +0000 |
4 | Subject: "LogLevel SILENT" compatibility | 4 | Subject: "LogLevel SILENT" compatibility |
@@ -33,10 +33,10 @@ index 32e1d2e..53e7b65 100644 | |||
33 | { "FATAL", SYSLOG_LEVEL_FATAL }, | 33 | { "FATAL", SYSLOG_LEVEL_FATAL }, |
34 | { "ERROR", SYSLOG_LEVEL_ERROR }, | 34 | { "ERROR", SYSLOG_LEVEL_ERROR }, |
35 | diff --git a/ssh.c b/ssh.c | 35 | diff --git a/ssh.c b/ssh.c |
36 | index 1e6cb90..3e63708 100644 | 36 | index 26e9681..5bce695 100644 |
37 | --- a/ssh.c | 37 | --- a/ssh.c |
38 | +++ b/ssh.c | 38 | +++ b/ssh.c |
39 | @@ -965,7 +965,7 @@ main(int ac, char **av) | 39 | @@ -989,7 +989,7 @@ main(int ac, char **av) |
40 | /* Do not allocate a tty if stdin is not a tty. */ | 40 | /* Do not allocate a tty if stdin is not a tty. */ |
41 | if ((!isatty(fileno(stdin)) || stdin_null_flag) && | 41 | if ((!isatty(fileno(stdin)) || stdin_null_flag) && |
42 | options.request_tty != REQUEST_TTY_FORCE) { | 42 | options.request_tty != REQUEST_TTY_FORCE) { |
diff --git a/debian/patches/user-group-modes.patch b/debian/patches/user-group-modes.patch index 3cdb9d8a1..e4e4657f3 100644 --- a/debian/patches/user-group-modes.patch +++ b/debian/patches/user-group-modes.patch | |||
@@ -1,4 +1,4 @@ | |||
1 | From 77638f6662ecd8500e1b97e537233b1277ca829f Mon Sep 17 00:00:00 2001 | 1 | From 28ea747089f695e58a476a2849133402d4f86b92 Mon Sep 17 00:00:00 2001 |
2 | From: Colin Watson <cjwatson@debian.org> | 2 | From: Colin Watson <cjwatson@debian.org> |
3 | Date: Sun, 9 Feb 2014 16:09:58 +0000 | 3 | Date: Sun, 9 Feb 2014 16:09:58 +0000 |
4 | Subject: Allow harmless group-writability | 4 | Subject: Allow harmless group-writability |
@@ -28,7 +28,7 @@ Patch-Name: user-group-modes.patch | |||
28 | 8 files changed, 82 insertions(+), 29 deletions(-) | 28 | 8 files changed, 82 insertions(+), 29 deletions(-) |
29 | 29 | ||
30 | diff --git a/auth-rhosts.c b/auth-rhosts.c | 30 | diff --git a/auth-rhosts.c b/auth-rhosts.c |
31 | index 06ae7f0..f202787 100644 | 31 | index b5bedee..11fcca6 100644 |
32 | --- a/auth-rhosts.c | 32 | --- a/auth-rhosts.c |
33 | +++ b/auth-rhosts.c | 33 | +++ b/auth-rhosts.c |
34 | @@ -256,8 +256,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam | 34 | @@ -256,8 +256,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam |
@@ -52,10 +52,10 @@ index 06ae7f0..f202787 100644 | |||
52 | pw->pw_name, buf); | 52 | pw->pw_name, buf); |
53 | auth_debug_add("Bad file modes for %.200s", buf); | 53 | auth_debug_add("Bad file modes for %.200s", buf); |
54 | diff --git a/auth.c b/auth.c | 54 | diff --git a/auth.c b/auth.c |
55 | index 9a36f1d..0c45f09 100644 | 55 | index 5e60682..18de51a 100644 |
56 | --- a/auth.c | 56 | --- a/auth.c |
57 | +++ b/auth.c | 57 | +++ b/auth.c |
58 | @@ -407,8 +407,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, | 58 | @@ -421,8 +421,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, |
59 | user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); | 59 | user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); |
60 | if (options.strict_modes && | 60 | if (options.strict_modes && |
61 | (stat(user_hostfile, &st) == 0) && | 61 | (stat(user_hostfile, &st) == 0) && |
@@ -65,7 +65,7 @@ index 9a36f1d..0c45f09 100644 | |||
65 | logit("Authentication refused for %.100s: " | 65 | logit("Authentication refused for %.100s: " |
66 | "bad owner or modes for %.200s", | 66 | "bad owner or modes for %.200s", |
67 | pw->pw_name, user_hostfile); | 67 | pw->pw_name, user_hostfile); |
68 | @@ -470,8 +469,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, | 68 | @@ -484,8 +483,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, |
69 | snprintf(err, errlen, "%s is not a regular file", buf); | 69 | snprintf(err, errlen, "%s is not a regular file", buf); |
70 | return -1; | 70 | return -1; |
71 | } | 71 | } |
@@ -75,7 +75,7 @@ index 9a36f1d..0c45f09 100644 | |||
75 | snprintf(err, errlen, "bad ownership or modes for file %s", | 75 | snprintf(err, errlen, "bad ownership or modes for file %s", |
76 | buf); | 76 | buf); |
77 | return -1; | 77 | return -1; |
78 | @@ -486,8 +484,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, | 78 | @@ -500,8 +498,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, |
79 | strlcpy(buf, cp, sizeof(buf)); | 79 | strlcpy(buf, cp, sizeof(buf)); |
80 | 80 | ||
81 | if (stat(buf, &st) < 0 || | 81 | if (stat(buf, &st) < 0 || |
@@ -86,10 +86,10 @@ index 9a36f1d..0c45f09 100644 | |||
86 | "bad ownership or modes for directory %s", buf); | 86 | "bad ownership or modes for directory %s", buf); |
87 | return -1; | 87 | return -1; |
88 | diff --git a/misc.c b/misc.c | 88 | diff --git a/misc.c b/misc.c |
89 | index e4c8c32..4e756b0 100644 | 89 | index 94b05b0..c25ccd8 100644 |
90 | --- a/misc.c | 90 | --- a/misc.c |
91 | +++ b/misc.c | 91 | +++ b/misc.c |
92 | @@ -49,8 +49,9 @@ | 92 | @@ -50,8 +50,9 @@ |
93 | #include <netdb.h> | 93 | #include <netdb.h> |
94 | #ifdef HAVE_PATHS_H | 94 | #ifdef HAVE_PATHS_H |
95 | # include <paths.h> | 95 | # include <paths.h> |
@@ -100,7 +100,7 @@ index e4c8c32..4e756b0 100644 | |||
100 | #ifdef SSH_TUN_OPENBSD | 100 | #ifdef SSH_TUN_OPENBSD |
101 | #include <net/if.h> | 101 | #include <net/if.h> |
102 | #endif | 102 | #endif |
103 | @@ -59,6 +60,7 @@ | 103 | @@ -60,6 +61,7 @@ |
104 | #include "misc.h" | 104 | #include "misc.h" |
105 | #include "log.h" | 105 | #include "log.h" |
106 | #include "ssh.h" | 106 | #include "ssh.h" |
@@ -108,7 +108,7 @@ index e4c8c32..4e756b0 100644 | |||
108 | 108 | ||
109 | /* remove newline at end of string */ | 109 | /* remove newline at end of string */ |
110 | char * | 110 | char * |
111 | @@ -643,6 +645,71 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, | 111 | @@ -644,6 +646,71 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, |
112 | return -1; | 112 | return -1; |
113 | } | 113 | } |
114 | 114 | ||
@@ -181,10 +181,10 @@ index e4c8c32..4e756b0 100644 | |||
181 | tun_open(int tun, int mode) | 181 | tun_open(int tun, int mode) |
182 | { | 182 | { |
183 | diff --git a/misc.h b/misc.h | 183 | diff --git a/misc.h b/misc.h |
184 | index d4df619..ceb173b 100644 | 184 | index 374c33c..89e1f75 100644 |
185 | --- a/misc.h | 185 | --- a/misc.h |
186 | +++ b/misc.h | 186 | +++ b/misc.h |
187 | @@ -106,4 +106,6 @@ char *read_passphrase(const char *, int); | 187 | @@ -135,4 +135,6 @@ char *read_passphrase(const char *, int); |
188 | int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); | 188 | int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); |
189 | int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *); | 189 | int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *); |
190 | 190 | ||
@@ -192,10 +192,10 @@ index d4df619..ceb173b 100644 | |||
192 | + | 192 | + |
193 | #endif /* _MISC_H */ | 193 | #endif /* _MISC_H */ |
194 | diff --git a/platform.c b/platform.c | 194 | diff --git a/platform.c b/platform.c |
195 | index 4aab9a9..f99de7f 100644 | 195 | index f35ec39..9a23e6e 100644 |
196 | --- a/platform.c | 196 | --- a/platform.c |
197 | +++ b/platform.c | 197 | +++ b/platform.c |
198 | @@ -196,19 +196,3 @@ platform_krb5_get_principal_name(const char *pw_name) | 198 | @@ -197,19 +197,3 @@ platform_krb5_get_principal_name(const char *pw_name) |
199 | return NULL; | 199 | return NULL; |
200 | #endif | 200 | #endif |
201 | } | 201 | } |
@@ -216,10 +216,10 @@ index 4aab9a9..f99de7f 100644 | |||
216 | - return 0; | 216 | - return 0; |
217 | -} | 217 | -} |
218 | diff --git a/readconf.c b/readconf.c | 218 | diff --git a/readconf.c b/readconf.c |
219 | index 6409937..32c4b42 100644 | 219 | index 337818c..0648867 100644 |
220 | --- a/readconf.c | 220 | --- a/readconf.c |
221 | +++ b/readconf.c | 221 | +++ b/readconf.c |
222 | @@ -37,6 +37,8 @@ | 222 | @@ -38,6 +38,8 @@ |
223 | #include <stdio.h> | 223 | #include <stdio.h> |
224 | #include <string.h> | 224 | #include <string.h> |
225 | #include <unistd.h> | 225 | #include <unistd.h> |
@@ -228,7 +228,7 @@ index 6409937..32c4b42 100644 | |||
228 | #ifdef HAVE_UTIL_H | 228 | #ifdef HAVE_UTIL_H |
229 | #include <util.h> | 229 | #include <util.h> |
230 | #endif | 230 | #endif |
231 | @@ -1477,8 +1479,7 @@ read_config_file(const char *filename, struct passwd *pw, const char *host, | 231 | @@ -1516,8 +1518,7 @@ read_config_file(const char *filename, struct passwd *pw, const char *host, |
232 | 232 | ||
233 | if (fstat(fileno(f), &sb) == -1) | 233 | if (fstat(fileno(f), &sb) == -1) |
234 | fatal("fstat %s: %s", filename, strerror(errno)); | 234 | fatal("fstat %s: %s", filename, strerror(errno)); |
@@ -239,10 +239,10 @@ index 6409937..32c4b42 100644 | |||
239 | } | 239 | } |
240 | 240 | ||
241 | diff --git a/ssh.1 b/ssh.1 | 241 | diff --git a/ssh.1 b/ssh.1 |
242 | index 27794e2..ff5e6ac 100644 | 242 | index fa5cfb2..7f6ab77 100644 |
243 | --- a/ssh.1 | 243 | --- a/ssh.1 |
244 | +++ b/ssh.1 | 244 | +++ b/ssh.1 |
245 | @@ -1352,6 +1352,8 @@ The file format and configuration options are described in | 245 | @@ -1342,6 +1342,8 @@ The file format and configuration options are described in |
246 | .Xr ssh_config 5 . | 246 | .Xr ssh_config 5 . |
247 | Because of the potential for abuse, this file must have strict permissions: | 247 | Because of the potential for abuse, this file must have strict permissions: |
248 | read/write for the user, and not writable by others. | 248 | read/write for the user, and not writable by others. |
@@ -252,10 +252,10 @@ index 27794e2..ff5e6ac 100644 | |||
252 | .It Pa ~/.ssh/environment | 252 | .It Pa ~/.ssh/environment |
253 | Contains additional definitions for environment variables; see | 253 | Contains additional definitions for environment variables; see |
254 | diff --git a/ssh_config.5 b/ssh_config.5 | 254 | diff --git a/ssh_config.5 b/ssh_config.5 |
255 | index 3172fd4..4bf7cbb 100644 | 255 | index ea92ea8..d68b45a 100644 |
256 | --- a/ssh_config.5 | 256 | --- a/ssh_config.5 |
257 | +++ b/ssh_config.5 | 257 | +++ b/ssh_config.5 |
258 | @@ -1529,6 +1529,8 @@ The format of this file is described above. | 258 | @@ -1587,6 +1587,8 @@ The format of this file is described above. |
259 | This file is used by the SSH client. | 259 | This file is used by the SSH client. |
260 | Because of the potential for abuse, this file must have strict permissions: | 260 | Because of the potential for abuse, this file must have strict permissions: |
261 | read/write for the user, and not accessible by others. | 261 | read/write for the user, and not accessible by others. |
@@ -25,7 +25,7 @@ | |||
25 | #ifndef _DEFINES_H | 25 | #ifndef _DEFINES_H |
26 | #define _DEFINES_H | 26 | #define _DEFINES_H |
27 | 27 | ||
28 | /* $Id: defines.h,v 1.176 2014/01/17 13:12:38 dtucker Exp $ */ | 28 | /* $Id: defines.h,v 1.183 2014/09/02 19:33:26 djm Exp $ */ |
29 | 29 | ||
30 | 30 | ||
31 | /* Constants */ | 31 | /* Constants */ |
@@ -405,7 +405,7 @@ struct winsize { | |||
405 | 405 | ||
406 | /* user may have set a different path */ | 406 | /* user may have set a different path */ |
407 | #if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) | 407 | #if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) |
408 | # undef _PATH_MAILDIR MAILDIR | 408 | # undef _PATH_MAILDIR |
409 | #endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */ | 409 | #endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */ |
410 | 410 | ||
411 | #ifdef MAIL_DIRECTORY | 411 | #ifdef MAIL_DIRECTORY |
@@ -603,10 +603,6 @@ struct winsize { | |||
603 | # define memmove(s1, s2, n) bcopy((s2), (s1), (n)) | 603 | # define memmove(s1, s2, n) bcopy((s2), (s1), (n)) |
604 | #endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ | 604 | #endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ |
605 | 605 | ||
606 | #if defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) | ||
607 | # define USE_VHANGUP | ||
608 | #endif /* defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) */ | ||
609 | |||
610 | #ifndef GETPGRP_VOID | 606 | #ifndef GETPGRP_VOID |
611 | # include <unistd.h> | 607 | # include <unistd.h> |
612 | # define getpgrp() getpgrp(0) | 608 | # define getpgrp() getpgrp(0) |
@@ -826,4 +822,23 @@ struct winsize { | |||
826 | # define arc4random_stir() | 822 | # define arc4random_stir() |
827 | #endif | 823 | #endif |
828 | 824 | ||
825 | #ifndef HAVE_VA_COPY | ||
826 | # ifdef HAVE___VA_COPY | ||
827 | # define va_copy(dest, src) __va_copy(dest, src) | ||
828 | # else | ||
829 | # define va_copy(dest, src) (dest) = (src) | ||
830 | # endif | ||
831 | #endif | ||
832 | |||
833 | #ifndef __predict_true | ||
834 | # if defined(__GNUC__) && \ | ||
835 | ((__GNUC__ > (2)) || (__GNUC__ == (2) && __GNUC_MINOR__ >= (96))) | ||
836 | # define __predict_true(exp) __builtin_expect(((exp) != 0), 1) | ||
837 | # define __predict_false(exp) __builtin_expect(((exp) != 0), 0) | ||
838 | # else | ||
839 | # define __predict_true(exp) ((exp) != 0) | ||
840 | # define __predict_false(exp) ((exp) != 0) | ||
841 | # endif /* gcc version */ | ||
842 | #endif /* __predict_true */ | ||
843 | |||
829 | #endif /* _DEFINES_H */ | 844 | #endif /* _DEFINES_H */ |
diff --git a/digest-libc.c b/digest-libc.c index 1804b0698..1b4423a05 100644 --- a/digest-libc.c +++ b/digest-libc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: digest-libc.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: digest-libc.c,v 1.3 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2013 Damien Miller <djm@mindrot.org> | 3 | * Copyright (c) 2013 Damien Miller <djm@mindrot.org> |
4 | * Copyright (c) 2014 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2014 Markus Friedl. All rights reserved. |
@@ -28,7 +28,8 @@ | |||
28 | #include <sha1.h> | 28 | #include <sha1.h> |
29 | #include <sha2.h> | 29 | #include <sha2.h> |
30 | 30 | ||
31 | #include "buffer.h" | 31 | #include "ssherr.h" |
32 | #include "sshbuf.h" | ||
32 | #include "digest.h" | 33 | #include "digest.h" |
33 | 34 | ||
34 | typedef void md_init_fn(void *mdctx); | 35 | typedef void md_init_fn(void *mdctx); |
@@ -164,7 +165,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) | |||
164 | const struct ssh_digest *digest = ssh_digest_by_alg(from->alg); | 165 | const struct ssh_digest *digest = ssh_digest_by_alg(from->alg); |
165 | 166 | ||
166 | if (digest == NULL || from->alg != to->alg) | 167 | if (digest == NULL || from->alg != to->alg) |
167 | return -1; | 168 | return SSH_ERR_INVALID_ARGUMENT; |
168 | memcpy(to->mdctx, from->mdctx, digest->ctx_len); | 169 | memcpy(to->mdctx, from->mdctx, digest->ctx_len); |
169 | return 0; | 170 | return 0; |
170 | } | 171 | } |
@@ -175,15 +176,15 @@ ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) | |||
175 | const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); | 176 | const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); |
176 | 177 | ||
177 | if (digest == NULL) | 178 | if (digest == NULL) |
178 | return -1; | 179 | return SSH_ERR_INVALID_ARGUMENT; |
179 | digest->md_update(ctx->mdctx, m, mlen); | 180 | digest->md_update(ctx->mdctx, m, mlen); |
180 | return 0; | 181 | return 0; |
181 | } | 182 | } |
182 | 183 | ||
183 | int | 184 | int |
184 | ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) | 185 | ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b) |
185 | { | 186 | { |
186 | return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); | 187 | return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b)); |
187 | } | 188 | } |
188 | 189 | ||
189 | int | 190 | int |
@@ -192,11 +193,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) | |||
192 | const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); | 193 | const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); |
193 | 194 | ||
194 | if (digest == NULL) | 195 | if (digest == NULL) |
195 | return -1; | 196 | return SSH_ERR_INVALID_ARGUMENT; |
196 | if (dlen > UINT_MAX) | 197 | if (dlen > UINT_MAX) |
197 | return -1; | 198 | return SSH_ERR_INVALID_ARGUMENT; |
198 | if (dlen < digest->digest_len) /* No truncation allowed */ | 199 | if (dlen < digest->digest_len) /* No truncation allowed */ |
199 | return -1; | 200 | return SSH_ERR_INVALID_ARGUMENT; |
200 | digest->md_final(d, ctx->mdctx); | 201 | digest->md_final(d, ctx->mdctx); |
201 | return 0; | 202 | return 0; |
202 | } | 203 | } |
@@ -223,16 +224,16 @@ ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) | |||
223 | struct ssh_digest_ctx *ctx = ssh_digest_start(alg); | 224 | struct ssh_digest_ctx *ctx = ssh_digest_start(alg); |
224 | 225 | ||
225 | if (ctx == NULL) | 226 | if (ctx == NULL) |
226 | return -1; | 227 | return SSH_ERR_INVALID_ARGUMENT; |
227 | if (ssh_digest_update(ctx, m, mlen) != 0 || | 228 | if (ssh_digest_update(ctx, m, mlen) != 0 || |
228 | ssh_digest_final(ctx, d, dlen) != 0) | 229 | ssh_digest_final(ctx, d, dlen) != 0) |
229 | return -1; | 230 | return SSH_ERR_INVALID_ARGUMENT; |
230 | ssh_digest_free(ctx); | 231 | ssh_digest_free(ctx); |
231 | return 0; | 232 | return 0; |
232 | } | 233 | } |
233 | 234 | ||
234 | int | 235 | int |
235 | ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) | 236 | ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) |
236 | { | 237 | { |
237 | return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); | 238 | return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen); |
238 | } | 239 | } |
diff --git a/digest-openssl.c b/digest-openssl.c index 863d37d03..02b170341 100644 --- a/digest-openssl.c +++ b/digest-openssl.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: digest-openssl.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: digest-openssl.c,v 1.4 2014/07/03 03:26:43 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2013 Damien Miller <djm@mindrot.org> | 3 | * Copyright (c) 2013 Damien Miller <djm@mindrot.org> |
4 | * | 4 | * |
@@ -26,8 +26,18 @@ | |||
26 | 26 | ||
27 | #include "openbsd-compat/openssl-compat.h" | 27 | #include "openbsd-compat/openssl-compat.h" |
28 | 28 | ||
29 | #include "buffer.h" | 29 | #include "sshbuf.h" |
30 | #include "digest.h" | 30 | #include "digest.h" |
31 | #include "ssherr.h" | ||
32 | |||
33 | #ifndef HAVE_EVP_RIPEMD160 | ||
34 | # define EVP_ripemd160 NULL | ||
35 | #endif /* HAVE_EVP_RIPEMD160 */ | ||
36 | #ifndef HAVE_EVP_SHA256 | ||
37 | # define EVP_sha256 NULL | ||
38 | # define EVP_sha384 NULL | ||
39 | # define EVP_sha512 NULL | ||
40 | #endif /* HAVE_EVP_SHA256 */ | ||
31 | 41 | ||
32 | struct ssh_digest_ctx { | 42 | struct ssh_digest_ctx { |
33 | int alg; | 43 | int alg; |
@@ -46,11 +56,9 @@ const struct ssh_digest digests[] = { | |||
46 | { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, | 56 | { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, |
47 | { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 }, | 57 | { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 }, |
48 | { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, | 58 | { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, |
49 | #ifdef HAVE_EVP_SHA256 /* XXX replace with local if missing */ | ||
50 | { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, | 59 | { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, |
51 | { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, | 60 | { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, |
52 | { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, | 61 | { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, |
53 | #endif | ||
54 | { -1, NULL, 0, NULL }, | 62 | { -1, NULL, 0, NULL }, |
55 | }; | 63 | }; |
56 | 64 | ||
@@ -61,6 +69,8 @@ ssh_digest_by_alg(int alg) | |||
61 | return NULL; | 69 | return NULL; |
62 | if (digests[alg].id != alg) /* sanity */ | 70 | if (digests[alg].id != alg) /* sanity */ |
63 | return NULL; | 71 | return NULL; |
72 | if (digests[alg].mdfunc == NULL) | ||
73 | return NULL; | ||
64 | return &(digests[alg]); | 74 | return &(digests[alg]); |
65 | } | 75 | } |
66 | 76 | ||
@@ -98,9 +108,11 @@ ssh_digest_start(int alg) | |||
98 | int | 108 | int |
99 | ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) | 109 | ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) |
100 | { | 110 | { |
111 | if (from->alg != to->alg) | ||
112 | return SSH_ERR_INVALID_ARGUMENT; | ||
101 | /* we have bcopy-style order while openssl has memcpy-style */ | 113 | /* we have bcopy-style order while openssl has memcpy-style */ |
102 | if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx)) | 114 | if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx)) |
103 | return -1; | 115 | return SSH_ERR_LIBCRYPTO_ERROR; |
104 | return 0; | 116 | return 0; |
105 | } | 117 | } |
106 | 118 | ||
@@ -108,14 +120,14 @@ int | |||
108 | ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) | 120 | ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) |
109 | { | 121 | { |
110 | if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) | 122 | if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) |
111 | return -1; | 123 | return SSH_ERR_LIBCRYPTO_ERROR; |
112 | return 0; | 124 | return 0; |
113 | } | 125 | } |
114 | 126 | ||
115 | int | 127 | int |
116 | ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) | 128 | ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b) |
117 | { | 129 | { |
118 | return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); | 130 | return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b)); |
119 | } | 131 | } |
120 | 132 | ||
121 | int | 133 | int |
@@ -125,13 +137,13 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) | |||
125 | u_int l = dlen; | 137 | u_int l = dlen; |
126 | 138 | ||
127 | if (dlen > UINT_MAX) | 139 | if (dlen > UINT_MAX) |
128 | return -1; | 140 | return SSH_ERR_INVALID_ARGUMENT; |
129 | if (dlen < digest->digest_len) /* No truncation allowed */ | 141 | if (dlen < digest->digest_len) /* No truncation allowed */ |
130 | return -1; | 142 | return SSH_ERR_INVALID_ARGUMENT; |
131 | if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) | 143 | if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) |
132 | return -1; | 144 | return SSH_ERR_LIBCRYPTO_ERROR; |
133 | if (l != digest->digest_len) /* sanity */ | 145 | if (l != digest->digest_len) /* sanity */ |
134 | return -1; | 146 | return SSH_ERR_INTERNAL_ERROR; |
135 | return 0; | 147 | return 0; |
136 | } | 148 | } |
137 | 149 | ||
@@ -148,19 +160,23 @@ ssh_digest_free(struct ssh_digest_ctx *ctx) | |||
148 | int | 160 | int |
149 | ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) | 161 | ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) |
150 | { | 162 | { |
151 | struct ssh_digest_ctx *ctx = ssh_digest_start(alg); | 163 | const struct ssh_digest *digest = ssh_digest_by_alg(alg); |
152 | 164 | u_int mdlen; | |
153 | if (ctx == NULL) | 165 | |
154 | return -1; | 166 | if (digest == NULL) |
155 | if (ssh_digest_update(ctx, m, mlen) != 0 || | 167 | return SSH_ERR_INVALID_ARGUMENT; |
156 | ssh_digest_final(ctx, d, dlen) != 0) | 168 | if (dlen > UINT_MAX) |
157 | return -1; | 169 | return SSH_ERR_INVALID_ARGUMENT; |
158 | ssh_digest_free(ctx); | 170 | if (dlen < digest->digest_len) |
171 | return SSH_ERR_INVALID_ARGUMENT; | ||
172 | mdlen = dlen; | ||
173 | if (!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL)) | ||
174 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
159 | return 0; | 175 | return 0; |
160 | } | 176 | } |
161 | 177 | ||
162 | int | 178 | int |
163 | ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) | 179 | ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) |
164 | { | 180 | { |
165 | return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); | 181 | return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen); |
166 | } | 182 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: digest.h,v 1.2 2014/01/27 18:58:14 markus Exp $ */ | 1 | /* $OpenBSD: digest.h,v 1.6 2014/07/03 04:36:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2013 Damien Miller <djm@mindrot.org> | 3 | * Copyright (c) 2013 Damien Miller <djm@mindrot.org> |
4 | * | 4 | * |
@@ -30,6 +30,7 @@ | |||
30 | #define SSH_DIGEST_SHA512 5 | 30 | #define SSH_DIGEST_SHA512 5 |
31 | #define SSH_DIGEST_MAX 6 | 31 | #define SSH_DIGEST_MAX 6 |
32 | 32 | ||
33 | struct sshbuf; | ||
33 | struct ssh_digest_ctx; | 34 | struct ssh_digest_ctx; |
34 | 35 | ||
35 | /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ | 36 | /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ |
@@ -47,14 +48,15 @@ int ssh_digest_memory(int alg, const void *m, size_t mlen, | |||
47 | u_char *d, size_t dlen) | 48 | u_char *d, size_t dlen) |
48 | __attribute__((__bounded__(__buffer__, 2, 3))) | 49 | __attribute__((__bounded__(__buffer__, 2, 3))) |
49 | __attribute__((__bounded__(__buffer__, 4, 5))); | 50 | __attribute__((__bounded__(__buffer__, 4, 5))); |
50 | int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) | 51 | int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) |
51 | __attribute__((__bounded__(__buffer__, 3, 4))); | 52 | __attribute__((__bounded__(__buffer__, 3, 4))); |
52 | 53 | ||
53 | /* Update API */ | 54 | /* Update API */ |
54 | struct ssh_digest_ctx *ssh_digest_start(int alg); | 55 | struct ssh_digest_ctx *ssh_digest_start(int alg); |
55 | int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) | 56 | int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) |
56 | __attribute__((__bounded__(__buffer__, 2, 3))); | 57 | __attribute__((__bounded__(__buffer__, 2, 3))); |
57 | int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b); | 58 | int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, |
59 | const struct sshbuf *b); | ||
58 | int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) | 60 | int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) |
59 | __attribute__((__bounded__(__buffer__, 2, 3))); | 61 | __attribute__((__bounded__(__buffer__, 2, 3))); |
60 | void ssh_digest_free(struct ssh_digest_ctx *ctx); | 62 | void ssh_digest_free(struct ssh_digest_ctx *ctx); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dns.c,v 1.29 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2003 Wesley Griffin. All rights reserved. | 4 | * Copyright (c) 2003 Wesley Griffin. All rights reserved. |
@@ -34,6 +34,8 @@ | |||
34 | #include <stdarg.h> | 34 | #include <stdarg.h> |
35 | #include <stdio.h> | 35 | #include <stdio.h> |
36 | #include <string.h> | 36 | #include <string.h> |
37 | #include <stdarg.h> | ||
38 | #include <stdlib.h> | ||
37 | 39 | ||
38 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
39 | #include "key.h" | 41 | #include "key.h" |
@@ -96,6 +98,11 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, | |||
96 | if (!*digest_type) | 98 | if (!*digest_type) |
97 | *digest_type = SSHFP_HASH_SHA256; | 99 | *digest_type = SSHFP_HASH_SHA256; |
98 | break; | 100 | break; |
101 | case KEY_ED25519: | ||
102 | *algorithm = SSHFP_KEY_ED25519; | ||
103 | if (!*digest_type) | ||
104 | *digest_type = SSHFP_HASH_SHA256; | ||
105 | break; | ||
99 | default: | 106 | default: |
100 | *algorithm = SSHFP_KEY_RESERVED; /* 0 */ | 107 | *algorithm = SSHFP_KEY_RESERVED; /* 0 */ |
101 | *digest_type = SSHFP_HASH_RESERVED; /* 0 */ | 108 | *digest_type = SSHFP_HASH_RESERVED; /* 0 */ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dns.h,v 1.12 2012/05/23 03:28:28 djm Exp $ */ | 1 | /* $OpenBSD: dns.h,v 1.13 2014/04/20 09:24:26 logan Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2003 Wesley Griffin. All rights reserved. | 4 | * Copyright (c) 2003 Wesley Griffin. All rights reserved. |
@@ -32,7 +32,8 @@ enum sshfp_types { | |||
32 | SSHFP_KEY_RESERVED = 0, | 32 | SSHFP_KEY_RESERVED = 0, |
33 | SSHFP_KEY_RSA = 1, | 33 | SSHFP_KEY_RSA = 1, |
34 | SSHFP_KEY_DSA = 2, | 34 | SSHFP_KEY_DSA = 2, |
35 | SSHFP_KEY_ECDSA = 3 | 35 | SSHFP_KEY_ECDSA = 3, |
36 | SSHFP_KEY_ED25519 = 4 | ||
36 | }; | 37 | }; |
37 | 38 | ||
38 | enum sshfp_hashes { | 39 | enum sshfp_hashes { |
@@ -43,6 +43,8 @@ | |||
43 | #include <openssl/crypto.h> | 43 | #include <openssl/crypto.h> |
44 | #include <openssl/err.h> | 44 | #include <openssl/err.h> |
45 | 45 | ||
46 | #include "openbsd-compat/openssl-compat.h" | ||
47 | |||
46 | #include "ssh.h" | 48 | #include "ssh.h" |
47 | #include "misc.h" | 49 | #include "misc.h" |
48 | #include "xmalloc.h" | 50 | #include "xmalloc.h" |
@@ -209,6 +211,9 @@ seed_rng(void) | |||
209 | #ifndef OPENSSL_PRNG_ONLY | 211 | #ifndef OPENSSL_PRNG_ONLY |
210 | unsigned char buf[RANDOM_SEED_SIZE]; | 212 | unsigned char buf[RANDOM_SEED_SIZE]; |
211 | #endif | 213 | #endif |
214 | if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, SSLeay())) | ||
215 | fatal("OpenSSL version mismatch. Built against %lx, you " | ||
216 | "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); | ||
212 | 217 | ||
213 | #ifndef OPENSSL_PRNG_ONLY | 218 | #ifndef OPENSSL_PRNG_ONLY |
214 | if (RAND_status() == 1) { | 219 | if (RAND_status() == 1) { |
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c index e678a2757..fd8b37183 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "hostfile.h" | 39 | #include "hostfile.h" |
40 | #include "auth.h" | 40 | #include "auth.h" |
41 | #include "log.h" | 41 | #include "log.h" |
42 | #include "misc.h" | ||
42 | #include "servconf.h" | 43 | #include "servconf.h" |
43 | 44 | ||
44 | #include "buffer.h" | 45 | #include "buffer.h" |
diff --git a/gss-serv.c b/gss-serv.c index c33463bdf..50fa43834 100644 --- a/gss-serv.c +++ b/gss-serv.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */ | 1 | /* $OpenBSD: gss-serv.c,v 1.27 2014/07/03 03:34:09 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. | 4 | * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. |
@@ -103,14 +103,14 @@ static OM_uint32 | |||
103 | ssh_gssapi_acquire_cred(Gssctxt *ctx) | 103 | ssh_gssapi_acquire_cred(Gssctxt *ctx) |
104 | { | 104 | { |
105 | OM_uint32 status; | 105 | OM_uint32 status; |
106 | char lname[MAXHOSTNAMELEN]; | 106 | char lname[NI_MAXHOST]; |
107 | gss_OID_set oidset; | 107 | gss_OID_set oidset; |
108 | 108 | ||
109 | if (options.gss_strict_acceptor) { | 109 | if (options.gss_strict_acceptor) { |
110 | gss_create_empty_oid_set(&status, &oidset); | 110 | gss_create_empty_oid_set(&status, &oidset); |
111 | gss_add_oid_set_member(&status, ctx->oid, &oidset); | 111 | gss_add_oid_set_member(&status, ctx->oid, &oidset); |
112 | 112 | ||
113 | if (gethostname(lname, MAXHOSTNAMELEN)) { | 113 | if (gethostname(lname, sizeof(lname))) { |
114 | gss_release_oid_set(&status, &oidset); | 114 | gss_release_oid_set(&status, &oidset); |
115 | return (-1); | 115 | return (-1); |
116 | } | 116 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: hmac.h,v 1.6 2014/01/27 18:58:14 markus Exp $ */ | 1 | /* $OpenBSD: hmac.h,v 1.9 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2014 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -21,6 +21,7 @@ | |||
21 | /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ | 21 | /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ |
22 | size_t ssh_hmac_bytes(int alg); | 22 | size_t ssh_hmac_bytes(int alg); |
23 | 23 | ||
24 | struct sshbuf; | ||
24 | struct ssh_hmac_ctx; | 25 | struct ssh_hmac_ctx; |
25 | struct ssh_hmac_ctx *ssh_hmac_start(int alg); | 26 | struct ssh_hmac_ctx *ssh_hmac_start(int alg); |
26 | 27 | ||
@@ -29,7 +30,7 @@ int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen) | |||
29 | __attribute__((__bounded__(__buffer__, 2, 3))); | 30 | __attribute__((__bounded__(__buffer__, 2, 3))); |
30 | int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen) | 31 | int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen) |
31 | __attribute__((__bounded__(__buffer__, 2, 3))); | 32 | __attribute__((__bounded__(__buffer__, 2, 3))); |
32 | int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b); | 33 | int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b); |
33 | int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen) | 34 | int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen) |
34 | __attribute__((__bounded__(__buffer__, 2, 3))); | 35 | __attribute__((__bounded__(__buffer__, 2, 3))); |
35 | void ssh_hmac_free(struct ssh_hmac_ctx *ctx); | 36 | void ssh_hmac_free(struct ssh_hmac_ctx *ctx); |
diff --git a/hostfile.c b/hostfile.c index 8bc9540b7..ee2daf45f 100644 --- a/hostfile.c +++ b/hostfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: hostfile.c,v 1.55 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: hostfile.c,v 1.57 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -47,6 +47,7 @@ | |||
47 | #include <stdio.h> | 47 | #include <stdio.h> |
48 | #include <stdlib.h> | 48 | #include <stdlib.h> |
49 | #include <string.h> | 49 | #include <string.h> |
50 | #include <stdarg.h> | ||
50 | 51 | ||
51 | #include "xmalloc.h" | 52 | #include "xmalloc.h" |
52 | #include "match.h" | 53 | #include "match.h" |
@@ -182,6 +183,7 @@ static int | |||
182 | hostfile_check_key(int bits, const Key *key, const char *host, | 183 | hostfile_check_key(int bits, const Key *key, const char *host, |
183 | const char *filename, u_long linenum) | 184 | const char *filename, u_long linenum) |
184 | { | 185 | { |
186 | #ifdef WITH_SSH1 | ||
185 | if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL) | 187 | if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL) |
186 | return 1; | 188 | return 1; |
187 | if (bits != BN_num_bits(key->rsa->n)) { | 189 | if (bits != BN_num_bits(key->rsa->n)) { |
@@ -191,6 +193,7 @@ hostfile_check_key(int bits, const Key *key, const char *host, | |||
191 | logit("Warning: replace %d with %d in %s, line %lu.", | 193 | logit("Warning: replace %d with %d in %s, line %lu.", |
192 | bits, BN_num_bits(key->rsa->n), filename, linenum); | 194 | bits, BN_num_bits(key->rsa->n), filename, linenum); |
193 | } | 195 | } |
196 | #endif | ||
194 | return 1; | 197 | return 1; |
195 | } | 198 | } |
196 | 199 | ||
@@ -296,11 +299,15 @@ load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) | |||
296 | key = key_new(KEY_UNSPEC); | 299 | key = key_new(KEY_UNSPEC); |
297 | if (!hostfile_read_key(&cp, &kbits, key)) { | 300 | if (!hostfile_read_key(&cp, &kbits, key)) { |
298 | key_free(key); | 301 | key_free(key); |
302 | #ifdef WITH_SSH1 | ||
299 | key = key_new(KEY_RSA1); | 303 | key = key_new(KEY_RSA1); |
300 | if (!hostfile_read_key(&cp, &kbits, key)) { | 304 | if (!hostfile_read_key(&cp, &kbits, key)) { |
301 | key_free(key); | 305 | key_free(key); |
302 | continue; | 306 | continue; |
303 | } | 307 | } |
308 | #else | ||
309 | continue; | ||
310 | #endif | ||
304 | } | 311 | } |
305 | if (!hostfile_check_key(kbits, key, host, path, linenum)) | 312 | if (!hostfile_check_key(kbits, key, host, path, linenum)) |
306 | continue; | 313 | continue; |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.98 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.99 2014/04/29 18:01:49 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -33,7 +33,9 @@ | |||
33 | #include <stdlib.h> | 33 | #include <stdlib.h> |
34 | #include <string.h> | 34 | #include <string.h> |
35 | 35 | ||
36 | #ifdef WITH_OPENSSL | ||
36 | #include <openssl/crypto.h> | 37 | #include <openssl/crypto.h> |
38 | #endif | ||
37 | 39 | ||
38 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
39 | #include "ssh2.h" | 41 | #include "ssh2.h" |
@@ -74,12 +76,13 @@ struct kexalg { | |||
74 | int hash_alg; | 76 | int hash_alg; |
75 | }; | 77 | }; |
76 | static const struct kexalg kexalgs[] = { | 78 | static const struct kexalg kexalgs[] = { |
79 | #ifdef WITH_OPENSSL | ||
77 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, | 80 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, |
78 | { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, | 81 | { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, |
79 | { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, | 82 | { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, |
80 | #ifdef HAVE_EVP_SHA256 | 83 | #ifdef HAVE_EVP_SHA256 |
81 | { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, | 84 | { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, |
82 | #endif | 85 | #endif /* HAVE_EVP_SHA256 */ |
83 | #ifdef OPENSSL_HAS_ECC | 86 | #ifdef OPENSSL_HAS_ECC |
84 | { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, | 87 | { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, |
85 | NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, | 88 | NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, |
@@ -88,12 +91,13 @@ static const struct kexalg kexalgs[] = { | |||
88 | # ifdef OPENSSL_HAS_NISTP521 | 91 | # ifdef OPENSSL_HAS_NISTP521 |
89 | { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, | 92 | { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, |
90 | SSH_DIGEST_SHA512 }, | 93 | SSH_DIGEST_SHA512 }, |
91 | # endif | 94 | # endif /* OPENSSL_HAS_NISTP521 */ |
92 | #endif | 95 | #endif /* OPENSSL_HAS_ECC */ |
93 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, | 96 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, |
97 | #endif /* WITH_OPENSSL */ | ||
94 | #ifdef HAVE_EVP_SHA256 | 98 | #ifdef HAVE_EVP_SHA256 |
95 | { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, | 99 | { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, |
96 | #endif | 100 | #endif /* HAVE_EVP_SHA256 */ |
97 | { NULL, -1, -1, -1}, | 101 | { NULL, -1, -1, -1}, |
98 | }; | 102 | }; |
99 | static const struct kexalg kexalg_prefixes[] = { | 103 | static const struct kexalg kexalg_prefixes[] = { |
@@ -631,6 +635,7 @@ kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, | |||
631 | } | 635 | } |
632 | } | 636 | } |
633 | 637 | ||
638 | #ifdef WITH_OPENSSL | ||
634 | void | 639 | void |
635 | kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) | 640 | kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) |
636 | { | 641 | { |
@@ -642,6 +647,7 @@ kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) | |||
642 | buffer_ptr(&shared_secret), buffer_len(&shared_secret)); | 647 | buffer_ptr(&shared_secret), buffer_len(&shared_secret)); |
643 | buffer_free(&shared_secret); | 648 | buffer_free(&shared_secret); |
644 | } | 649 | } |
650 | #endif | ||
645 | 651 | ||
646 | Newkeys * | 652 | Newkeys * |
647 | kex_get_newkeys(int mode) | 653 | kex_get_newkeys(int mode) |
@@ -653,6 +659,7 @@ kex_get_newkeys(int mode) | |||
653 | return ret; | 659 | return ret; |
654 | } | 660 | } |
655 | 661 | ||
662 | #ifdef WITH_SSH1 | ||
656 | void | 663 | void |
657 | derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, | 664 | derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, |
658 | u_int8_t cookie[8], u_int8_t id[16]) | 665 | u_int8_t cookie[8], u_int8_t id[16]) |
@@ -685,6 +692,7 @@ derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, | |||
685 | explicit_bzero(nbuf, sizeof(nbuf)); | 692 | explicit_bzero(nbuf, sizeof(nbuf)); |
686 | explicit_bzero(obuf, sizeof(obuf)); | 693 | explicit_bzero(obuf, sizeof(obuf)); |
687 | } | 694 | } |
695 | #endif | ||
688 | 696 | ||
689 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) | 697 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) |
690 | void | 698 | void |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.h,v 1.62 2014/01/27 18:58:14 markus Exp $ */ | 1 | /* $OpenBSD: kex.h,v 1.64 2014/05/02 03:27:54 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
diff --git a/kexc25519.c b/kexc25519.c index ee79b4327..e3afa0055 100644 --- a/kexc25519.c +++ b/kexc25519.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexc25519.c,v 1.5 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: kexc25519.c,v 1.7 2014/05/02 03:27:54 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -42,6 +42,7 @@ | |||
42 | #include "dh.h" | 42 | #include "dh.h" |
43 | #include "ssh-gss.h" | 43 | #include "ssh-gss.h" |
44 | #include "monitor_wrap.h" | 44 | #include "monitor_wrap.h" |
45 | #include "misc.h" | ||
45 | #include "servconf.h" | 46 | #include "servconf.h" |
46 | 47 | ||
47 | extern ServerOptions options; | 48 | extern ServerOptions options; |
@@ -1,2090 +1,242 @@ | |||
1 | /* $OpenBSD: key.c,v 1.116 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: key.c,v 1.122 2014/07/22 01:18:50 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * read_bignum(): | 3 | * placed in the public domain |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
5 | * | ||
6 | * As far as I am concerned, the code I have written for this software | ||
7 | * can be used freely for any purpose. Any derived versions of this | ||
8 | * software must be clearly marked as such, and if the derived work is | ||
9 | * incompatible with the protocol description in the RFC file, it must be | ||
10 | * called by a name other than "ssh" or "Secure Shell". | ||
11 | * | ||
12 | * | ||
13 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | ||
14 | * Copyright (c) 2008 Alexander von Gernler. 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 | */ | 4 | */ |
36 | 5 | ||
37 | #include "includes.h" | 6 | #include "includes.h" |
38 | 7 | ||
39 | #include <sys/param.h> | 8 | #include <sys/param.h> |
40 | #include <sys/types.h> | 9 | #include <sys/types.h> |
41 | 10 | #include <errno.h> | |
42 | #include "crypto_api.h" | ||
43 | |||
44 | #include <openssl/evp.h> | ||
45 | #include <openbsd-compat/openssl-compat.h> | ||
46 | |||
47 | #include <stdarg.h> | 11 | #include <stdarg.h> |
48 | #include <stdio.h> | 12 | #include <stdio.h> |
49 | #include <string.h> | ||
50 | 13 | ||
51 | #include "xmalloc.h" | 14 | #define SSH_KEY_NO_DEFINE |
52 | #include "key.h" | 15 | #include "key.h" |
53 | #include "rsa.h" | ||
54 | #include "uuencode.h" | ||
55 | #include "buffer.h" | ||
56 | #include "log.h" | ||
57 | #include "misc.h" | ||
58 | #include "ssh2.h" | ||
59 | #include "digest.h" | ||
60 | |||
61 | static int to_blob(const Key *, u_char **, u_int *, int); | ||
62 | static Key *key_from_blob2(const u_char *, u_int, int); | ||
63 | |||
64 | static struct KeyCert * | ||
65 | cert_new(void) | ||
66 | { | ||
67 | struct KeyCert *cert; | ||
68 | |||
69 | cert = xcalloc(1, sizeof(*cert)); | ||
70 | buffer_init(&cert->certblob); | ||
71 | buffer_init(&cert->critical); | ||
72 | buffer_init(&cert->extensions); | ||
73 | cert->key_id = NULL; | ||
74 | cert->principals = NULL; | ||
75 | cert->signature_key = NULL; | ||
76 | return cert; | ||
77 | } | ||
78 | |||
79 | Key * | ||
80 | key_new(int type) | ||
81 | { | ||
82 | Key *k; | ||
83 | RSA *rsa; | ||
84 | DSA *dsa; | ||
85 | k = xcalloc(1, sizeof(*k)); | ||
86 | k->type = type; | ||
87 | k->ecdsa = NULL; | ||
88 | k->ecdsa_nid = -1; | ||
89 | k->dsa = NULL; | ||
90 | k->rsa = NULL; | ||
91 | k->cert = NULL; | ||
92 | k->ed25519_sk = NULL; | ||
93 | k->ed25519_pk = NULL; | ||
94 | switch (k->type) { | ||
95 | case KEY_RSA1: | ||
96 | case KEY_RSA: | ||
97 | case KEY_RSA_CERT_V00: | ||
98 | case KEY_RSA_CERT: | ||
99 | if ((rsa = RSA_new()) == NULL) | ||
100 | fatal("key_new: RSA_new failed"); | ||
101 | if ((rsa->n = BN_new()) == NULL) | ||
102 | fatal("key_new: BN_new failed"); | ||
103 | if ((rsa->e = BN_new()) == NULL) | ||
104 | fatal("key_new: BN_new failed"); | ||
105 | k->rsa = rsa; | ||
106 | break; | ||
107 | case KEY_DSA: | ||
108 | case KEY_DSA_CERT_V00: | ||
109 | case KEY_DSA_CERT: | ||
110 | if ((dsa = DSA_new()) == NULL) | ||
111 | fatal("key_new: DSA_new failed"); | ||
112 | if ((dsa->p = BN_new()) == NULL) | ||
113 | fatal("key_new: BN_new failed"); | ||
114 | if ((dsa->q = BN_new()) == NULL) | ||
115 | fatal("key_new: BN_new failed"); | ||
116 | if ((dsa->g = BN_new()) == NULL) | ||
117 | fatal("key_new: BN_new failed"); | ||
118 | if ((dsa->pub_key = BN_new()) == NULL) | ||
119 | fatal("key_new: BN_new failed"); | ||
120 | k->dsa = dsa; | ||
121 | break; | ||
122 | #ifdef OPENSSL_HAS_ECC | ||
123 | case KEY_ECDSA: | ||
124 | case KEY_ECDSA_CERT: | ||
125 | /* Cannot do anything until we know the group */ | ||
126 | break; | ||
127 | #endif | ||
128 | case KEY_ED25519: | ||
129 | case KEY_ED25519_CERT: | ||
130 | /* no need to prealloc */ | ||
131 | break; | ||
132 | case KEY_UNSPEC: | ||
133 | break; | ||
134 | default: | ||
135 | fatal("key_new: bad key type %d", k->type); | ||
136 | break; | ||
137 | } | ||
138 | 16 | ||
139 | if (key_is_cert(k)) | 17 | #include "compat.h" |
140 | k->cert = cert_new(); | 18 | #include "sshkey.h" |
141 | 19 | #include "ssherr.h" | |
142 | return k; | 20 | #include "log.h" |
143 | } | 21 | #include "authfile.h" |
144 | 22 | ||
145 | void | 23 | void |
146 | key_add_private(Key *k) | 24 | key_add_private(Key *k) |
147 | { | 25 | { |
148 | switch (k->type) { | 26 | int r; |
149 | case KEY_RSA1: | 27 | |
150 | case KEY_RSA: | 28 | if ((r = sshkey_add_private(k)) != 0) |
151 | case KEY_RSA_CERT_V00: | 29 | fatal("%s: %s", __func__, ssh_err(r)); |
152 | case KEY_RSA_CERT: | ||
153 | if ((k->rsa->d = BN_new()) == NULL) | ||
154 | fatal("key_new_private: BN_new failed"); | ||
155 | if ((k->rsa->iqmp = BN_new()) == NULL) | ||
156 | fatal("key_new_private: BN_new failed"); | ||
157 | if ((k->rsa->q = BN_new()) == NULL) | ||
158 | fatal("key_new_private: BN_new failed"); | ||
159 | if ((k->rsa->p = BN_new()) == NULL) | ||
160 | fatal("key_new_private: BN_new failed"); | ||
161 | if ((k->rsa->dmq1 = BN_new()) == NULL) | ||
162 | fatal("key_new_private: BN_new failed"); | ||
163 | if ((k->rsa->dmp1 = BN_new()) == NULL) | ||
164 | fatal("key_new_private: BN_new failed"); | ||
165 | break; | ||
166 | case KEY_DSA: | ||
167 | case KEY_DSA_CERT_V00: | ||
168 | case KEY_DSA_CERT: | ||
169 | if ((k->dsa->priv_key = BN_new()) == NULL) | ||
170 | fatal("key_new_private: BN_new failed"); | ||
171 | break; | ||
172 | case KEY_ECDSA: | ||
173 | case KEY_ECDSA_CERT: | ||
174 | /* Cannot do anything until we know the group */ | ||
175 | break; | ||
176 | case KEY_ED25519: | ||
177 | case KEY_ED25519_CERT: | ||
178 | /* no need to prealloc */ | ||
179 | break; | ||
180 | case KEY_UNSPEC: | ||
181 | break; | ||
182 | default: | ||
183 | break; | ||
184 | } | ||
185 | } | 30 | } |
186 | 31 | ||
187 | Key * | 32 | Key * |
188 | key_new_private(int type) | 33 | key_new_private(int type) |
189 | { | 34 | { |
190 | Key *k = key_new(type); | 35 | Key *ret = NULL; |
191 | |||
192 | key_add_private(k); | ||
193 | return k; | ||
194 | } | ||
195 | |||
196 | static void | ||
197 | cert_free(struct KeyCert *cert) | ||
198 | { | ||
199 | u_int i; | ||
200 | |||
201 | buffer_free(&cert->certblob); | ||
202 | buffer_free(&cert->critical); | ||
203 | buffer_free(&cert->extensions); | ||
204 | free(cert->key_id); | ||
205 | for (i = 0; i < cert->nprincipals; i++) | ||
206 | free(cert->principals[i]); | ||
207 | free(cert->principals); | ||
208 | if (cert->signature_key != NULL) | ||
209 | key_free(cert->signature_key); | ||
210 | free(cert); | ||
211 | } | ||
212 | |||
213 | void | ||
214 | key_free(Key *k) | ||
215 | { | ||
216 | if (k == NULL) | ||
217 | fatal("key_free: key is NULL"); | ||
218 | switch (k->type) { | ||
219 | case KEY_RSA1: | ||
220 | case KEY_RSA: | ||
221 | case KEY_RSA_CERT_V00: | ||
222 | case KEY_RSA_CERT: | ||
223 | if (k->rsa != NULL) | ||
224 | RSA_free(k->rsa); | ||
225 | k->rsa = NULL; | ||
226 | break; | ||
227 | case KEY_DSA: | ||
228 | case KEY_DSA_CERT_V00: | ||
229 | case KEY_DSA_CERT: | ||
230 | if (k->dsa != NULL) | ||
231 | DSA_free(k->dsa); | ||
232 | k->dsa = NULL; | ||
233 | break; | ||
234 | #ifdef OPENSSL_HAS_ECC | ||
235 | case KEY_ECDSA: | ||
236 | case KEY_ECDSA_CERT: | ||
237 | if (k->ecdsa != NULL) | ||
238 | EC_KEY_free(k->ecdsa); | ||
239 | k->ecdsa = NULL; | ||
240 | break; | ||
241 | #endif | ||
242 | case KEY_ED25519: | ||
243 | case KEY_ED25519_CERT: | ||
244 | if (k->ed25519_pk) { | ||
245 | explicit_bzero(k->ed25519_pk, ED25519_PK_SZ); | ||
246 | free(k->ed25519_pk); | ||
247 | k->ed25519_pk = NULL; | ||
248 | } | ||
249 | if (k->ed25519_sk) { | ||
250 | explicit_bzero(k->ed25519_sk, ED25519_SK_SZ); | ||
251 | free(k->ed25519_sk); | ||
252 | k->ed25519_sk = NULL; | ||
253 | } | ||
254 | break; | ||
255 | case KEY_UNSPEC: | ||
256 | break; | ||
257 | default: | ||
258 | fatal("key_free: bad key type %d", k->type); | ||
259 | break; | ||
260 | } | ||
261 | if (key_is_cert(k)) { | ||
262 | if (k->cert != NULL) | ||
263 | cert_free(k->cert); | ||
264 | k->cert = NULL; | ||
265 | } | ||
266 | |||
267 | free(k); | ||
268 | } | ||
269 | |||
270 | static int | ||
271 | cert_compare(struct KeyCert *a, struct KeyCert *b) | ||
272 | { | ||
273 | if (a == NULL && b == NULL) | ||
274 | return 1; | ||
275 | if (a == NULL || b == NULL) | ||
276 | return 0; | ||
277 | if (buffer_len(&a->certblob) != buffer_len(&b->certblob)) | ||
278 | return 0; | ||
279 | if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob), | ||
280 | buffer_len(&a->certblob)) != 0) | ||
281 | return 0; | ||
282 | return 1; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Compare public portions of key only, allowing comparisons between | ||
287 | * certificates and plain keys too. | ||
288 | */ | ||
289 | int | ||
290 | key_equal_public(const Key *a, const Key *b) | ||
291 | { | ||
292 | #ifdef OPENSSL_HAS_ECC | ||
293 | BN_CTX *bnctx; | ||
294 | #endif | ||
295 | 36 | ||
296 | if (a == NULL || b == NULL || | 37 | if ((ret = sshkey_new_private(type)) == NULL) |
297 | key_type_plain(a->type) != key_type_plain(b->type)) | 38 | fatal("%s: failed", __func__); |
298 | return 0; | 39 | return ret; |
299 | |||
300 | switch (a->type) { | ||
301 | case KEY_RSA1: | ||
302 | case KEY_RSA_CERT_V00: | ||
303 | case KEY_RSA_CERT: | ||
304 | case KEY_RSA: | ||
305 | return a->rsa != NULL && b->rsa != NULL && | ||
306 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && | ||
307 | BN_cmp(a->rsa->n, b->rsa->n) == 0; | ||
308 | case KEY_DSA_CERT_V00: | ||
309 | case KEY_DSA_CERT: | ||
310 | case KEY_DSA: | ||
311 | return a->dsa != NULL && b->dsa != NULL && | ||
312 | BN_cmp(a->dsa->p, b->dsa->p) == 0 && | ||
313 | BN_cmp(a->dsa->q, b->dsa->q) == 0 && | ||
314 | BN_cmp(a->dsa->g, b->dsa->g) == 0 && | ||
315 | BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; | ||
316 | #ifdef OPENSSL_HAS_ECC | ||
317 | case KEY_ECDSA_CERT: | ||
318 | case KEY_ECDSA: | ||
319 | if (a->ecdsa == NULL || b->ecdsa == NULL || | ||
320 | EC_KEY_get0_public_key(a->ecdsa) == NULL || | ||
321 | EC_KEY_get0_public_key(b->ecdsa) == NULL) | ||
322 | return 0; | ||
323 | if ((bnctx = BN_CTX_new()) == NULL) | ||
324 | fatal("%s: BN_CTX_new failed", __func__); | ||
325 | if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa), | ||
326 | EC_KEY_get0_group(b->ecdsa), bnctx) != 0 || | ||
327 | EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa), | ||
328 | EC_KEY_get0_public_key(a->ecdsa), | ||
329 | EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) { | ||
330 | BN_CTX_free(bnctx); | ||
331 | return 0; | ||
332 | } | ||
333 | BN_CTX_free(bnctx); | ||
334 | return 1; | ||
335 | #endif /* OPENSSL_HAS_ECC */ | ||
336 | case KEY_ED25519: | ||
337 | case KEY_ED25519_CERT: | ||
338 | return a->ed25519_pk != NULL && b->ed25519_pk != NULL && | ||
339 | memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0; | ||
340 | default: | ||
341 | fatal("key_equal: bad key type %d", a->type); | ||
342 | } | ||
343 | /* NOTREACHED */ | ||
344 | } | ||
345 | |||
346 | int | ||
347 | key_equal(const Key *a, const Key *b) | ||
348 | { | ||
349 | if (a == NULL || b == NULL || a->type != b->type) | ||
350 | return 0; | ||
351 | if (key_is_cert(a)) { | ||
352 | if (!cert_compare(a->cert, b->cert)) | ||
353 | return 0; | ||
354 | } | ||
355 | return key_equal_public(a, b); | ||
356 | } | 40 | } |
357 | 41 | ||
358 | u_char* | 42 | u_char* |
359 | key_fingerprint_raw(const Key *k, enum fp_type dgst_type, | 43 | key_fingerprint_raw(const Key *k, enum fp_type dgst_type, |
360 | u_int *dgst_raw_length) | 44 | u_int *dgst_raw_length) |
361 | { | 45 | { |
362 | u_char *blob = NULL; | 46 | u_char *ret = NULL; |
363 | u_char *retval = NULL; | 47 | size_t dlen; |
364 | u_int len = 0; | 48 | int r; |
365 | int nlen, elen, hash_alg = -1; | 49 | |
366 | 50 | if (dgst_raw_length != NULL) | |
367 | *dgst_raw_length = 0; | 51 | *dgst_raw_length = 0; |
368 | 52 | if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0) | |
369 | /* XXX switch to DIGEST_* directly? */ | 53 | fatal("%s: %s", __func__, ssh_err(r)); |
370 | switch (dgst_type) { | 54 | if (dlen > INT_MAX) |
371 | case SSH_FP_MD5: | 55 | fatal("%s: giant len %zu", __func__, dlen); |
372 | hash_alg = SSH_DIGEST_MD5; | 56 | *dgst_raw_length = dlen; |
373 | break; | 57 | return ret; |
374 | case SSH_FP_SHA1: | ||
375 | hash_alg = SSH_DIGEST_SHA1; | ||
376 | break; | ||
377 | case SSH_FP_SHA256: | ||
378 | hash_alg = SSH_DIGEST_SHA256; | ||
379 | break; | ||
380 | default: | ||
381 | fatal("%s: bad digest type %d", __func__, dgst_type); | ||
382 | } | ||
383 | switch (k->type) { | ||
384 | case KEY_RSA1: | ||
385 | nlen = BN_num_bytes(k->rsa->n); | ||
386 | elen = BN_num_bytes(k->rsa->e); | ||
387 | len = nlen + elen; | ||
388 | blob = xmalloc(len); | ||
389 | BN_bn2bin(k->rsa->n, blob); | ||
390 | BN_bn2bin(k->rsa->e, blob + nlen); | ||
391 | break; | ||
392 | case KEY_DSA: | ||
393 | case KEY_ECDSA: | ||
394 | case KEY_RSA: | ||
395 | case KEY_ED25519: | ||
396 | key_to_blob(k, &blob, &len); | ||
397 | break; | ||
398 | case KEY_DSA_CERT_V00: | ||
399 | case KEY_RSA_CERT_V00: | ||
400 | case KEY_DSA_CERT: | ||
401 | case KEY_ECDSA_CERT: | ||
402 | case KEY_RSA_CERT: | ||
403 | case KEY_ED25519_CERT: | ||
404 | /* We want a fingerprint of the _key_ not of the cert */ | ||
405 | to_blob(k, &blob, &len, 1); | ||
406 | break; | ||
407 | case KEY_UNSPEC: | ||
408 | return retval; | ||
409 | default: | ||
410 | fatal("%s: bad key type %d", __func__, k->type); | ||
411 | break; | ||
412 | } | ||
413 | if (blob != NULL) { | ||
414 | retval = xmalloc(SSH_DIGEST_MAX_LENGTH); | ||
415 | if ((ssh_digest_memory(hash_alg, blob, len, | ||
416 | retval, SSH_DIGEST_MAX_LENGTH)) != 0) | ||
417 | fatal("%s: digest_memory failed", __func__); | ||
418 | explicit_bzero(blob, len); | ||
419 | free(blob); | ||
420 | *dgst_raw_length = ssh_digest_bytes(hash_alg); | ||
421 | } else { | ||
422 | fatal("%s: blob is null", __func__); | ||
423 | } | ||
424 | return retval; | ||
425 | } | ||
426 | |||
427 | static char * | ||
428 | key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len) | ||
429 | { | ||
430 | char *retval; | ||
431 | u_int i; | ||
432 | |||
433 | retval = xcalloc(1, dgst_raw_len * 3 + 1); | ||
434 | for (i = 0; i < dgst_raw_len; i++) { | ||
435 | char hex[4]; | ||
436 | snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); | ||
437 | strlcat(retval, hex, dgst_raw_len * 3 + 1); | ||
438 | } | ||
439 | |||
440 | /* Remove the trailing ':' character */ | ||
441 | retval[(dgst_raw_len * 3) - 1] = '\0'; | ||
442 | return retval; | ||
443 | } | ||
444 | |||
445 | static char * | ||
446 | key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len) | ||
447 | { | ||
448 | char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; | ||
449 | char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', | ||
450 | 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; | ||
451 | u_int i, j = 0, rounds, seed = 1; | ||
452 | char *retval; | ||
453 | |||
454 | rounds = (dgst_raw_len / 2) + 1; | ||
455 | retval = xcalloc((rounds * 6), sizeof(char)); | ||
456 | retval[j++] = 'x'; | ||
457 | for (i = 0; i < rounds; i++) { | ||
458 | u_int idx0, idx1, idx2, idx3, idx4; | ||
459 | if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { | ||
460 | idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + | ||
461 | seed) % 6; | ||
462 | idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; | ||
463 | idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + | ||
464 | (seed / 6)) % 6; | ||
465 | retval[j++] = vowels[idx0]; | ||
466 | retval[j++] = consonants[idx1]; | ||
467 | retval[j++] = vowels[idx2]; | ||
468 | if ((i + 1) < rounds) { | ||
469 | idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; | ||
470 | idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; | ||
471 | retval[j++] = consonants[idx3]; | ||
472 | retval[j++] = '-'; | ||
473 | retval[j++] = consonants[idx4]; | ||
474 | seed = ((seed * 5) + | ||
475 | ((((u_int)(dgst_raw[2 * i])) * 7) + | ||
476 | ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; | ||
477 | } | ||
478 | } else { | ||
479 | idx0 = seed % 6; | ||
480 | idx1 = 16; | ||
481 | idx2 = seed / 6; | ||
482 | retval[j++] = vowels[idx0]; | ||
483 | retval[j++] = consonants[idx1]; | ||
484 | retval[j++] = vowels[idx2]; | ||
485 | } | ||
486 | } | ||
487 | retval[j++] = 'x'; | ||
488 | retval[j++] = '\0'; | ||
489 | return retval; | ||
490 | } | ||
491 | |||
492 | /* | ||
493 | * Draw an ASCII-Art representing the fingerprint so human brain can | ||
494 | * profit from its built-in pattern recognition ability. | ||
495 | * This technique is called "random art" and can be found in some | ||
496 | * scientific publications like this original paper: | ||
497 | * | ||
498 | * "Hash Visualization: a New Technique to improve Real-World Security", | ||
499 | * Perrig A. and Song D., 1999, International Workshop on Cryptographic | ||
500 | * Techniques and E-Commerce (CrypTEC '99) | ||
501 | * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf | ||
502 | * | ||
503 | * The subject came up in a talk by Dan Kaminsky, too. | ||
504 | * | ||
505 | * If you see the picture is different, the key is different. | ||
506 | * If the picture looks the same, you still know nothing. | ||
507 | * | ||
508 | * The algorithm used here is a worm crawling over a discrete plane, | ||
509 | * leaving a trace (augmenting the field) everywhere it goes. | ||
510 | * Movement is taken from dgst_raw 2bit-wise. Bumping into walls | ||
511 | * makes the respective movement vector be ignored for this turn. | ||
512 | * Graphs are not unambiguous, because circles in graphs can be | ||
513 | * walked in either direction. | ||
514 | */ | ||
515 | |||
516 | /* | ||
517 | * Field sizes for the random art. Have to be odd, so the starting point | ||
518 | * can be in the exact middle of the picture, and FLDBASE should be >=8 . | ||
519 | * Else pictures would be too dense, and drawing the frame would | ||
520 | * fail, too, because the key type would not fit in anymore. | ||
521 | */ | ||
522 | #define FLDBASE 8 | ||
523 | #define FLDSIZE_Y (FLDBASE + 1) | ||
524 | #define FLDSIZE_X (FLDBASE * 2 + 1) | ||
525 | static char * | ||
526 | key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) | ||
527 | { | ||
528 | /* | ||
529 | * Chars to be used after each other every time the worm | ||
530 | * intersects with itself. Matter of taste. | ||
531 | */ | ||
532 | char *augmentation_string = " .o+=*BOX@%&#/^SE"; | ||
533 | char *retval, *p; | ||
534 | u_char field[FLDSIZE_X][FLDSIZE_Y]; | ||
535 | u_int i, b; | ||
536 | int x, y; | ||
537 | size_t len = strlen(augmentation_string) - 1; | ||
538 | |||
539 | retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2)); | ||
540 | |||
541 | /* initialize field */ | ||
542 | memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); | ||
543 | x = FLDSIZE_X / 2; | ||
544 | y = FLDSIZE_Y / 2; | ||
545 | |||
546 | /* process raw key */ | ||
547 | for (i = 0; i < dgst_raw_len; i++) { | ||
548 | int input; | ||
549 | /* each byte conveys four 2-bit move commands */ | ||
550 | input = dgst_raw[i]; | ||
551 | for (b = 0; b < 4; b++) { | ||
552 | /* evaluate 2 bit, rest is shifted later */ | ||
553 | x += (input & 0x1) ? 1 : -1; | ||
554 | y += (input & 0x2) ? 1 : -1; | ||
555 | |||
556 | /* assure we are still in bounds */ | ||
557 | x = MAX(x, 0); | ||
558 | y = MAX(y, 0); | ||
559 | x = MIN(x, FLDSIZE_X - 1); | ||
560 | y = MIN(y, FLDSIZE_Y - 1); | ||
561 | |||
562 | /* augment the field */ | ||
563 | if (field[x][y] < len - 2) | ||
564 | field[x][y]++; | ||
565 | input = input >> 2; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | /* mark starting point and end point*/ | ||
570 | field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; | ||
571 | field[x][y] = len; | ||
572 | |||
573 | /* fill in retval */ | ||
574 | snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k)); | ||
575 | p = strchr(retval, '\0'); | ||
576 | |||
577 | /* output upper border */ | ||
578 | for (i = p - retval - 1; i < FLDSIZE_X; i++) | ||
579 | *p++ = '-'; | ||
580 | *p++ = '+'; | ||
581 | *p++ = '\n'; | ||
582 | |||
583 | /* output content */ | ||
584 | for (y = 0; y < FLDSIZE_Y; y++) { | ||
585 | *p++ = '|'; | ||
586 | for (x = 0; x < FLDSIZE_X; x++) | ||
587 | *p++ = augmentation_string[MIN(field[x][y], len)]; | ||
588 | *p++ = '|'; | ||
589 | *p++ = '\n'; | ||
590 | } | ||
591 | |||
592 | /* output lower border */ | ||
593 | *p++ = '+'; | ||
594 | for (i = 0; i < FLDSIZE_X; i++) | ||
595 | *p++ = '-'; | ||
596 | *p++ = '+'; | ||
597 | |||
598 | return retval; | ||
599 | } | ||
600 | |||
601 | char * | ||
602 | key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) | ||
603 | { | ||
604 | char *retval = NULL; | ||
605 | u_char *dgst_raw; | ||
606 | u_int dgst_raw_len; | ||
607 | |||
608 | dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); | ||
609 | if (!dgst_raw) | ||
610 | fatal("key_fingerprint: null from key_fingerprint_raw()"); | ||
611 | switch (dgst_rep) { | ||
612 | case SSH_FP_HEX: | ||
613 | retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); | ||
614 | break; | ||
615 | case SSH_FP_BUBBLEBABBLE: | ||
616 | retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); | ||
617 | break; | ||
618 | case SSH_FP_RANDOMART: | ||
619 | retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k); | ||
620 | break; | ||
621 | default: | ||
622 | fatal("key_fingerprint: bad digest representation %d", | ||
623 | dgst_rep); | ||
624 | break; | ||
625 | } | ||
626 | explicit_bzero(dgst_raw, dgst_raw_len); | ||
627 | free(dgst_raw); | ||
628 | return retval; | ||
629 | } | ||
630 | |||
631 | /* | ||
632 | * Reads a multiple-precision integer in decimal from the buffer, and advances | ||
633 | * the pointer. The integer must already be initialized. This function is | ||
634 | * permitted to modify the buffer. This leaves *cpp to point just beyond the | ||
635 | * last processed (and maybe modified) character. Note that this may modify | ||
636 | * the buffer containing the number. | ||
637 | */ | ||
638 | static int | ||
639 | read_bignum(char **cpp, BIGNUM * value) | ||
640 | { | ||
641 | char *cp = *cpp; | ||
642 | int old; | ||
643 | |||
644 | /* Skip any leading whitespace. */ | ||
645 | for (; *cp == ' ' || *cp == '\t'; cp++) | ||
646 | ; | ||
647 | |||
648 | /* Check that it begins with a decimal digit. */ | ||
649 | if (*cp < '0' || *cp > '9') | ||
650 | return 0; | ||
651 | |||
652 | /* Save starting position. */ | ||
653 | *cpp = cp; | ||
654 | |||
655 | /* Move forward until all decimal digits skipped. */ | ||
656 | for (; *cp >= '0' && *cp <= '9'; cp++) | ||
657 | ; | ||
658 | |||
659 | /* Save the old terminating character, and replace it by \0. */ | ||
660 | old = *cp; | ||
661 | *cp = 0; | ||
662 | |||
663 | /* Parse the number. */ | ||
664 | if (BN_dec2bn(&value, *cpp) == 0) | ||
665 | return 0; | ||
666 | |||
667 | /* Restore old terminating character. */ | ||
668 | *cp = old; | ||
669 | |||
670 | /* Move beyond the number and return success. */ | ||
671 | *cpp = cp; | ||
672 | return 1; | ||
673 | } | ||
674 | |||
675 | static int | ||
676 | write_bignum(FILE *f, BIGNUM *num) | ||
677 | { | ||
678 | char *buf = BN_bn2dec(num); | ||
679 | if (buf == NULL) { | ||
680 | error("write_bignum: BN_bn2dec() failed"); | ||
681 | return 0; | ||
682 | } | ||
683 | fprintf(f, " %s", buf); | ||
684 | OPENSSL_free(buf); | ||
685 | return 1; | ||
686 | } | 58 | } |
687 | 59 | ||
688 | /* returns 1 ok, -1 error */ | ||
689 | int | 60 | int |
690 | key_read(Key *ret, char **cpp) | 61 | key_read(Key *ret, char **cpp) |
691 | { | 62 | { |
692 | Key *k; | 63 | return sshkey_read(ret, cpp) == 0 ? 1 : -1; |
693 | int success = -1; | ||
694 | char *cp, *space; | ||
695 | int len, n, type; | ||
696 | u_int bits; | ||
697 | u_char *blob; | ||
698 | #ifdef OPENSSL_HAS_ECC | ||
699 | int curve_nid = -1; | ||
700 | #endif | ||
701 | |||
702 | cp = *cpp; | ||
703 | |||
704 | switch (ret->type) { | ||
705 | case KEY_RSA1: | ||
706 | /* Get number of bits. */ | ||
707 | if (*cp < '0' || *cp > '9') | ||
708 | return -1; /* Bad bit count... */ | ||
709 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) | ||
710 | bits = 10 * bits + *cp - '0'; | ||
711 | if (bits == 0) | ||
712 | return -1; | ||
713 | *cpp = cp; | ||
714 | /* Get public exponent, public modulus. */ | ||
715 | if (!read_bignum(cpp, ret->rsa->e)) | ||
716 | return -1; | ||
717 | if (!read_bignum(cpp, ret->rsa->n)) | ||
718 | return -1; | ||
719 | /* validate the claimed number of bits */ | ||
720 | if ((u_int)BN_num_bits(ret->rsa->n) != bits) { | ||
721 | verbose("key_read: claimed key size %d does not match " | ||
722 | "actual %d", bits, BN_num_bits(ret->rsa->n)); | ||
723 | return -1; | ||
724 | } | ||
725 | success = 1; | ||
726 | break; | ||
727 | case KEY_UNSPEC: | ||
728 | case KEY_RSA: | ||
729 | case KEY_DSA: | ||
730 | case KEY_ECDSA: | ||
731 | case KEY_ED25519: | ||
732 | case KEY_DSA_CERT_V00: | ||
733 | case KEY_RSA_CERT_V00: | ||
734 | case KEY_DSA_CERT: | ||
735 | case KEY_ECDSA_CERT: | ||
736 | case KEY_RSA_CERT: | ||
737 | case KEY_ED25519_CERT: | ||
738 | space = strchr(cp, ' '); | ||
739 | if (space == NULL) { | ||
740 | debug3("key_read: missing whitespace"); | ||
741 | return -1; | ||
742 | } | ||
743 | *space = '\0'; | ||
744 | type = key_type_from_name(cp); | ||
745 | #ifdef OPENSSL_HAS_ECC | ||
746 | if (key_type_plain(type) == KEY_ECDSA && | ||
747 | (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) { | ||
748 | debug("key_read: invalid curve"); | ||
749 | return -1; | ||
750 | } | ||
751 | #endif | ||
752 | *space = ' '; | ||
753 | if (type == KEY_UNSPEC) { | ||
754 | debug3("key_read: missing keytype"); | ||
755 | return -1; | ||
756 | } | ||
757 | cp = space+1; | ||
758 | if (*cp == '\0') { | ||
759 | debug3("key_read: short string"); | ||
760 | return -1; | ||
761 | } | ||
762 | if (ret->type == KEY_UNSPEC) { | ||
763 | ret->type = type; | ||
764 | } else if (ret->type != type) { | ||
765 | /* is a key, but different type */ | ||
766 | debug3("key_read: type mismatch"); | ||
767 | return -1; | ||
768 | } | ||
769 | len = 2*strlen(cp); | ||
770 | blob = xmalloc(len); | ||
771 | n = uudecode(cp, blob, len); | ||
772 | if (n < 0) { | ||
773 | error("key_read: uudecode %s failed", cp); | ||
774 | free(blob); | ||
775 | return -1; | ||
776 | } | ||
777 | k = key_from_blob(blob, (u_int)n); | ||
778 | free(blob); | ||
779 | if (k == NULL) { | ||
780 | error("key_read: key_from_blob %s failed", cp); | ||
781 | return -1; | ||
782 | } | ||
783 | if (k->type != type) { | ||
784 | error("key_read: type mismatch: encoding error"); | ||
785 | key_free(k); | ||
786 | return -1; | ||
787 | } | ||
788 | #ifdef OPENSSL_HAS_ECC | ||
789 | if (key_type_plain(type) == KEY_ECDSA && | ||
790 | curve_nid != k->ecdsa_nid) { | ||
791 | error("key_read: type mismatch: EC curve mismatch"); | ||
792 | key_free(k); | ||
793 | return -1; | ||
794 | } | ||
795 | #endif | ||
796 | /*XXXX*/ | ||
797 | if (key_is_cert(ret)) { | ||
798 | if (!key_is_cert(k)) { | ||
799 | error("key_read: loaded key is not a cert"); | ||
800 | key_free(k); | ||
801 | return -1; | ||
802 | } | ||
803 | if (ret->cert != NULL) | ||
804 | cert_free(ret->cert); | ||
805 | ret->cert = k->cert; | ||
806 | k->cert = NULL; | ||
807 | } | ||
808 | if (key_type_plain(ret->type) == KEY_RSA) { | ||
809 | if (ret->rsa != NULL) | ||
810 | RSA_free(ret->rsa); | ||
811 | ret->rsa = k->rsa; | ||
812 | k->rsa = NULL; | ||
813 | #ifdef DEBUG_PK | ||
814 | RSA_print_fp(stderr, ret->rsa, 8); | ||
815 | #endif | ||
816 | } | ||
817 | if (key_type_plain(ret->type) == KEY_DSA) { | ||
818 | if (ret->dsa != NULL) | ||
819 | DSA_free(ret->dsa); | ||
820 | ret->dsa = k->dsa; | ||
821 | k->dsa = NULL; | ||
822 | #ifdef DEBUG_PK | ||
823 | DSA_print_fp(stderr, ret->dsa, 8); | ||
824 | #endif | ||
825 | } | ||
826 | #ifdef OPENSSL_HAS_ECC | ||
827 | if (key_type_plain(ret->type) == KEY_ECDSA) { | ||
828 | if (ret->ecdsa != NULL) | ||
829 | EC_KEY_free(ret->ecdsa); | ||
830 | ret->ecdsa = k->ecdsa; | ||
831 | ret->ecdsa_nid = k->ecdsa_nid; | ||
832 | k->ecdsa = NULL; | ||
833 | k->ecdsa_nid = -1; | ||
834 | #ifdef DEBUG_PK | ||
835 | key_dump_ec_key(ret->ecdsa); | ||
836 | #endif | ||
837 | } | ||
838 | #endif | ||
839 | if (key_type_plain(ret->type) == KEY_ED25519) { | ||
840 | free(ret->ed25519_pk); | ||
841 | ret->ed25519_pk = k->ed25519_pk; | ||
842 | k->ed25519_pk = NULL; | ||
843 | #ifdef DEBUG_PK | ||
844 | /* XXX */ | ||
845 | #endif | ||
846 | } | ||
847 | success = 1; | ||
848 | /*XXXX*/ | ||
849 | key_free(k); | ||
850 | if (success != 1) | ||
851 | break; | ||
852 | /* advance cp: skip whitespace and data */ | ||
853 | while (*cp == ' ' || *cp == '\t') | ||
854 | cp++; | ||
855 | while (*cp != '\0' && *cp != ' ' && *cp != '\t') | ||
856 | cp++; | ||
857 | *cpp = cp; | ||
858 | break; | ||
859 | default: | ||
860 | fatal("key_read: bad key type: %d", ret->type); | ||
861 | break; | ||
862 | } | ||
863 | return success; | ||
864 | } | 64 | } |
865 | 65 | ||
866 | int | 66 | int |
867 | key_write(const Key *key, FILE *f) | 67 | key_write(const Key *key, FILE *f) |
868 | { | 68 | { |
869 | int n, success = 0; | 69 | return sshkey_write(key, f) == 0 ? 1 : 0; |
870 | u_int len, bits = 0; | ||
871 | u_char *blob; | ||
872 | char *uu; | ||
873 | |||
874 | if (key_is_cert(key)) { | ||
875 | if (key->cert == NULL) { | ||
876 | error("%s: no cert data", __func__); | ||
877 | return 0; | ||
878 | } | ||
879 | if (buffer_len(&key->cert->certblob) == 0) { | ||
880 | error("%s: no signed certificate blob", __func__); | ||
881 | return 0; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | switch (key->type) { | ||
886 | case KEY_RSA1: | ||
887 | if (key->rsa == NULL) | ||
888 | return 0; | ||
889 | /* size of modulus 'n' */ | ||
890 | bits = BN_num_bits(key->rsa->n); | ||
891 | fprintf(f, "%u", bits); | ||
892 | if (write_bignum(f, key->rsa->e) && | ||
893 | write_bignum(f, key->rsa->n)) | ||
894 | return 1; | ||
895 | error("key_write: failed for RSA key"); | ||
896 | return 0; | ||
897 | case KEY_DSA: | ||
898 | case KEY_DSA_CERT_V00: | ||
899 | case KEY_DSA_CERT: | ||
900 | if (key->dsa == NULL) | ||
901 | return 0; | ||
902 | break; | ||
903 | #ifdef OPENSSL_HAS_ECC | ||
904 | case KEY_ECDSA: | ||
905 | case KEY_ECDSA_CERT: | ||
906 | if (key->ecdsa == NULL) | ||
907 | return 0; | ||
908 | break; | ||
909 | #endif | ||
910 | case KEY_ED25519: | ||
911 | case KEY_ED25519_CERT: | ||
912 | if (key->ed25519_pk == NULL) | ||
913 | return 0; | ||
914 | break; | ||
915 | case KEY_RSA: | ||
916 | case KEY_RSA_CERT_V00: | ||
917 | case KEY_RSA_CERT: | ||
918 | if (key->rsa == NULL) | ||
919 | return 0; | ||
920 | break; | ||
921 | default: | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | key_to_blob(key, &blob, &len); | ||
926 | uu = xmalloc(2*len); | ||
927 | n = uuencode(blob, len, uu, 2*len); | ||
928 | if (n > 0) { | ||
929 | fprintf(f, "%s %s", key_ssh_name(key), uu); | ||
930 | success = 1; | ||
931 | } | ||
932 | free(blob); | ||
933 | free(uu); | ||
934 | |||
935 | return success; | ||
936 | } | ||
937 | |||
938 | const char * | ||
939 | key_cert_type(const Key *k) | ||
940 | { | ||
941 | switch (k->cert->type) { | ||
942 | case SSH2_CERT_TYPE_USER: | ||
943 | return "user"; | ||
944 | case SSH2_CERT_TYPE_HOST: | ||
945 | return "host"; | ||
946 | default: | ||
947 | return "unknown"; | ||
948 | } | ||
949 | } | ||
950 | |||
951 | struct keytype { | ||
952 | char *name; | ||
953 | char *shortname; | ||
954 | int type; | ||
955 | int nid; | ||
956 | int cert; | ||
957 | }; | ||
958 | static const struct keytype keytypes[] = { | ||
959 | { NULL, "RSA1", KEY_RSA1, 0, 0 }, | ||
960 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, | ||
961 | { "ssh-dss", "DSA", KEY_DSA, 0, 0 }, | ||
962 | { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 }, | ||
963 | #ifdef OPENSSL_HAS_ECC | ||
964 | { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, | ||
965 | { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, | ||
966 | # ifdef OPENSSL_HAS_NISTP521 | ||
967 | { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, | ||
968 | # endif | ||
969 | #endif /* OPENSSL_HAS_ECC */ | ||
970 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 }, | ||
971 | { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 }, | ||
972 | #ifdef OPENSSL_HAS_ECC | ||
973 | { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", | ||
974 | KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 }, | ||
975 | { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", | ||
976 | KEY_ECDSA_CERT, NID_secp384r1, 1 }, | ||
977 | # ifdef OPENSSL_HAS_NISTP521 | ||
978 | { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", | ||
979 | KEY_ECDSA_CERT, NID_secp521r1, 1 }, | ||
980 | # endif | ||
981 | #endif /* OPENSSL_HAS_ECC */ | ||
982 | { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00", | ||
983 | KEY_RSA_CERT_V00, 0, 1 }, | ||
984 | { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", | ||
985 | KEY_DSA_CERT_V00, 0, 1 }, | ||
986 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", | ||
987 | KEY_ED25519_CERT, 0, 1 }, | ||
988 | { "null", "null", KEY_NULL, 0, 0 }, | ||
989 | { NULL, NULL, -1, -1, 0 } | ||
990 | }; | ||
991 | |||
992 | const char * | ||
993 | key_type(const Key *k) | ||
994 | { | ||
995 | const struct keytype *kt; | ||
996 | |||
997 | for (kt = keytypes; kt->type != -1; kt++) { | ||
998 | if (kt->type == k->type) | ||
999 | return kt->shortname; | ||
1000 | } | ||
1001 | return "unknown"; | ||
1002 | } | ||
1003 | |||
1004 | static const char * | ||
1005 | key_ssh_name_from_type_nid(int type, int nid) | ||
1006 | { | ||
1007 | const struct keytype *kt; | ||
1008 | |||
1009 | for (kt = keytypes; kt->type != -1; kt++) { | ||
1010 | if (kt->type == type && (kt->nid == 0 || kt->nid == nid)) | ||
1011 | return kt->name; | ||
1012 | } | ||
1013 | return "ssh-unknown"; | ||
1014 | } | ||
1015 | |||
1016 | const char * | ||
1017 | key_ssh_name(const Key *k) | ||
1018 | { | ||
1019 | return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid); | ||
1020 | } | ||
1021 | |||
1022 | const char * | ||
1023 | key_ssh_name_plain(const Key *k) | ||
1024 | { | ||
1025 | return key_ssh_name_from_type_nid(key_type_plain(k->type), | ||
1026 | k->ecdsa_nid); | ||
1027 | } | ||
1028 | |||
1029 | int | ||
1030 | key_type_from_name(char *name) | ||
1031 | { | ||
1032 | const struct keytype *kt; | ||
1033 | |||
1034 | for (kt = keytypes; kt->type != -1; kt++) { | ||
1035 | /* Only allow shortname matches for plain key types */ | ||
1036 | if ((kt->name != NULL && strcmp(name, kt->name) == 0) || | ||
1037 | (!kt->cert && strcasecmp(kt->shortname, name) == 0)) | ||
1038 | return kt->type; | ||
1039 | } | ||
1040 | debug2("key_type_from_name: unknown key type '%s'", name); | ||
1041 | return KEY_UNSPEC; | ||
1042 | } | ||
1043 | |||
1044 | int | ||
1045 | key_ecdsa_nid_from_name(const char *name) | ||
1046 | { | ||
1047 | const struct keytype *kt; | ||
1048 | |||
1049 | for (kt = keytypes; kt->type != -1; kt++) { | ||
1050 | if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) | ||
1051 | continue; | ||
1052 | if (kt->name != NULL && strcmp(name, kt->name) == 0) | ||
1053 | return kt->nid; | ||
1054 | } | ||
1055 | debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name); | ||
1056 | return -1; | ||
1057 | } | ||
1058 | |||
1059 | char * | ||
1060 | key_alg_list(int certs_only, int plain_only) | ||
1061 | { | ||
1062 | char *ret = NULL; | ||
1063 | size_t nlen, rlen = 0; | ||
1064 | const struct keytype *kt; | ||
1065 | |||
1066 | for (kt = keytypes; kt->type != -1; kt++) { | ||
1067 | if (kt->name == NULL || kt->type == KEY_NULL) | ||
1068 | continue; | ||
1069 | if ((certs_only && !kt->cert) || (plain_only && kt->cert)) | ||
1070 | continue; | ||
1071 | if (ret != NULL) | ||
1072 | ret[rlen++] = '\n'; | ||
1073 | nlen = strlen(kt->name); | ||
1074 | ret = xrealloc(ret, 1, rlen + nlen + 2); | ||
1075 | memcpy(ret + rlen, kt->name, nlen + 1); | ||
1076 | rlen += nlen; | ||
1077 | } | ||
1078 | return ret; | ||
1079 | } | ||
1080 | |||
1081 | int | ||
1082 | key_type_is_cert(int type) | ||
1083 | { | ||
1084 | const struct keytype *kt; | ||
1085 | |||
1086 | for (kt = keytypes; kt->type != -1; kt++) { | ||
1087 | if (kt->type == type) | ||
1088 | return kt->cert; | ||
1089 | } | ||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | static int | ||
1094 | key_type_is_valid_ca(int type) | ||
1095 | { | ||
1096 | switch (type) { | ||
1097 | case KEY_RSA: | ||
1098 | case KEY_DSA: | ||
1099 | case KEY_ECDSA: | ||
1100 | case KEY_ED25519: | ||
1101 | return 1; | ||
1102 | default: | ||
1103 | return 0; | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | u_int | ||
1108 | key_size(const Key *k) | ||
1109 | { | ||
1110 | switch (k->type) { | ||
1111 | case KEY_RSA1: | ||
1112 | case KEY_RSA: | ||
1113 | case KEY_RSA_CERT_V00: | ||
1114 | case KEY_RSA_CERT: | ||
1115 | return BN_num_bits(k->rsa->n); | ||
1116 | case KEY_DSA: | ||
1117 | case KEY_DSA_CERT_V00: | ||
1118 | case KEY_DSA_CERT: | ||
1119 | return BN_num_bits(k->dsa->p); | ||
1120 | case KEY_ED25519: | ||
1121 | return 256; /* XXX */ | ||
1122 | #ifdef OPENSSL_HAS_ECC | ||
1123 | case KEY_ECDSA: | ||
1124 | case KEY_ECDSA_CERT: | ||
1125 | return key_curve_nid_to_bits(k->ecdsa_nid); | ||
1126 | #endif | ||
1127 | } | ||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | static RSA * | ||
1132 | rsa_generate_private_key(u_int bits) | ||
1133 | { | ||
1134 | RSA *private = RSA_new(); | ||
1135 | BIGNUM *f4 = BN_new(); | ||
1136 | |||
1137 | if (private == NULL) | ||
1138 | fatal("%s: RSA_new failed", __func__); | ||
1139 | if (f4 == NULL) | ||
1140 | fatal("%s: BN_new failed", __func__); | ||
1141 | if (!BN_set_word(f4, RSA_F4)) | ||
1142 | fatal("%s: BN_new failed", __func__); | ||
1143 | if (!RSA_generate_key_ex(private, bits, f4, NULL)) | ||
1144 | fatal("%s: key generation failed.", __func__); | ||
1145 | BN_free(f4); | ||
1146 | return private; | ||
1147 | } | ||
1148 | |||
1149 | static DSA* | ||
1150 | dsa_generate_private_key(u_int bits) | ||
1151 | { | ||
1152 | DSA *private = DSA_new(); | ||
1153 | |||
1154 | if (private == NULL) | ||
1155 | fatal("%s: DSA_new failed", __func__); | ||
1156 | if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, | ||
1157 | NULL, NULL)) | ||
1158 | fatal("%s: DSA_generate_parameters failed", __func__); | ||
1159 | if (!DSA_generate_key(private)) | ||
1160 | fatal("%s: DSA_generate_key failed.", __func__); | ||
1161 | return private; | ||
1162 | } | ||
1163 | |||
1164 | int | ||
1165 | key_ecdsa_bits_to_nid(int bits) | ||
1166 | { | ||
1167 | switch (bits) { | ||
1168 | #ifdef OPENSSL_HAS_ECC | ||
1169 | case 256: | ||
1170 | return NID_X9_62_prime256v1; | ||
1171 | case 384: | ||
1172 | return NID_secp384r1; | ||
1173 | # ifdef OPENSSL_HAS_NISTP521 | ||
1174 | case 521: | ||
1175 | return NID_secp521r1; | ||
1176 | # endif | ||
1177 | #endif | ||
1178 | default: | ||
1179 | return -1; | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | #ifdef OPENSSL_HAS_ECC | ||
1184 | int | ||
1185 | key_ecdsa_key_to_nid(EC_KEY *k) | ||
1186 | { | ||
1187 | EC_GROUP *eg; | ||
1188 | int nids[] = { | ||
1189 | NID_X9_62_prime256v1, | ||
1190 | NID_secp384r1, | ||
1191 | # ifdef OPENSSL_HAS_NISTP521 | ||
1192 | NID_secp521r1, | ||
1193 | # endif | ||
1194 | -1 | ||
1195 | }; | ||
1196 | int nid; | ||
1197 | u_int i; | ||
1198 | BN_CTX *bnctx; | ||
1199 | const EC_GROUP *g = EC_KEY_get0_group(k); | ||
1200 | |||
1201 | /* | ||
1202 | * The group may be stored in a ASN.1 encoded private key in one of two | ||
1203 | * ways: as a "named group", which is reconstituted by ASN.1 object ID | ||
1204 | * or explicit group parameters encoded into the key blob. Only the | ||
1205 | * "named group" case sets the group NID for us, but we can figure | ||
1206 | * it out for the other case by comparing against all the groups that | ||
1207 | * are supported. | ||
1208 | */ | ||
1209 | if ((nid = EC_GROUP_get_curve_name(g)) > 0) | ||
1210 | return nid; | ||
1211 | if ((bnctx = BN_CTX_new()) == NULL) | ||
1212 | fatal("%s: BN_CTX_new() failed", __func__); | ||
1213 | for (i = 0; nids[i] != -1; i++) { | ||
1214 | if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) | ||
1215 | fatal("%s: EC_GROUP_new_by_curve_name failed", | ||
1216 | __func__); | ||
1217 | if (EC_GROUP_cmp(g, eg, bnctx) == 0) | ||
1218 | break; | ||
1219 | EC_GROUP_free(eg); | ||
1220 | } | ||
1221 | BN_CTX_free(bnctx); | ||
1222 | debug3("%s: nid = %d", __func__, nids[i]); | ||
1223 | if (nids[i] != -1) { | ||
1224 | /* Use the group with the NID attached */ | ||
1225 | EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); | ||
1226 | if (EC_KEY_set_group(k, eg) != 1) | ||
1227 | fatal("%s: EC_KEY_set_group", __func__); | ||
1228 | } | ||
1229 | return nids[i]; | ||
1230 | } | ||
1231 | |||
1232 | static EC_KEY* | ||
1233 | ecdsa_generate_private_key(u_int bits, int *nid) | ||
1234 | { | ||
1235 | EC_KEY *private; | ||
1236 | |||
1237 | if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1) | ||
1238 | fatal("%s: invalid key length", __func__); | ||
1239 | if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) | ||
1240 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | ||
1241 | if (EC_KEY_generate_key(private) != 1) | ||
1242 | fatal("%s: EC_KEY_generate_key failed", __func__); | ||
1243 | EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); | ||
1244 | return private; | ||
1245 | } | 70 | } |
1246 | #endif /* OPENSSL_HAS_ECC */ | ||
1247 | 71 | ||
1248 | Key * | 72 | Key * |
1249 | key_generate(int type, u_int bits) | 73 | key_generate(int type, u_int bits) |
1250 | { | 74 | { |
1251 | Key *k = key_new(KEY_UNSPEC); | 75 | int r; |
1252 | switch (type) { | 76 | Key *ret = NULL; |
1253 | case KEY_DSA: | 77 | |
1254 | k->dsa = dsa_generate_private_key(bits); | 78 | if ((r = sshkey_generate(type, bits, &ret)) != 0) |
1255 | break; | 79 | fatal("%s: %s", __func__, ssh_err(r)); |
1256 | #ifdef OPENSSL_HAS_ECC | 80 | return ret; |
1257 | case KEY_ECDSA: | ||
1258 | k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid); | ||
1259 | break; | ||
1260 | #endif | ||
1261 | case KEY_RSA: | ||
1262 | case KEY_RSA1: | ||
1263 | k->rsa = rsa_generate_private_key(bits); | ||
1264 | break; | ||
1265 | case KEY_ED25519: | ||
1266 | k->ed25519_pk = xmalloc(ED25519_PK_SZ); | ||
1267 | k->ed25519_sk = xmalloc(ED25519_SK_SZ); | ||
1268 | crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); | ||
1269 | break; | ||
1270 | case KEY_RSA_CERT_V00: | ||
1271 | case KEY_DSA_CERT_V00: | ||
1272 | case KEY_RSA_CERT: | ||
1273 | case KEY_DSA_CERT: | ||
1274 | fatal("key_generate: cert keys cannot be generated directly"); | ||
1275 | default: | ||
1276 | fatal("key_generate: unknown type %d", type); | ||
1277 | } | ||
1278 | k->type = type; | ||
1279 | return k; | ||
1280 | } | 81 | } |
1281 | 82 | ||
1282 | void | 83 | void |
1283 | key_cert_copy(const Key *from_key, struct Key *to_key) | 84 | key_cert_copy(const Key *from_key, Key *to_key) |
1284 | { | 85 | { |
1285 | u_int i; | 86 | int r; |
1286 | const struct KeyCert *from; | ||
1287 | struct KeyCert *to; | ||
1288 | |||
1289 | if (to_key->cert != NULL) { | ||
1290 | cert_free(to_key->cert); | ||
1291 | to_key->cert = NULL; | ||
1292 | } | ||
1293 | 87 | ||
1294 | if ((from = from_key->cert) == NULL) | 88 | if ((r = sshkey_cert_copy(from_key, to_key)) != 0) |
1295 | return; | 89 | fatal("%s: %s", __func__, ssh_err(r)); |
1296 | |||
1297 | to = to_key->cert = cert_new(); | ||
1298 | |||
1299 | buffer_append(&to->certblob, buffer_ptr(&from->certblob), | ||
1300 | buffer_len(&from->certblob)); | ||
1301 | |||
1302 | buffer_append(&to->critical, | ||
1303 | buffer_ptr(&from->critical), buffer_len(&from->critical)); | ||
1304 | buffer_append(&to->extensions, | ||
1305 | buffer_ptr(&from->extensions), buffer_len(&from->extensions)); | ||
1306 | |||
1307 | to->serial = from->serial; | ||
1308 | to->type = from->type; | ||
1309 | to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id); | ||
1310 | to->valid_after = from->valid_after; | ||
1311 | to->valid_before = from->valid_before; | ||
1312 | to->signature_key = from->signature_key == NULL ? | ||
1313 | NULL : key_from_private(from->signature_key); | ||
1314 | |||
1315 | to->nprincipals = from->nprincipals; | ||
1316 | if (to->nprincipals > CERT_MAX_PRINCIPALS) | ||
1317 | fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)", | ||
1318 | __func__, to->nprincipals, CERT_MAX_PRINCIPALS); | ||
1319 | if (to->nprincipals > 0) { | ||
1320 | to->principals = xcalloc(from->nprincipals, | ||
1321 | sizeof(*to->principals)); | ||
1322 | for (i = 0; i < to->nprincipals; i++) | ||
1323 | to->principals[i] = xstrdup(from->principals[i]); | ||
1324 | } | ||
1325 | } | 90 | } |
1326 | 91 | ||
1327 | Key * | 92 | Key * |
1328 | key_from_private(const Key *k) | 93 | key_from_private(const Key *k) |
1329 | { | 94 | { |
1330 | Key *n = NULL; | 95 | int r; |
1331 | switch (k->type) { | 96 | Key *ret = NULL; |
1332 | case KEY_DSA: | ||
1333 | case KEY_DSA_CERT_V00: | ||
1334 | case KEY_DSA_CERT: | ||
1335 | n = key_new(k->type); | ||
1336 | if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || | ||
1337 | (BN_copy(n->dsa->q, k->dsa->q) == NULL) || | ||
1338 | (BN_copy(n->dsa->g, k->dsa->g) == NULL) || | ||
1339 | (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) | ||
1340 | fatal("key_from_private: BN_copy failed"); | ||
1341 | break; | ||
1342 | #ifdef OPENSSL_HAS_ECC | ||
1343 | case KEY_ECDSA: | ||
1344 | case KEY_ECDSA_CERT: | ||
1345 | n = key_new(k->type); | ||
1346 | n->ecdsa_nid = k->ecdsa_nid; | ||
1347 | if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) | ||
1348 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | ||
1349 | if (EC_KEY_set_public_key(n->ecdsa, | ||
1350 | EC_KEY_get0_public_key(k->ecdsa)) != 1) | ||
1351 | fatal("%s: EC_KEY_set_public_key failed", __func__); | ||
1352 | break; | ||
1353 | #endif | ||
1354 | case KEY_RSA: | ||
1355 | case KEY_RSA1: | ||
1356 | case KEY_RSA_CERT_V00: | ||
1357 | case KEY_RSA_CERT: | ||
1358 | n = key_new(k->type); | ||
1359 | if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || | ||
1360 | (BN_copy(n->rsa->e, k->rsa->e) == NULL)) | ||
1361 | fatal("key_from_private: BN_copy failed"); | ||
1362 | break; | ||
1363 | case KEY_ED25519: | ||
1364 | case KEY_ED25519_CERT: | ||
1365 | n = key_new(k->type); | ||
1366 | if (k->ed25519_pk != NULL) { | ||
1367 | n->ed25519_pk = xmalloc(ED25519_PK_SZ); | ||
1368 | memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); | ||
1369 | } | ||
1370 | break; | ||
1371 | default: | ||
1372 | fatal("key_from_private: unknown type %d", k->type); | ||
1373 | break; | ||
1374 | } | ||
1375 | if (key_is_cert(k)) | ||
1376 | key_cert_copy(k, n); | ||
1377 | return n; | ||
1378 | } | ||
1379 | |||
1380 | int | ||
1381 | key_names_valid2(const char *names) | ||
1382 | { | ||
1383 | char *s, *cp, *p; | ||
1384 | |||
1385 | if (names == NULL || strcmp(names, "") == 0) | ||
1386 | return 0; | ||
1387 | s = cp = xstrdup(names); | ||
1388 | for ((p = strsep(&cp, ",")); p && *p != '\0'; | ||
1389 | (p = strsep(&cp, ","))) { | ||
1390 | switch (key_type_from_name(p)) { | ||
1391 | case KEY_RSA1: | ||
1392 | case KEY_UNSPEC: | ||
1393 | free(s); | ||
1394 | return 0; | ||
1395 | } | ||
1396 | } | ||
1397 | debug3("key names ok: [%s]", names); | ||
1398 | free(s); | ||
1399 | return 1; | ||
1400 | } | ||
1401 | |||
1402 | static int | ||
1403 | cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) | ||
1404 | { | ||
1405 | u_char *principals, *critical, *exts, *sig_key, *sig; | ||
1406 | u_int signed_len, plen, clen, sklen, slen, kidlen, elen; | ||
1407 | Buffer tmp; | ||
1408 | char *principal; | ||
1409 | int ret = -1; | ||
1410 | int v00 = key->type == KEY_DSA_CERT_V00 || | ||
1411 | key->type == KEY_RSA_CERT_V00; | ||
1412 | |||
1413 | buffer_init(&tmp); | ||
1414 | |||
1415 | /* Copy the entire key blob for verification and later serialisation */ | ||
1416 | buffer_append(&key->cert->certblob, blob, blen); | ||
1417 | |||
1418 | elen = 0; /* Not touched for v00 certs */ | ||
1419 | principals = exts = critical = sig_key = sig = NULL; | ||
1420 | if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) || | ||
1421 | buffer_get_int_ret(&key->cert->type, b) != 0 || | ||
1422 | (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL || | ||
1423 | (principals = buffer_get_string_ret(b, &plen)) == NULL || | ||
1424 | buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || | ||
1425 | buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || | ||
1426 | (critical = buffer_get_string_ret(b, &clen)) == NULL || | ||
1427 | (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) || | ||
1428 | (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */ | ||
1429 | buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */ | ||
1430 | (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) { | ||
1431 | error("%s: parse error", __func__); | ||
1432 | goto out; | ||
1433 | } | ||
1434 | |||
1435 | /* Signature is left in the buffer so we can calculate this length */ | ||
1436 | signed_len = buffer_len(&key->cert->certblob) - buffer_len(b); | ||
1437 | |||
1438 | if ((sig = buffer_get_string_ret(b, &slen)) == NULL) { | ||
1439 | error("%s: parse error", __func__); | ||
1440 | goto out; | ||
1441 | } | ||
1442 | |||
1443 | if (key->cert->type != SSH2_CERT_TYPE_USER && | ||
1444 | key->cert->type != SSH2_CERT_TYPE_HOST) { | ||
1445 | error("Unknown certificate type %u", key->cert->type); | ||
1446 | goto out; | ||
1447 | } | ||
1448 | 97 | ||
1449 | buffer_append(&tmp, principals, plen); | 98 | if ((r = sshkey_from_private(k, &ret)) != 0) |
1450 | while (buffer_len(&tmp) > 0) { | 99 | fatal("%s: %s", __func__, ssh_err(r)); |
1451 | if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) { | ||
1452 | error("%s: Too many principals", __func__); | ||
1453 | goto out; | ||
1454 | } | ||
1455 | if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) { | ||
1456 | error("%s: Principals data invalid", __func__); | ||
1457 | goto out; | ||
1458 | } | ||
1459 | key->cert->principals = xrealloc(key->cert->principals, | ||
1460 | key->cert->nprincipals + 1, sizeof(*key->cert->principals)); | ||
1461 | key->cert->principals[key->cert->nprincipals++] = principal; | ||
1462 | } | ||
1463 | |||
1464 | buffer_clear(&tmp); | ||
1465 | |||
1466 | buffer_append(&key->cert->critical, critical, clen); | ||
1467 | buffer_append(&tmp, critical, clen); | ||
1468 | /* validate structure */ | ||
1469 | while (buffer_len(&tmp) != 0) { | ||
1470 | if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL || | ||
1471 | buffer_get_string_ptr_ret(&tmp, NULL) == NULL) { | ||
1472 | error("%s: critical option data invalid", __func__); | ||
1473 | goto out; | ||
1474 | } | ||
1475 | } | ||
1476 | buffer_clear(&tmp); | ||
1477 | |||
1478 | buffer_append(&key->cert->extensions, exts, elen); | ||
1479 | buffer_append(&tmp, exts, elen); | ||
1480 | /* validate structure */ | ||
1481 | while (buffer_len(&tmp) != 0) { | ||
1482 | if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL || | ||
1483 | buffer_get_string_ptr_ret(&tmp, NULL) == NULL) { | ||
1484 | error("%s: extension data invalid", __func__); | ||
1485 | goto out; | ||
1486 | } | ||
1487 | } | ||
1488 | buffer_clear(&tmp); | ||
1489 | |||
1490 | if ((key->cert->signature_key = key_from_blob2(sig_key, sklen, 0)) | ||
1491 | == NULL) { | ||
1492 | error("%s: Signature key invalid", __func__); | ||
1493 | goto out; | ||
1494 | } | ||
1495 | if (!key_type_is_valid_ca(key->cert->signature_key->type)) { | ||
1496 | error("%s: Invalid signature key type %s (%d)", __func__, | ||
1497 | key_type(key->cert->signature_key), | ||
1498 | key->cert->signature_key->type); | ||
1499 | goto out; | ||
1500 | } | ||
1501 | |||
1502 | switch (key_verify(key->cert->signature_key, sig, slen, | ||
1503 | buffer_ptr(&key->cert->certblob), signed_len)) { | ||
1504 | case 1: | ||
1505 | ret = 0; | ||
1506 | break; /* Good signature */ | ||
1507 | case 0: | ||
1508 | error("%s: Invalid signature on certificate", __func__); | ||
1509 | goto out; | ||
1510 | case -1: | ||
1511 | error("%s: Certificate signature verification failed", | ||
1512 | __func__); | ||
1513 | goto out; | ||
1514 | } | ||
1515 | |||
1516 | out: | ||
1517 | buffer_free(&tmp); | ||
1518 | free(principals); | ||
1519 | free(critical); | ||
1520 | free(exts); | ||
1521 | free(sig_key); | ||
1522 | free(sig); | ||
1523 | return ret; | 100 | return ret; |
1524 | } | 101 | } |
1525 | 102 | ||
1526 | static Key * | 103 | static void |
1527 | key_from_blob2(const u_char *blob, u_int blen, int allow_cert) | 104 | fatal_on_fatal_errors(int r, const char *func, int extra_fatal) |
1528 | { | 105 | { |
1529 | Buffer b; | 106 | if (r == SSH_ERR_INTERNAL_ERROR || |
1530 | int rlen, type; | 107 | r == SSH_ERR_ALLOC_FAIL || |
1531 | u_int len; | 108 | (extra_fatal != 0 && r == extra_fatal)) |
1532 | char *ktype = NULL, *curve = NULL; | 109 | fatal("%s: %s", func, ssh_err(r)); |
1533 | u_char *pk = NULL; | ||
1534 | Key *key = NULL; | ||
1535 | #ifdef OPENSSL_HAS_ECC | ||
1536 | EC_POINT *q = NULL; | ||
1537 | int nid = -1; | ||
1538 | #endif | ||
1539 | |||
1540 | #ifdef DEBUG_PK | ||
1541 | dump_base64(stderr, blob, blen); | ||
1542 | #endif | ||
1543 | buffer_init(&b); | ||
1544 | buffer_append(&b, blob, blen); | ||
1545 | if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) { | ||
1546 | error("key_from_blob: can't read key type"); | ||
1547 | goto out; | ||
1548 | } | ||
1549 | |||
1550 | type = key_type_from_name(ktype); | ||
1551 | #ifdef OPENSSL_HAS_ECC | ||
1552 | if (key_type_plain(type) == KEY_ECDSA) | ||
1553 | nid = key_ecdsa_nid_from_name(ktype); | ||
1554 | #endif | ||
1555 | if (!allow_cert && key_type_is_cert(type)) { | ||
1556 | error("key_from_blob: certificate not allowed in this context"); | ||
1557 | goto out; | ||
1558 | } | ||
1559 | switch (type) { | ||
1560 | case KEY_RSA_CERT: | ||
1561 | (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ | ||
1562 | /* FALLTHROUGH */ | ||
1563 | case KEY_RSA: | ||
1564 | case KEY_RSA_CERT_V00: | ||
1565 | key = key_new(type); | ||
1566 | if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || | ||
1567 | buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { | ||
1568 | error("key_from_blob: can't read rsa key"); | ||
1569 | badkey: | ||
1570 | key_free(key); | ||
1571 | key = NULL; | ||
1572 | goto out; | ||
1573 | } | ||
1574 | #ifdef DEBUG_PK | ||
1575 | RSA_print_fp(stderr, key->rsa, 8); | ||
1576 | #endif | ||
1577 | break; | ||
1578 | case KEY_DSA_CERT: | ||
1579 | (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ | ||
1580 | /* FALLTHROUGH */ | ||
1581 | case KEY_DSA: | ||
1582 | case KEY_DSA_CERT_V00: | ||
1583 | key = key_new(type); | ||
1584 | if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || | ||
1585 | buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || | ||
1586 | buffer_get_bignum2_ret(&b, key->dsa->g) == -1 || | ||
1587 | buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) { | ||
1588 | error("key_from_blob: can't read dsa key"); | ||
1589 | goto badkey; | ||
1590 | } | ||
1591 | #ifdef DEBUG_PK | ||
1592 | DSA_print_fp(stderr, key->dsa, 8); | ||
1593 | #endif | ||
1594 | break; | ||
1595 | #ifdef OPENSSL_HAS_ECC | ||
1596 | case KEY_ECDSA_CERT: | ||
1597 | (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ | ||
1598 | /* FALLTHROUGH */ | ||
1599 | case KEY_ECDSA: | ||
1600 | key = key_new(type); | ||
1601 | key->ecdsa_nid = nid; | ||
1602 | if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) { | ||
1603 | error("key_from_blob: can't read ecdsa curve"); | ||
1604 | goto badkey; | ||
1605 | } | ||
1606 | if (key->ecdsa_nid != key_curve_name_to_nid(curve)) { | ||
1607 | error("key_from_blob: ecdsa curve doesn't match type"); | ||
1608 | goto badkey; | ||
1609 | } | ||
1610 | if (key->ecdsa != NULL) | ||
1611 | EC_KEY_free(key->ecdsa); | ||
1612 | if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) | ||
1613 | == NULL) | ||
1614 | fatal("key_from_blob: EC_KEY_new_by_curve_name failed"); | ||
1615 | if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) | ||
1616 | fatal("key_from_blob: EC_POINT_new failed"); | ||
1617 | if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa), | ||
1618 | q) == -1) { | ||
1619 | error("key_from_blob: can't read ecdsa key point"); | ||
1620 | goto badkey; | ||
1621 | } | ||
1622 | if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa), | ||
1623 | q) != 0) | ||
1624 | goto badkey; | ||
1625 | if (EC_KEY_set_public_key(key->ecdsa, q) != 1) | ||
1626 | fatal("key_from_blob: EC_KEY_set_public_key failed"); | ||
1627 | #ifdef DEBUG_PK | ||
1628 | key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); | ||
1629 | #endif | ||
1630 | break; | ||
1631 | #endif /* OPENSSL_HAS_ECC */ | ||
1632 | case KEY_ED25519_CERT: | ||
1633 | (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ | ||
1634 | /* FALLTHROUGH */ | ||
1635 | case KEY_ED25519: | ||
1636 | if ((pk = buffer_get_string_ret(&b, &len)) == NULL) { | ||
1637 | error("key_from_blob: can't read ed25519 key"); | ||
1638 | goto badkey; | ||
1639 | } | ||
1640 | if (len != ED25519_PK_SZ) { | ||
1641 | error("key_from_blob: ed25519 len %d != %d", | ||
1642 | len, ED25519_PK_SZ); | ||
1643 | goto badkey; | ||
1644 | } | ||
1645 | key = key_new(type); | ||
1646 | key->ed25519_pk = pk; | ||
1647 | pk = NULL; | ||
1648 | break; | ||
1649 | case KEY_UNSPEC: | ||
1650 | key = key_new(type); | ||
1651 | break; | ||
1652 | default: | ||
1653 | error("key_from_blob: cannot handle type %s", ktype); | ||
1654 | goto out; | ||
1655 | } | ||
1656 | if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) { | ||
1657 | error("key_from_blob: can't parse cert data"); | ||
1658 | goto badkey; | ||
1659 | } | ||
1660 | rlen = buffer_len(&b); | ||
1661 | if (key != NULL && rlen != 0) | ||
1662 | error("key_from_blob: remaining bytes in key blob %d", rlen); | ||
1663 | out: | ||
1664 | free(ktype); | ||
1665 | free(curve); | ||
1666 | free(pk); | ||
1667 | #ifdef OPENSSL_HAS_ECC | ||
1668 | if (q != NULL) | ||
1669 | EC_POINT_free(q); | ||
1670 | #endif | ||
1671 | buffer_free(&b); | ||
1672 | return key; | ||
1673 | } | 110 | } |
1674 | 111 | ||
1675 | Key * | 112 | Key * |
1676 | key_from_blob(const u_char *blob, u_int blen) | 113 | key_from_blob(const u_char *blob, u_int blen) |
1677 | { | 114 | { |
1678 | return key_from_blob2(blob, blen, 1); | 115 | int r; |
116 | Key *ret = NULL; | ||
117 | |||
118 | if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) { | ||
119 | fatal_on_fatal_errors(r, __func__, 0); | ||
120 | error("%s: %s", __func__, ssh_err(r)); | ||
121 | return NULL; | ||
122 | } | ||
123 | return ret; | ||
1679 | } | 124 | } |
1680 | 125 | ||
1681 | static int | 126 | int |
1682 | to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain) | 127 | key_to_blob(const Key *key, u_char **blobp, u_int *lenp) |
1683 | { | 128 | { |
1684 | Buffer b; | 129 | u_char *blob; |
1685 | int len, type; | 130 | size_t blen; |
131 | int r; | ||
1686 | 132 | ||
1687 | if (blobp != NULL) | 133 | if (blobp != NULL) |
1688 | *blobp = NULL; | 134 | *blobp = NULL; |
1689 | if (lenp != NULL) | 135 | if (lenp != NULL) |
1690 | *lenp = 0; | 136 | *lenp = 0; |
1691 | if (key == NULL) { | 137 | if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { |
1692 | error("key_to_blob: key == NULL"); | 138 | fatal_on_fatal_errors(r, __func__, 0); |
1693 | return 0; | 139 | error("%s: %s", __func__, ssh_err(r)); |
1694 | } | ||
1695 | buffer_init(&b); | ||
1696 | type = force_plain ? key_type_plain(key->type) : key->type; | ||
1697 | switch (type) { | ||
1698 | case KEY_DSA_CERT_V00: | ||
1699 | case KEY_RSA_CERT_V00: | ||
1700 | case KEY_DSA_CERT: | ||
1701 | case KEY_ECDSA_CERT: | ||
1702 | case KEY_RSA_CERT: | ||
1703 | case KEY_ED25519_CERT: | ||
1704 | /* Use the existing blob */ | ||
1705 | buffer_append(&b, buffer_ptr(&key->cert->certblob), | ||
1706 | buffer_len(&key->cert->certblob)); | ||
1707 | break; | ||
1708 | case KEY_DSA: | ||
1709 | buffer_put_cstring(&b, | ||
1710 | key_ssh_name_from_type_nid(type, key->ecdsa_nid)); | ||
1711 | buffer_put_bignum2(&b, key->dsa->p); | ||
1712 | buffer_put_bignum2(&b, key->dsa->q); | ||
1713 | buffer_put_bignum2(&b, key->dsa->g); | ||
1714 | buffer_put_bignum2(&b, key->dsa->pub_key); | ||
1715 | break; | ||
1716 | #ifdef OPENSSL_HAS_ECC | ||
1717 | case KEY_ECDSA: | ||
1718 | buffer_put_cstring(&b, | ||
1719 | key_ssh_name_from_type_nid(type, key->ecdsa_nid)); | ||
1720 | buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid)); | ||
1721 | buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa), | ||
1722 | EC_KEY_get0_public_key(key->ecdsa)); | ||
1723 | break; | ||
1724 | #endif | ||
1725 | case KEY_RSA: | ||
1726 | buffer_put_cstring(&b, | ||
1727 | key_ssh_name_from_type_nid(type, key->ecdsa_nid)); | ||
1728 | buffer_put_bignum2(&b, key->rsa->e); | ||
1729 | buffer_put_bignum2(&b, key->rsa->n); | ||
1730 | break; | ||
1731 | case KEY_ED25519: | ||
1732 | buffer_put_cstring(&b, | ||
1733 | key_ssh_name_from_type_nid(type, key->ecdsa_nid)); | ||
1734 | buffer_put_string(&b, key->ed25519_pk, ED25519_PK_SZ); | ||
1735 | break; | ||
1736 | default: | ||
1737 | error("key_to_blob: unsupported key type %d", key->type); | ||
1738 | buffer_free(&b); | ||
1739 | return 0; | 140 | return 0; |
1740 | } | 141 | } |
1741 | len = buffer_len(&b); | 142 | if (blen > INT_MAX) |
143 | fatal("%s: giant len %zu", __func__, blen); | ||
144 | if (blobp != NULL) | ||
145 | *blobp = blob; | ||
1742 | if (lenp != NULL) | 146 | if (lenp != NULL) |
1743 | *lenp = len; | 147 | *lenp = blen; |
1744 | if (blobp != NULL) { | 148 | return blen; |
1745 | *blobp = xmalloc(len); | ||
1746 | memcpy(*blobp, buffer_ptr(&b), len); | ||
1747 | } | ||
1748 | explicit_bzero(buffer_ptr(&b), len); | ||
1749 | buffer_free(&b); | ||
1750 | return len; | ||
1751 | } | ||
1752 | |||
1753 | int | ||
1754 | key_to_blob(const Key *key, u_char **blobp, u_int *lenp) | ||
1755 | { | ||
1756 | return to_blob(key, blobp, lenp, 0); | ||
1757 | } | 149 | } |
1758 | 150 | ||
1759 | int | 151 | int |
1760 | key_sign( | 152 | key_sign(const Key *key, u_char **sigp, u_int *lenp, |
1761 | const Key *key, | ||
1762 | u_char **sigp, u_int *lenp, | ||
1763 | const u_char *data, u_int datalen) | 153 | const u_char *data, u_int datalen) |
1764 | { | 154 | { |
1765 | switch (key->type) { | 155 | int r; |
1766 | case KEY_DSA_CERT_V00: | 156 | u_char *sig; |
1767 | case KEY_DSA_CERT: | 157 | size_t siglen; |
1768 | case KEY_DSA: | 158 | |
1769 | return ssh_dss_sign(key, sigp, lenp, data, datalen); | 159 | if (sigp != NULL) |
1770 | #ifdef OPENSSL_HAS_ECC | 160 | *sigp = NULL; |
1771 | case KEY_ECDSA_CERT: | 161 | if (lenp != NULL) |
1772 | case KEY_ECDSA: | 162 | *lenp = 0; |
1773 | return ssh_ecdsa_sign(key, sigp, lenp, data, datalen); | 163 | if ((r = sshkey_sign(key, &sig, &siglen, |
1774 | #endif | 164 | data, datalen, datafellows)) != 0) { |
1775 | case KEY_RSA_CERT_V00: | 165 | fatal_on_fatal_errors(r, __func__, 0); |
1776 | case KEY_RSA_CERT: | 166 | error("%s: %s", __func__, ssh_err(r)); |
1777 | case KEY_RSA: | ||
1778 | return ssh_rsa_sign(key, sigp, lenp, data, datalen); | ||
1779 | case KEY_ED25519: | ||
1780 | case KEY_ED25519_CERT: | ||
1781 | return ssh_ed25519_sign(key, sigp, lenp, data, datalen); | ||
1782 | default: | ||
1783 | error("key_sign: invalid key type %d", key->type); | ||
1784 | return -1; | 167 | return -1; |
1785 | } | 168 | } |
169 | if (siglen > INT_MAX) | ||
170 | fatal("%s: giant len %zu", __func__, siglen); | ||
171 | if (sigp != NULL) | ||
172 | *sigp = sig; | ||
173 | if (lenp != NULL) | ||
174 | *lenp = siglen; | ||
175 | return 0; | ||
1786 | } | 176 | } |
1787 | 177 | ||
1788 | /* | ||
1789 | * key_verify returns 1 for a correct signature, 0 for an incorrect signature | ||
1790 | * and -1 on error. | ||
1791 | */ | ||
1792 | int | 178 | int |
1793 | key_verify( | 179 | key_verify(const Key *key, const u_char *signature, u_int signaturelen, |
1794 | const Key *key, | ||
1795 | const u_char *signature, u_int signaturelen, | ||
1796 | const u_char *data, u_int datalen) | 180 | const u_char *data, u_int datalen) |
1797 | { | 181 | { |
1798 | if (signaturelen == 0) | 182 | int r; |
1799 | return -1; | ||
1800 | 183 | ||
1801 | switch (key->type) { | 184 | if ((r = sshkey_verify(key, signature, signaturelen, |
1802 | case KEY_DSA_CERT_V00: | 185 | data, datalen, datafellows)) != 0) { |
1803 | case KEY_DSA_CERT: | 186 | fatal_on_fatal_errors(r, __func__, 0); |
1804 | case KEY_DSA: | 187 | error("%s: %s", __func__, ssh_err(r)); |
1805 | return ssh_dss_verify(key, signature, signaturelen, data, datalen); | 188 | return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1; |
1806 | #ifdef OPENSSL_HAS_ECC | ||
1807 | case KEY_ECDSA_CERT: | ||
1808 | case KEY_ECDSA: | ||
1809 | return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen); | ||
1810 | #endif | ||
1811 | case KEY_RSA_CERT_V00: | ||
1812 | case KEY_RSA_CERT: | ||
1813 | case KEY_RSA: | ||
1814 | return ssh_rsa_verify(key, signature, signaturelen, data, datalen); | ||
1815 | case KEY_ED25519: | ||
1816 | case KEY_ED25519_CERT: | ||
1817 | return ssh_ed25519_verify(key, signature, signaturelen, data, datalen); | ||
1818 | default: | ||
1819 | error("key_verify: invalid key type %d", key->type); | ||
1820 | return -1; | ||
1821 | } | 189 | } |
190 | return 1; | ||
1822 | } | 191 | } |
1823 | 192 | ||
1824 | /* Converts a private to a public key */ | ||
1825 | Key * | 193 | Key * |
1826 | key_demote(const Key *k) | 194 | key_demote(const Key *k) |
1827 | { | 195 | { |
1828 | Key *pk; | 196 | int r; |
1829 | 197 | Key *ret = NULL; | |
1830 | pk = xcalloc(1, sizeof(*pk)); | ||
1831 | pk->type = k->type; | ||
1832 | pk->flags = k->flags; | ||
1833 | pk->ecdsa_nid = k->ecdsa_nid; | ||
1834 | pk->dsa = NULL; | ||
1835 | pk->ecdsa = NULL; | ||
1836 | pk->rsa = NULL; | ||
1837 | pk->ed25519_pk = NULL; | ||
1838 | pk->ed25519_sk = NULL; | ||
1839 | |||
1840 | switch (k->type) { | ||
1841 | case KEY_RSA_CERT_V00: | ||
1842 | case KEY_RSA_CERT: | ||
1843 | key_cert_copy(k, pk); | ||
1844 | /* FALLTHROUGH */ | ||
1845 | case KEY_RSA1: | ||
1846 | case KEY_RSA: | ||
1847 | if ((pk->rsa = RSA_new()) == NULL) | ||
1848 | fatal("key_demote: RSA_new failed"); | ||
1849 | if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) | ||
1850 | fatal("key_demote: BN_dup failed"); | ||
1851 | if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) | ||
1852 | fatal("key_demote: BN_dup failed"); | ||
1853 | break; | ||
1854 | case KEY_DSA_CERT_V00: | ||
1855 | case KEY_DSA_CERT: | ||
1856 | key_cert_copy(k, pk); | ||
1857 | /* FALLTHROUGH */ | ||
1858 | case KEY_DSA: | ||
1859 | if ((pk->dsa = DSA_new()) == NULL) | ||
1860 | fatal("key_demote: DSA_new failed"); | ||
1861 | if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) | ||
1862 | fatal("key_demote: BN_dup failed"); | ||
1863 | if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL) | ||
1864 | fatal("key_demote: BN_dup failed"); | ||
1865 | if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL) | ||
1866 | fatal("key_demote: BN_dup failed"); | ||
1867 | if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) | ||
1868 | fatal("key_demote: BN_dup failed"); | ||
1869 | break; | ||
1870 | #ifdef OPENSSL_HAS_ECC | ||
1871 | case KEY_ECDSA_CERT: | ||
1872 | key_cert_copy(k, pk); | ||
1873 | /* FALLTHROUGH */ | ||
1874 | case KEY_ECDSA: | ||
1875 | if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL) | ||
1876 | fatal("key_demote: EC_KEY_new_by_curve_name failed"); | ||
1877 | if (EC_KEY_set_public_key(pk->ecdsa, | ||
1878 | EC_KEY_get0_public_key(k->ecdsa)) != 1) | ||
1879 | fatal("key_demote: EC_KEY_set_public_key failed"); | ||
1880 | break; | ||
1881 | #endif | ||
1882 | case KEY_ED25519_CERT: | ||
1883 | key_cert_copy(k, pk); | ||
1884 | /* FALLTHROUGH */ | ||
1885 | case KEY_ED25519: | ||
1886 | if (k->ed25519_pk != NULL) { | ||
1887 | pk->ed25519_pk = xmalloc(ED25519_PK_SZ); | ||
1888 | memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); | ||
1889 | } | ||
1890 | break; | ||
1891 | default: | ||
1892 | fatal("key_demote: bad key type %d", k->type); | ||
1893 | break; | ||
1894 | } | ||
1895 | |||
1896 | return (pk); | ||
1897 | } | ||
1898 | 198 | ||
1899 | int | 199 | if ((r = sshkey_demote(k, &ret)) != 0) |
1900 | key_is_cert(const Key *k) | 200 | fatal("%s: %s", __func__, ssh_err(r)); |
1901 | { | 201 | return ret; |
1902 | if (k == NULL) | ||
1903 | return 0; | ||
1904 | return key_type_is_cert(k->type); | ||
1905 | } | ||
1906 | |||
1907 | /* Return the cert-less equivalent to a certified key type */ | ||
1908 | int | ||
1909 | key_type_plain(int type) | ||
1910 | { | ||
1911 | switch (type) { | ||
1912 | case KEY_RSA_CERT_V00: | ||
1913 | case KEY_RSA_CERT: | ||
1914 | return KEY_RSA; | ||
1915 | case KEY_DSA_CERT_V00: | ||
1916 | case KEY_DSA_CERT: | ||
1917 | return KEY_DSA; | ||
1918 | case KEY_ECDSA_CERT: | ||
1919 | return KEY_ECDSA; | ||
1920 | case KEY_ED25519_CERT: | ||
1921 | return KEY_ED25519; | ||
1922 | default: | ||
1923 | return type; | ||
1924 | } | ||
1925 | } | 202 | } |
1926 | 203 | ||
1927 | /* Convert a plain key to their _CERT equivalent */ | ||
1928 | int | 204 | int |
1929 | key_to_certified(Key *k, int legacy) | 205 | key_to_certified(Key *k, int legacy) |
1930 | { | 206 | { |
1931 | switch (k->type) { | 207 | int r; |
1932 | case KEY_RSA: | 208 | |
1933 | k->cert = cert_new(); | 209 | if ((r = sshkey_to_certified(k, legacy)) != 0) { |
1934 | k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT; | 210 | fatal_on_fatal_errors(r, __func__, 0); |
1935 | return 0; | 211 | error("%s: %s", __func__, ssh_err(r)); |
1936 | case KEY_DSA: | ||
1937 | k->cert = cert_new(); | ||
1938 | k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT; | ||
1939 | return 0; | ||
1940 | case KEY_ECDSA: | ||
1941 | if (legacy) | ||
1942 | fatal("%s: legacy ECDSA certificates are not supported", | ||
1943 | __func__); | ||
1944 | k->cert = cert_new(); | ||
1945 | k->type = KEY_ECDSA_CERT; | ||
1946 | return 0; | ||
1947 | case KEY_ED25519: | ||
1948 | if (legacy) | ||
1949 | fatal("%s: legacy ED25519 certificates are not " | ||
1950 | "supported", __func__); | ||
1951 | k->cert = cert_new(); | ||
1952 | k->type = KEY_ED25519_CERT; | ||
1953 | return 0; | ||
1954 | default: | ||
1955 | error("%s: key has incorrect type %s", __func__, key_type(k)); | ||
1956 | return -1; | 212 | return -1; |
1957 | } | 213 | } |
214 | return 0; | ||
1958 | } | 215 | } |
1959 | 216 | ||
1960 | /* Convert a certificate to its raw key equivalent */ | ||
1961 | int | 217 | int |
1962 | key_drop_cert(Key *k) | 218 | key_drop_cert(Key *k) |
1963 | { | 219 | { |
1964 | if (!key_type_is_cert(k->type)) { | 220 | int r; |
1965 | error("%s: key has incorrect type %s", __func__, key_type(k)); | 221 | |
222 | if ((r = sshkey_drop_cert(k)) != 0) { | ||
223 | fatal_on_fatal_errors(r, __func__, 0); | ||
224 | error("%s: %s", __func__, ssh_err(r)); | ||
1966 | return -1; | 225 | return -1; |
1967 | } | 226 | } |
1968 | cert_free(k->cert); | ||
1969 | k->cert = NULL; | ||
1970 | k->type = key_type_plain(k->type); | ||
1971 | return 0; | 227 | return 0; |
1972 | } | 228 | } |
1973 | 229 | ||
1974 | /* Sign a certified key, (re-)generating the signed certblob. */ | ||
1975 | int | 230 | int |
1976 | key_certify(Key *k, Key *ca) | 231 | key_certify(Key *k, Key *ca) |
1977 | { | 232 | { |
1978 | Buffer principals; | 233 | int r; |
1979 | u_char *ca_blob, *sig_blob, nonce[32]; | ||
1980 | u_int i, ca_len, sig_len; | ||
1981 | |||
1982 | if (k->cert == NULL) { | ||
1983 | error("%s: key lacks cert info", __func__); | ||
1984 | return -1; | ||
1985 | } | ||
1986 | |||
1987 | if (!key_is_cert(k)) { | ||
1988 | error("%s: certificate has unknown type %d", __func__, | ||
1989 | k->cert->type); | ||
1990 | return -1; | ||
1991 | } | ||
1992 | |||
1993 | if (!key_type_is_valid_ca(ca->type)) { | ||
1994 | error("%s: CA key has unsupported type %s", __func__, | ||
1995 | key_type(ca)); | ||
1996 | return -1; | ||
1997 | } | ||
1998 | |||
1999 | key_to_blob(ca, &ca_blob, &ca_len); | ||
2000 | |||
2001 | buffer_clear(&k->cert->certblob); | ||
2002 | buffer_put_cstring(&k->cert->certblob, key_ssh_name(k)); | ||
2003 | |||
2004 | /* -v01 certs put nonce first */ | ||
2005 | arc4random_buf(&nonce, sizeof(nonce)); | ||
2006 | if (!key_cert_is_legacy(k)) | ||
2007 | buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); | ||
2008 | |||
2009 | /* XXX this substantially duplicates to_blob(); refactor */ | ||
2010 | switch (k->type) { | ||
2011 | case KEY_DSA_CERT_V00: | ||
2012 | case KEY_DSA_CERT: | ||
2013 | buffer_put_bignum2(&k->cert->certblob, k->dsa->p); | ||
2014 | buffer_put_bignum2(&k->cert->certblob, k->dsa->q); | ||
2015 | buffer_put_bignum2(&k->cert->certblob, k->dsa->g); | ||
2016 | buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key); | ||
2017 | break; | ||
2018 | #ifdef OPENSSL_HAS_ECC | ||
2019 | case KEY_ECDSA_CERT: | ||
2020 | buffer_put_cstring(&k->cert->certblob, | ||
2021 | key_curve_nid_to_name(k->ecdsa_nid)); | ||
2022 | buffer_put_ecpoint(&k->cert->certblob, | ||
2023 | EC_KEY_get0_group(k->ecdsa), | ||
2024 | EC_KEY_get0_public_key(k->ecdsa)); | ||
2025 | break; | ||
2026 | #endif | ||
2027 | case KEY_RSA_CERT_V00: | ||
2028 | case KEY_RSA_CERT: | ||
2029 | buffer_put_bignum2(&k->cert->certblob, k->rsa->e); | ||
2030 | buffer_put_bignum2(&k->cert->certblob, k->rsa->n); | ||
2031 | break; | ||
2032 | case KEY_ED25519_CERT: | ||
2033 | buffer_put_string(&k->cert->certblob, | ||
2034 | k->ed25519_pk, ED25519_PK_SZ); | ||
2035 | break; | ||
2036 | default: | ||
2037 | error("%s: key has incorrect type %s", __func__, key_type(k)); | ||
2038 | buffer_clear(&k->cert->certblob); | ||
2039 | free(ca_blob); | ||
2040 | return -1; | ||
2041 | } | ||
2042 | |||
2043 | /* -v01 certs have a serial number next */ | ||
2044 | if (!key_cert_is_legacy(k)) | ||
2045 | buffer_put_int64(&k->cert->certblob, k->cert->serial); | ||
2046 | |||
2047 | buffer_put_int(&k->cert->certblob, k->cert->type); | ||
2048 | buffer_put_cstring(&k->cert->certblob, k->cert->key_id); | ||
2049 | |||
2050 | buffer_init(&principals); | ||
2051 | for (i = 0; i < k->cert->nprincipals; i++) | ||
2052 | buffer_put_cstring(&principals, k->cert->principals[i]); | ||
2053 | buffer_put_string(&k->cert->certblob, buffer_ptr(&principals), | ||
2054 | buffer_len(&principals)); | ||
2055 | buffer_free(&principals); | ||
2056 | |||
2057 | buffer_put_int64(&k->cert->certblob, k->cert->valid_after); | ||
2058 | buffer_put_int64(&k->cert->certblob, k->cert->valid_before); | ||
2059 | buffer_put_string(&k->cert->certblob, | ||
2060 | buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical)); | ||
2061 | |||
2062 | /* -v01 certs have non-critical options here */ | ||
2063 | if (!key_cert_is_legacy(k)) { | ||
2064 | buffer_put_string(&k->cert->certblob, | ||
2065 | buffer_ptr(&k->cert->extensions), | ||
2066 | buffer_len(&k->cert->extensions)); | ||
2067 | } | ||
2068 | |||
2069 | /* -v00 certs put the nonce at the end */ | ||
2070 | if (key_cert_is_legacy(k)) | ||
2071 | buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); | ||
2072 | |||
2073 | buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ | ||
2074 | buffer_put_string(&k->cert->certblob, ca_blob, ca_len); | ||
2075 | free(ca_blob); | ||
2076 | 234 | ||
2077 | /* Sign the whole mess */ | 235 | if ((r = sshkey_certify(k, ca)) != 0) { |
2078 | if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob), | 236 | fatal_on_fatal_errors(r, __func__, 0); |
2079 | buffer_len(&k->cert->certblob)) != 0) { | 237 | error("%s: %s", __func__, ssh_err(r)); |
2080 | error("%s: signature operation failed", __func__); | ||
2081 | buffer_clear(&k->cert->certblob); | ||
2082 | return -1; | 238 | return -1; |
2083 | } | 239 | } |
2084 | /* Append signature and we are done */ | ||
2085 | buffer_put_string(&k->cert->certblob, sig_blob, sig_len); | ||
2086 | free(sig_blob); | ||
2087 | |||
2088 | return 0; | 240 | return 0; |
2089 | } | 241 | } |
2090 | 242 | ||
@@ -2092,535 +244,236 @@ int | |||
2092 | key_cert_check_authority(const Key *k, int want_host, int require_principal, | 244 | key_cert_check_authority(const Key *k, int want_host, int require_principal, |
2093 | const char *name, const char **reason) | 245 | const char *name, const char **reason) |
2094 | { | 246 | { |
2095 | u_int i, principal_matches; | 247 | int r; |
2096 | time_t now = time(NULL); | 248 | |
2097 | 249 | if ((r = sshkey_cert_check_authority(k, want_host, require_principal, | |
2098 | if (want_host) { | 250 | name, reason)) != 0) { |
2099 | if (k->cert->type != SSH2_CERT_TYPE_HOST) { | 251 | fatal_on_fatal_errors(r, __func__, 0); |
2100 | *reason = "Certificate invalid: not a host certificate"; | 252 | error("%s: %s", __func__, ssh_err(r)); |
2101 | return -1; | ||
2102 | } | ||
2103 | } else { | ||
2104 | if (k->cert->type != SSH2_CERT_TYPE_USER) { | ||
2105 | *reason = "Certificate invalid: not a user certificate"; | ||
2106 | return -1; | ||
2107 | } | ||
2108 | } | ||
2109 | if (now < 0) { | ||
2110 | error("%s: system clock lies before epoch", __func__); | ||
2111 | *reason = "Certificate invalid: not yet valid"; | ||
2112 | return -1; | ||
2113 | } | ||
2114 | if ((u_int64_t)now < k->cert->valid_after) { | ||
2115 | *reason = "Certificate invalid: not yet valid"; | ||
2116 | return -1; | ||
2117 | } | ||
2118 | if ((u_int64_t)now >= k->cert->valid_before) { | ||
2119 | *reason = "Certificate invalid: expired"; | ||
2120 | return -1; | 253 | return -1; |
2121 | } | 254 | } |
2122 | if (k->cert->nprincipals == 0) { | ||
2123 | if (require_principal) { | ||
2124 | *reason = "Certificate lacks principal list"; | ||
2125 | return -1; | ||
2126 | } | ||
2127 | } else if (name != NULL) { | ||
2128 | principal_matches = 0; | ||
2129 | for (i = 0; i < k->cert->nprincipals; i++) { | ||
2130 | if (strcmp(name, k->cert->principals[i]) == 0) { | ||
2131 | principal_matches = 1; | ||
2132 | break; | ||
2133 | } | ||
2134 | } | ||
2135 | if (!principal_matches) { | ||
2136 | *reason = "Certificate invalid: name is not a listed " | ||
2137 | "principal"; | ||
2138 | return -1; | ||
2139 | } | ||
2140 | } | ||
2141 | return 0; | 255 | return 0; |
2142 | } | 256 | } |
2143 | 257 | ||
258 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | ||
2144 | int | 259 | int |
2145 | key_cert_is_legacy(const Key *k) | 260 | key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) |
2146 | { | 261 | { |
2147 | switch (k->type) { | 262 | int r; |
2148 | case KEY_DSA_CERT_V00: | 263 | |
2149 | case KEY_RSA_CERT_V00: | 264 | if ((r = sshkey_ec_validate_public(group, public)) != 0) { |
2150 | return 1; | 265 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2151 | default: | 266 | error("%s: %s", __func__, ssh_err(r)); |
2152 | return 0; | 267 | return -1; |
2153 | } | 268 | } |
269 | return 0; | ||
2154 | } | 270 | } |
2155 | 271 | ||
2156 | /* XXX: these are really begging for a table-driven approach */ | ||
2157 | int | 272 | int |
2158 | key_curve_name_to_nid(const char *name) | 273 | key_ec_validate_private(const EC_KEY *key) |
2159 | { | 274 | { |
2160 | #ifdef OPENSSL_HAS_ECC | 275 | int r; |
2161 | if (strcmp(name, "nistp256") == 0) | 276 | |
2162 | return NID_X9_62_prime256v1; | 277 | if ((r = sshkey_ec_validate_private(key)) != 0) { |
2163 | else if (strcmp(name, "nistp384") == 0) | 278 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2164 | return NID_secp384r1; | 279 | error("%s: %s", __func__, ssh_err(r)); |
2165 | # ifdef OPENSSL_HAS_NISTP521 | 280 | return -1; |
2166 | else if (strcmp(name, "nistp521") == 0) | 281 | } |
2167 | return NID_secp521r1; | 282 | return 0; |
2168 | # endif | ||
2169 | #endif | ||
2170 | |||
2171 | debug("%s: unsupported EC curve name \"%.100s\"", __func__, name); | ||
2172 | return -1; | ||
2173 | } | 283 | } |
284 | #endif /* WITH_OPENSSL */ | ||
2174 | 285 | ||
2175 | u_int | 286 | void |
2176 | key_curve_nid_to_bits(int nid) | 287 | key_private_serialize(const Key *key, struct sshbuf *b) |
2177 | { | 288 | { |
2178 | switch (nid) { | 289 | int r; |
2179 | #ifdef OPENSSL_HAS_ECC | 290 | |
2180 | case NID_X9_62_prime256v1: | 291 | if ((r = sshkey_private_serialize(key, b)) != 0) |
2181 | return 256; | 292 | fatal("%s: %s", __func__, ssh_err(r)); |
2182 | case NID_secp384r1: | ||
2183 | return 384; | ||
2184 | # ifdef OPENSSL_HAS_NISTP521 | ||
2185 | case NID_secp521r1: | ||
2186 | return 521; | ||
2187 | # endif | ||
2188 | #endif | ||
2189 | default: | ||
2190 | error("%s: unsupported EC curve nid %d", __func__, nid); | ||
2191 | return 0; | ||
2192 | } | ||
2193 | } | 293 | } |
2194 | 294 | ||
2195 | const char * | 295 | Key * |
2196 | key_curve_nid_to_name(int nid) | 296 | key_private_deserialize(struct sshbuf *blob) |
2197 | { | 297 | { |
2198 | #ifdef OPENSSL_HAS_ECC | 298 | int r; |
2199 | if (nid == NID_X9_62_prime256v1) | 299 | Key *ret = NULL; |
2200 | return "nistp256"; | 300 | |
2201 | else if (nid == NID_secp384r1) | 301 | if ((r = sshkey_private_deserialize(blob, &ret)) != 0) { |
2202 | return "nistp384"; | 302 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2203 | # ifdef OPENSSL_HAS_NISTP521 | 303 | error("%s: %s", __func__, ssh_err(r)); |
2204 | else if (nid == NID_secp521r1) | 304 | return NULL; |
2205 | return "nistp521"; | 305 | } |
2206 | # endif | 306 | return ret; |
2207 | #endif | ||
2208 | error("%s: unsupported EC curve nid %d", __func__, nid); | ||
2209 | return NULL; | ||
2210 | } | 307 | } |
2211 | 308 | ||
2212 | #ifdef OPENSSL_HAS_ECC | 309 | /* authfile.c */ |
310 | |||
2213 | int | 311 | int |
2214 | key_ec_nid_to_hash_alg(int nid) | 312 | key_save_private(Key *key, const char *filename, const char *passphrase, |
313 | const char *comment, int force_new_format, const char *new_format_cipher, | ||
314 | int new_format_rounds) | ||
2215 | { | 315 | { |
2216 | int kbits = key_curve_nid_to_bits(nid); | 316 | int r; |
2217 | 317 | ||
2218 | if (kbits == 0) | 318 | if ((r = sshkey_save_private(key, filename, passphrase, comment, |
2219 | fatal("%s: invalid nid %d", __func__, nid); | 319 | force_new_format, new_format_cipher, new_format_rounds)) != 0) { |
2220 | /* RFC5656 section 6.2.1 */ | 320 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2221 | if (kbits <= 256) | 321 | error("%s: %s", __func__, ssh_err(r)); |
2222 | return SSH_DIGEST_SHA256; | 322 | return 0; |
2223 | else if (kbits <= 384) | 323 | } |
2224 | return SSH_DIGEST_SHA384; | 324 | return 1; |
2225 | else | ||
2226 | return SSH_DIGEST_SHA512; | ||
2227 | } | 325 | } |
2228 | 326 | ||
2229 | int | 327 | int |
2230 | key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) | 328 | key_load_file(int fd, const char *filename, struct sshbuf *blob) |
2231 | { | 329 | { |
2232 | BN_CTX *bnctx; | 330 | int r; |
2233 | EC_POINT *nq = NULL; | ||
2234 | BIGNUM *order, *x, *y, *tmp; | ||
2235 | int ret = -1; | ||
2236 | |||
2237 | if ((bnctx = BN_CTX_new()) == NULL) | ||
2238 | fatal("%s: BN_CTX_new failed", __func__); | ||
2239 | BN_CTX_start(bnctx); | ||
2240 | |||
2241 | /* | ||
2242 | * We shouldn't ever hit this case because bignum_get_ecpoint() | ||
2243 | * refuses to load GF2m points. | ||
2244 | */ | ||
2245 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != | ||
2246 | NID_X9_62_prime_field) { | ||
2247 | error("%s: group is not a prime field", __func__); | ||
2248 | goto out; | ||
2249 | } | ||
2250 | 331 | ||
2251 | /* Q != infinity */ | 332 | if ((r = sshkey_load_file(fd, filename, blob)) != 0) { |
2252 | if (EC_POINT_is_at_infinity(group, public)) { | 333 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2253 | error("%s: received degenerate public key (infinity)", | 334 | error("%s: %s", __func__, ssh_err(r)); |
2254 | __func__); | 335 | return 0; |
2255 | goto out; | ||
2256 | } | 336 | } |
337 | return 1; | ||
338 | } | ||
2257 | 339 | ||
2258 | if ((x = BN_CTX_get(bnctx)) == NULL || | 340 | Key * |
2259 | (y = BN_CTX_get(bnctx)) == NULL || | 341 | key_load_cert(const char *filename) |
2260 | (order = BN_CTX_get(bnctx)) == NULL || | 342 | { |
2261 | (tmp = BN_CTX_get(bnctx)) == NULL) | 343 | int r; |
2262 | fatal("%s: BN_CTX_get failed", __func__); | 344 | Key *ret = NULL; |
2263 | 345 | ||
2264 | /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ | 346 | if ((r = sshkey_load_cert(filename, &ret)) != 0) { |
2265 | if (EC_GROUP_get_order(group, order, bnctx) != 1) | 347 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2266 | fatal("%s: EC_GROUP_get_order failed", __func__); | 348 | /* Old authfile.c ignored all file errors. */ |
2267 | if (EC_POINT_get_affine_coordinates_GFp(group, public, | 349 | if (r == SSH_ERR_SYSTEM_ERROR) |
2268 | x, y, bnctx) != 1) | 350 | debug("%s: %s", __func__, ssh_err(r)); |
2269 | fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__); | 351 | else |
2270 | if (BN_num_bits(x) <= BN_num_bits(order) / 2) { | 352 | error("%s: %s", __func__, ssh_err(r)); |
2271 | error("%s: public key x coordinate too small: " | 353 | return NULL; |
2272 | "bits(x) = %d, bits(order)/2 = %d", __func__, | ||
2273 | BN_num_bits(x), BN_num_bits(order) / 2); | ||
2274 | goto out; | ||
2275 | } | ||
2276 | if (BN_num_bits(y) <= BN_num_bits(order) / 2) { | ||
2277 | error("%s: public key y coordinate too small: " | ||
2278 | "bits(y) = %d, bits(order)/2 = %d", __func__, | ||
2279 | BN_num_bits(x), BN_num_bits(order) / 2); | ||
2280 | goto out; | ||
2281 | } | 354 | } |
355 | return ret; | ||
2282 | 356 | ||
2283 | /* nQ == infinity (n == order of subgroup) */ | 357 | } |
2284 | if ((nq = EC_POINT_new(group)) == NULL) | ||
2285 | fatal("%s: BN_CTX_tmp failed", __func__); | ||
2286 | if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) | ||
2287 | fatal("%s: EC_GROUP_mul failed", __func__); | ||
2288 | if (EC_POINT_is_at_infinity(group, nq) != 1) { | ||
2289 | error("%s: received degenerate public key (nQ != infinity)", | ||
2290 | __func__); | ||
2291 | goto out; | ||
2292 | } | ||
2293 | 358 | ||
2294 | /* x < order - 1, y < order - 1 */ | 359 | Key * |
2295 | if (!BN_sub(tmp, order, BN_value_one())) | 360 | key_load_public(const char *filename, char **commentp) |
2296 | fatal("%s: BN_sub failed", __func__); | 361 | { |
2297 | if (BN_cmp(x, tmp) >= 0) { | 362 | int r; |
2298 | error("%s: public key x coordinate >= group order - 1", | 363 | Key *ret = NULL; |
2299 | __func__); | 364 | |
2300 | goto out; | 365 | if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) { |
2301 | } | 366 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2302 | if (BN_cmp(y, tmp) >= 0) { | 367 | /* Old authfile.c ignored all file errors. */ |
2303 | error("%s: public key y coordinate >= group order - 1", | 368 | if (r == SSH_ERR_SYSTEM_ERROR) |
2304 | __func__); | 369 | debug("%s: %s", __func__, ssh_err(r)); |
2305 | goto out; | 370 | else |
371 | error("%s: %s", __func__, ssh_err(r)); | ||
372 | return NULL; | ||
2306 | } | 373 | } |
2307 | ret = 0; | ||
2308 | out: | ||
2309 | BN_CTX_free(bnctx); | ||
2310 | EC_POINT_free(nq); | ||
2311 | return ret; | 374 | return ret; |
2312 | } | 375 | } |
2313 | 376 | ||
2314 | int | 377 | Key * |
2315 | key_ec_validate_private(const EC_KEY *key) | 378 | key_load_private(const char *path, const char *passphrase, |
2316 | { | 379 | char **commentp) |
2317 | BN_CTX *bnctx; | 380 | { |
2318 | BIGNUM *order, *tmp; | 381 | int r; |
2319 | int ret = -1; | 382 | Key *ret = NULL; |
2320 | 383 | ||
2321 | if ((bnctx = BN_CTX_new()) == NULL) | 384 | if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) { |
2322 | fatal("%s: BN_CTX_new failed", __func__); | 385 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2323 | BN_CTX_start(bnctx); | 386 | /* Old authfile.c ignored all file errors. */ |
2324 | 387 | if (r == SSH_ERR_SYSTEM_ERROR || | |
2325 | if ((order = BN_CTX_get(bnctx)) == NULL || | 388 | r == SSH_ERR_KEY_WRONG_PASSPHRASE) |
2326 | (tmp = BN_CTX_get(bnctx)) == NULL) | 389 | debug("%s: %s", __func__, ssh_err(r)); |
2327 | fatal("%s: BN_CTX_get failed", __func__); | 390 | else |
2328 | 391 | error("%s: %s", __func__, ssh_err(r)); | |
2329 | /* log2(private) > log2(order)/2 */ | 392 | return NULL; |
2330 | if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) | ||
2331 | fatal("%s: EC_GROUP_get_order failed", __func__); | ||
2332 | if (BN_num_bits(EC_KEY_get0_private_key(key)) <= | ||
2333 | BN_num_bits(order) / 2) { | ||
2334 | error("%s: private key too small: " | ||
2335 | "bits(y) = %d, bits(order)/2 = %d", __func__, | ||
2336 | BN_num_bits(EC_KEY_get0_private_key(key)), | ||
2337 | BN_num_bits(order) / 2); | ||
2338 | goto out; | ||
2339 | } | 393 | } |
394 | return ret; | ||
395 | } | ||
2340 | 396 | ||
2341 | /* private < order - 1 */ | 397 | Key * |
2342 | if (!BN_sub(tmp, order, BN_value_one())) | 398 | key_load_private_cert(int type, const char *filename, const char *passphrase, |
2343 | fatal("%s: BN_sub failed", __func__); | 399 | int *perm_ok) |
2344 | if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) { | 400 | { |
2345 | error("%s: private key >= group order - 1", __func__); | 401 | int r; |
2346 | goto out; | 402 | Key *ret = NULL; |
403 | |||
404 | if ((r = sshkey_load_private_cert(type, filename, passphrase, | ||
405 | &ret, perm_ok)) != 0) { | ||
406 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); | ||
407 | /* Old authfile.c ignored all file errors. */ | ||
408 | if (r == SSH_ERR_SYSTEM_ERROR || | ||
409 | r == SSH_ERR_KEY_WRONG_PASSPHRASE) | ||
410 | debug("%s: %s", __func__, ssh_err(r)); | ||
411 | else | ||
412 | error("%s: %s", __func__, ssh_err(r)); | ||
413 | return NULL; | ||
2347 | } | 414 | } |
2348 | ret = 0; | ||
2349 | out: | ||
2350 | BN_CTX_free(bnctx); | ||
2351 | return ret; | 415 | return ret; |
2352 | } | 416 | } |
2353 | 417 | ||
2354 | #if defined(DEBUG_KEXECDH) || defined(DEBUG_PK) | 418 | Key * |
2355 | void | 419 | key_load_private_type(int type, const char *filename, const char *passphrase, |
2356 | key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) | 420 | char **commentp, int *perm_ok) |
2357 | { | 421 | { |
2358 | BIGNUM *x, *y; | 422 | int r; |
2359 | BN_CTX *bnctx; | 423 | Key *ret = NULL; |
2360 | 424 | ||
2361 | if (point == NULL) { | 425 | if ((r = sshkey_load_private_type(type, filename, passphrase, |
2362 | fputs("point=(NULL)\n", stderr); | 426 | &ret, commentp, perm_ok)) != 0) { |
2363 | return; | 427 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
428 | /* Old authfile.c ignored all file errors. */ | ||
429 | if (r == SSH_ERR_SYSTEM_ERROR || | ||
430 | (r == SSH_ERR_KEY_WRONG_PASSPHRASE)) | ||
431 | debug("%s: %s", __func__, ssh_err(r)); | ||
432 | else | ||
433 | error("%s: %s", __func__, ssh_err(r)); | ||
434 | return NULL; | ||
2364 | } | 435 | } |
2365 | if ((bnctx = BN_CTX_new()) == NULL) | 436 | return ret; |
2366 | fatal("%s: BN_CTX_new failed", __func__); | ||
2367 | BN_CTX_start(bnctx); | ||
2368 | if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL) | ||
2369 | fatal("%s: BN_CTX_get failed", __func__); | ||
2370 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != | ||
2371 | NID_X9_62_prime_field) | ||
2372 | fatal("%s: group is not a prime field", __func__); | ||
2373 | if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1) | ||
2374 | fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__); | ||
2375 | fputs("x=", stderr); | ||
2376 | BN_print_fp(stderr, x); | ||
2377 | fputs("\ny=", stderr); | ||
2378 | BN_print_fp(stderr, y); | ||
2379 | fputs("\n", stderr); | ||
2380 | BN_CTX_free(bnctx); | ||
2381 | } | 437 | } |
2382 | 438 | ||
2383 | void | 439 | #ifdef WITH_OPENSSL |
2384 | key_dump_ec_key(const EC_KEY *key) | 440 | Key * |
2385 | { | 441 | key_load_private_pem(int fd, int type, const char *passphrase, |
2386 | const BIGNUM *exponent; | 442 | char **commentp) |
2387 | 443 | { | |
2388 | key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key)); | 444 | int r; |
2389 | fputs("exponent=", stderr); | 445 | Key *ret = NULL; |
2390 | if ((exponent = EC_KEY_get0_private_key(key)) == NULL) | 446 | |
2391 | fputs("(NULL)", stderr); | 447 | if ((r = sshkey_load_private_pem(fd, type, passphrase, |
2392 | else | 448 | &ret, commentp)) != 0) { |
2393 | BN_print_fp(stderr, EC_KEY_get0_private_key(key)); | 449 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2394 | fputs("\n", stderr); | 450 | if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) |
451 | debug("%s: %s", __func__, ssh_err(r)); | ||
452 | else | ||
453 | error("%s: %s", __func__, ssh_err(r)); | ||
454 | return NULL; | ||
455 | } | ||
456 | return ret; | ||
2395 | } | 457 | } |
2396 | #endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */ | 458 | #endif /* WITH_OPENSSL */ |
2397 | #endif /* OPENSSL_HAS_ECC */ | ||
2398 | 459 | ||
2399 | void | 460 | int |
2400 | key_private_serialize(const Key *key, Buffer *b) | 461 | key_perm_ok(int fd, const char *filename) |
2401 | { | 462 | { |
2402 | buffer_put_cstring(b, key_ssh_name(key)); | 463 | return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0; |
2403 | switch (key->type) { | ||
2404 | case KEY_RSA: | ||
2405 | buffer_put_bignum2(b, key->rsa->n); | ||
2406 | buffer_put_bignum2(b, key->rsa->e); | ||
2407 | buffer_put_bignum2(b, key->rsa->d); | ||
2408 | buffer_put_bignum2(b, key->rsa->iqmp); | ||
2409 | buffer_put_bignum2(b, key->rsa->p); | ||
2410 | buffer_put_bignum2(b, key->rsa->q); | ||
2411 | break; | ||
2412 | case KEY_RSA_CERT_V00: | ||
2413 | case KEY_RSA_CERT: | ||
2414 | if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) | ||
2415 | fatal("%s: no cert/certblob", __func__); | ||
2416 | buffer_put_string(b, buffer_ptr(&key->cert->certblob), | ||
2417 | buffer_len(&key->cert->certblob)); | ||
2418 | buffer_put_bignum2(b, key->rsa->d); | ||
2419 | buffer_put_bignum2(b, key->rsa->iqmp); | ||
2420 | buffer_put_bignum2(b, key->rsa->p); | ||
2421 | buffer_put_bignum2(b, key->rsa->q); | ||
2422 | break; | ||
2423 | case KEY_DSA: | ||
2424 | buffer_put_bignum2(b, key->dsa->p); | ||
2425 | buffer_put_bignum2(b, key->dsa->q); | ||
2426 | buffer_put_bignum2(b, key->dsa->g); | ||
2427 | buffer_put_bignum2(b, key->dsa->pub_key); | ||
2428 | buffer_put_bignum2(b, key->dsa->priv_key); | ||
2429 | break; | ||
2430 | case KEY_DSA_CERT_V00: | ||
2431 | case KEY_DSA_CERT: | ||
2432 | if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) | ||
2433 | fatal("%s: no cert/certblob", __func__); | ||
2434 | buffer_put_string(b, buffer_ptr(&key->cert->certblob), | ||
2435 | buffer_len(&key->cert->certblob)); | ||
2436 | buffer_put_bignum2(b, key->dsa->priv_key); | ||
2437 | break; | ||
2438 | #ifdef OPENSSL_HAS_ECC | ||
2439 | case KEY_ECDSA: | ||
2440 | buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid)); | ||
2441 | buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa), | ||
2442 | EC_KEY_get0_public_key(key->ecdsa)); | ||
2443 | buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); | ||
2444 | break; | ||
2445 | case KEY_ECDSA_CERT: | ||
2446 | if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) | ||
2447 | fatal("%s: no cert/certblob", __func__); | ||
2448 | buffer_put_string(b, buffer_ptr(&key->cert->certblob), | ||
2449 | buffer_len(&key->cert->certblob)); | ||
2450 | buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); | ||
2451 | break; | ||
2452 | #endif /* OPENSSL_HAS_ECC */ | ||
2453 | case KEY_ED25519: | ||
2454 | buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ); | ||
2455 | buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ); | ||
2456 | break; | ||
2457 | case KEY_ED25519_CERT: | ||
2458 | if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) | ||
2459 | fatal("%s: no cert/certblob", __func__); | ||
2460 | buffer_put_string(b, buffer_ptr(&key->cert->certblob), | ||
2461 | buffer_len(&key->cert->certblob)); | ||
2462 | buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ); | ||
2463 | buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ); | ||
2464 | break; | ||
2465 | } | ||
2466 | } | 464 | } |
2467 | 465 | ||
2468 | Key * | 466 | int |
2469 | key_private_deserialize(Buffer *blob) | 467 | key_in_file(Key *key, const char *filename, int strict_type) |
2470 | { | 468 | { |
2471 | char *type_name; | 469 | int r; |
2472 | Key *k = NULL; | 470 | |
2473 | u_char *cert; | 471 | if ((r = sshkey_in_file(key, filename, strict_type)) != 0) { |
2474 | u_int len, pklen, sklen; | 472 | fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); |
2475 | int type; | 473 | if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) |
2476 | #ifdef OPENSSL_HAS_ECC | 474 | return 0; |
2477 | char *curve; | 475 | error("%s: %s", __func__, ssh_err(r)); |
2478 | BIGNUM *exponent; | 476 | return r == SSH_ERR_KEY_NOT_FOUND ? 0 : -1; |
2479 | EC_POINT *q; | ||
2480 | #endif | ||
2481 | |||
2482 | type_name = buffer_get_string(blob, NULL); | ||
2483 | type = key_type_from_name(type_name); | ||
2484 | switch (type) { | ||
2485 | case KEY_DSA: | ||
2486 | k = key_new_private(type); | ||
2487 | buffer_get_bignum2(blob, k->dsa->p); | ||
2488 | buffer_get_bignum2(blob, k->dsa->q); | ||
2489 | buffer_get_bignum2(blob, k->dsa->g); | ||
2490 | buffer_get_bignum2(blob, k->dsa->pub_key); | ||
2491 | buffer_get_bignum2(blob, k->dsa->priv_key); | ||
2492 | break; | ||
2493 | case KEY_DSA_CERT_V00: | ||
2494 | case KEY_DSA_CERT: | ||
2495 | cert = buffer_get_string(blob, &len); | ||
2496 | if ((k = key_from_blob(cert, len)) == NULL) | ||
2497 | fatal("Certificate parse failed"); | ||
2498 | free(cert); | ||
2499 | key_add_private(k); | ||
2500 | buffer_get_bignum2(blob, k->dsa->priv_key); | ||
2501 | break; | ||
2502 | #ifdef OPENSSL_HAS_ECC | ||
2503 | case KEY_ECDSA: | ||
2504 | k = key_new_private(type); | ||
2505 | k->ecdsa_nid = key_ecdsa_nid_from_name(type_name); | ||
2506 | curve = buffer_get_string(blob, NULL); | ||
2507 | if (k->ecdsa_nid != key_curve_name_to_nid(curve)) | ||
2508 | fatal("%s: curve names mismatch", __func__); | ||
2509 | free(curve); | ||
2510 | k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); | ||
2511 | if (k->ecdsa == NULL) | ||
2512 | fatal("%s: EC_KEY_new_by_curve_name failed", | ||
2513 | __func__); | ||
2514 | q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa)); | ||
2515 | if (q == NULL) | ||
2516 | fatal("%s: BN_new failed", __func__); | ||
2517 | if ((exponent = BN_new()) == NULL) | ||
2518 | fatal("%s: BN_new failed", __func__); | ||
2519 | buffer_get_ecpoint(blob, | ||
2520 | EC_KEY_get0_group(k->ecdsa), q); | ||
2521 | buffer_get_bignum2(blob, exponent); | ||
2522 | if (EC_KEY_set_public_key(k->ecdsa, q) != 1) | ||
2523 | fatal("%s: EC_KEY_set_public_key failed", | ||
2524 | __func__); | ||
2525 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) | ||
2526 | fatal("%s: EC_KEY_set_private_key failed", | ||
2527 | __func__); | ||
2528 | if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
2529 | EC_KEY_get0_public_key(k->ecdsa)) != 0) | ||
2530 | fatal("%s: bad ECDSA public key", __func__); | ||
2531 | if (key_ec_validate_private(k->ecdsa) != 0) | ||
2532 | fatal("%s: bad ECDSA private key", __func__); | ||
2533 | BN_clear_free(exponent); | ||
2534 | EC_POINT_free(q); | ||
2535 | break; | ||
2536 | case KEY_ECDSA_CERT: | ||
2537 | cert = buffer_get_string(blob, &len); | ||
2538 | if ((k = key_from_blob(cert, len)) == NULL) | ||
2539 | fatal("Certificate parse failed"); | ||
2540 | free(cert); | ||
2541 | key_add_private(k); | ||
2542 | if ((exponent = BN_new()) == NULL) | ||
2543 | fatal("%s: BN_new failed", __func__); | ||
2544 | buffer_get_bignum2(blob, exponent); | ||
2545 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) | ||
2546 | fatal("%s: EC_KEY_set_private_key failed", | ||
2547 | __func__); | ||
2548 | if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
2549 | EC_KEY_get0_public_key(k->ecdsa)) != 0 || | ||
2550 | key_ec_validate_private(k->ecdsa) != 0) | ||
2551 | fatal("%s: bad ECDSA key", __func__); | ||
2552 | BN_clear_free(exponent); | ||
2553 | break; | ||
2554 | #endif | ||
2555 | case KEY_RSA: | ||
2556 | k = key_new_private(type); | ||
2557 | buffer_get_bignum2(blob, k->rsa->n); | ||
2558 | buffer_get_bignum2(blob, k->rsa->e); | ||
2559 | buffer_get_bignum2(blob, k->rsa->d); | ||
2560 | buffer_get_bignum2(blob, k->rsa->iqmp); | ||
2561 | buffer_get_bignum2(blob, k->rsa->p); | ||
2562 | buffer_get_bignum2(blob, k->rsa->q); | ||
2563 | |||
2564 | /* Generate additional parameters */ | ||
2565 | rsa_generate_additional_parameters(k->rsa); | ||
2566 | break; | ||
2567 | case KEY_RSA_CERT_V00: | ||
2568 | case KEY_RSA_CERT: | ||
2569 | cert = buffer_get_string(blob, &len); | ||
2570 | if ((k = key_from_blob(cert, len)) == NULL) | ||
2571 | fatal("Certificate parse failed"); | ||
2572 | free(cert); | ||
2573 | key_add_private(k); | ||
2574 | buffer_get_bignum2(blob, k->rsa->d); | ||
2575 | buffer_get_bignum2(blob, k->rsa->iqmp); | ||
2576 | buffer_get_bignum2(blob, k->rsa->p); | ||
2577 | buffer_get_bignum2(blob, k->rsa->q); | ||
2578 | break; | ||
2579 | case KEY_ED25519: | ||
2580 | k = key_new_private(type); | ||
2581 | k->ed25519_pk = buffer_get_string(blob, &pklen); | ||
2582 | k->ed25519_sk = buffer_get_string(blob, &sklen); | ||
2583 | if (pklen != ED25519_PK_SZ) | ||
2584 | fatal("%s: ed25519 pklen %d != %d", | ||
2585 | __func__, pklen, ED25519_PK_SZ); | ||
2586 | if (sklen != ED25519_SK_SZ) | ||
2587 | fatal("%s: ed25519 sklen %d != %d", | ||
2588 | __func__, sklen, ED25519_SK_SZ); | ||
2589 | break; | ||
2590 | case KEY_ED25519_CERT: | ||
2591 | cert = buffer_get_string(blob, &len); | ||
2592 | if ((k = key_from_blob(cert, len)) == NULL) | ||
2593 | fatal("Certificate parse failed"); | ||
2594 | free(cert); | ||
2595 | key_add_private(k); | ||
2596 | k->ed25519_pk = buffer_get_string(blob, &pklen); | ||
2597 | k->ed25519_sk = buffer_get_string(blob, &sklen); | ||
2598 | if (pklen != ED25519_PK_SZ) | ||
2599 | fatal("%s: ed25519 pklen %d != %d", | ||
2600 | __func__, pklen, ED25519_PK_SZ); | ||
2601 | if (sklen != ED25519_SK_SZ) | ||
2602 | fatal("%s: ed25519 sklen %d != %d", | ||
2603 | __func__, sklen, ED25519_SK_SZ); | ||
2604 | break; | ||
2605 | default: | ||
2606 | free(type_name); | ||
2607 | buffer_clear(blob); | ||
2608 | return NULL; | ||
2609 | } | ||
2610 | free(type_name); | ||
2611 | |||
2612 | /* enable blinding */ | ||
2613 | switch (k->type) { | ||
2614 | case KEY_RSA: | ||
2615 | case KEY_RSA_CERT_V00: | ||
2616 | case KEY_RSA_CERT: | ||
2617 | case KEY_RSA1: | ||
2618 | if (RSA_blinding_on(k->rsa, NULL) != 1) { | ||
2619 | error("%s: RSA_blinding_on failed", __func__); | ||
2620 | key_free(k); | ||
2621 | return NULL; | ||
2622 | } | ||
2623 | break; | ||
2624 | } | 477 | } |
2625 | return k; | 478 | return 1; |
2626 | } | 479 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.h,v 1.41 2014/01/09 23:20:00 djm Exp $ */ | 1 | /* $OpenBSD: key.h,v 1.42 2014/06/24 01:13:21 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -26,142 +26,86 @@ | |||
26 | #ifndef KEY_H | 26 | #ifndef KEY_H |
27 | #define KEY_H | 27 | #define KEY_H |
28 | 28 | ||
29 | #include "buffer.h" | 29 | #include "sshkey.h" |
30 | #include <openssl/rsa.h> | 30 | |
31 | #include <openssl/dsa.h> | 31 | typedef struct sshkey Key; |
32 | #ifdef OPENSSL_HAS_ECC | 32 | |
33 | #include <openssl/ec.h> | 33 | #define types sshkey_types |
34 | #define fp_type sshkey_fp_type | ||
35 | #define fp_rep sshkey_fp_rep | ||
36 | |||
37 | #ifndef SSH_KEY_NO_DEFINE | ||
38 | #define key_new sshkey_new | ||
39 | #define key_free sshkey_free | ||
40 | #define key_equal_public sshkey_equal_public | ||
41 | #define key_equal sshkey_equal | ||
42 | #define key_fingerprint sshkey_fingerprint | ||
43 | #define key_type sshkey_type | ||
44 | #define key_cert_type sshkey_cert_type | ||
45 | #define key_ssh_name sshkey_ssh_name | ||
46 | #define key_ssh_name_plain sshkey_ssh_name_plain | ||
47 | #define key_type_from_name sshkey_type_from_name | ||
48 | #define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name | ||
49 | #define key_type_is_cert sshkey_type_is_cert | ||
50 | #define key_size sshkey_size | ||
51 | #define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid | ||
52 | #define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid | ||
53 | #define key_names_valid2 sshkey_names_valid2 | ||
54 | #define key_is_cert sshkey_is_cert | ||
55 | #define key_type_plain sshkey_type_plain | ||
56 | #define key_cert_is_legacy sshkey_cert_is_legacy | ||
57 | #define key_curve_name_to_nid sshkey_curve_name_to_nid | ||
58 | #define key_curve_nid_to_bits sshkey_curve_nid_to_bits | ||
59 | #define key_curve_nid_to_name sshkey_curve_nid_to_name | ||
60 | #define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg | ||
61 | #define key_dump_ec_point sshkey_dump_ec_point | ||
62 | #define key_dump_ec_key sshkey_dump_ec_key | ||
63 | #define key_fingerprint sshkey_fingerprint | ||
34 | #endif | 64 | #endif |
35 | 65 | ||
36 | typedef struct Key Key; | 66 | void key_add_private(Key *); |
37 | enum types { | 67 | Key *key_new_private(int); |
38 | KEY_RSA1, | 68 | void key_free(Key *); |
39 | KEY_RSA, | 69 | Key *key_demote(const Key *); |
40 | KEY_DSA, | 70 | u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); |
41 | KEY_ECDSA, | 71 | int key_write(const Key *, FILE *); |
42 | KEY_ED25519, | 72 | int key_read(Key *, char **); |
43 | KEY_RSA_CERT, | ||
44 | KEY_DSA_CERT, | ||
45 | KEY_ECDSA_CERT, | ||
46 | KEY_ED25519_CERT, | ||
47 | KEY_RSA_CERT_V00, | ||
48 | KEY_DSA_CERT_V00, | ||
49 | KEY_NULL, | ||
50 | KEY_UNSPEC | ||
51 | }; | ||
52 | enum fp_type { | ||
53 | SSH_FP_SHA1, | ||
54 | SSH_FP_MD5, | ||
55 | SSH_FP_SHA256 | ||
56 | }; | ||
57 | enum fp_rep { | ||
58 | SSH_FP_HEX, | ||
59 | SSH_FP_BUBBLEBABBLE, | ||
60 | SSH_FP_RANDOMART | ||
61 | }; | ||
62 | |||
63 | /* key is stored in external hardware */ | ||
64 | #define KEY_FLAG_EXT 0x0001 | ||
65 | |||
66 | #define CERT_MAX_PRINCIPALS 256 | ||
67 | struct KeyCert { | ||
68 | Buffer certblob; /* Kept around for use on wire */ | ||
69 | u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ | ||
70 | u_int64_t serial; | ||
71 | char *key_id; | ||
72 | u_int nprincipals; | ||
73 | char **principals; | ||
74 | u_int64_t valid_after, valid_before; | ||
75 | Buffer critical; | ||
76 | Buffer extensions; | ||
77 | Key *signature_key; | ||
78 | }; | ||
79 | |||
80 | struct Key { | ||
81 | int type; | ||
82 | int flags; | ||
83 | RSA *rsa; | ||
84 | DSA *dsa; | ||
85 | int ecdsa_nid; /* NID of curve */ | ||
86 | #ifdef OPENSSL_HAS_ECC | ||
87 | EC_KEY *ecdsa; | ||
88 | #else | ||
89 | void *ecdsa; | ||
90 | #endif | ||
91 | struct KeyCert *cert; | ||
92 | u_char *ed25519_sk; | ||
93 | u_char *ed25519_pk; | ||
94 | }; | ||
95 | |||
96 | #define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES | ||
97 | #define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES | ||
98 | |||
99 | Key *key_new(int); | ||
100 | void key_add_private(Key *); | ||
101 | Key *key_new_private(int); | ||
102 | void key_free(Key *); | ||
103 | Key *key_demote(const Key *); | ||
104 | int key_equal_public(const Key *, const Key *); | ||
105 | int key_equal(const Key *, const Key *); | ||
106 | char *key_fingerprint(const Key *, enum fp_type, enum fp_rep); | ||
107 | u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); | ||
108 | const char *key_type(const Key *); | ||
109 | const char *key_cert_type(const Key *); | ||
110 | int key_write(const Key *, FILE *); | ||
111 | int key_read(Key *, char **); | ||
112 | u_int key_size(const Key *); | ||
113 | 73 | ||
114 | Key *key_generate(int, u_int); | 74 | Key *key_generate(int, u_int); |
115 | Key *key_from_private(const Key *); | 75 | Key *key_from_private(const Key *); |
116 | int key_type_from_name(char *); | ||
117 | int key_is_cert(const Key *); | ||
118 | int key_type_is_cert(int); | ||
119 | int key_type_plain(int); | ||
120 | int key_to_certified(Key *, int); | 76 | int key_to_certified(Key *, int); |
121 | int key_drop_cert(Key *); | 77 | int key_drop_cert(Key *); |
122 | int key_certify(Key *, Key *); | 78 | int key_certify(Key *, Key *); |
123 | void key_cert_copy(const Key *, struct Key *); | 79 | void key_cert_copy(const Key *, Key *); |
124 | int key_cert_check_authority(const Key *, int, int, const char *, | 80 | int key_cert_check_authority(const Key *, int, int, const char *, |
125 | const char **); | 81 | const char **); |
126 | int key_cert_is_legacy(const Key *); | 82 | char *key_alg_list(int, int); |
127 | 83 | ||
128 | int key_ecdsa_nid_from_name(const char *); | 84 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) |
129 | int key_curve_name_to_nid(const char *); | 85 | int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); |
130 | const char *key_curve_nid_to_name(int); | 86 | int key_ec_validate_private(const EC_KEY *); |
131 | u_int key_curve_nid_to_bits(int); | 87 | #endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ |
132 | int key_ecdsa_bits_to_nid(int); | ||
133 | #ifdef OPENSSL_HAS_ECC | ||
134 | int key_ecdsa_key_to_nid(EC_KEY *); | ||
135 | int key_ec_nid_to_hash_alg(int nid); | ||
136 | int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); | ||
137 | int key_ec_validate_private(const EC_KEY *); | ||
138 | #endif | ||
139 | char *key_alg_list(int, int); | ||
140 | 88 | ||
141 | Key *key_from_blob(const u_char *, u_int); | 89 | Key *key_from_blob(const u_char *, u_int); |
142 | int key_to_blob(const Key *, u_char **, u_int *); | 90 | int key_to_blob(const Key *, u_char **, u_int *); |
143 | const char *key_ssh_name(const Key *); | ||
144 | const char *key_ssh_name_plain(const Key *); | ||
145 | int key_names_valid2(const char *); | ||
146 | 91 | ||
147 | int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 92 | int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); |
148 | int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | 93 | int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); |
149 | 94 | ||
150 | int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 95 | void key_private_serialize(const Key *, struct sshbuf *); |
151 | int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | 96 | Key *key_private_deserialize(struct sshbuf *); |
152 | int ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 97 | |
153 | int ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | 98 | /* authfile.c */ |
154 | int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 99 | int key_save_private(Key *, const char *, const char *, const char *, |
155 | int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | 100 | int, const char *, int); |
156 | int ssh_ed25519_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 101 | int key_load_file(int, const char *, struct sshbuf *); |
157 | int ssh_ed25519_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | 102 | Key *key_load_cert(const char *); |
158 | 103 | Key *key_load_public(const char *, char **); | |
159 | #if defined(OPENSSL_HAS_ECC) && (defined(DEBUG_KEXECDH) || defined(DEBUG_PK)) | 104 | Key *key_load_private(const char *, const char *, char **); |
160 | void key_dump_ec_point(const EC_GROUP *, const EC_POINT *); | 105 | Key *key_load_private_cert(int, const char *, const char *, int *); |
161 | void key_dump_ec_key(const EC_KEY *); | 106 | Key *key_load_private_type(int, const char *, const char *, char **, int *); |
162 | #endif | 107 | Key *key_load_private_pem(int, int, const char *, char **); |
163 | 108 | int key_perm_ok(int, const char *); | |
164 | void key_private_serialize(const Key *, Buffer *); | 109 | int key_in_file(Key *, const char *, int); |
165 | Key *key_private_deserialize(Buffer *); | ||
166 | 110 | ||
167 | #endif | 111 | #endif |
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /* $OpenBSD: krl.c,v 1.14 2014/01/31 16:39:19 tedu Exp $ */ | 17 | /* $OpenBSD: krl.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | 20 | ||
@@ -366,7 +366,7 @@ plain_key_blob(const Key *key, u_char **blob, u_int *blen) | |||
366 | } | 366 | } |
367 | r = key_to_blob(kcopy, blob, blen); | 367 | r = key_to_blob(kcopy, blob, blen); |
368 | free(kcopy); | 368 | free(kcopy); |
369 | return r == 0 ? -1 : 0; | 369 | return r; |
370 | } | 370 | } |
371 | 371 | ||
372 | /* Revoke a key blob. Ownership of blob is transferred to the tree */ | 372 | /* Revoke a key blob. Ownership of blob is transferred to the tree */ |
@@ -394,7 +394,7 @@ ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key) | |||
394 | u_int len; | 394 | u_int len; |
395 | 395 | ||
396 | debug3("%s: revoke type %s", __func__, key_type(key)); | 396 | debug3("%s: revoke type %s", __func__, key_type(key)); |
397 | if (plain_key_blob(key, &blob, &len) != 0) | 397 | if (plain_key_blob(key, &blob, &len) < 0) |
398 | return -1; | 398 | return -1; |
399 | return revoke_blob(&krl->revoked_keys, blob, len); | 399 | return revoke_blob(&krl->revoked_keys, blob, len); |
400 | } | 400 | } |
@@ -575,6 +575,7 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) | |||
575 | buffer_put_char(buf, state); | 575 | buffer_put_char(buf, state); |
576 | buffer_put_string(buf, | 576 | buffer_put_string(buf, |
577 | buffer_ptr(§), buffer_len(§)); | 577 | buffer_ptr(§), buffer_len(§)); |
578 | buffer_clear(§); | ||
578 | } | 579 | } |
579 | 580 | ||
580 | /* If we are starting a new section then prepare it now */ | 581 | /* If we are starting a new section then prepare it now */ |
@@ -753,7 +754,8 @@ static int | |||
753 | parse_revoked_certs(Buffer *buf, struct ssh_krl *krl) | 754 | parse_revoked_certs(Buffer *buf, struct ssh_krl *krl) |
754 | { | 755 | { |
755 | int ret = -1, nbits; | 756 | int ret = -1, nbits; |
756 | u_char type, *blob; | 757 | u_char type; |
758 | const u_char *blob; | ||
757 | u_int blen; | 759 | u_int blen; |
758 | Buffer subsect; | 760 | Buffer subsect; |
759 | u_int64_t serial, serial_lo, serial_hi; | 761 | u_int64_t serial, serial_lo, serial_hi; |
@@ -887,7 +889,8 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, | |||
887 | char timestamp[64]; | 889 | char timestamp[64]; |
888 | int ret = -1, r, sig_seen; | 890 | int ret = -1, r, sig_seen; |
889 | Key *key = NULL, **ca_used = NULL; | 891 | Key *key = NULL, **ca_used = NULL; |
890 | u_char type, *blob, *rdata = NULL; | 892 | u_char type, *rdata = NULL; |
893 | const u_char *blob; | ||
891 | u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used; | 894 | u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used; |
892 | 895 | ||
893 | nca_used = 0; | 896 | nca_used = 0; |
@@ -1127,7 +1130,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key) | |||
1127 | 1130 | ||
1128 | /* Next, explicit keys */ | 1131 | /* Next, explicit keys */ |
1129 | memset(&rb, 0, sizeof(rb)); | 1132 | memset(&rb, 0, sizeof(rb)); |
1130 | if (plain_key_blob(key, &rb.blob, &rb.len) != 0) | 1133 | if (plain_key_blob(key, &rb.blob, &rb.len) < 0) |
1131 | return -1; | 1134 | return -1; |
1132 | erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); | 1135 | erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); |
1133 | free(rb.blob); | 1136 | free(rb.blob); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mac.c,v 1.28 2014/02/07 06:55:54 djm Exp $ */ | 1 | /* $OpenBSD: mac.c,v 1.30 2014/04/30 19:07:48 naddy Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -175,7 +175,8 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) | |||
175 | u_char m[EVP_MAX_MD_SIZE]; | 175 | u_char m[EVP_MAX_MD_SIZE]; |
176 | u_int64_t for_align; | 176 | u_int64_t for_align; |
177 | } u; | 177 | } u; |
178 | u_char b[4], nonce[8]; | 178 | u_char b[4]; |
179 | u_char nonce[8]; | ||
179 | 180 | ||
180 | if (mac->mac_len > sizeof(u)) | 181 | if (mac->mac_len > sizeof(u)) |
181 | fatal("mac_compute: mac too long %u %zu", | 182 | fatal("mac_compute: mac too long %u %zu", |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.92 2013/10/14 23:28:23 djm Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.94 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -29,6 +29,7 @@ | |||
29 | #include <sys/types.h> | 29 | #include <sys/types.h> |
30 | #include <sys/ioctl.h> | 30 | #include <sys/ioctl.h> |
31 | #include <sys/socket.h> | 31 | #include <sys/socket.h> |
32 | #include <sys/un.h> | ||
32 | #include <sys/param.h> | 33 | #include <sys/param.h> |
33 | 34 | ||
34 | #include <stdarg.h> | 35 | #include <stdarg.h> |
@@ -855,6 +856,20 @@ get_u32(const void *vp) | |||
855 | return (v); | 856 | return (v); |
856 | } | 857 | } |
857 | 858 | ||
859 | u_int32_t | ||
860 | get_u32_le(const void *vp) | ||
861 | { | ||
862 | const u_char *p = (const u_char *)vp; | ||
863 | u_int32_t v; | ||
864 | |||
865 | v = (u_int32_t)p[0]; | ||
866 | v |= (u_int32_t)p[1] << 8; | ||
867 | v |= (u_int32_t)p[2] << 16; | ||
868 | v |= (u_int32_t)p[3] << 24; | ||
869 | |||
870 | return (v); | ||
871 | } | ||
872 | |||
858 | u_int16_t | 873 | u_int16_t |
859 | get_u16(const void *vp) | 874 | get_u16(const void *vp) |
860 | { | 875 | { |
@@ -893,6 +908,16 @@ put_u32(void *vp, u_int32_t v) | |||
893 | p[3] = (u_char)v & 0xff; | 908 | p[3] = (u_char)v & 0xff; |
894 | } | 909 | } |
895 | 910 | ||
911 | void | ||
912 | put_u32_le(void *vp, u_int32_t v) | ||
913 | { | ||
914 | u_char *p = (u_char *)vp; | ||
915 | |||
916 | p[0] = (u_char)v & 0xff; | ||
917 | p[1] = (u_char)(v >> 8) & 0xff; | ||
918 | p[2] = (u_char)(v >> 16) & 0xff; | ||
919 | p[3] = (u_char)(v >> 24) & 0xff; | ||
920 | } | ||
896 | 921 | ||
897 | void | 922 | void |
898 | put_u16(void *vp, u_int16_t v) | 923 | put_u16(void *vp, u_int16_t v) |
@@ -925,17 +950,24 @@ ms_to_timeval(struct timeval *tv, int ms) | |||
925 | time_t | 950 | time_t |
926 | monotime(void) | 951 | monotime(void) |
927 | { | 952 | { |
928 | #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) | 953 | #if defined(HAVE_CLOCK_GETTIME) && \ |
954 | (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) | ||
929 | struct timespec ts; | 955 | struct timespec ts; |
930 | static int gettime_failed = 0; | 956 | static int gettime_failed = 0; |
931 | 957 | ||
932 | if (!gettime_failed) { | 958 | if (!gettime_failed) { |
959 | #if defined(CLOCK_BOOTTIME) | ||
960 | if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) | ||
961 | return (ts.tv_sec); | ||
962 | #endif | ||
963 | #if defined(CLOCK_MONOTONIC) | ||
933 | if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) | 964 | if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) |
934 | return (ts.tv_sec); | 965 | return (ts.tv_sec); |
966 | #endif | ||
935 | debug3("clock_gettime: %s", strerror(errno)); | 967 | debug3("clock_gettime: %s", strerror(errno)); |
936 | gettime_failed = 1; | 968 | gettime_failed = 1; |
937 | } | 969 | } |
938 | #endif | 970 | #endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ |
939 | 971 | ||
940 | return time(NULL); | 972 | return time(NULL); |
941 | } | 973 | } |
@@ -1092,6 +1124,53 @@ lowercase(char *s) | |||
1092 | for (; *s; s++) | 1124 | for (; *s; s++) |
1093 | *s = tolower((u_char)*s); | 1125 | *s = tolower((u_char)*s); |
1094 | } | 1126 | } |
1127 | |||
1128 | int | ||
1129 | unix_listener(const char *path, int backlog, int unlink_first) | ||
1130 | { | ||
1131 | struct sockaddr_un sunaddr; | ||
1132 | int saved_errno, sock; | ||
1133 | |||
1134 | memset(&sunaddr, 0, sizeof(sunaddr)); | ||
1135 | sunaddr.sun_family = AF_UNIX; | ||
1136 | if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { | ||
1137 | error("%s: \"%s\" too long for Unix domain socket", __func__, | ||
1138 | path); | ||
1139 | errno = ENAMETOOLONG; | ||
1140 | return -1; | ||
1141 | } | ||
1142 | |||
1143 | sock = socket(PF_UNIX, SOCK_STREAM, 0); | ||
1144 | if (sock < 0) { | ||
1145 | saved_errno = errno; | ||
1146 | error("socket: %.100s", strerror(errno)); | ||
1147 | errno = saved_errno; | ||
1148 | return -1; | ||
1149 | } | ||
1150 | if (unlink_first == 1) { | ||
1151 | if (unlink(path) != 0 && errno != ENOENT) | ||
1152 | error("unlink(%s): %.100s", path, strerror(errno)); | ||
1153 | } | ||
1154 | if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { | ||
1155 | saved_errno = errno; | ||
1156 | error("bind: %.100s", strerror(errno)); | ||
1157 | close(sock); | ||
1158 | error("%s: cannot bind to path: %s", __func__, path); | ||
1159 | errno = saved_errno; | ||
1160 | return -1; | ||
1161 | } | ||
1162 | if (listen(sock, backlog) < 0) { | ||
1163 | saved_errno = errno; | ||
1164 | error("listen: %.100s", strerror(errno)); | ||
1165 | close(sock); | ||
1166 | unlink(path); | ||
1167 | error("%s: cannot listen on path: %s", __func__, path); | ||
1168 | errno = saved_errno; | ||
1169 | return -1; | ||
1170 | } | ||
1171 | return sock; | ||
1172 | } | ||
1173 | |||
1095 | void | 1174 | void |
1096 | sock_set_v6only(int s) | 1175 | sock_set_v6only(int s) |
1097 | { | 1176 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.h,v 1.50 2013/10/14 23:28:23 djm Exp $ */ | 1 | /* $OpenBSD: misc.h,v 1.54 2014/07/15 15:54:14 millert Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -15,6 +15,25 @@ | |||
15 | #ifndef _MISC_H | 15 | #ifndef _MISC_H |
16 | #define _MISC_H | 16 | #define _MISC_H |
17 | 17 | ||
18 | /* Data structure for representing a forwarding request. */ | ||
19 | struct Forward { | ||
20 | char *listen_host; /* Host (address) to listen on. */ | ||
21 | int listen_port; /* Port to forward. */ | ||
22 | char *listen_path; /* Path to bind domain socket. */ | ||
23 | char *connect_host; /* Host to connect. */ | ||
24 | int connect_port; /* Port to connect on connect_host. */ | ||
25 | char *connect_path; /* Path to connect domain socket. */ | ||
26 | int allocated_port; /* Dynamically allocated listen port */ | ||
27 | int handle; /* Handle for dynamic listen ports */ | ||
28 | }; | ||
29 | |||
30 | /* Common server and client forwarding options. */ | ||
31 | struct ForwardOptions { | ||
32 | int gateway_ports; /* Allow remote connects to forwarded ports. */ | ||
33 | mode_t streamlocal_bind_mask; /* umask for streamlocal binds */ | ||
34 | int streamlocal_bind_unlink; /* unlink socket before bind */ | ||
35 | }; | ||
36 | |||
18 | /* misc.c */ | 37 | /* misc.c */ |
19 | 38 | ||
20 | char *chop(char *); | 39 | char *chop(char *); |
@@ -37,6 +56,7 @@ void ms_subtract_diff(struct timeval *, int *); | |||
37 | void ms_to_timeval(struct timeval *, int); | 56 | void ms_to_timeval(struct timeval *, int); |
38 | time_t monotime(void); | 57 | time_t monotime(void); |
39 | void lowercase(char *s); | 58 | void lowercase(char *s); |
59 | int unix_listener(const char *, int, int); | ||
40 | 60 | ||
41 | void sock_set_v6only(int); | 61 | void sock_set_v6only(int); |
42 | 62 | ||
@@ -68,6 +88,9 @@ int tun_open(int, int); | |||
68 | #define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) | 88 | #define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) |
69 | #define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) | 89 | #define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) |
70 | 90 | ||
91 | /* Fake port to indicate that host field is really a path. */ | ||
92 | #define PORT_STREAMLOCAL -2 | ||
93 | |||
71 | /* Functions to extract or store big-endian words of various sizes */ | 94 | /* Functions to extract or store big-endian words of various sizes */ |
72 | u_int64_t get_u64(const void *) | 95 | u_int64_t get_u64(const void *) |
73 | __attribute__((__bounded__( __minbytes__, 1, 8))); | 96 | __attribute__((__bounded__( __minbytes__, 1, 8))); |
@@ -82,6 +105,12 @@ void put_u32(void *, u_int32_t) | |||
82 | void put_u16(void *, u_int16_t) | 105 | void put_u16(void *, u_int16_t) |
83 | __attribute__((__bounded__( __minbytes__, 1, 2))); | 106 | __attribute__((__bounded__( __minbytes__, 1, 2))); |
84 | 107 | ||
108 | /* Little-endian store/load, used by umac.c */ | ||
109 | u_int32_t get_u32_le(const void *) | ||
110 | __attribute__((__bounded__(__minbytes__, 1, 4))); | ||
111 | void put_u32_le(void *, u_int32_t) | ||
112 | __attribute__((__bounded__(__minbytes__, 1, 4))); | ||
113 | |||
85 | struct bwlimit { | 114 | struct bwlimit { |
86 | size_t buflen; | 115 | size_t buflen; |
87 | u_int64_t rate, thresh, lamt; | 116 | u_int64_t rate, thresh, lamt; |
@@ -1,4 +1,4 @@ | |||
1 | MODULI(5) OpenBSD Programmer's Manual MODULI(5) | 1 | MODULI(5) File Formats Manual MODULI(5) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | moduli - Diffie-Hellman moduli | 4 | moduli - Diffie-Hellman moduli |
@@ -71,4 +71,4 @@ STANDARDS | |||
71 | the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006, | 71 | the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006, |
72 | 2006. | 72 | 2006. |
73 | 73 | ||
74 | OpenBSD 5.5 September 26, 2012 OpenBSD 5.5 | 74 | OpenBSD 5.6 September 26, 2012 OpenBSD 5.6 |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.131 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -40,9 +40,10 @@ | |||
40 | #endif | 40 | #endif |
41 | #include <pwd.h> | 41 | #include <pwd.h> |
42 | #include <signal.h> | 42 | #include <signal.h> |
43 | #include <stdarg.h> | ||
44 | #include <stdlib.h> | 43 | #include <stdlib.h> |
45 | #include <string.h> | 44 | #include <string.h> |
45 | #include <stdarg.h> | ||
46 | #include <stdio.h> | ||
46 | #include <unistd.h> | 47 | #include <unistd.h> |
47 | #ifdef HAVE_POLL_H | 48 | #ifdef HAVE_POLL_H |
48 | #include <poll.h> | 49 | #include <poll.h> |
@@ -56,7 +57,9 @@ | |||
56 | #include <skey.h> | 57 | #include <skey.h> |
57 | #endif | 58 | #endif |
58 | 59 | ||
60 | #ifdef WITH_OPENSSL | ||
59 | #include <openssl/dh.h> | 61 | #include <openssl/dh.h> |
62 | #endif | ||
60 | 63 | ||
61 | #include "openbsd-compat/sys-queue.h" | 64 | #include "openbsd-compat/sys-queue.h" |
62 | #include "atomicio.h" | 65 | #include "atomicio.h" |
@@ -84,6 +87,7 @@ | |||
84 | #include "sshlogin.h" | 87 | #include "sshlogin.h" |
85 | #include "canohost.h" | 88 | #include "canohost.h" |
86 | #include "log.h" | 89 | #include "log.h" |
90 | #include "misc.h" | ||
87 | #include "servconf.h" | 91 | #include "servconf.h" |
88 | #include "monitor.h" | 92 | #include "monitor.h" |
89 | #include "monitor_mm.h" | 93 | #include "monitor_mm.h" |
@@ -92,7 +96,6 @@ | |||
92 | #endif | 96 | #endif |
93 | #include "monitor_wrap.h" | 97 | #include "monitor_wrap.h" |
94 | #include "monitor_fdpass.h" | 98 | #include "monitor_fdpass.h" |
95 | #include "misc.h" | ||
96 | #include "compat.h" | 99 | #include "compat.h" |
97 | #include "ssh2.h" | 100 | #include "ssh2.h" |
98 | #include "roaming.h" | 101 | #include "roaming.h" |
@@ -195,7 +198,10 @@ int mm_answer_consolekit_register(int, Buffer *); | |||
195 | #endif | 198 | #endif |
196 | 199 | ||
197 | static Authctxt *authctxt; | 200 | static Authctxt *authctxt; |
201 | |||
202 | #ifdef WITH_SSH1 | ||
198 | static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ | 203 | static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ |
204 | #endif | ||
199 | 205 | ||
200 | /* local state for key verify */ | 206 | /* local state for key verify */ |
201 | static u_char *key_blob = NULL; | 207 | static u_char *key_blob = NULL; |
@@ -225,7 +231,9 @@ struct mon_table { | |||
225 | #define MON_PERMIT 0x1000 /* Request is permitted */ | 231 | #define MON_PERMIT 0x1000 /* Request is permitted */ |
226 | 232 | ||
227 | struct mon_table mon_dispatch_proto20[] = { | 233 | struct mon_table mon_dispatch_proto20[] = { |
234 | #ifdef WITH_OPENSSL | ||
228 | {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, | 235 | {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, |
236 | #endif | ||
229 | {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, | 237 | {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, |
230 | {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, | 238 | {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, |
231 | {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, | 239 | {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, |
@@ -270,7 +278,9 @@ struct mon_table mon_dispatch_postauth20[] = { | |||
270 | {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, | 278 | {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, |
271 | {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, | 279 | {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, |
272 | #endif | 280 | #endif |
281 | #ifdef WITH_OPENSSL | ||
273 | {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, | 282 | {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, |
283 | #endif | ||
274 | {MONITOR_REQ_SIGN, 0, mm_answer_sign}, | 284 | {MONITOR_REQ_SIGN, 0, mm_answer_sign}, |
275 | {MONITOR_REQ_PTY, 0, mm_answer_pty}, | 285 | {MONITOR_REQ_PTY, 0, mm_answer_pty}, |
276 | {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, | 286 | {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, |
@@ -286,6 +296,7 @@ struct mon_table mon_dispatch_postauth20[] = { | |||
286 | }; | 296 | }; |
287 | 297 | ||
288 | struct mon_table mon_dispatch_proto15[] = { | 298 | struct mon_table mon_dispatch_proto15[] = { |
299 | #ifdef WITH_SSH1 | ||
289 | {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, | 300 | {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, |
290 | {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, | 301 | {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, |
291 | {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, | 302 | {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, |
@@ -313,10 +324,12 @@ struct mon_table mon_dispatch_proto15[] = { | |||
313 | #ifdef SSH_AUDIT_EVENTS | 324 | #ifdef SSH_AUDIT_EVENTS |
314 | {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, | 325 | {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, |
315 | #endif | 326 | #endif |
327 | #endif /* WITH_SSH1 */ | ||
316 | {0, 0, NULL} | 328 | {0, 0, NULL} |
317 | }; | 329 | }; |
318 | 330 | ||
319 | struct mon_table mon_dispatch_postauth15[] = { | 331 | struct mon_table mon_dispatch_postauth15[] = { |
332 | #ifdef WITH_SSH1 | ||
320 | {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, | 333 | {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, |
321 | {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, | 334 | {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, |
322 | {MONITOR_REQ_TERM, 0, mm_answer_term}, | 335 | {MONITOR_REQ_TERM, 0, mm_answer_term}, |
@@ -327,6 +340,7 @@ struct mon_table mon_dispatch_postauth15[] = { | |||
327 | #ifdef USE_CONSOLEKIT | 340 | #ifdef USE_CONSOLEKIT |
328 | {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register}, | 341 | {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register}, |
329 | #endif | 342 | #endif |
343 | #endif /* WITH_SSH1 */ | ||
330 | {0, 0, NULL} | 344 | {0, 0, NULL} |
331 | }; | 345 | }; |
332 | 346 | ||
@@ -485,6 +499,9 @@ monitor_child_postauth(struct monitor *pmonitor) | |||
485 | signal(SIGHUP, &monitor_child_handler); | 499 | signal(SIGHUP, &monitor_child_handler); |
486 | signal(SIGTERM, &monitor_child_handler); | 500 | signal(SIGTERM, &monitor_child_handler); |
487 | signal(SIGINT, &monitor_child_handler); | 501 | signal(SIGINT, &monitor_child_handler); |
502 | #ifdef SIGXFSZ | ||
503 | signal(SIGXFSZ, SIG_IGN); | ||
504 | #endif | ||
488 | 505 | ||
489 | if (compat20) { | 506 | if (compat20) { |
490 | mon_dispatch = mon_dispatch_postauth20; | 507 | mon_dispatch = mon_dispatch_postauth20; |
@@ -665,6 +682,7 @@ monitor_reset_key_state(void) | |||
665 | hostbased_chost = NULL; | 682 | hostbased_chost = NULL; |
666 | } | 683 | } |
667 | 684 | ||
685 | #ifdef WITH_OPENSSL | ||
668 | int | 686 | int |
669 | mm_answer_moduli(int sock, Buffer *m) | 687 | mm_answer_moduli(int sock, Buffer *m) |
670 | { | 688 | { |
@@ -699,6 +717,7 @@ mm_answer_moduli(int sock, Buffer *m) | |||
699 | mm_request_send(sock, MONITOR_ANS_MODULI, m); | 717 | mm_request_send(sock, MONITOR_ANS_MODULI, m); |
700 | return (0); | 718 | return (0); |
701 | } | 719 | } |
720 | #endif | ||
702 | 721 | ||
703 | extern AuthenticationConnection *auth_conn; | 722 | extern AuthenticationConnection *auth_conn; |
704 | 723 | ||
@@ -1225,6 +1244,7 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1225 | cuser, chost); | 1244 | cuser, chost); |
1226 | auth_method = "hostbased"; | 1245 | auth_method = "hostbased"; |
1227 | break; | 1246 | break; |
1247 | #ifdef WITH_SSH1 | ||
1228 | case MM_RSAHOSTKEY: | 1248 | case MM_RSAHOSTKEY: |
1229 | key->type = KEY_RSA1; /* XXX */ | 1249 | key->type = KEY_RSA1; /* XXX */ |
1230 | allowed = options.rhosts_rsa_authentication && | 1250 | allowed = options.rhosts_rsa_authentication && |
@@ -1234,6 +1254,7 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1234 | auth_clear_options(); | 1254 | auth_clear_options(); |
1235 | auth_method = "rsa"; | 1255 | auth_method = "rsa"; |
1236 | break; | 1256 | break; |
1257 | #endif | ||
1237 | default: | 1258 | default: |
1238 | fatal("%s: unknown key type %d", __func__, type); | 1259 | fatal("%s: unknown key type %d", __func__, type); |
1239 | break; | 1260 | break; |
@@ -1570,6 +1591,7 @@ mm_answer_pty_cleanup(int sock, Buffer *m) | |||
1570 | return (0); | 1591 | return (0); |
1571 | } | 1592 | } |
1572 | 1593 | ||
1594 | #ifdef WITH_SSH1 | ||
1573 | int | 1595 | int |
1574 | mm_answer_sesskey(int sock, Buffer *m) | 1596 | mm_answer_sesskey(int sock, Buffer *m) |
1575 | { | 1597 | { |
@@ -1747,6 +1769,7 @@ mm_answer_rsa_response(int sock, Buffer *m) | |||
1747 | 1769 | ||
1748 | return (success); | 1770 | return (success); |
1749 | } | 1771 | } |
1772 | #endif | ||
1750 | 1773 | ||
1751 | int | 1774 | int |
1752 | mm_answer_term(int sock, Buffer *req) | 1775 | mm_answer_term(int sock, Buffer *req) |
@@ -1851,6 +1874,8 @@ monitor_apply_keystate(struct monitor *pmonitor) | |||
1851 | if (options.compression) | 1874 | if (options.compression) |
1852 | mm_init_compression(pmonitor->m_zlib); | 1875 | mm_init_compression(pmonitor->m_zlib); |
1853 | 1876 | ||
1877 | packet_set_postauth(); | ||
1878 | |||
1854 | if (options.rekey_limit || options.rekey_interval) | 1879 | if (options.rekey_limit || options.rekey_interval) |
1855 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, | 1880 | packet_set_rekey_limits((u_int32_t)options.rekey_limit, |
1856 | (time_t)options.rekey_interval); | 1881 | (time_t)options.rekey_interval); |
@@ -1887,11 +1912,13 @@ mm_get_kex(Buffer *m) | |||
1887 | timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0) | 1912 | timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0) |
1888 | fatal("mm_get_get: internal error: bad session id"); | 1913 | fatal("mm_get_get: internal error: bad session id"); |
1889 | kex->we_need = buffer_get_int(m); | 1914 | kex->we_need = buffer_get_int(m); |
1915 | #ifdef WITH_OPENSSL | ||
1890 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 1916 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
1891 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 1917 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
1892 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 1918 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
1893 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 1919 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
1894 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 1920 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
1921 | #endif | ||
1895 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 1922 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
1896 | #ifdef GSSAPI | 1923 | #ifdef GSSAPI |
1897 | if (options.gss_keyex) { | 1924 | if (options.gss_keyex) { |
diff --git a/monitor_fdpass.c b/monitor_fdpass.c index 7eb6f5c6e..100fa5660 100644 --- a/monitor_fdpass.c +++ b/monitor_fdpass.c | |||
@@ -34,12 +34,17 @@ | |||
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #include <errno.h> | 36 | #include <errno.h> |
37 | #ifdef HAVE_POLL_H | ||
38 | #include <poll.h> | ||
39 | #endif | ||
40 | #include <string.h> | 37 | #include <string.h> |
41 | #include <stdarg.h> | 38 | #include <stdarg.h> |
42 | 39 | ||
40 | #ifdef HAVE_POLL_H | ||
41 | # include <poll.h> | ||
42 | #else | ||
43 | # ifdef HAVE_SYS_POLL_H | ||
44 | # include <sys/poll.h> | ||
45 | # endif | ||
46 | #endif | ||
47 | |||
43 | #include "log.h" | 48 | #include "log.h" |
44 | #include "monitor_fdpass.h" | 49 | #include "monitor_fdpass.h" |
45 | 50 | ||
diff --git a/monitor_wrap.c b/monitor_wrap.c index a8fb07b52..4c57d4df3 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.c,v 1.79 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.c,v 1.80 2014/04/29 18:01:49 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -38,14 +38,18 @@ | |||
38 | #include <string.h> | 38 | #include <string.h> |
39 | #include <unistd.h> | 39 | #include <unistd.h> |
40 | 40 | ||
41 | #ifdef WITH_OPENSSL | ||
41 | #include <openssl/bn.h> | 42 | #include <openssl/bn.h> |
42 | #include <openssl/dh.h> | 43 | #include <openssl/dh.h> |
43 | #include <openssl/evp.h> | 44 | #include <openssl/evp.h> |
45 | #endif | ||
44 | 46 | ||
45 | #include "openbsd-compat/sys-queue.h" | 47 | #include "openbsd-compat/sys-queue.h" |
46 | #include "xmalloc.h" | 48 | #include "xmalloc.h" |
47 | #include "ssh.h" | 49 | #include "ssh.h" |
50 | #ifdef WITH_OPENSSL | ||
48 | #include "dh.h" | 51 | #include "dh.h" |
52 | #endif | ||
49 | #include "buffer.h" | 53 | #include "buffer.h" |
50 | #include "key.h" | 54 | #include "key.h" |
51 | #include "cipher.h" | 55 | #include "cipher.h" |
@@ -174,6 +178,7 @@ mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m) | |||
174 | rtype, type); | 178 | rtype, type); |
175 | } | 179 | } |
176 | 180 | ||
181 | #ifdef WITH_OPENSSL | ||
177 | DH * | 182 | DH * |
178 | mm_choose_dh(int min, int nbits, int max) | 183 | mm_choose_dh(int min, int nbits, int max) |
179 | { | 184 | { |
@@ -207,6 +212,7 @@ mm_choose_dh(int min, int nbits, int max) | |||
207 | 212 | ||
208 | return (dh_new_group(g, p)); | 213 | return (dh_new_group(g, p)); |
209 | } | 214 | } |
215 | #endif | ||
210 | 216 | ||
211 | int | 217 | int |
212 | mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) | 218 | mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) |
@@ -930,6 +936,7 @@ mm_terminate(void) | |||
930 | buffer_free(&m); | 936 | buffer_free(&m); |
931 | } | 937 | } |
932 | 938 | ||
939 | #ifdef WITH_SSH1 | ||
933 | int | 940 | int |
934 | mm_ssh1_session_key(BIGNUM *num) | 941 | mm_ssh1_session_key(BIGNUM *num) |
935 | { | 942 | { |
@@ -949,6 +956,7 @@ mm_ssh1_session_key(BIGNUM *num) | |||
949 | 956 | ||
950 | return (rsafail); | 957 | return (rsafail); |
951 | } | 958 | } |
959 | #endif | ||
952 | 960 | ||
953 | static void | 961 | static void |
954 | mm_chall_setup(char **name, char **infotxt, u_int *numprompts, | 962 | mm_chall_setup(char **name, char **infotxt, u_int *numprompts, |
@@ -1096,6 +1104,7 @@ mm_ssh1_session_id(u_char session_id[16]) | |||
1096 | buffer_free(&m); | 1104 | buffer_free(&m); |
1097 | } | 1105 | } |
1098 | 1106 | ||
1107 | #ifdef WITH_SSH1 | ||
1099 | int | 1108 | int |
1100 | mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) | 1109 | mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) |
1101 | { | 1110 | { |
@@ -1191,6 +1200,7 @@ mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) | |||
1191 | 1200 | ||
1192 | return (success); | 1201 | return (success); |
1193 | } | 1202 | } |
1203 | #endif | ||
1194 | 1204 | ||
1195 | #ifdef SSH_AUDIT_EVENTS | 1205 | #ifdef SSH_AUDIT_EVENTS |
1196 | void | 1206 | void |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.44 2013/07/12 00:19:58 djm Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.48 2014/07/17 07:22:19 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -105,6 +105,11 @@ struct mux_session_confirm_ctx { | |||
105 | u_int rid; | 105 | u_int rid; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | /* Context for stdio fwd open confirmation callback */ | ||
109 | struct mux_stdio_confirm_ctx { | ||
110 | u_int rid; | ||
111 | }; | ||
112 | |||
108 | /* Context for global channel callback */ | 113 | /* Context for global channel callback */ |
109 | struct mux_channel_confirm_ctx { | 114 | struct mux_channel_confirm_ctx { |
110 | u_int cid; /* channel id */ | 115 | u_int cid; /* channel id */ |
@@ -157,6 +162,7 @@ struct mux_master_state { | |||
157 | #define MUX_FWD_DYNAMIC 3 | 162 | #define MUX_FWD_DYNAMIC 3 |
158 | 163 | ||
159 | static void mux_session_confirm(int, int, void *); | 164 | static void mux_session_confirm(int, int, void *); |
165 | static void mux_stdio_confirm(int, int, void *); | ||
160 | 166 | ||
161 | static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); | 167 | static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); |
162 | static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); | 168 | static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); |
@@ -509,29 +515,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
509 | } | 515 | } |
510 | 516 | ||
511 | static char * | 517 | static char * |
512 | format_forward(u_int ftype, Forward *fwd) | 518 | format_forward(u_int ftype, struct Forward *fwd) |
513 | { | 519 | { |
514 | char *ret; | 520 | char *ret; |
515 | 521 | ||
516 | switch (ftype) { | 522 | switch (ftype) { |
517 | case MUX_FWD_LOCAL: | 523 | case MUX_FWD_LOCAL: |
518 | xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", | 524 | xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", |
525 | (fwd->listen_path != NULL) ? fwd->listen_path : | ||
519 | (fwd->listen_host == NULL) ? | 526 | (fwd->listen_host == NULL) ? |
520 | (options.gateway_ports ? "*" : "LOCALHOST") : | 527 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
521 | fwd->listen_host, fwd->listen_port, | 528 | fwd->listen_host, fwd->listen_port, |
529 | (fwd->connect_path != NULL) ? fwd->connect_path : | ||
522 | fwd->connect_host, fwd->connect_port); | 530 | fwd->connect_host, fwd->connect_port); |
523 | break; | 531 | break; |
524 | case MUX_FWD_DYNAMIC: | 532 | case MUX_FWD_DYNAMIC: |
525 | xasprintf(&ret, "dynamic forward %.200s:%d -> *", | 533 | xasprintf(&ret, "dynamic forward %.200s:%d -> *", |
526 | (fwd->listen_host == NULL) ? | 534 | (fwd->listen_host == NULL) ? |
527 | (options.gateway_ports ? "*" : "LOCALHOST") : | 535 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
528 | fwd->listen_host, fwd->listen_port); | 536 | fwd->listen_host, fwd->listen_port); |
529 | break; | 537 | break; |
530 | case MUX_FWD_REMOTE: | 538 | case MUX_FWD_REMOTE: |
531 | xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", | 539 | xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", |
540 | (fwd->listen_path != NULL) ? fwd->listen_path : | ||
532 | (fwd->listen_host == NULL) ? | 541 | (fwd->listen_host == NULL) ? |
533 | "LOCALHOST" : fwd->listen_host, | 542 | "LOCALHOST" : fwd->listen_host, |
534 | fwd->listen_port, | 543 | fwd->listen_port, |
544 | (fwd->connect_path != NULL) ? fwd->connect_path : | ||
535 | fwd->connect_host, fwd->connect_port); | 545 | fwd->connect_host, fwd->connect_port); |
536 | break; | 546 | break; |
537 | default: | 547 | default: |
@@ -551,14 +561,18 @@ compare_host(const char *a, const char *b) | |||
551 | } | 561 | } |
552 | 562 | ||
553 | static int | 563 | static int |
554 | compare_forward(Forward *a, Forward *b) | 564 | compare_forward(struct Forward *a, struct Forward *b) |
555 | { | 565 | { |
556 | if (!compare_host(a->listen_host, b->listen_host)) | 566 | if (!compare_host(a->listen_host, b->listen_host)) |
557 | return 0; | 567 | return 0; |
568 | if (!compare_host(a->listen_path, b->listen_path)) | ||
569 | return 0; | ||
558 | if (a->listen_port != b->listen_port) | 570 | if (a->listen_port != b->listen_port) |
559 | return 0; | 571 | return 0; |
560 | if (!compare_host(a->connect_host, b->connect_host)) | 572 | if (!compare_host(a->connect_host, b->connect_host)) |
561 | return 0; | 573 | return 0; |
574 | if (!compare_host(a->connect_path, b->connect_path)) | ||
575 | return 0; | ||
562 | if (a->connect_port != b->connect_port) | 576 | if (a->connect_port != b->connect_port) |
563 | return 0; | 577 | return 0; |
564 | 578 | ||
@@ -570,7 +584,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
570 | { | 584 | { |
571 | struct mux_channel_confirm_ctx *fctx = ctxt; | 585 | struct mux_channel_confirm_ctx *fctx = ctxt; |
572 | char *failmsg = NULL; | 586 | char *failmsg = NULL; |
573 | Forward *rfwd; | 587 | struct Forward *rfwd; |
574 | Channel *c; | 588 | Channel *c; |
575 | Buffer out; | 589 | Buffer out; |
576 | 590 | ||
@@ -587,7 +601,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
587 | rfwd = &options.remote_forwards[fctx->fid]; | 601 | rfwd = &options.remote_forwards[fctx->fid]; |
588 | debug("%s: %s for: listen %d, connect %s:%d", __func__, | 602 | debug("%s: %s for: listen %d, connect %s:%d", __func__, |
589 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 603 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", |
590 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); | 604 | rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : |
605 | rfwd->connect_host, rfwd->connect_port); | ||
591 | if (type == SSH2_MSG_REQUEST_SUCCESS) { | 606 | if (type == SSH2_MSG_REQUEST_SUCCESS) { |
592 | if (rfwd->listen_port == 0) { | 607 | if (rfwd->listen_port == 0) { |
593 | rfwd->allocated_port = packet_get_int(); | 608 | rfwd->allocated_port = packet_get_int(); |
@@ -607,8 +622,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
607 | } else { | 622 | } else { |
608 | if (rfwd->listen_port == 0) | 623 | if (rfwd->listen_port == 0) |
609 | channel_update_permitted_opens(rfwd->handle, -1); | 624 | channel_update_permitted_opens(rfwd->handle, -1); |
610 | xasprintf(&failmsg, "remote port forwarding failed for " | 625 | if (rfwd->listen_path != NULL) |
611 | "listen port %d", rfwd->listen_port); | 626 | xasprintf(&failmsg, "remote port forwarding failed for " |
627 | "listen path %s", rfwd->listen_path); | ||
628 | else | ||
629 | xasprintf(&failmsg, "remote port forwarding failed for " | ||
630 | "listen port %d", rfwd->listen_port); | ||
612 | } | 631 | } |
613 | fail: | 632 | fail: |
614 | error("%s: %s", __func__, failmsg); | 633 | error("%s: %s", __func__, failmsg); |
@@ -627,34 +646,46 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
627 | static int | 646 | static int |
628 | process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 647 | process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
629 | { | 648 | { |
630 | Forward fwd; | 649 | struct Forward fwd; |
631 | char *fwd_desc = NULL; | 650 | char *fwd_desc = NULL; |
651 | char *listen_addr, *connect_addr; | ||
632 | u_int ftype; | 652 | u_int ftype; |
633 | u_int lport, cport; | 653 | u_int lport, cport; |
634 | int i, ret = 0, freefwd = 1; | 654 | int i, ret = 0, freefwd = 1; |
635 | 655 | ||
636 | fwd.listen_host = fwd.connect_host = NULL; | 656 | /* XXX - lport/cport check redundant */ |
637 | if (buffer_get_int_ret(&ftype, m) != 0 || | 657 | if (buffer_get_int_ret(&ftype, m) != 0 || |
638 | (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || | 658 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || |
639 | buffer_get_int_ret(&lport, m) != 0 || | 659 | buffer_get_int_ret(&lport, m) != 0 || |
640 | (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || | 660 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || |
641 | buffer_get_int_ret(&cport, m) != 0 || | 661 | buffer_get_int_ret(&cport, m) != 0 || |
642 | lport > 65535 || cport > 65535) { | 662 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
663 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | ||
643 | error("%s: malformed message", __func__); | 664 | error("%s: malformed message", __func__); |
644 | ret = -1; | 665 | ret = -1; |
645 | goto out; | 666 | goto out; |
646 | } | 667 | } |
647 | fwd.listen_port = lport; | 668 | if (*listen_addr == '\0') { |
648 | fwd.connect_port = cport; | 669 | free(listen_addr); |
649 | if (*fwd.listen_host == '\0') { | 670 | listen_addr = NULL; |
650 | free(fwd.listen_host); | ||
651 | fwd.listen_host = NULL; | ||
652 | } | 671 | } |
653 | if (*fwd.connect_host == '\0') { | 672 | if (*connect_addr == '\0') { |
654 | free(fwd.connect_host); | 673 | free(connect_addr); |
655 | fwd.connect_host = NULL; | 674 | connect_addr = NULL; |
656 | } | 675 | } |
657 | 676 | ||
677 | memset(&fwd, 0, sizeof(fwd)); | ||
678 | fwd.listen_port = lport; | ||
679 | if (fwd.listen_port == PORT_STREAMLOCAL) | ||
680 | fwd.listen_path = listen_addr; | ||
681 | else | ||
682 | fwd.listen_host = listen_addr; | ||
683 | fwd.connect_port = cport; | ||
684 | if (fwd.connect_port == PORT_STREAMLOCAL) | ||
685 | fwd.connect_path = connect_addr; | ||
686 | else | ||
687 | fwd.connect_host = connect_addr; | ||
688 | |||
658 | debug2("%s: channel %d: request %s", __func__, c->self, | 689 | debug2("%s: channel %d: request %s", __func__, c->self, |
659 | (fwd_desc = format_forward(ftype, &fwd))); | 690 | (fwd_desc = format_forward(ftype, &fwd))); |
660 | 691 | ||
@@ -662,25 +693,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
662 | ftype != MUX_FWD_DYNAMIC) { | 693 | ftype != MUX_FWD_DYNAMIC) { |
663 | logit("%s: invalid forwarding type %u", __func__, ftype); | 694 | logit("%s: invalid forwarding type %u", __func__, ftype); |
664 | invalid: | 695 | invalid: |
665 | free(fwd.listen_host); | 696 | free(listen_addr); |
666 | free(fwd.connect_host); | 697 | free(connect_addr); |
667 | buffer_put_int(r, MUX_S_FAILURE); | 698 | buffer_put_int(r, MUX_S_FAILURE); |
668 | buffer_put_int(r, rid); | 699 | buffer_put_int(r, rid); |
669 | buffer_put_cstring(r, "Invalid forwarding request"); | 700 | buffer_put_cstring(r, "Invalid forwarding request"); |
670 | return 0; | 701 | return 0; |
671 | } | 702 | } |
672 | if (fwd.listen_port >= 65536) { | 703 | if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { |
704 | logit("%s: streamlocal and dynamic forwards " | ||
705 | "are mutually exclusive", __func__); | ||
706 | goto invalid; | ||
707 | } | ||
708 | if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { | ||
673 | logit("%s: invalid listen port %u", __func__, | 709 | logit("%s: invalid listen port %u", __func__, |
674 | fwd.listen_port); | 710 | fwd.listen_port); |
675 | goto invalid; | 711 | goto invalid; |
676 | } | 712 | } |
677 | if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && | 713 | if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) |
678 | ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { | 714 | || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { |
679 | logit("%s: invalid connect port %u", __func__, | 715 | logit("%s: invalid connect port %u", __func__, |
680 | fwd.connect_port); | 716 | fwd.connect_port); |
681 | goto invalid; | 717 | goto invalid; |
682 | } | 718 | } |
683 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { | 719 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { |
684 | logit("%s: missing connect host", __func__); | 720 | logit("%s: missing connect host", __func__); |
685 | goto invalid; | 721 | goto invalid; |
686 | } | 722 | } |
@@ -731,9 +767,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
731 | } | 767 | } |
732 | 768 | ||
733 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { | 769 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { |
734 | if (!channel_setup_local_fwd_listener(fwd.listen_host, | 770 | if (!channel_setup_local_fwd_listener(&fwd, |
735 | fwd.listen_port, fwd.connect_host, fwd.connect_port, | 771 | &options.fwd_opts)) { |
736 | options.gateway_ports)) { | ||
737 | fail: | 772 | fail: |
738 | logit("slave-requested %s failed", fwd_desc); | 773 | logit("slave-requested %s failed", fwd_desc); |
739 | buffer_put_int(r, MUX_S_FAILURE); | 774 | buffer_put_int(r, MUX_S_FAILURE); |
@@ -746,8 +781,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
746 | } else { | 781 | } else { |
747 | struct mux_channel_confirm_ctx *fctx; | 782 | struct mux_channel_confirm_ctx *fctx; |
748 | 783 | ||
749 | fwd.handle = channel_request_remote_forwarding(fwd.listen_host, | 784 | fwd.handle = channel_request_remote_forwarding(&fwd); |
750 | fwd.listen_port, fwd.connect_host, fwd.connect_port); | ||
751 | if (fwd.handle < 0) | 785 | if (fwd.handle < 0) |
752 | goto fail; | 786 | goto fail; |
753 | add_remote_forward(&options, &fwd); | 787 | add_remote_forward(&options, &fwd); |
@@ -768,7 +802,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
768 | free(fwd_desc); | 802 | free(fwd_desc); |
769 | if (freefwd) { | 803 | if (freefwd) { |
770 | free(fwd.listen_host); | 804 | free(fwd.listen_host); |
805 | free(fwd.listen_path); | ||
771 | free(fwd.connect_host); | 806 | free(fwd.connect_host); |
807 | free(fwd.connect_path); | ||
772 | } | 808 | } |
773 | return ret; | 809 | return ret; |
774 | } | 810 | } |
@@ -776,36 +812,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
776 | static int | 812 | static int |
777 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 813 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
778 | { | 814 | { |
779 | Forward fwd, *found_fwd; | 815 | struct Forward fwd, *found_fwd; |
780 | char *fwd_desc = NULL; | 816 | char *fwd_desc = NULL; |
781 | const char *error_reason = NULL; | 817 | const char *error_reason = NULL; |
818 | char *listen_addr = NULL, *connect_addr = NULL; | ||
782 | u_int ftype; | 819 | u_int ftype; |
783 | int i, listen_port, ret = 0; | 820 | int i, ret = 0; |
784 | u_int lport, cport; | 821 | u_int lport, cport; |
785 | 822 | ||
786 | fwd.listen_host = fwd.connect_host = NULL; | ||
787 | if (buffer_get_int_ret(&ftype, m) != 0 || | 823 | if (buffer_get_int_ret(&ftype, m) != 0 || |
788 | (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || | 824 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || |
789 | buffer_get_int_ret(&lport, m) != 0 || | 825 | buffer_get_int_ret(&lport, m) != 0 || |
790 | (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || | 826 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || |
791 | buffer_get_int_ret(&cport, m) != 0 || | 827 | buffer_get_int_ret(&cport, m) != 0 || |
792 | lport > 65535 || cport > 65535) { | 828 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
829 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | ||
793 | error("%s: malformed message", __func__); | 830 | error("%s: malformed message", __func__); |
794 | ret = -1; | 831 | ret = -1; |
795 | goto out; | 832 | goto out; |
796 | } | 833 | } |
797 | fwd.listen_port = lport; | ||
798 | fwd.connect_port = cport; | ||
799 | 834 | ||
800 | if (*fwd.listen_host == '\0') { | 835 | if (*listen_addr == '\0') { |
801 | free(fwd.listen_host); | 836 | free(listen_addr); |
802 | fwd.listen_host = NULL; | 837 | listen_addr = NULL; |
803 | } | 838 | } |
804 | if (*fwd.connect_host == '\0') { | 839 | if (*connect_addr == '\0') { |
805 | free(fwd.connect_host); | 840 | free(connect_addr); |
806 | fwd.connect_host = NULL; | 841 | connect_addr = NULL; |
807 | } | 842 | } |
808 | 843 | ||
844 | memset(&fwd, 0, sizeof(fwd)); | ||
845 | fwd.listen_port = lport; | ||
846 | if (fwd.listen_port == PORT_STREAMLOCAL) | ||
847 | fwd.listen_path = listen_addr; | ||
848 | else | ||
849 | fwd.listen_host = listen_addr; | ||
850 | fwd.connect_port = cport; | ||
851 | if (fwd.connect_port == PORT_STREAMLOCAL) | ||
852 | fwd.connect_path = connect_addr; | ||
853 | else | ||
854 | fwd.connect_host = connect_addr; | ||
855 | |||
809 | debug2("%s: channel %d: request cancel %s", __func__, c->self, | 856 | debug2("%s: channel %d: request cancel %s", __func__, c->self, |
810 | (fwd_desc = format_forward(ftype, &fwd))); | 857 | (fwd_desc = format_forward(ftype, &fwd))); |
811 | 858 | ||
@@ -840,18 +887,14 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
840 | * This shouldn't fail unless we confused the host/port | 887 | * This shouldn't fail unless we confused the host/port |
841 | * between options.remote_forwards and permitted_opens. | 888 | * between options.remote_forwards and permitted_opens. |
842 | * However, for dynamic allocated listen ports we need | 889 | * However, for dynamic allocated listen ports we need |
843 | * to lookup the actual listen port. | 890 | * to use the actual listen port. |
844 | */ | 891 | */ |
845 | listen_port = (fwd.listen_port == 0) ? | 892 | if (channel_request_rforward_cancel(found_fwd) == -1) |
846 | found_fwd->allocated_port : fwd.listen_port; | ||
847 | if (channel_request_rforward_cancel(fwd.listen_host, | ||
848 | listen_port) == -1) | ||
849 | error_reason = "port not in permitted opens"; | 893 | error_reason = "port not in permitted opens"; |
850 | } else { /* local and dynamic forwards */ | 894 | } else { /* local and dynamic forwards */ |
851 | /* Ditto */ | 895 | /* Ditto */ |
852 | if (channel_cancel_lport_listener(fwd.listen_host, | 896 | if (channel_cancel_lport_listener(&fwd, fwd.connect_port, |
853 | fwd.listen_port, fwd.connect_port, | 897 | &options.fwd_opts) == -1) |
854 | options.gateway_ports) == -1) | ||
855 | error_reason = "port not found"; | 898 | error_reason = "port not found"; |
856 | } | 899 | } |
857 | 900 | ||
@@ -860,8 +903,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
860 | buffer_put_int(r, rid); | 903 | buffer_put_int(r, rid); |
861 | 904 | ||
862 | free(found_fwd->listen_host); | 905 | free(found_fwd->listen_host); |
906 | free(found_fwd->listen_path); | ||
863 | free(found_fwd->connect_host); | 907 | free(found_fwd->connect_host); |
908 | free(found_fwd->connect_path); | ||
864 | found_fwd->listen_host = found_fwd->connect_host = NULL; | 909 | found_fwd->listen_host = found_fwd->connect_host = NULL; |
910 | found_fwd->listen_path = found_fwd->connect_path = NULL; | ||
865 | found_fwd->listen_port = found_fwd->connect_port = 0; | 911 | found_fwd->listen_port = found_fwd->connect_port = 0; |
866 | } else { | 912 | } else { |
867 | buffer_put_int(r, MUX_S_FAILURE); | 913 | buffer_put_int(r, MUX_S_FAILURE); |
@@ -870,8 +916,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
870 | } | 916 | } |
871 | out: | 917 | out: |
872 | free(fwd_desc); | 918 | free(fwd_desc); |
873 | free(fwd.listen_host); | 919 | free(listen_addr); |
874 | free(fwd.connect_host); | 920 | free(connect_addr); |
875 | 921 | ||
876 | return ret; | 922 | return ret; |
877 | } | 923 | } |
@@ -883,6 +929,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
883 | char *reserved, *chost; | 929 | char *reserved, *chost; |
884 | u_int cport, i, j; | 930 | u_int cport, i, j; |
885 | int new_fd[2]; | 931 | int new_fd[2]; |
932 | struct mux_stdio_confirm_ctx *cctx; | ||
886 | 933 | ||
887 | chost = reserved = NULL; | 934 | chost = reserved = NULL; |
888 | if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || | 935 | if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || |
@@ -962,15 +1009,60 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
962 | 1009 | ||
963 | channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); | 1010 | channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); |
964 | 1011 | ||
965 | /* prepare reply */ | 1012 | cctx = xcalloc(1, sizeof(*cctx)); |
966 | /* XXX defer until channel confirmed */ | 1013 | cctx->rid = rid; |
967 | buffer_put_int(r, MUX_S_SESSION_OPENED); | 1014 | channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx); |
968 | buffer_put_int(r, rid); | 1015 | c->mux_pause = 1; /* stop handling messages until open_confirm done */ |
969 | buffer_put_int(r, nc->self); | ||
970 | 1016 | ||
1017 | /* reply is deferred, sent by mux_session_confirm */ | ||
971 | return 0; | 1018 | return 0; |
972 | } | 1019 | } |
973 | 1020 | ||
1021 | /* Callback on open confirmation in mux master for a mux stdio fwd session. */ | ||
1022 | static void | ||
1023 | mux_stdio_confirm(int id, int success, void *arg) | ||
1024 | { | ||
1025 | struct mux_stdio_confirm_ctx *cctx = arg; | ||
1026 | Channel *c, *cc; | ||
1027 | Buffer reply; | ||
1028 | |||
1029 | if (cctx == NULL) | ||
1030 | fatal("%s: cctx == NULL", __func__); | ||
1031 | if ((c = channel_by_id(id)) == NULL) | ||
1032 | fatal("%s: no channel for id %d", __func__, id); | ||
1033 | if ((cc = channel_by_id(c->ctl_chan)) == NULL) | ||
1034 | fatal("%s: channel %d lacks control channel %d", __func__, | ||
1035 | id, c->ctl_chan); | ||
1036 | |||
1037 | if (!success) { | ||
1038 | debug3("%s: sending failure reply", __func__); | ||
1039 | /* prepare reply */ | ||
1040 | buffer_init(&reply); | ||
1041 | buffer_put_int(&reply, MUX_S_FAILURE); | ||
1042 | buffer_put_int(&reply, cctx->rid); | ||
1043 | buffer_put_cstring(&reply, "Session open refused by peer"); | ||
1044 | goto done; | ||
1045 | } | ||
1046 | |||
1047 | debug3("%s: sending success reply", __func__); | ||
1048 | /* prepare reply */ | ||
1049 | buffer_init(&reply); | ||
1050 | buffer_put_int(&reply, MUX_S_SESSION_OPENED); | ||
1051 | buffer_put_int(&reply, cctx->rid); | ||
1052 | buffer_put_int(&reply, c->self); | ||
1053 | |||
1054 | done: | ||
1055 | /* Send reply */ | ||
1056 | buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); | ||
1057 | buffer_free(&reply); | ||
1058 | |||
1059 | if (cc->mux_pause <= 0) | ||
1060 | fatal("%s: mux_pause %d", __func__, cc->mux_pause); | ||
1061 | cc->mux_pause = 0; /* start processing messages again */ | ||
1062 | c->open_confirm_ctx = NULL; | ||
1063 | free(cctx); | ||
1064 | } | ||
1065 | |||
974 | static int | 1066 | static int |
975 | process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) | 1067 | process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) |
976 | { | 1068 | { |
@@ -1010,7 +1102,7 @@ mux_master_read_cb(Channel *c) | |||
1010 | { | 1102 | { |
1011 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; | 1103 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; |
1012 | Buffer in, out; | 1104 | Buffer in, out; |
1013 | void *ptr; | 1105 | const u_char *ptr; |
1014 | u_int type, rid, have, i; | 1106 | u_int type, rid, have, i; |
1015 | int ret = -1; | 1107 | int ret = -1; |
1016 | 1108 | ||
@@ -1133,12 +1225,11 @@ mux_tty_alloc_failed(Channel *c) | |||
1133 | void | 1225 | void |
1134 | muxserver_listen(void) | 1226 | muxserver_listen(void) |
1135 | { | 1227 | { |
1136 | struct sockaddr_un addr; | ||
1137 | socklen_t sun_len; | ||
1138 | mode_t old_umask; | 1228 | mode_t old_umask; |
1139 | char *orig_control_path = options.control_path; | 1229 | char *orig_control_path = options.control_path; |
1140 | char rbuf[16+1]; | 1230 | char rbuf[16+1]; |
1141 | u_int i, r; | 1231 | u_int i, r; |
1232 | int oerrno; | ||
1142 | 1233 | ||
1143 | if (options.control_path == NULL || | 1234 | if (options.control_path == NULL || |
1144 | options.control_master == SSHCTL_MASTER_NO) | 1235 | options.control_master == SSHCTL_MASTER_NO) |
@@ -1163,24 +1254,12 @@ muxserver_listen(void) | |||
1163 | xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); | 1254 | xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); |
1164 | debug3("%s: temporary control path %s", __func__, options.control_path); | 1255 | debug3("%s: temporary control path %s", __func__, options.control_path); |
1165 | 1256 | ||
1166 | memset(&addr, '\0', sizeof(addr)); | ||
1167 | addr.sun_family = AF_UNIX; | ||
1168 | sun_len = offsetof(struct sockaddr_un, sun_path) + | ||
1169 | strlen(options.control_path) + 1; | ||
1170 | |||
1171 | if (strlcpy(addr.sun_path, options.control_path, | ||
1172 | sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { | ||
1173 | error("ControlPath \"%s\" too long for Unix domain socket", | ||
1174 | options.control_path); | ||
1175 | goto disable_mux_master; | ||
1176 | } | ||
1177 | |||
1178 | if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) | ||
1179 | fatal("%s socket(): %s", __func__, strerror(errno)); | ||
1180 | |||
1181 | old_umask = umask(0177); | 1257 | old_umask = umask(0177); |
1182 | if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { | 1258 | muxserver_sock = unix_listener(options.control_path, 64, 0); |
1183 | if (errno == EINVAL || errno == EADDRINUSE) { | 1259 | oerrno = errno; |
1260 | umask(old_umask); | ||
1261 | if (muxserver_sock < 0) { | ||
1262 | if (oerrno == EINVAL || oerrno == EADDRINUSE) { | ||
1184 | error("ControlSocket %s already exists, " | 1263 | error("ControlSocket %s already exists, " |
1185 | "disabling multiplexing", options.control_path); | 1264 | "disabling multiplexing", options.control_path); |
1186 | disable_mux_master: | 1265 | disable_mux_master: |
@@ -1193,13 +1272,11 @@ muxserver_listen(void) | |||
1193 | options.control_path = NULL; | 1272 | options.control_path = NULL; |
1194 | options.control_master = SSHCTL_MASTER_NO; | 1273 | options.control_master = SSHCTL_MASTER_NO; |
1195 | return; | 1274 | return; |
1196 | } else | 1275 | } else { |
1197 | fatal("%s bind(): %s", __func__, strerror(errno)); | 1276 | /* unix_listener() logs the error */ |
1277 | cleanup_exit(255); | ||
1278 | } | ||
1198 | } | 1279 | } |
1199 | umask(old_umask); | ||
1200 | |||
1201 | if (listen(muxserver_sock, 64) == -1) | ||
1202 | fatal("%s listen(): %s", __func__, strerror(errno)); | ||
1203 | 1280 | ||
1204 | /* Now atomically "move" the mux socket into position */ | 1281 | /* Now atomically "move" the mux socket into position */ |
1205 | if (link(options.control_path, orig_control_path) != 0) { | 1282 | if (link(options.control_path, orig_control_path) != 0) { |
@@ -1429,7 +1506,7 @@ mux_client_read_packet(int fd, Buffer *m) | |||
1429 | { | 1506 | { |
1430 | Buffer queue; | 1507 | Buffer queue; |
1431 | u_int need, have; | 1508 | u_int need, have; |
1432 | void *ptr; | 1509 | const u_char *ptr; |
1433 | int oerrno; | 1510 | int oerrno; |
1434 | 1511 | ||
1435 | buffer_init(&queue); | 1512 | buffer_init(&queue); |
@@ -1593,7 +1670,7 @@ mux_client_request_terminate(int fd) | |||
1593 | } | 1670 | } |
1594 | 1671 | ||
1595 | static int | 1672 | static int |
1596 | mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) | 1673 | mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) |
1597 | { | 1674 | { |
1598 | Buffer m; | 1675 | Buffer m; |
1599 | char *e, *fwd_desc; | 1676 | char *e, *fwd_desc; |
@@ -1608,11 +1685,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) | |||
1608 | buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); | 1685 | buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); |
1609 | buffer_put_int(&m, muxclient_request_id); | 1686 | buffer_put_int(&m, muxclient_request_id); |
1610 | buffer_put_int(&m, ftype); | 1687 | buffer_put_int(&m, ftype); |
1611 | buffer_put_cstring(&m, | 1688 | if (fwd->listen_path != NULL) { |
1612 | fwd->listen_host == NULL ? "" : fwd->listen_host); | 1689 | buffer_put_cstring(&m, fwd->listen_path); |
1690 | } else { | ||
1691 | buffer_put_cstring(&m, | ||
1692 | fwd->listen_host == NULL ? "" : fwd->listen_host); | ||
1693 | } | ||
1613 | buffer_put_int(&m, fwd->listen_port); | 1694 | buffer_put_int(&m, fwd->listen_port); |
1614 | buffer_put_cstring(&m, | 1695 | if (fwd->connect_path != NULL) { |
1615 | fwd->connect_host == NULL ? "" : fwd->connect_host); | 1696 | buffer_put_cstring(&m, fwd->connect_path); |
1697 | } else { | ||
1698 | buffer_put_cstring(&m, | ||
1699 | fwd->connect_host == NULL ? "" : fwd->connect_host); | ||
1700 | } | ||
1616 | buffer_put_int(&m, fwd->connect_port); | 1701 | buffer_put_int(&m, fwd->connect_port); |
1617 | 1702 | ||
1618 | if (mux_client_write_packet(fd, &m) != 0) | 1703 | if (mux_client_write_packet(fd, &m) != 0) |
@@ -1922,7 +2007,7 @@ mux_client_request_stdio_fwd(int fd) | |||
1922 | case MUX_S_FAILURE: | 2007 | case MUX_S_FAILURE: |
1923 | e = buffer_get_string(&m, NULL); | 2008 | e = buffer_get_string(&m, NULL); |
1924 | buffer_free(&m); | 2009 | buffer_free(&m); |
1925 | fatal("%s: stdio forwarding request failed: %s", __func__, e); | 2010 | fatal("Stdio forwarding request failed: %s", e); |
1926 | default: | 2011 | default: |
1927 | buffer_free(&m); | 2012 | buffer_free(&m); |
1928 | error("%s: unexpected response from master 0x%08x", | 2013 | error("%s: unexpected response from master 0x%08x", |
diff --git a/myproposal.h b/myproposal.h index 3a0f5aeab..b35b2b8bd 100644 --- a/myproposal.h +++ b/myproposal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: myproposal.h,v 1.35 2013/12/06 13:39:49 markus Exp $ */ | 1 | /* $OpenBSD: myproposal.h,v 1.41 2014/07/11 13:54:34 tedu Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -69,23 +69,28 @@ | |||
69 | #ifdef HAVE_EVP_SHA256 | 69 | #ifdef HAVE_EVP_SHA256 |
70 | # define KEX_SHA256_METHODS \ | 70 | # define KEX_SHA256_METHODS \ |
71 | "diffie-hellman-group-exchange-sha256," | 71 | "diffie-hellman-group-exchange-sha256," |
72 | #define KEX_CURVE25519_METHODS \ | ||
73 | "curve25519-sha256@libssh.org," | ||
74 | #define SHA2_HMAC_MODES \ | 72 | #define SHA2_HMAC_MODES \ |
75 | "hmac-sha2-256," \ | 73 | "hmac-sha2-256," \ |
76 | "hmac-sha2-512," | 74 | "hmac-sha2-512," |
77 | #else | 75 | #else |
78 | # define KEX_SHA256_METHODS | 76 | # define KEX_SHA256_METHODS |
79 | # define KEX_CURVE25519_METHODS | ||
80 | # define SHA2_HMAC_MODES | 77 | # define SHA2_HMAC_MODES |
81 | #endif | 78 | #endif |
82 | 79 | ||
83 | # define KEX_DEFAULT_KEX \ | 80 | #ifdef WITH_OPENSSL |
81 | # ifdef HAVE_EVP_SHA256 | ||
82 | # define KEX_CURVE25519_METHODS "curve25519-sha256@libssh.org," | ||
83 | # else | ||
84 | # define KEX_CURVE25519_METHODS "" | ||
85 | # endif | ||
86 | #define KEX_SERVER_KEX \ | ||
84 | KEX_CURVE25519_METHODS \ | 87 | KEX_CURVE25519_METHODS \ |
85 | KEX_ECDH_METHODS \ | 88 | KEX_ECDH_METHODS \ |
86 | KEX_SHA256_METHODS \ | 89 | KEX_SHA256_METHODS \ |
90 | "diffie-hellman-group14-sha1" | ||
91 | |||
92 | #define KEX_CLIENT_KEX KEX_SERVER_KEX "," \ | ||
87 | "diffie-hellman-group-exchange-sha1," \ | 93 | "diffie-hellman-group-exchange-sha1," \ |
88 | "diffie-hellman-group14-sha1," \ | ||
89 | "diffie-hellman-group1-sha1" | 94 | "diffie-hellman-group1-sha1" |
90 | 95 | ||
91 | #define KEX_DEFAULT_PK_ALG \ | 96 | #define KEX_DEFAULT_PK_ALG \ |
@@ -102,47 +107,91 @@ | |||
102 | 107 | ||
103 | /* the actual algorithms */ | 108 | /* the actual algorithms */ |
104 | 109 | ||
105 | #define KEX_DEFAULT_ENCRYPT \ | 110 | #define KEX_SERVER_ENCRYPT \ |
106 | "aes128-ctr,aes192-ctr,aes256-ctr," \ | 111 | "aes128-ctr,aes192-ctr,aes256-ctr," \ |
107 | "arcfour256,arcfour128," \ | ||
108 | AESGCM_CIPHER_MODES \ | 112 | AESGCM_CIPHER_MODES \ |
109 | "chacha20-poly1305@openssh.com," \ | 113 | "chacha20-poly1305@openssh.com" |
114 | |||
115 | #define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT "," \ | ||
116 | "arcfour256,arcfour128," \ | ||
110 | "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ | 117 | "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ |
111 | "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" | 118 | "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" |
112 | 119 | ||
113 | #define KEX_DEFAULT_MAC \ | 120 | #define KEX_SERVER_MAC \ |
114 | "hmac-md5-etm@openssh.com," \ | ||
115 | "hmac-sha1-etm@openssh.com," \ | ||
116 | "umac-64-etm@openssh.com," \ | 121 | "umac-64-etm@openssh.com," \ |
117 | "umac-128-etm@openssh.com," \ | 122 | "umac-128-etm@openssh.com," \ |
118 | "hmac-sha2-256-etm@openssh.com," \ | 123 | "hmac-sha2-256-etm@openssh.com," \ |
119 | "hmac-sha2-512-etm@openssh.com," \ | 124 | "hmac-sha2-512-etm@openssh.com," \ |
125 | "hmac-sha1-etm@openssh.com," \ | ||
126 | "umac-64@openssh.com," \ | ||
127 | "umac-128@openssh.com," \ | ||
128 | "hmac-sha2-256," \ | ||
129 | "hmac-sha2-512," \ | ||
130 | "hmac-sha1" | ||
131 | |||
132 | #define KEX_CLIENT_MAC KEX_SERVER_MAC "," \ | ||
133 | "hmac-md5-etm@openssh.com," \ | ||
120 | "hmac-ripemd160-etm@openssh.com," \ | 134 | "hmac-ripemd160-etm@openssh.com," \ |
121 | "hmac-sha1-96-etm@openssh.com," \ | 135 | "hmac-sha1-96-etm@openssh.com," \ |
122 | "hmac-md5-96-etm@openssh.com," \ | 136 | "hmac-md5-96-etm@openssh.com," \ |
123 | "hmac-md5," \ | 137 | "hmac-md5," \ |
124 | "hmac-sha1," \ | ||
125 | "umac-64@openssh.com," \ | ||
126 | "umac-128@openssh.com," \ | ||
127 | SHA2_HMAC_MODES \ | ||
128 | "hmac-ripemd160," \ | 138 | "hmac-ripemd160," \ |
129 | "hmac-ripemd160@openssh.com," \ | 139 | "hmac-ripemd160@openssh.com," \ |
130 | "hmac-sha1-96," \ | 140 | "hmac-sha1-96," \ |
131 | "hmac-md5-96" | 141 | "hmac-md5-96" |
132 | 142 | ||
143 | #else | ||
144 | |||
145 | #define KEX_SERVER_KEX \ | ||
146 | "curve25519-sha256@libssh.org" | ||
147 | #define KEX_DEFAULT_PK_ALG \ | ||
148 | "ssh-ed25519-cert-v01@openssh.com," \ | ||
149 | "ssh-ed25519" | ||
150 | #define KEX_SERVER_ENCRYPT \ | ||
151 | "aes128-ctr,aes192-ctr,aes256-ctr," \ | ||
152 | "chacha20-poly1305@openssh.com" | ||
153 | #define KEX_SERVER_MAC \ | ||
154 | "umac-64-etm@openssh.com," \ | ||
155 | "umac-128-etm@openssh.com," \ | ||
156 | "hmac-sha2-256-etm@openssh.com," \ | ||
157 | "hmac-sha2-512-etm@openssh.com," \ | ||
158 | "hmac-sha1-etm@openssh.com," \ | ||
159 | "umac-64@openssh.com," \ | ||
160 | "umac-128@openssh.com," \ | ||
161 | "hmac-sha2-256," \ | ||
162 | "hmac-sha2-512," \ | ||
163 | "hmac-sha1" | ||
164 | |||
165 | #define KEX_CLIENT_KEX KEX_SERVER_KEX | ||
166 | #define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT | ||
167 | #define KEX_CLIENT_MAC KEX_SERVER_MAC | ||
168 | |||
169 | #endif /* WITH_OPENSSL */ | ||
170 | |||
133 | #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" | 171 | #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" |
134 | #define KEX_DEFAULT_LANG "" | 172 | #define KEX_DEFAULT_LANG "" |
135 | 173 | ||
174 | #define KEX_CLIENT \ | ||
175 | KEX_CLIENT_KEX, \ | ||
176 | KEX_DEFAULT_PK_ALG, \ | ||
177 | KEX_CLIENT_ENCRYPT, \ | ||
178 | KEX_CLIENT_ENCRYPT, \ | ||
179 | KEX_CLIENT_MAC, \ | ||
180 | KEX_CLIENT_MAC, \ | ||
181 | KEX_DEFAULT_COMP, \ | ||
182 | KEX_DEFAULT_COMP, \ | ||
183 | KEX_DEFAULT_LANG, \ | ||
184 | KEX_DEFAULT_LANG | ||
136 | 185 | ||
137 | static char *myproposal[PROPOSAL_MAX] = { | 186 | #define KEX_SERVER \ |
138 | KEX_DEFAULT_KEX, | 187 | KEX_SERVER_KEX, \ |
139 | KEX_DEFAULT_PK_ALG, | 188 | KEX_DEFAULT_PK_ALG, \ |
140 | KEX_DEFAULT_ENCRYPT, | 189 | KEX_SERVER_ENCRYPT, \ |
141 | KEX_DEFAULT_ENCRYPT, | 190 | KEX_SERVER_ENCRYPT, \ |
142 | KEX_DEFAULT_MAC, | 191 | KEX_SERVER_MAC, \ |
143 | KEX_DEFAULT_MAC, | 192 | KEX_SERVER_MAC, \ |
144 | KEX_DEFAULT_COMP, | 193 | KEX_DEFAULT_COMP, \ |
145 | KEX_DEFAULT_COMP, | 194 | KEX_DEFAULT_COMP, \ |
146 | KEX_DEFAULT_LANG, | 195 | KEX_DEFAULT_LANG, \ |
147 | KEX_DEFAULT_LANG | 196 | KEX_DEFAULT_LANG |
148 | }; | 197 | |
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index 6ecfb93d5..ab1a3e315 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile.in,v 1.55 2014/02/04 00:37:50 djm Exp $ | 1 | # $Id: Makefile.in,v 1.56 2014/09/30 23:43:08 djm Exp $ |
2 | 2 | ||
3 | sysconfdir=@sysconfdir@ | 3 | sysconfdir=@sysconfdir@ |
4 | piddir=@piddir@ | 4 | piddir=@piddir@ |
@@ -18,7 +18,7 @@ LDFLAGS=-L. @LDFLAGS@ | |||
18 | 18 | ||
19 | OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o | 19 | OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o |
20 | 20 | ||
21 | COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o | 21 | COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o kludge-fd_set.o |
22 | 22 | ||
23 | PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o | 23 | PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o |
24 | 24 | ||
diff --git a/openbsd-compat/arc4random.c b/openbsd-compat/arc4random.c index eac073cc0..09dbfda16 100644 --- a/openbsd-compat/arc4random.c +++ b/openbsd-compat/arc4random.c | |||
@@ -87,7 +87,7 @@ _rs_stir(void) | |||
87 | _rs_init(rnd, sizeof(rnd)); | 87 | _rs_init(rnd, sizeof(rnd)); |
88 | } else | 88 | } else |
89 | _rs_rekey(rnd, sizeof(rnd)); | 89 | _rs_rekey(rnd, sizeof(rnd)); |
90 | memset(rnd, 0, sizeof(rnd)); | 90 | explicit_bzero(rnd, sizeof(rnd)); |
91 | 91 | ||
92 | /* invalidate rs_buf */ | 92 | /* invalidate rs_buf */ |
93 | rs_have = 0; | 93 | rs_have = 0; |
@@ -229,7 +229,7 @@ arc4random_buf(void *_buf, size_t n) | |||
229 | buf[i] = r & 0xff; | 229 | buf[i] = r & 0xff; |
230 | r >>= 8; | 230 | r >>= 8; |
231 | } | 231 | } |
232 | i = r = 0; | 232 | explicit_bzero(&r, sizeof(r)); |
233 | } | 233 | } |
234 | #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ | 234 | #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ |
235 | 235 | ||
diff --git a/openbsd-compat/bsd-cygwin_util.c b/openbsd-compat/bsd-cygwin_util.c index 267e77a11..a2d82126d 100644 --- a/openbsd-compat/bsd-cygwin_util.c +++ b/openbsd-compat/bsd-cygwin_util.c | |||
@@ -57,6 +57,22 @@ check_ntsec(const char *filename) | |||
57 | return (pathconf(filename, _PC_POSIX_PERMISSIONS)); | 57 | return (pathconf(filename, _PC_POSIX_PERMISSIONS)); |
58 | } | 58 | } |
59 | 59 | ||
60 | const char * | ||
61 | cygwin_ssh_privsep_user() | ||
62 | { | ||
63 | static char cyg_privsep_user[DNLEN + UNLEN + 2]; | ||
64 | |||
65 | if (!cyg_privsep_user[0]) | ||
66 | { | ||
67 | #ifdef CW_CYGNAME_FROM_WINNAME | ||
68 | if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user, | ||
69 | sizeof cyg_privsep_user) != 0) | ||
70 | #endif | ||
71 | strcpy (cyg_privsep_user, "sshd"); | ||
72 | } | ||
73 | return cyg_privsep_user; | ||
74 | } | ||
75 | |||
60 | #define NL(x) x, (sizeof (x) - 1) | 76 | #define NL(x) x, (sizeof (x) - 1) |
61 | #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) | 77 | #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) |
62 | 78 | ||
diff --git a/openbsd-compat/bsd-cygwin_util.h b/openbsd-compat/bsd-cygwin_util.h index 1177366f1..79cb2a197 100644 --- a/openbsd-compat/bsd-cygwin_util.h +++ b/openbsd-compat/bsd-cygwin_util.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: bsd-cygwin_util.h,v 1.17 2014/01/18 10:04:00 dtucker Exp $ */ | 1 | /* $Id: bsd-cygwin_util.h,v 1.18 2014/05/27 04:34:43 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com> | 4 | * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com> |
@@ -39,6 +39,8 @@ | |||
39 | /* Avoid including windows headers. */ | 39 | /* Avoid including windows headers. */ |
40 | typedef void *HANDLE; | 40 | typedef void *HANDLE; |
41 | #define INVALID_HANDLE_VALUE ((HANDLE) -1) | 41 | #define INVALID_HANDLE_VALUE ((HANDLE) -1) |
42 | #define DNLEN 16 | ||
43 | #define UNLEN 256 | ||
42 | 44 | ||
43 | /* Cygwin functions for which declarations are only available when including | 45 | /* Cygwin functions for which declarations are only available when including |
44 | windows headers, so we have to define them here explicitely. */ | 46 | windows headers, so we have to define them here explicitely. */ |
@@ -48,6 +50,8 @@ extern void cygwin_set_impersonation_token (const HANDLE); | |||
48 | #include <sys/cygwin.h> | 50 | #include <sys/cygwin.h> |
49 | #include <io.h> | 51 | #include <io.h> |
50 | 52 | ||
53 | #define CYGWIN_SSH_PRIVSEP_USER (cygwin_ssh_privsep_user()) | ||
54 | const char *cygwin_ssh_privsep_user(); | ||
51 | 55 | ||
52 | int binary_open(const char *, int , ...); | 56 | int binary_open(const char *, int , ...); |
53 | int check_ntsec(const char *); | 57 | int check_ntsec(const char *); |
diff --git a/openbsd-compat/bsd-snprintf.c b/openbsd-compat/bsd-snprintf.c index 975991e7f..23a635989 100644 --- a/openbsd-compat/bsd-snprintf.c +++ b/openbsd-compat/bsd-snprintf.c | |||
@@ -538,7 +538,7 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen, | |||
538 | } | 538 | } |
539 | while (*value && (cnt < max)) { | 539 | while (*value && (cnt < max)) { |
540 | DOPR_OUTCH(buffer, *currlen, maxlen, *value); | 540 | DOPR_OUTCH(buffer, *currlen, maxlen, *value); |
541 | *value++; | 541 | value++; |
542 | ++cnt; | 542 | ++cnt; |
543 | } | 543 | } |
544 | while ((padlen < 0) && (cnt < max)) { | 544 | while ((padlen < 0) && (cnt < max)) { |
@@ -553,7 +553,7 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen, | |||
553 | 553 | ||
554 | static int | 554 | static int |
555 | fmtint(char *buffer, size_t *currlen, size_t maxlen, | 555 | fmtint(char *buffer, size_t *currlen, size_t maxlen, |
556 | LLONG value, int base, int min, int max, int flags) | 556 | intmax_t value, int base, int min, int max, int flags) |
557 | { | 557 | { |
558 | int signvalue = 0; | 558 | int signvalue = 0; |
559 | unsigned LLONG uvalue; | 559 | unsigned LLONG uvalue; |
diff --git a/openbsd-compat/explicit_bzero.c b/openbsd-compat/explicit_bzero.c index b106741e5..3c85a4843 100644 --- a/openbsd-compat/explicit_bzero.c +++ b/openbsd-compat/explicit_bzero.c | |||
@@ -7,14 +7,34 @@ | |||
7 | 7 | ||
8 | #include "includes.h" | 8 | #include "includes.h" |
9 | 9 | ||
10 | /* | ||
11 | * explicit_bzero - don't let the compiler optimize away bzero | ||
12 | */ | ||
13 | |||
10 | #ifndef HAVE_EXPLICIT_BZERO | 14 | #ifndef HAVE_EXPLICIT_BZERO |
11 | 15 | ||
16 | #ifdef HAVE_MEMSET_S | ||
17 | |||
18 | void | ||
19 | explicit_bzero(void *p, size_t n) | ||
20 | { | ||
21 | (void)memset_s(p, n, 0, n); | ||
22 | } | ||
23 | |||
24 | #else /* HAVE_MEMSET_S */ | ||
25 | |||
12 | /* | 26 | /* |
13 | * explicit_bzero - don't let the compiler optimize away bzero | 27 | * Indirect bzero through a volatile pointer to hopefully avoid |
28 | * dead-store optimisation eliminating the call. | ||
14 | */ | 29 | */ |
30 | static void (* volatile ssh_bzero)(void *, size_t) = bzero; | ||
31 | |||
15 | void | 32 | void |
16 | explicit_bzero(void *p, size_t n) | 33 | explicit_bzero(void *p, size_t n) |
17 | { | 34 | { |
18 | bzero(p, n); | 35 | ssh_bzero(p, n); |
19 | } | 36 | } |
20 | #endif | 37 | |
38 | #endif /* HAVE_MEMSET_S */ | ||
39 | |||
40 | #endif /* HAVE_EXPLICIT_BZERO */ | ||
diff --git a/openbsd-compat/kludge-fd_set.c b/openbsd-compat/kludge-fd_set.c new file mode 100644 index 000000000..6c2ffb64b --- /dev/null +++ b/openbsd-compat/kludge-fd_set.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /* Placed in the public domain. */ | ||
2 | |||
3 | /* | ||
4 | * _FORTIFY_SOURCE includes a misguided check for FD_SET(n)/FD_ISSET(b) | ||
5 | * where n > FD_SETSIZE. This breaks OpenSSH and other programs that | ||
6 | * explicitly allocate fd_sets. To avoid this, we wrap FD_SET in a | ||
7 | * function compiled without _FORTIFY_SOURCE. | ||
8 | */ | ||
9 | |||
10 | #include "config.h" | ||
11 | |||
12 | #if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE) | ||
13 | # include <features.h> | ||
14 | # if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ) | ||
15 | # if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) | ||
16 | # undef _FORTIFY_SOURCE | ||
17 | # undef __USE_FORTIFY_LEVEL | ||
18 | # include <sys/socket.h> | ||
19 | void kludge_FD_SET(int n, fd_set *set) { | ||
20 | FD_SET(n, set); | ||
21 | } | ||
22 | int kludge_FD_ISSET(int n, fd_set *set) { | ||
23 | return FD_ISSET(n, set); | ||
24 | } | ||
25 | # endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */ | ||
26 | # endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */ | ||
27 | #endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */ | ||
28 | |||
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index bc9888e31..ce6abae82 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: openbsd-compat.h,v 1.61 2014/02/04 00:18:23 djm Exp $ */ | 1 | /* $Id: openbsd-compat.h,v 1.62 2014/09/30 23:43:08 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 1999-2003 Damien Miller. All rights reserved. | 4 | * Copyright (c) 1999-2003 Damien Miller. All rights reserved. |
@@ -268,4 +268,20 @@ char *shadow_pw(struct passwd *pw); | |||
268 | #include "port-tun.h" | 268 | #include "port-tun.h" |
269 | #include "port-uw.h" | 269 | #include "port-uw.h" |
270 | 270 | ||
271 | /* _FORTIFY_SOURCE breaks FD_ISSET(n)/FD_SET(n) for n > FD_SETSIZE. Avoid. */ | ||
272 | #if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE) | ||
273 | # include <features.h> | ||
274 | # if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ) | ||
275 | # if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) | ||
276 | # include <sys/socket.h> /* Ensure include guard is defined */ | ||
277 | # undef FD_SET | ||
278 | # undef FD_ISSET | ||
279 | # define FD_SET(n, set) kludge_FD_SET(n, set) | ||
280 | # define FD_ISSET(n, set) kludge_FD_ISSET(n, set) | ||
281 | void kludge_FD_SET(int, fd_set *); | ||
282 | int kludge_FD_ISSET(int, fd_set *); | ||
283 | # endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */ | ||
284 | # endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */ | ||
285 | #endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */ | ||
286 | |||
271 | #endif /* _OPENBSD_COMPAT_H */ | 287 | #endif /* _OPENBSD_COMPAT_H */ |
diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c index 885c121f2..defd5fb61 100644 --- a/openbsd-compat/openssl-compat.c +++ b/openbsd-compat/openssl-compat.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: openssl-compat.c,v 1.17 2014/02/13 05:38:33 dtucker Exp $ */ | 1 | /* $Id: openssl-compat.c,v 1.19 2014/07/02 05:28:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> | 4 | * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> |
@@ -16,6 +16,7 @@ | |||
16 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define SSH_DONT_OVERLOAD_OPENSSL_FUNCS | ||
19 | #include "includes.h" | 20 | #include "includes.h" |
20 | 21 | ||
21 | #include <stdarg.h> | 22 | #include <stdarg.h> |
@@ -26,147 +27,44 @@ | |||
26 | # include <openssl/conf.h> | 27 | # include <openssl/conf.h> |
27 | #endif | 28 | #endif |
28 | 29 | ||
29 | #ifndef HAVE_RSA_GET_DEFAULT_METHOD | ||
30 | # include <openssl/rsa.h> | ||
31 | #endif | ||
32 | |||
33 | #include "log.h" | 30 | #include "log.h" |
34 | 31 | ||
35 | #define SSH_DONT_OVERLOAD_OPENSSL_FUNCS | ||
36 | #include "openssl-compat.h" | 32 | #include "openssl-compat.h" |
37 | 33 | ||
38 | #ifdef SSH_OLD_EVP | 34 | /* |
39 | int | 35 | * OpenSSL version numbers: MNNFFPPS: major minor fix patch status |
40 | ssh_EVP_CipherInit(EVP_CIPHER_CTX *evp, const EVP_CIPHER *type, | 36 | * We match major, minor, fix and status (not patch) for <1.0.0. |
41 | unsigned char *key, unsigned char *iv, int enc) | 37 | * After that, we accept compatible fix and status versions (so we |
42 | { | 38 | * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed |
43 | EVP_CipherInit(evp, type, key, iv, enc); | 39 | * within a patch series. |
44 | return 1; | 40 | */ |
45 | } | ||
46 | |||
47 | int | ||
48 | ssh_EVP_Cipher(EVP_CIPHER_CTX *evp, char *dst, char *src, int len) | ||
49 | { | ||
50 | EVP_Cipher(evp, dst, src, len); | ||
51 | return 1; | ||
52 | } | ||
53 | |||
54 | int | ||
55 | ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *evp) | ||
56 | { | ||
57 | EVP_CIPHER_CTX_cleanup(evp); | ||
58 | return 1; | ||
59 | } | ||
60 | #endif | ||
61 | |||
62 | #ifndef HAVE_EVP_DIGESTINIT_EX | ||
63 | int | ||
64 | EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, void *engine) | ||
65 | { | ||
66 | if (engine != NULL) | ||
67 | fatal("%s: ENGINE is not supported", __func__); | ||
68 | # ifdef OPENSSL_EVP_DIGESTUPDATE_VOID | ||
69 | EVP_DigestInit(ctx, md); | ||
70 | return 1; | ||
71 | # else | ||
72 | return EVP_DigestInit(ctx, md); | ||
73 | # endif | ||
74 | } | ||
75 | #endif | ||
76 | |||
77 | #ifndef HAVE_EVP_DIGESTFINAL_EX | ||
78 | int | ||
79 | EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s) | ||
80 | { | ||
81 | # ifdef OPENSSL_EVP_DIGESTUPDATE_VOID | ||
82 | EVP_DigestFinal(ctx, md, s); | ||
83 | return 1; | ||
84 | # else | ||
85 | return EVP_DigestFinal(ctx, md, s); | ||
86 | # endif | ||
87 | } | ||
88 | #endif | ||
89 | |||
90 | #ifdef OPENSSL_EVP_DIGESTUPDATE_VOID | ||
91 | int | ||
92 | ssh_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt) | ||
93 | { | ||
94 | EVP_DigestUpdate(ctx, d, cnt); | ||
95 | return 1; | ||
96 | } | ||
97 | #endif | ||
98 | |||
99 | #ifndef HAVE_EVP_MD_CTX_COPY_EX | ||
100 | int | ||
101 | EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) | ||
102 | { | ||
103 | return EVP_MD_CTX_copy(out, in); | ||
104 | } | ||
105 | #endif | ||
106 | |||
107 | #ifndef HAVE_BN_IS_PRIME_EX | ||
108 | int | ||
109 | BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, void *cb) | ||
110 | { | ||
111 | if (cb != NULL) | ||
112 | fatal("%s: callback args not supported", __func__); | ||
113 | return BN_is_prime(p, nchecks, NULL, ctx, NULL); | ||
114 | } | ||
115 | #endif | ||
116 | |||
117 | #ifndef HAVE_RSA_GENERATE_KEY_EX | ||
118 | int | ||
119 | RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *bn_e, void *cb) | ||
120 | { | ||
121 | RSA *new_rsa, tmp_rsa; | ||
122 | unsigned long e; | ||
123 | |||
124 | if (cb != NULL) | ||
125 | fatal("%s: callback args not supported", __func__); | ||
126 | e = BN_get_word(bn_e); | ||
127 | if (e == 0xffffffffL) | ||
128 | fatal("%s: value of e too large", __func__); | ||
129 | new_rsa = RSA_generate_key(bits, e, NULL, NULL); | ||
130 | if (new_rsa == NULL) | ||
131 | return 0; | ||
132 | /* swap rsa/new_rsa then free new_rsa */ | ||
133 | tmp_rsa = *rsa; | ||
134 | *rsa = *new_rsa; | ||
135 | *new_rsa = tmp_rsa; | ||
136 | RSA_free(new_rsa); | ||
137 | return 1; | ||
138 | } | ||
139 | #endif | ||
140 | 41 | ||
141 | #ifndef HAVE_DSA_GENERATE_PARAMETERS_EX | ||
142 | int | 42 | int |
143 | DSA_generate_parameters_ex(DSA *dsa, int bits, const unsigned char *seed, | 43 | ssh_compatible_openssl(long headerver, long libver) |
144 | int seed_len, int *counter_ret, unsigned long *h_ret, void *cb) | ||
145 | { | 44 | { |
146 | DSA *new_dsa, tmp_dsa; | 45 | long mask, hfix, lfix; |
147 | 46 | ||
148 | if (cb != NULL) | 47 | /* exact match is always OK */ |
149 | fatal("%s: callback args not supported", __func__); | 48 | if (headerver == libver) |
150 | new_dsa = DSA_generate_parameters(bits, (unsigned char *)seed, seed_len, | 49 | return 1; |
151 | counter_ret, h_ret, NULL, NULL); | 50 | |
152 | if (new_dsa == NULL) | 51 | /* for versions < 1.0.0, major,minor,fix,status must match */ |
153 | return 0; | 52 | if (headerver < 0x1000000f) { |
154 | /* swap dsa/new_dsa then free new_dsa */ | 53 | mask = 0xfffff00fL; /* major,minor,fix,status */ |
155 | tmp_dsa = *dsa; | 54 | return (headerver & mask) == (libver & mask); |
156 | *dsa = *new_dsa; | 55 | } |
157 | *new_dsa = tmp_dsa; | 56 | |
158 | DSA_free(new_dsa); | 57 | /* |
159 | return 1; | 58 | * For versions >= 1.0.0, major,minor must match and library |
160 | } | 59 | * fix version must be equal to or newer than the header. |
161 | #endif | 60 | */ |
162 | 61 | mask = 0xfff00000L; /* major,minor */ | |
163 | #ifndef HAVE_RSA_GET_DEFAULT_METHOD | 62 | hfix = (headerver & 0x000ff000) >> 12; |
164 | RSA_METHOD * | 63 | lfix = (libver & 0x000ff000) >> 12; |
165 | RSA_get_default_method(void) | 64 | if ( (headerver & mask) == (libver & mask) && lfix >= hfix) |
166 | { | 65 | return 1; |
167 | return RSA_PKCS1_SSLeay(); | 66 | return 0; |
168 | } | 67 | } |
169 | #endif | ||
170 | 68 | ||
171 | #ifdef USE_OPENSSL_ENGINE | 69 | #ifdef USE_OPENSSL_ENGINE |
172 | void | 70 | void |
diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h index 276b9706d..3695d412b 100644 --- a/openbsd-compat/openssl-compat.h +++ b/openbsd-compat/openssl-compat.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: openssl-compat.h,v 1.26 2014/02/13 05:38:33 dtucker Exp $ */ | 1 | /* $Id: openssl-compat.h,v 1.31 2014/08/29 18:18:29 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> | 4 | * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> |
@@ -16,28 +16,19 @@ | |||
16 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #ifndef _OPENSSL_COMPAT_H | ||
20 | #define _OPENSSL_COMPAT_H | ||
21 | |||
19 | #include "includes.h" | 22 | #include "includes.h" |
20 | #include <openssl/opensslv.h> | 23 | #include <openssl/opensslv.h> |
21 | #include <openssl/evp.h> | 24 | #include <openssl/evp.h> |
22 | #include <openssl/rsa.h> | 25 | #include <openssl/rsa.h> |
23 | #include <openssl/dsa.h> | 26 | #include <openssl/dsa.h> |
24 | 27 | ||
25 | /* Only in 0.9.8 */ | 28 | int ssh_compatible_openssl(long, long); |
26 | #ifndef OPENSSL_DSA_MAX_MODULUS_BITS | ||
27 | # define OPENSSL_DSA_MAX_MODULUS_BITS 10000 | ||
28 | #endif | ||
29 | #ifndef OPENSSL_RSA_MAX_MODULUS_BITS | ||
30 | # define OPENSSL_RSA_MAX_MODULUS_BITS 16384 | ||
31 | #endif | ||
32 | |||
33 | /* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */ | ||
34 | #if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f) | ||
35 | # define OPENSSL_free(x) Free(x) | ||
36 | #endif | ||
37 | 29 | ||
38 | #if OPENSSL_VERSION_NUMBER < 0x00906000L | 30 | #if (OPENSSL_VERSION_NUMBER <= 0x0090805fL) |
39 | # define SSH_OLD_EVP | 31 | # error OpenSSL 0.9.8f or greater is required |
40 | # define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data) | ||
41 | #endif | 32 | #endif |
42 | 33 | ||
43 | #if OPENSSL_VERSION_NUMBER < 0x10000001L | 34 | #if OPENSSL_VERSION_NUMBER < 0x10000001L |
@@ -46,27 +37,17 @@ | |||
46 | # define LIBCRYPTO_EVP_INL_TYPE size_t | 37 | # define LIBCRYPTO_EVP_INL_TYPE size_t |
47 | #endif | 38 | #endif |
48 | 39 | ||
49 | #if (OPENSSL_VERSION_NUMBER < 0x00907000L) || defined(OPENSSL_LOBOTOMISED_AES) | 40 | #ifndef OPENSSL_RSA_MAX_MODULUS_BITS |
50 | # define USE_BUILTIN_RIJNDAEL | 41 | # define OPENSSL_RSA_MAX_MODULUS_BITS 16384 |
51 | #endif | 42 | #endif |
52 | 43 | #ifndef OPENSSL_DSA_MAX_MODULUS_BITS | |
53 | #ifdef USE_BUILTIN_RIJNDAEL | 44 | # define OPENSSL_DSA_MAX_MODULUS_BITS 10000 |
54 | # include "rijndael.h" | ||
55 | # define AES_KEY rijndael_ctx | ||
56 | # define AES_BLOCK_SIZE 16 | ||
57 | # define AES_encrypt(a, b, c) rijndael_encrypt(c, a, b) | ||
58 | # define AES_set_encrypt_key(a, b, c) rijndael_set_key(c, (char *)a, b, 1) | ||
59 | # define EVP_aes_128_cbc evp_rijndael | ||
60 | # define EVP_aes_192_cbc evp_rijndael | ||
61 | # define EVP_aes_256_cbc evp_rijndael | ||
62 | const EVP_CIPHER *evp_rijndael(void); | ||
63 | void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); | ||
64 | #endif | 45 | #endif |
65 | 46 | ||
66 | #ifndef OPENSSL_HAVE_EVPCTR | 47 | #ifndef OPENSSL_HAVE_EVPCTR |
67 | #define EVP_aes_128_ctr evp_aes_128_ctr | 48 | # define EVP_aes_128_ctr evp_aes_128_ctr |
68 | #define EVP_aes_192_ctr evp_aes_128_ctr | 49 | # define EVP_aes_192_ctr evp_aes_128_ctr |
69 | #define EVP_aes_256_ctr evp_aes_128_ctr | 50 | # define EVP_aes_256_ctr evp_aes_128_ctr |
70 | const EVP_CIPHER *evp_aes_128_ctr(void); | 51 | const EVP_CIPHER *evp_aes_128_ctr(void); |
71 | void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); | 52 | void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); |
72 | #endif | 53 | #endif |
@@ -88,26 +69,9 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); | |||
88 | # endif | 69 | # endif |
89 | #endif | 70 | #endif |
90 | 71 | ||
91 | #if OPENSSL_VERSION_NUMBER < 0x00907000L | ||
92 | #define EVP_X_STATE(evp) &(evp).c | ||
93 | #define EVP_X_STATE_LEN(evp) sizeof((evp).c) | ||
94 | #else | ||
95 | #define EVP_X_STATE(evp) (evp).cipher_data | ||
96 | #define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size | ||
97 | #endif | ||
98 | |||
99 | /* OpenSSL 0.9.8e returns cipher key len not context key len */ | ||
100 | #if (OPENSSL_VERSION_NUMBER == 0x0090805fL) | ||
101 | # define EVP_CIPHER_CTX_key_length(c) ((c)->key_len) | ||
102 | #endif | ||
103 | |||
104 | #ifndef HAVE_RSA_GET_DEFAULT_METHOD | ||
105 | RSA_METHOD *RSA_get_default_method(void); | ||
106 | #endif | ||
107 | |||
108 | /* | 72 | /* |
109 | * We overload some of the OpenSSL crypto functions with ssh_* equivalents | 73 | * We overload some of the OpenSSL crypto functions with ssh_* equivalents |
110 | * which cater for older and/or less featureful OpenSSL version. | 74 | * to automatically handle OpenSSL engine initialisation. |
111 | * | 75 | * |
112 | * In order for the compat library to call the real functions, it must | 76 | * In order for the compat library to call the real functions, it must |
113 | * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and | 77 | * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and |
@@ -115,19 +79,6 @@ RSA_METHOD *RSA_get_default_method(void); | |||
115 | */ | 79 | */ |
116 | #ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS | 80 | #ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS |
117 | 81 | ||
118 | # ifdef SSH_OLD_EVP | ||
119 | # ifdef EVP_Cipher | ||
120 | # undef EVP_Cipher | ||
121 | # endif | ||
122 | # define EVP_CipherInit(a,b,c,d,e) ssh_EVP_CipherInit((a),(b),(c),(d),(e)) | ||
123 | # define EVP_Cipher(a,b,c,d) ssh_EVP_Cipher((a),(b),(c),(d)) | ||
124 | # define EVP_CIPHER_CTX_cleanup(a) ssh_EVP_CIPHER_CTX_cleanup((a)) | ||
125 | # endif /* SSH_OLD_EVP */ | ||
126 | |||
127 | # ifdef OPENSSL_EVP_DIGESTUPDATE_VOID | ||
128 | # define EVP_DigestUpdate(a,b,c) ssh_EVP_DigestUpdate((a),(b),(c)) | ||
129 | # endif | ||
130 | |||
131 | # ifdef USE_OPENSSL_ENGINE | 82 | # ifdef USE_OPENSSL_ENGINE |
132 | # ifdef OpenSSL_add_all_algorithms | 83 | # ifdef OpenSSL_add_all_algorithms |
133 | # undef OpenSSL_add_all_algorithms | 84 | # undef OpenSSL_add_all_algorithms |
@@ -135,48 +86,8 @@ RSA_METHOD *RSA_get_default_method(void); | |||
135 | # define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms() | 86 | # define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms() |
136 | # endif | 87 | # endif |
137 | 88 | ||
138 | # ifndef HAVE_BN_IS_PRIME_EX | ||
139 | int BN_is_prime_ex(const BIGNUM *, int, BN_CTX *, void *); | ||
140 | # endif | ||
141 | |||
142 | # ifndef HAVE_DSA_GENERATE_PARAMETERS_EX | ||
143 | int DSA_generate_parameters_ex(DSA *, int, const unsigned char *, int, int *, | ||
144 | unsigned long *, void *); | ||
145 | # endif | ||
146 | |||
147 | # ifndef HAVE_RSA_GENERATE_KEY_EX | ||
148 | int RSA_generate_key_ex(RSA *, int, BIGNUM *, void *); | ||
149 | # endif | ||
150 | |||
151 | # ifndef HAVE_EVP_DIGESTINIT_EX | ||
152 | int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, void *); | ||
153 | # endif | ||
154 | |||
155 | # ifndef HAVE_EVP_DISESTFINAL_EX | ||
156 | int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *); | ||
157 | # endif | ||
158 | |||
159 | # ifndef EVP_MD_CTX_COPY_EX | ||
160 | int EVP_MD_CTX_copy_ex(EVP_MD_CTX *, const EVP_MD_CTX *); | ||
161 | # endif | ||
162 | |||
163 | int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *, | ||
164 | unsigned char *, int); | ||
165 | int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int); | ||
166 | int ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *); | ||
167 | void ssh_OpenSSL_add_all_algorithms(void); | 89 | void ssh_OpenSSL_add_all_algorithms(void); |
168 | 90 | ||
169 | # ifndef HAVE_HMAC_CTX_INIT | ||
170 | # define HMAC_CTX_init(a) | ||
171 | # endif | ||
172 | |||
173 | # ifndef HAVE_EVP_MD_CTX_INIT | ||
174 | # define EVP_MD_CTX_init(a) | ||
175 | # endif | ||
176 | |||
177 | # ifndef HAVE_EVP_MD_CTX_CLEANUP | ||
178 | # define EVP_MD_CTX_cleanup(a) | ||
179 | # endif | ||
180 | |||
181 | #endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */ | 91 | #endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */ |
182 | 92 | ||
93 | #endif /* _OPENSSL_COMPAT_H */ | ||
diff --git a/openbsd-compat/port-uw.c b/openbsd-compat/port-uw.c index b1fbfa208..db24dbb94 100644 --- a/openbsd-compat/port-uw.c +++ b/openbsd-compat/port-uw.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "key.h" | 42 | #include "key.h" |
43 | #include "auth-options.h" | 43 | #include "auth-options.h" |
44 | #include "log.h" | 44 | #include "log.h" |
45 | #include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ | ||
45 | #include "servconf.h" | 46 | #include "servconf.h" |
46 | #include "hostfile.h" | 47 | #include "hostfile.h" |
47 | #include "auth.h" | 48 | #include "auth.h" |
diff --git a/openbsd-compat/regress/Makefile.in b/openbsd-compat/regress/Makefile.in index bcf214bd0..dabdb0912 100644 --- a/openbsd-compat/regress/Makefile.in +++ b/openbsd-compat/regress/Makefile.in | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile.in,v 1.4 2006/08/19 09:12:14 dtucker Exp $ | 1 | # $Id: Makefile.in,v 1.5 2014/06/17 13:06:08 dtucker Exp $ |
2 | 2 | ||
3 | sysconfdir=@sysconfdir@ | 3 | sysconfdir=@sysconfdir@ |
4 | piddir=@piddir@ | 4 | piddir=@piddir@ |
@@ -16,11 +16,11 @@ LIBS=@LIBS@ | |||
16 | LDFLAGS=@LDFLAGS@ $(LIBCOMPAT) | 16 | LDFLAGS=@LDFLAGS@ $(LIBCOMPAT) |
17 | 17 | ||
18 | TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \ | 18 | TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \ |
19 | strtonumtest$(EXEEXT) | 19 | strtonumtest$(EXEEXT) opensslvertest$(EXEEXT) |
20 | 20 | ||
21 | all: t-exec ${OTHERTESTS} | 21 | all: t-exec ${OTHERTESTS} |
22 | 22 | ||
23 | %$(EXEEXT): %.c | 23 | %$(EXEEXT): %.c $(LIBCOMPAT) |
24 | $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBS) | 24 | $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBS) |
25 | 25 | ||
26 | t-exec: $(TESTPROGS) | 26 | t-exec: $(TESTPROGS) |
diff --git a/openbsd-compat/regress/opensslvertest.c b/openbsd-compat/regress/opensslvertest.c new file mode 100644 index 000000000..58474873d --- /dev/null +++ b/openbsd-compat/regress/opensslvertest.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Darren Tucker | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <stdio.h> | ||
18 | #include <stdlib.h> | ||
19 | |||
20 | int ssh_compatible_openssl(long, long); | ||
21 | |||
22 | struct version_test { | ||
23 | long headerver; | ||
24 | long libver; | ||
25 | int result; | ||
26 | } version_tests[] = { | ||
27 | /* built with 0.9.8b release headers */ | ||
28 | { 0x0090802fL, 0x0090802fL, 1}, /* exact match */ | ||
29 | { 0x0090802fL, 0x0090804fL, 1}, /* newer library fix version: ok */ | ||
30 | { 0x0090802fL, 0x0090801fL, 1}, /* older library fix version: ok */ | ||
31 | { 0x0090802fL, 0x0090702fL, 0}, /* older library minor version: NO */ | ||
32 | { 0x0090802fL, 0x0090902fL, 0}, /* newer library minor version: NO */ | ||
33 | { 0x0090802fL, 0x0080802fL, 0}, /* older library major version: NO */ | ||
34 | { 0x0090802fL, 0x1000100fL, 0}, /* newer library major version: NO */ | ||
35 | |||
36 | /* built with 1.0.1b release headers */ | ||
37 | { 0x1000101fL, 0x1000101fL, 1},/* exact match */ | ||
38 | { 0x1000101fL, 0x10001010L, 1}, /* different status: ok */ | ||
39 | { 0x1000101fL, 0x1000102fL, 1}, /* newer library patch version: ok */ | ||
40 | { 0x1000101fL, 0x1000100fL, 1}, /* older library patch version: ok */ | ||
41 | { 0x1000101fL, 0x1000201fL, 1}, /* newer library fix version: ok */ | ||
42 | { 0x1000101fL, 0x1000001fL, 0}, /* older library fix version: NO */ | ||
43 | { 0x1000101fL, 0x1010101fL, 0}, /* newer library minor version: NO */ | ||
44 | { 0x1000101fL, 0x0000101fL, 0}, /* older library major version: NO */ | ||
45 | { 0x1000101fL, 0x2000101fL, 0}, /* newer library major version: NO */ | ||
46 | }; | ||
47 | |||
48 | void | ||
49 | fail(long hver, long lver, int result) | ||
50 | { | ||
51 | fprintf(stderr, "opensslver: header %lx library %lx != %d \n", hver, lver, result); | ||
52 | exit(1); | ||
53 | } | ||
54 | |||
55 | int | ||
56 | main(void) | ||
57 | { | ||
58 | unsigned int i; | ||
59 | int res; | ||
60 | long hver, lver; | ||
61 | |||
62 | for (i = 0; i < sizeof(version_tests) / sizeof(version_tests[0]); i++) { | ||
63 | hver = version_tests[i].headerver; | ||
64 | lver = version_tests[i].libver; | ||
65 | res = version_tests[i].result; | ||
66 | if (ssh_compatible_openssl(hver, lver) != res) | ||
67 | fail(hver, lver, res); | ||
68 | } | ||
69 | exit(0); | ||
70 | } | ||
diff --git a/opensshd.init.in b/opensshd.init.in index 0db60caa7..517345bfb 100755 --- a/opensshd.init.in +++ b/opensshd.init.in | |||
@@ -21,6 +21,7 @@ HOST_KEY_RSA1=$sysconfdir/ssh_host_key | |||
21 | HOST_KEY_DSA=$sysconfdir/ssh_host_dsa_key | 21 | HOST_KEY_DSA=$sysconfdir/ssh_host_dsa_key |
22 | HOST_KEY_RSA=$sysconfdir/ssh_host_rsa_key | 22 | HOST_KEY_RSA=$sysconfdir/ssh_host_rsa_key |
23 | @COMMENT_OUT_ECC@HOST_KEY_ECDSA=$sysconfdir/ssh_host_ecdsa_key | 23 | @COMMENT_OUT_ECC@HOST_KEY_ECDSA=$sysconfdir/ssh_host_ecdsa_key |
24 | HOST_KEY_ED25519=$sysconfdir/ssh_host_ed25519_key | ||
24 | 25 | ||
25 | 26 | ||
26 | checkkeys() { | 27 | checkkeys() { |
@@ -36,6 +37,9 @@ checkkeys() { | |||
36 | @COMMENT_OUT_ECC@ if [ ! -f $HOST_KEY_ECDSA ]; then | 37 | @COMMENT_OUT_ECC@ if [ ! -f $HOST_KEY_ECDSA ]; then |
37 | @COMMENT_OUT_ECC@ ${SSH_KEYGEN} -t ecdsa -f ${HOST_KEY_ECDSA} -N "" | 38 | @COMMENT_OUT_ECC@ ${SSH_KEYGEN} -t ecdsa -f ${HOST_KEY_ECDSA} -N "" |
38 | @COMMENT_OUT_ECC@ fi | 39 | @COMMENT_OUT_ECC@ fi |
40 | if [ ! -f $HOST_KEY_ED25519 ]; then | ||
41 | ${SSH_KEYGEN} -t ed25519 -f ${HOST_KEY_ED25519} -N "" | ||
42 | fi | ||
39 | } | 43 | } |
40 | 44 | ||
41 | stop_service() { | 45 | stop_service() { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.192 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.198 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -66,7 +66,6 @@ | |||
66 | #include "crc32.h" | 66 | #include "crc32.h" |
67 | #include "compress.h" | 67 | #include "compress.h" |
68 | #include "deattack.h" | 68 | #include "deattack.h" |
69 | #include "channels.h" | ||
70 | #include "compat.h" | 69 | #include "compat.h" |
71 | #include "ssh1.h" | 70 | #include "ssh1.h" |
72 | #include "ssh2.h" | 71 | #include "ssh2.h" |
@@ -77,7 +76,9 @@ | |||
77 | #include "log.h" | 76 | #include "log.h" |
78 | #include "canohost.h" | 77 | #include "canohost.h" |
79 | #include "misc.h" | 78 | #include "misc.h" |
79 | #include "channels.h" | ||
80 | #include "ssh.h" | 80 | #include "ssh.h" |
81 | #include "ssherr.h" | ||
81 | #include "roaming.h" | 82 | #include "roaming.h" |
82 | 83 | ||
83 | #ifdef PACKET_DEBUG | 84 | #ifdef PACKET_DEBUG |
@@ -222,6 +223,7 @@ void | |||
222 | packet_set_connection(int fd_in, int fd_out) | 223 | packet_set_connection(int fd_in, int fd_out) |
223 | { | 224 | { |
224 | const Cipher *none = cipher_by_name("none"); | 225 | const Cipher *none = cipher_by_name("none"); |
226 | int r; | ||
225 | 227 | ||
226 | if (none == NULL) | 228 | if (none == NULL) |
227 | fatal("packet_set_connection: cannot load cipher 'none'"); | 229 | fatal("packet_set_connection: cannot load cipher 'none'"); |
@@ -229,10 +231,11 @@ packet_set_connection(int fd_in, int fd_out) | |||
229 | active_state = alloc_session_state(); | 231 | active_state = alloc_session_state(); |
230 | active_state->connection_in = fd_in; | 232 | active_state->connection_in = fd_in; |
231 | active_state->connection_out = fd_out; | 233 | active_state->connection_out = fd_out; |
232 | cipher_init(&active_state->send_context, none, (const u_char *)"", | 234 | if ((r = cipher_init(&active_state->send_context, none, |
233 | 0, NULL, 0, CIPHER_ENCRYPT); | 235 | (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 || |
234 | cipher_init(&active_state->receive_context, none, (const u_char *)"", | 236 | (r = cipher_init(&active_state->receive_context, none, |
235 | 0, NULL, 0, CIPHER_DECRYPT); | 237 | (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) |
238 | fatal("%s: cipher_init: %s", __func__, ssh_err(r)); | ||
236 | active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL; | 239 | active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL; |
237 | if (!active_state->initialized) { | 240 | if (!active_state->initialized) { |
238 | active_state->initialized = 1; | 241 | active_state->initialized = 1; |
@@ -329,13 +332,15 @@ void | |||
329 | packet_get_keyiv(int mode, u_char *iv, u_int len) | 332 | packet_get_keyiv(int mode, u_char *iv, u_int len) |
330 | { | 333 | { |
331 | CipherContext *cc; | 334 | CipherContext *cc; |
335 | int r; | ||
332 | 336 | ||
333 | if (mode == MODE_OUT) | 337 | if (mode == MODE_OUT) |
334 | cc = &active_state->send_context; | 338 | cc = &active_state->send_context; |
335 | else | 339 | else |
336 | cc = &active_state->receive_context; | 340 | cc = &active_state->receive_context; |
337 | 341 | ||
338 | cipher_get_keyiv(cc, iv, len); | 342 | if ((r = cipher_get_keyiv(cc, iv, len)) != 0) |
343 | fatal("%s: cipher_get_keyiv: %s", __func__, ssh_err(r)); | ||
339 | } | 344 | } |
340 | 345 | ||
341 | int | 346 | int |
@@ -381,13 +386,15 @@ void | |||
381 | packet_set_iv(int mode, u_char *dat) | 386 | packet_set_iv(int mode, u_char *dat) |
382 | { | 387 | { |
383 | CipherContext *cc; | 388 | CipherContext *cc; |
389 | int r; | ||
384 | 390 | ||
385 | if (mode == MODE_OUT) | 391 | if (mode == MODE_OUT) |
386 | cc = &active_state->send_context; | 392 | cc = &active_state->send_context; |
387 | else | 393 | else |
388 | cc = &active_state->receive_context; | 394 | cc = &active_state->receive_context; |
389 | 395 | ||
390 | cipher_set_keyiv(cc, dat); | 396 | if ((r = cipher_set_keyiv(cc, dat)) != 0) |
397 | fatal("%s: cipher_set_keyiv: %s", __func__, ssh_err(r)); | ||
391 | } | 398 | } |
392 | 399 | ||
393 | int | 400 | int |
@@ -552,6 +559,7 @@ void | |||
552 | packet_set_encryption_key(const u_char *key, u_int keylen, int number) | 559 | packet_set_encryption_key(const u_char *key, u_int keylen, int number) |
553 | { | 560 | { |
554 | const Cipher *cipher = cipher_by_number(number); | 561 | const Cipher *cipher = cipher_by_number(number); |
562 | int r; | ||
555 | 563 | ||
556 | if (cipher == NULL) | 564 | if (cipher == NULL) |
557 | fatal("packet_set_encryption_key: unknown cipher number %d", number); | 565 | fatal("packet_set_encryption_key: unknown cipher number %d", number); |
@@ -561,10 +569,11 @@ packet_set_encryption_key(const u_char *key, u_int keylen, int number) | |||
561 | fatal("packet_set_encryption_key: keylen too big: %d", keylen); | 569 | fatal("packet_set_encryption_key: keylen too big: %d", keylen); |
562 | memcpy(active_state->ssh1_key, key, keylen); | 570 | memcpy(active_state->ssh1_key, key, keylen); |
563 | active_state->ssh1_keylen = keylen; | 571 | active_state->ssh1_keylen = keylen; |
564 | cipher_init(&active_state->send_context, cipher, key, keylen, NULL, | 572 | if ((r = cipher_init(&active_state->send_context, cipher, |
565 | 0, CIPHER_ENCRYPT); | 573 | key, keylen, NULL, 0, CIPHER_ENCRYPT)) != 0 || |
566 | cipher_init(&active_state->receive_context, cipher, key, keylen, NULL, | 574 | (r = cipher_init(&active_state->receive_context, cipher, |
567 | 0, CIPHER_DECRYPT); | 575 | key, keylen, NULL, 0, CIPHER_DECRYPT)) != 0) |
576 | fatal("%s: cipher_init: %s", __func__, ssh_err(r)); | ||
568 | } | 577 | } |
569 | 578 | ||
570 | u_int | 579 | u_int |
@@ -630,6 +639,7 @@ packet_put_raw(const void *buf, u_int len) | |||
630 | buffer_append(&active_state->outgoing_packet, buf, len); | 639 | buffer_append(&active_state->outgoing_packet, buf, len); |
631 | } | 640 | } |
632 | 641 | ||
642 | #ifdef WITH_OPENSSL | ||
633 | void | 643 | void |
634 | packet_put_bignum(BIGNUM * value) | 644 | packet_put_bignum(BIGNUM * value) |
635 | { | 645 | { |
@@ -641,6 +651,7 @@ packet_put_bignum2(BIGNUM * value) | |||
641 | { | 651 | { |
642 | buffer_put_bignum2(&active_state->outgoing_packet, value); | 652 | buffer_put_bignum2(&active_state->outgoing_packet, value); |
643 | } | 653 | } |
654 | #endif | ||
644 | 655 | ||
645 | #ifdef OPENSSL_HAS_ECC | 656 | #ifdef OPENSSL_HAS_ECC |
646 | void | 657 | void |
@@ -742,7 +753,7 @@ set_newkeys(int mode) | |||
742 | Comp *comp; | 753 | Comp *comp; |
743 | CipherContext *cc; | 754 | CipherContext *cc; |
744 | u_int64_t *max_blocks; | 755 | u_int64_t *max_blocks; |
745 | int crypt_type; | 756 | int r, crypt_type; |
746 | 757 | ||
747 | debug2("set_newkeys: mode %d", mode); | 758 | debug2("set_newkeys: mode %d", mode); |
748 | 759 | ||
@@ -784,8 +795,9 @@ set_newkeys(int mode) | |||
784 | if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) | 795 | if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) |
785 | mac->enabled = 1; | 796 | mac->enabled = 1; |
786 | DBG(debug("cipher_init_context: %d", mode)); | 797 | DBG(debug("cipher_init_context: %d", mode)); |
787 | cipher_init(cc, enc->cipher, enc->key, enc->key_len, | 798 | if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len, |
788 | enc->iv, enc->iv_len, crypt_type); | 799 | enc->iv, enc->iv_len, crypt_type)) != 0) |
800 | fatal("%s: cipher_init: %s", __func__, ssh_err(r)); | ||
789 | /* Deleting the keys does not gain extra security */ | 801 | /* Deleting the keys does not gain extra security */ |
790 | /* explicit_bzero(enc->iv, enc->block_size); | 802 | /* explicit_bzero(enc->iv, enc->block_size); |
791 | explicit_bzero(enc->key, enc->key_len); | 803 | explicit_bzero(enc->key, enc->key_len); |
@@ -912,8 +924,8 @@ packet_send2_wrapped(void) | |||
912 | roundup(active_state->extra_pad, block_size); | 924 | roundup(active_state->extra_pad, block_size); |
913 | pad = active_state->extra_pad - | 925 | pad = active_state->extra_pad - |
914 | ((len + padlen) % active_state->extra_pad); | 926 | ((len + padlen) % active_state->extra_pad); |
915 | debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", | 927 | DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)", |
916 | pad, len, padlen, active_state->extra_pad); | 928 | __func__, pad, len, padlen, active_state->extra_pad)); |
917 | padlen += pad; | 929 | padlen += pad; |
918 | active_state->extra_pad = 0; | 930 | active_state->extra_pad = 0; |
919 | } | 931 | } |
@@ -1569,6 +1581,7 @@ packet_get_int64(void) | |||
1569 | * must have been initialized before this call. | 1581 | * must have been initialized before this call. |
1570 | */ | 1582 | */ |
1571 | 1583 | ||
1584 | #ifdef WITH_OPENSSL | ||
1572 | void | 1585 | void |
1573 | packet_get_bignum(BIGNUM * value) | 1586 | packet_get_bignum(BIGNUM * value) |
1574 | { | 1587 | { |
@@ -1598,6 +1611,7 @@ packet_get_raw(u_int *length_ptr) | |||
1598 | *length_ptr = bytes; | 1611 | *length_ptr = bytes; |
1599 | return buffer_ptr(&active_state->incoming_packet); | 1612 | return buffer_ptr(&active_state->incoming_packet); |
1600 | } | 1613 | } |
1614 | #endif | ||
1601 | 1615 | ||
1602 | int | 1616 | int |
1603 | packet_remaining(void) | 1617 | packet_remaining(void) |
@@ -1618,7 +1632,7 @@ packet_get_string(u_int *length_ptr) | |||
1618 | return buffer_get_string(&active_state->incoming_packet, length_ptr); | 1632 | return buffer_get_string(&active_state->incoming_packet, length_ptr); |
1619 | } | 1633 | } |
1620 | 1634 | ||
1621 | void * | 1635 | const void * |
1622 | packet_get_string_ptr(u_int *length_ptr) | 1636 | packet_get_string_ptr(u_int *length_ptr) |
1623 | { | 1637 | { |
1624 | return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr); | 1638 | return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr); |
@@ -2055,3 +2069,23 @@ packet_restore_state(void) | |||
2055 | add_recv_bytes(len); | 2069 | add_recv_bytes(len); |
2056 | } | 2070 | } |
2057 | } | 2071 | } |
2072 | |||
2073 | /* Reset after_authentication and reset compression in post-auth privsep */ | ||
2074 | void | ||
2075 | packet_set_postauth(void) | ||
2076 | { | ||
2077 | Comp *comp; | ||
2078 | int mode; | ||
2079 | |||
2080 | debug("%s: called", __func__); | ||
2081 | /* This was set in net child, but is not visible in user child */ | ||
2082 | active_state->after_authentication = 1; | ||
2083 | active_state->rekeying = 0; | ||
2084 | for (mode = 0; mode < MODE_MAX; mode++) { | ||
2085 | if (active_state->newkeys[mode] == NULL) | ||
2086 | continue; | ||
2087 | comp = &active_state->newkeys[mode]->comp; | ||
2088 | if (comp && comp->enabled) | ||
2089 | packet_init_compression(); | ||
2090 | } | ||
2091 | } | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.h,v 1.59 2013/07/12 00:19:59 djm Exp $ */ | 1 | /* $OpenBSD: packet.h,v 1.61 2014/05/03 17:20:34 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -70,7 +70,7 @@ void packet_get_ecpoint(const EC_GROUP *, EC_POINT *); | |||
70 | void *packet_get_raw(u_int *length_ptr); | 70 | void *packet_get_raw(u_int *length_ptr); |
71 | void *packet_get_string(u_int *length_ptr); | 71 | void *packet_get_string(u_int *length_ptr); |
72 | char *packet_get_cstring(u_int *length_ptr); | 72 | char *packet_get_cstring(u_int *length_ptr); |
73 | void *packet_get_string_ptr(u_int *length_ptr); | 73 | const void *packet_get_string_ptr(u_int *length_ptr); |
74 | void packet_disconnect(const char *fmt,...) __attribute__((noreturn)) __attribute__((format(printf, 1, 2))); | 74 | void packet_disconnect(const char *fmt,...) __attribute__((noreturn)) __attribute__((format(printf, 1, 2))); |
75 | void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); | 75 | void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); |
76 | 76 | ||
@@ -120,6 +120,7 @@ time_t packet_get_rekey_timeout(void); | |||
120 | 120 | ||
121 | void packet_backup_state(void); | 121 | void packet_backup_state(void); |
122 | void packet_restore_state(void); | 122 | void packet_restore_state(void); |
123 | void packet_set_postauth(void); | ||
123 | 124 | ||
124 | void *packet_get_input(void); | 125 | void *packet_get_input(void); |
125 | void *packet_get_output(void); | 126 | void *packet_get_output(void); |
diff --git a/platform.c b/platform.c index f99de7fab..9a23e6e3e 100644 --- a/platform.c +++ b/platform.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: platform.c,v 1.21 2014/01/21 01:59:29 tim Exp $ */ | 1 | /* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2006 Darren Tucker. All rights reserved. | 4 | * Copyright (c) 2006 Darren Tucker. All rights reserved. |
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include "log.h" | 26 | #include "log.h" |
27 | #include "buffer.h" | 27 | #include "buffer.h" |
28 | #include "misc.h" | ||
28 | #include "servconf.h" | 29 | #include "servconf.h" |
29 | #include "key.h" | 30 | #include "key.h" |
30 | #include "hostfile.h" | 31 | #include "hostfile.h" |
diff --git a/poly1305.h b/poly1305.h index 221efc462..f7db5f8d7 100644 --- a/poly1305.h +++ b/poly1305.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: poly1305.h,v 1.2 2013/12/19 22:57:13 djm Exp $ */ | 1 | /* $OpenBSD: poly1305.h,v 1.4 2014/05/02 03:27:54 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Public Domain poly1305 from Andrew Moon | 4 | * Public Domain poly1305 from Andrew Moon |
diff --git a/readconf.c b/readconf.c index 5429fc2ad..29338b619 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.218 2014/02/23 20:11:36 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.220 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -18,6 +18,7 @@ | |||
18 | #include <sys/stat.h> | 18 | #include <sys/stat.h> |
19 | #include <sys/socket.h> | 19 | #include <sys/socket.h> |
20 | #include <sys/wait.h> | 20 | #include <sys/wait.h> |
21 | #include <sys/un.h> | ||
21 | 22 | ||
22 | #include <netinet/in.h> | 23 | #include <netinet/in.h> |
23 | #include <netinet/in_systm.h> | 24 | #include <netinet/in_systm.h> |
@@ -50,9 +51,9 @@ | |||
50 | #include "pathnames.h" | 51 | #include "pathnames.h" |
51 | #include "log.h" | 52 | #include "log.h" |
52 | #include "key.h" | 53 | #include "key.h" |
54 | #include "misc.h" | ||
53 | #include "readconf.h" | 55 | #include "readconf.h" |
54 | #include "match.h" | 56 | #include "match.h" |
55 | #include "misc.h" | ||
56 | #include "buffer.h" | 57 | #include "buffer.h" |
57 | #include "kex.h" | 58 | #include "kex.h" |
58 | #include "mac.h" | 59 | #include "mac.h" |
@@ -153,6 +154,7 @@ typedef enum { | |||
153 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, | 154 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, |
154 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, | 155 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
155 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, | 156 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
157 | oStreamLocalBindMask, oStreamLocalBindUnlink, | ||
156 | oProtocolKeepAlives, oSetupTimeOut, | 158 | oProtocolKeepAlives, oSetupTimeOut, |
157 | oIgnoredUnknownOption, oDeprecated, oUnsupported | 159 | oIgnoredUnknownOption, oDeprecated, oUnsupported |
158 | } OpCodes; | 160 | } OpCodes; |
@@ -276,6 +278,8 @@ static struct { | |||
276 | { "canonicalizehostname", oCanonicalizeHostname }, | 278 | { "canonicalizehostname", oCanonicalizeHostname }, |
277 | { "canonicalizemaxdots", oCanonicalizeMaxDots }, | 279 | { "canonicalizemaxdots", oCanonicalizeMaxDots }, |
278 | { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, | 280 | { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, |
281 | { "streamlocalbindmask", oStreamLocalBindMask }, | ||
282 | { "streamlocalbindunlink", oStreamLocalBindUnlink }, | ||
279 | { "ignoreunknown", oIgnoreUnknown }, | 283 | { "ignoreunknown", oIgnoreUnknown }, |
280 | { "protocolkeepalives", oProtocolKeepAlives }, | 284 | { "protocolkeepalives", oProtocolKeepAlives }, |
281 | { "setuptimeout", oSetupTimeOut }, | 285 | { "setuptimeout", oSetupTimeOut }, |
@@ -289,12 +293,13 @@ static struct { | |||
289 | */ | 293 | */ |
290 | 294 | ||
291 | void | 295 | void |
292 | add_local_forward(Options *options, const Forward *newfwd) | 296 | add_local_forward(Options *options, const struct Forward *newfwd) |
293 | { | 297 | { |
294 | Forward *fwd; | 298 | struct Forward *fwd; |
295 | #ifndef NO_IPPORT_RESERVED_CONCEPT | 299 | #ifndef NO_IPPORT_RESERVED_CONCEPT |
296 | extern uid_t original_real_uid; | 300 | extern uid_t original_real_uid; |
297 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) | 301 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 && |
302 | newfwd->listen_path == NULL) | ||
298 | fatal("Privileged ports can only be forwarded by root."); | 303 | fatal("Privileged ports can only be forwarded by root."); |
299 | #endif | 304 | #endif |
300 | options->local_forwards = xrealloc(options->local_forwards, | 305 | options->local_forwards = xrealloc(options->local_forwards, |
@@ -304,8 +309,10 @@ add_local_forward(Options *options, const Forward *newfwd) | |||
304 | 309 | ||
305 | fwd->listen_host = newfwd->listen_host; | 310 | fwd->listen_host = newfwd->listen_host; |
306 | fwd->listen_port = newfwd->listen_port; | 311 | fwd->listen_port = newfwd->listen_port; |
312 | fwd->listen_path = newfwd->listen_path; | ||
307 | fwd->connect_host = newfwd->connect_host; | 313 | fwd->connect_host = newfwd->connect_host; |
308 | fwd->connect_port = newfwd->connect_port; | 314 | fwd->connect_port = newfwd->connect_port; |
315 | fwd->connect_path = newfwd->connect_path; | ||
309 | } | 316 | } |
310 | 317 | ||
311 | /* | 318 | /* |
@@ -314,9 +321,9 @@ add_local_forward(Options *options, const Forward *newfwd) | |||
314 | */ | 321 | */ |
315 | 322 | ||
316 | void | 323 | void |
317 | add_remote_forward(Options *options, const Forward *newfwd) | 324 | add_remote_forward(Options *options, const struct Forward *newfwd) |
318 | { | 325 | { |
319 | Forward *fwd; | 326 | struct Forward *fwd; |
320 | 327 | ||
321 | options->remote_forwards = xrealloc(options->remote_forwards, | 328 | options->remote_forwards = xrealloc(options->remote_forwards, |
322 | options->num_remote_forwards + 1, | 329 | options->num_remote_forwards + 1, |
@@ -325,8 +332,10 @@ add_remote_forward(Options *options, const Forward *newfwd) | |||
325 | 332 | ||
326 | fwd->listen_host = newfwd->listen_host; | 333 | fwd->listen_host = newfwd->listen_host; |
327 | fwd->listen_port = newfwd->listen_port; | 334 | fwd->listen_port = newfwd->listen_port; |
335 | fwd->listen_path = newfwd->listen_path; | ||
328 | fwd->connect_host = newfwd->connect_host; | 336 | fwd->connect_host = newfwd->connect_host; |
329 | fwd->connect_port = newfwd->connect_port; | 337 | fwd->connect_port = newfwd->connect_port; |
338 | fwd->connect_path = newfwd->connect_path; | ||
330 | fwd->handle = newfwd->handle; | 339 | fwd->handle = newfwd->handle; |
331 | fwd->allocated_port = 0; | 340 | fwd->allocated_port = 0; |
332 | } | 341 | } |
@@ -338,7 +347,9 @@ clear_forwardings(Options *options) | |||
338 | 347 | ||
339 | for (i = 0; i < options->num_local_forwards; i++) { | 348 | for (i = 0; i < options->num_local_forwards; i++) { |
340 | free(options->local_forwards[i].listen_host); | 349 | free(options->local_forwards[i].listen_host); |
350 | free(options->local_forwards[i].listen_path); | ||
341 | free(options->local_forwards[i].connect_host); | 351 | free(options->local_forwards[i].connect_host); |
352 | free(options->local_forwards[i].connect_path); | ||
342 | } | 353 | } |
343 | if (options->num_local_forwards > 0) { | 354 | if (options->num_local_forwards > 0) { |
344 | free(options->local_forwards); | 355 | free(options->local_forwards); |
@@ -347,7 +358,9 @@ clear_forwardings(Options *options) | |||
347 | options->num_local_forwards = 0; | 358 | options->num_local_forwards = 0; |
348 | for (i = 0; i < options->num_remote_forwards; i++) { | 359 | for (i = 0; i < options->num_remote_forwards; i++) { |
349 | free(options->remote_forwards[i].listen_host); | 360 | free(options->remote_forwards[i].listen_host); |
361 | free(options->remote_forwards[i].listen_path); | ||
350 | free(options->remote_forwards[i].connect_host); | 362 | free(options->remote_forwards[i].connect_host); |
363 | free(options->remote_forwards[i].connect_path); | ||
351 | } | 364 | } |
352 | if (options->num_remote_forwards > 0) { | 365 | if (options->num_remote_forwards > 0) { |
353 | free(options->remote_forwards); | 366 | free(options->remote_forwards); |
@@ -362,6 +375,7 @@ add_identity_file(Options *options, const char *dir, const char *filename, | |||
362 | int userprovided) | 375 | int userprovided) |
363 | { | 376 | { |
364 | char *path; | 377 | char *path; |
378 | int i; | ||
365 | 379 | ||
366 | if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) | 380 | if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) |
367 | fatal("Too many identity files specified (max %d)", | 381 | fatal("Too many identity files specified (max %d)", |
@@ -372,6 +386,16 @@ add_identity_file(Options *options, const char *dir, const char *filename, | |||
372 | else | 386 | else |
373 | (void)xasprintf(&path, "%.100s%.100s", dir, filename); | 387 | (void)xasprintf(&path, "%.100s%.100s", dir, filename); |
374 | 388 | ||
389 | /* Avoid registering duplicates */ | ||
390 | for (i = 0; i < options->num_identity_files; i++) { | ||
391 | if (options->identity_file_userprovided[i] == userprovided && | ||
392 | strcmp(options->identity_files[i], path) == 0) { | ||
393 | debug2("%s: ignoring duplicate key %s", __func__, path); | ||
394 | free(path); | ||
395 | return; | ||
396 | } | ||
397 | } | ||
398 | |||
375 | options->identity_file_userprovided[options->num_identity_files] = | 399 | options->identity_file_userprovided[options->num_identity_files] = |
376 | userprovided; | 400 | userprovided; |
377 | options->identity_files[options->num_identity_files++] = path; | 401 | options->identity_files[options->num_identity_files++] = path; |
@@ -721,7 +745,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
721 | LogLevel *log_level_ptr; | 745 | LogLevel *log_level_ptr; |
722 | long long val64; | 746 | long long val64; |
723 | size_t len; | 747 | size_t len; |
724 | Forward fwd; | 748 | struct Forward fwd; |
725 | const struct multistate *multistate_ptr; | 749 | const struct multistate *multistate_ptr; |
726 | struct allowed_cname *cname; | 750 | struct allowed_cname *cname; |
727 | 751 | ||
@@ -811,7 +835,7 @@ parse_time: | |||
811 | goto parse_time; | 835 | goto parse_time; |
812 | 836 | ||
813 | case oGatewayPorts: | 837 | case oGatewayPorts: |
814 | intptr = &options->gateway_ports; | 838 | intptr = &options->fwd_opts.gateway_ports; |
815 | goto parse_flag; | 839 | goto parse_flag; |
816 | 840 | ||
817 | case oExitOnForwardFailure: | 841 | case oExitOnForwardFailure: |
@@ -1433,6 +1457,21 @@ parse_int: | |||
1433 | intptr = &options->canonicalize_fallback_local; | 1457 | intptr = &options->canonicalize_fallback_local; |
1434 | goto parse_flag; | 1458 | goto parse_flag; |
1435 | 1459 | ||
1460 | case oStreamLocalBindMask: | ||
1461 | arg = strdelim(&s); | ||
1462 | if (!arg || *arg == '\0') | ||
1463 | fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); | ||
1464 | /* Parse mode in octal format */ | ||
1465 | value = strtol(arg, &endofnumber, 8); | ||
1466 | if (arg == endofnumber || value < 0 || value > 0777) | ||
1467 | fatal("%.200s line %d: Bad mask.", filename, linenum); | ||
1468 | options->fwd_opts.streamlocal_bind_mask = (mode_t)value; | ||
1469 | break; | ||
1470 | |||
1471 | case oStreamLocalBindUnlink: | ||
1472 | intptr = &options->fwd_opts.streamlocal_bind_unlink; | ||
1473 | goto parse_flag; | ||
1474 | |||
1436 | case oDeprecated: | 1475 | case oDeprecated: |
1437 | debug("%s line %d: Deprecated option \"%s\"", | 1476 | debug("%s line %d: Deprecated option \"%s\"", |
1438 | filename, linenum, keyword); | 1477 | filename, linenum, keyword); |
@@ -1529,7 +1568,9 @@ initialize_options(Options * options) | |||
1529 | options->forward_x11_timeout = -1; | 1568 | options->forward_x11_timeout = -1; |
1530 | options->exit_on_forward_failure = -1; | 1569 | options->exit_on_forward_failure = -1; |
1531 | options->xauth_location = NULL; | 1570 | options->xauth_location = NULL; |
1532 | options->gateway_ports = -1; | 1571 | options->fwd_opts.gateway_ports = -1; |
1572 | options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; | ||
1573 | options->fwd_opts.streamlocal_bind_unlink = -1; | ||
1533 | options->use_privileged_port = -1; | 1574 | options->use_privileged_port = -1; |
1534 | options->rsa_authentication = -1; | 1575 | options->rsa_authentication = -1; |
1535 | options->pubkey_authentication = -1; | 1576 | options->pubkey_authentication = -1; |
@@ -1647,8 +1688,12 @@ fill_default_options(Options * options) | |||
1647 | options->exit_on_forward_failure = 0; | 1688 | options->exit_on_forward_failure = 0; |
1648 | if (options->xauth_location == NULL) | 1689 | if (options->xauth_location == NULL) |
1649 | options->xauth_location = _PATH_XAUTH; | 1690 | options->xauth_location = _PATH_XAUTH; |
1650 | if (options->gateway_ports == -1) | 1691 | if (options->fwd_opts.gateway_ports == -1) |
1651 | options->gateway_ports = 0; | 1692 | options->fwd_opts.gateway_ports = 0; |
1693 | if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) | ||
1694 | options->fwd_opts.streamlocal_bind_mask = 0177; | ||
1695 | if (options->fwd_opts.streamlocal_bind_unlink == -1) | ||
1696 | options->fwd_opts.streamlocal_bind_unlink = 0; | ||
1652 | if (options->use_privileged_port == -1) | 1697 | if (options->use_privileged_port == -1) |
1653 | options->use_privileged_port = 0; | 1698 | options->use_privileged_port = 0; |
1654 | if (options->rsa_authentication == -1) | 1699 | if (options->rsa_authentication == -1) |
@@ -1811,22 +1856,92 @@ fill_default_options(Options * options) | |||
1811 | /* options->preferred_authentications will be set in ssh */ | 1856 | /* options->preferred_authentications will be set in ssh */ |
1812 | } | 1857 | } |
1813 | 1858 | ||
1859 | struct fwdarg { | ||
1860 | char *arg; | ||
1861 | int ispath; | ||
1862 | }; | ||
1863 | |||
1864 | /* | ||
1865 | * parse_fwd_field | ||
1866 | * parses the next field in a port forwarding specification. | ||
1867 | * sets fwd to the parsed field and advances p past the colon | ||
1868 | * or sets it to NULL at end of string. | ||
1869 | * returns 0 on success, else non-zero. | ||
1870 | */ | ||
1871 | static int | ||
1872 | parse_fwd_field(char **p, struct fwdarg *fwd) | ||
1873 | { | ||
1874 | char *ep, *cp = *p; | ||
1875 | int ispath = 0; | ||
1876 | |||
1877 | if (*cp == '\0') { | ||
1878 | *p = NULL; | ||
1879 | return -1; /* end of string */ | ||
1880 | } | ||
1881 | |||
1882 | /* | ||
1883 | * A field escaped with square brackets is used literally. | ||
1884 | * XXX - allow ']' to be escaped via backslash? | ||
1885 | */ | ||
1886 | if (*cp == '[') { | ||
1887 | /* find matching ']' */ | ||
1888 | for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { | ||
1889 | if (*ep == '/') | ||
1890 | ispath = 1; | ||
1891 | } | ||
1892 | /* no matching ']' or not at end of field. */ | ||
1893 | if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) | ||
1894 | return -1; | ||
1895 | /* NUL terminate the field and advance p past the colon */ | ||
1896 | *ep++ = '\0'; | ||
1897 | if (*ep != '\0') | ||
1898 | *ep++ = '\0'; | ||
1899 | fwd->arg = cp + 1; | ||
1900 | fwd->ispath = ispath; | ||
1901 | *p = ep; | ||
1902 | return 0; | ||
1903 | } | ||
1904 | |||
1905 | for (cp = *p; *cp != '\0'; cp++) { | ||
1906 | switch (*cp) { | ||
1907 | case '\\': | ||
1908 | memmove(cp, cp + 1, strlen(cp + 1) + 1); | ||
1909 | cp++; | ||
1910 | break; | ||
1911 | case '/': | ||
1912 | ispath = 1; | ||
1913 | break; | ||
1914 | case ':': | ||
1915 | *cp++ = '\0'; | ||
1916 | goto done; | ||
1917 | } | ||
1918 | } | ||
1919 | done: | ||
1920 | fwd->arg = *p; | ||
1921 | fwd->ispath = ispath; | ||
1922 | *p = cp; | ||
1923 | return 0; | ||
1924 | } | ||
1925 | |||
1814 | /* | 1926 | /* |
1815 | * parse_forward | 1927 | * parse_forward |
1816 | * parses a string containing a port forwarding specification of the form: | 1928 | * parses a string containing a port forwarding specification of the form: |
1817 | * dynamicfwd == 0 | 1929 | * dynamicfwd == 0 |
1818 | * [listenhost:]listenport:connecthost:connectport | 1930 | * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath |
1931 | * listenpath:connectpath | ||
1819 | * dynamicfwd == 1 | 1932 | * dynamicfwd == 1 |
1820 | * [listenhost:]listenport | 1933 | * [listenhost:]listenport |
1821 | * returns number of arguments parsed or zero on error | 1934 | * returns number of arguments parsed or zero on error |
1822 | */ | 1935 | */ |
1823 | int | 1936 | int |
1824 | parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | 1937 | parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) |
1825 | { | 1938 | { |
1939 | struct fwdarg fwdargs[4]; | ||
1940 | char *p, *cp; | ||
1826 | int i; | 1941 | int i; |
1827 | char *p, *cp, *fwdarg[4]; | ||
1828 | 1942 | ||
1829 | memset(fwd, '\0', sizeof(*fwd)); | 1943 | memset(fwd, 0, sizeof(*fwd)); |
1944 | memset(fwdargs, 0, sizeof(fwdargs)); | ||
1830 | 1945 | ||
1831 | cp = p = xstrdup(fwdspec); | 1946 | cp = p = xstrdup(fwdspec); |
1832 | 1947 | ||
@@ -1834,39 +1949,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1834 | while (isspace((u_char)*cp)) | 1949 | while (isspace((u_char)*cp)) |
1835 | cp++; | 1950 | cp++; |
1836 | 1951 | ||
1837 | for (i = 0; i < 4; ++i) | 1952 | for (i = 0; i < 4; ++i) { |
1838 | if ((fwdarg[i] = hpdelim(&cp)) == NULL) | 1953 | if (parse_fwd_field(&cp, &fwdargs[i]) != 0) |
1839 | break; | 1954 | break; |
1955 | } | ||
1840 | 1956 | ||
1841 | /* Check for trailing garbage */ | 1957 | /* Check for trailing garbage */ |
1842 | if (cp != NULL) | 1958 | if (cp != NULL && *cp != '\0') { |
1843 | i = 0; /* failure */ | 1959 | i = 0; /* failure */ |
1960 | } | ||
1844 | 1961 | ||
1845 | switch (i) { | 1962 | switch (i) { |
1846 | case 1: | 1963 | case 1: |
1847 | fwd->listen_host = NULL; | 1964 | if (fwdargs[0].ispath) { |
1848 | fwd->listen_port = a2port(fwdarg[0]); | 1965 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1966 | fwd->listen_port = PORT_STREAMLOCAL; | ||
1967 | } else { | ||
1968 | fwd->listen_host = NULL; | ||
1969 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
1970 | } | ||
1849 | fwd->connect_host = xstrdup("socks"); | 1971 | fwd->connect_host = xstrdup("socks"); |
1850 | break; | 1972 | break; |
1851 | 1973 | ||
1852 | case 2: | 1974 | case 2: |
1853 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 1975 | if (fwdargs[0].ispath && fwdargs[1].ispath) { |
1854 | fwd->listen_port = a2port(fwdarg[1]); | 1976 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1855 | fwd->connect_host = xstrdup("socks"); | 1977 | fwd->listen_port = PORT_STREAMLOCAL; |
1978 | fwd->connect_path = xstrdup(fwdargs[1].arg); | ||
1979 | fwd->connect_port = PORT_STREAMLOCAL; | ||
1980 | } else if (fwdargs[1].ispath) { | ||
1981 | fwd->listen_host = NULL; | ||
1982 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
1983 | fwd->connect_path = xstrdup(fwdargs[1].arg); | ||
1984 | fwd->connect_port = PORT_STREAMLOCAL; | ||
1985 | } else { | ||
1986 | fwd->listen_host = xstrdup(fwdargs[0].arg); | ||
1987 | fwd->listen_port = a2port(fwdargs[1].arg); | ||
1988 | fwd->connect_host = xstrdup("socks"); | ||
1989 | } | ||
1856 | break; | 1990 | break; |
1857 | 1991 | ||
1858 | case 3: | 1992 | case 3: |
1859 | fwd->listen_host = NULL; | 1993 | if (fwdargs[0].ispath) { |
1860 | fwd->listen_port = a2port(fwdarg[0]); | 1994 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1861 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); | 1995 | fwd->listen_port = PORT_STREAMLOCAL; |
1862 | fwd->connect_port = a2port(fwdarg[2]); | 1996 | fwd->connect_host = xstrdup(fwdargs[1].arg); |
1997 | fwd->connect_port = a2port(fwdargs[2].arg); | ||
1998 | } else if (fwdargs[2].ispath) { | ||
1999 | fwd->listen_host = xstrdup(fwdargs[0].arg); | ||
2000 | fwd->listen_port = a2port(fwdargs[1].arg); | ||
2001 | fwd->connect_path = xstrdup(fwdargs[2].arg); | ||
2002 | fwd->connect_port = PORT_STREAMLOCAL; | ||
2003 | } else { | ||
2004 | fwd->listen_host = NULL; | ||
2005 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
2006 | fwd->connect_host = xstrdup(fwdargs[1].arg); | ||
2007 | fwd->connect_port = a2port(fwdargs[2].arg); | ||
2008 | } | ||
1863 | break; | 2009 | break; |
1864 | 2010 | ||
1865 | case 4: | 2011 | case 4: |
1866 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 2012 | fwd->listen_host = xstrdup(fwdargs[0].arg); |
1867 | fwd->listen_port = a2port(fwdarg[1]); | 2013 | fwd->listen_port = a2port(fwdargs[1].arg); |
1868 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); | 2014 | fwd->connect_host = xstrdup(fwdargs[2].arg); |
1869 | fwd->connect_port = a2port(fwdarg[3]); | 2015 | fwd->connect_port = a2port(fwdargs[3].arg); |
1870 | break; | 2016 | break; |
1871 | default: | 2017 | default: |
1872 | i = 0; /* failure */ | 2018 | i = 0; /* failure */ |
@@ -1878,29 +2024,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1878 | if (!(i == 1 || i == 2)) | 2024 | if (!(i == 1 || i == 2)) |
1879 | goto fail_free; | 2025 | goto fail_free; |
1880 | } else { | 2026 | } else { |
1881 | if (!(i == 3 || i == 4)) | 2027 | if (!(i == 3 || i == 4)) { |
1882 | goto fail_free; | 2028 | if (fwd->connect_path == NULL && |
1883 | if (fwd->connect_port <= 0) | 2029 | fwd->listen_path == NULL) |
2030 | goto fail_free; | ||
2031 | } | ||
2032 | if (fwd->connect_port <= 0 && fwd->connect_path == NULL) | ||
1884 | goto fail_free; | 2033 | goto fail_free; |
1885 | } | 2034 | } |
1886 | 2035 | ||
1887 | if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) | 2036 | if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || |
2037 | (!remotefwd && fwd->listen_port == 0)) | ||
1888 | goto fail_free; | 2038 | goto fail_free; |
1889 | |||
1890 | if (fwd->connect_host != NULL && | 2039 | if (fwd->connect_host != NULL && |
1891 | strlen(fwd->connect_host) >= NI_MAXHOST) | 2040 | strlen(fwd->connect_host) >= NI_MAXHOST) |
1892 | goto fail_free; | 2041 | goto fail_free; |
2042 | /* XXX - if connecting to a remote socket, max sun len may not match this host */ | ||
2043 | if (fwd->connect_path != NULL && | ||
2044 | strlen(fwd->connect_path) >= PATH_MAX_SUN) | ||
2045 | goto fail_free; | ||
1893 | if (fwd->listen_host != NULL && | 2046 | if (fwd->listen_host != NULL && |
1894 | strlen(fwd->listen_host) >= NI_MAXHOST) | 2047 | strlen(fwd->listen_host) >= NI_MAXHOST) |
1895 | goto fail_free; | 2048 | goto fail_free; |
1896 | 2049 | if (fwd->listen_path != NULL && | |
2050 | strlen(fwd->listen_path) >= PATH_MAX_SUN) | ||
2051 | goto fail_free; | ||
1897 | 2052 | ||
1898 | return (i); | 2053 | return (i); |
1899 | 2054 | ||
1900 | fail_free: | 2055 | fail_free: |
1901 | free(fwd->connect_host); | 2056 | free(fwd->connect_host); |
1902 | fwd->connect_host = NULL; | 2057 | fwd->connect_host = NULL; |
2058 | free(fwd->connect_path); | ||
2059 | fwd->connect_path = NULL; | ||
1903 | free(fwd->listen_host); | 2060 | free(fwd->listen_host); |
1904 | fwd->listen_host = NULL; | 2061 | fwd->listen_host = NULL; |
2062 | free(fwd->listen_path); | ||
2063 | fwd->listen_path = NULL; | ||
1905 | return (0); | 2064 | return (0); |
1906 | } | 2065 | } |
diff --git a/readconf.h b/readconf.h index 5cc97f0da..0e298898a 100644 --- a/readconf.h +++ b/readconf.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */ | 1 | /* $OpenBSD: readconf.h,v 1.102 2014/07/15 15:54:14 millert Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -16,21 +16,12 @@ | |||
16 | #ifndef READCONF_H | 16 | #ifndef READCONF_H |
17 | #define READCONF_H | 17 | #define READCONF_H |
18 | 18 | ||
19 | /* Data structure for representing a forwarding request. */ | ||
20 | |||
21 | typedef struct { | ||
22 | char *listen_host; /* Host (address) to listen on. */ | ||
23 | int listen_port; /* Port to forward. */ | ||
24 | char *connect_host; /* Host to connect. */ | ||
25 | int connect_port; /* Port to connect on connect_host. */ | ||
26 | int allocated_port; /* Dynamically allocated listen port */ | ||
27 | int handle; /* Handle for dynamic listen ports */ | ||
28 | } Forward; | ||
29 | /* Data structure for representing option data. */ | 19 | /* Data structure for representing option data. */ |
30 | 20 | ||
31 | #define MAX_SEND_ENV 256 | 21 | #define MAX_SEND_ENV 256 |
32 | #define SSH_MAX_HOSTS_FILES 32 | 22 | #define SSH_MAX_HOSTS_FILES 32 |
33 | #define MAX_CANON_DOMAINS 32 | 23 | #define MAX_CANON_DOMAINS 32 |
24 | #define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path) | ||
34 | 25 | ||
35 | struct allowed_cname { | 26 | struct allowed_cname { |
36 | char *source_list; | 27 | char *source_list; |
@@ -44,7 +35,7 @@ typedef struct { | |||
44 | int forward_x11_trusted; /* Trust Forward X11 display. */ | 35 | int forward_x11_trusted; /* Trust Forward X11 display. */ |
45 | int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ | 36 | int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ |
46 | char *xauth_location; /* Location for xauth program */ | 37 | char *xauth_location; /* Location for xauth program */ |
47 | int gateway_ports; /* Allow remote connects to forwarded ports. */ | 38 | struct ForwardOptions fwd_opts; /* forwarding options */ |
48 | int use_privileged_port; /* Don't use privileged port if false. */ | 39 | int use_privileged_port; /* Don't use privileged port if false. */ |
49 | int rhosts_rsa_authentication; /* Try rhosts with RSA | 40 | int rhosts_rsa_authentication; /* Try rhosts with RSA |
50 | * authentication. */ | 41 | * authentication. */ |
@@ -111,11 +102,11 @@ typedef struct { | |||
111 | 102 | ||
112 | /* Local TCP/IP forward requests. */ | 103 | /* Local TCP/IP forward requests. */ |
113 | int num_local_forwards; | 104 | int num_local_forwards; |
114 | Forward *local_forwards; | 105 | struct Forward *local_forwards; |
115 | 106 | ||
116 | /* Remote TCP/IP forward requests. */ | 107 | /* Remote TCP/IP forward requests. */ |
117 | int num_remote_forwards; | 108 | int num_remote_forwards; |
118 | Forward *remote_forwards; | 109 | struct Forward *remote_forwards; |
119 | int clear_forwardings; | 110 | int clear_forwardings; |
120 | 111 | ||
121 | int enable_ssh_keysign; | 112 | int enable_ssh_keysign; |
@@ -186,12 +177,12 @@ int process_config_line(Options *, struct passwd *, const char *, char *, | |||
186 | const char *, int, int *, int); | 177 | const char *, int, int *, int); |
187 | int read_config_file(const char *, struct passwd *, const char *, | 178 | int read_config_file(const char *, struct passwd *, const char *, |
188 | Options *, int); | 179 | Options *, int); |
189 | int parse_forward(Forward *, const char *, int, int); | 180 | int parse_forward(struct Forward *, const char *, int, int); |
190 | int default_ssh_port(void); | 181 | int default_ssh_port(void); |
191 | int option_clear_or_none(const char *); | 182 | int option_clear_or_none(const char *); |
192 | 183 | ||
193 | void add_local_forward(Options *, const Forward *); | 184 | void add_local_forward(Options *, const struct Forward *); |
194 | void add_remote_forward(Options *, const Forward *); | 185 | void add_remote_forward(Options *, const struct Forward *); |
195 | void add_identity_file(Options *, const char *, const char *, int); | 186 | void add_identity_file(Options *, const char *, const char *, int); |
196 | 187 | ||
197 | #endif /* READCONF_H */ | 188 | #endif /* READCONF_H */ |
diff --git a/regress/Makefile b/regress/Makefile index 6e3b8d634..3feb7a997 100644 --- a/regress/Makefile +++ b/regress/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # $OpenBSD: Makefile,v 1.68 2014/01/25 04:35:32 dtucker Exp $ | 1 | # $OpenBSD: Makefile,v 1.70 2014/06/24 01:14:17 djm Exp $ |
2 | 2 | ||
3 | REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec | 3 | REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec |
4 | tests: $(REGRESS_TARGETS) | 4 | tests: $(REGRESS_TARGETS) |
5 | 5 | ||
6 | # Interop tests are not run by default | 6 | # Interop tests are not run by default |
@@ -180,3 +180,11 @@ t-exec-interop: ${INTEROP_TESTS:=.sh} | |||
180 | 180 | ||
181 | # Not run by default | 181 | # Not run by default |
182 | interop: ${INTEROP_TARGETS} | 182 | interop: ${INTEROP_TARGETS} |
183 | |||
184 | # Unit tests, built by top-level Makefile | ||
185 | unit: | ||
186 | set -e ; if test -z "${SKIP_UNIT}" ; then \ | ||
187 | ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ | ||
188 | ${.OBJDIR}/unittests/sshkey/test_sshkey \ | ||
189 | -d ${.CURDIR}//unittests/sshkey/testdata ; \ | ||
190 | fi | ||
diff --git a/regress/connect-privsep.sh b/regress/connect-privsep.sh index 94cc64acf..41cb7af69 100644 --- a/regress/connect-privsep.sh +++ b/regress/connect-privsep.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: connect-privsep.sh,v 1.4 2012/07/02 14:37:06 dtucker Exp $ | 1 | # $OpenBSD: connect-privsep.sh,v 1.5 2014/05/04 10:40:59 logan Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="proxy connect with privsep" | 4 | tid="proxy connect with privsep" |
@@ -26,7 +26,7 @@ done | |||
26 | 26 | ||
27 | # Because sandbox is sensitive to changes in libc, especially malloc, retest | 27 | # Because sandbox is sensitive to changes in libc, especially malloc, retest |
28 | # with every malloc.conf option (and none). | 28 | # with every malloc.conf option (and none). |
29 | for m in '' A F G H J P R S X Z '<' '>'; do | 29 | for m in '' A F G H J P R S X '<' '>'; do |
30 | for p in 1 2; do | 30 | for p in 1 2; do |
31 | env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true | 31 | env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true |
32 | if [ $? -ne 0 ]; then | 32 | if [ $? -ne 0 ]; then |
diff --git a/regress/dhgex.sh b/regress/dhgex.sh index 4c1a3d83c..57fca4a32 100644 --- a/regress/dhgex.sh +++ b/regress/dhgex.sh | |||
@@ -1,10 +1,11 @@ | |||
1 | # $OpenBSD: dhgex.sh,v 1.1 2014/01/25 04:35:32 dtucker Exp $ | 1 | # $OpenBSD: dhgex.sh,v 1.2 2014/04/21 22:15:37 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="dhgex" | 4 | tid="dhgex" |
5 | 5 | ||
6 | LOG=${TEST_SSH_LOGFILE} | 6 | LOG=${TEST_SSH_LOGFILE} |
7 | rm -f ${LOG} | 7 | rm -f ${LOG} |
8 | cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak | ||
8 | 9 | ||
9 | kexs=`${SSH} -Q kex | grep diffie-hellman-group-exchange` | 10 | kexs=`${SSH} -Q kex | grep diffie-hellman-group-exchange` |
10 | 11 | ||
@@ -14,6 +15,9 @@ ssh_test_dhgex() | |||
14 | cipher="$1"; shift | 15 | cipher="$1"; shift |
15 | kex="$1"; shift | 16 | kex="$1"; shift |
16 | 17 | ||
18 | cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy | ||
19 | echo "KexAlgorithms=$kex" >> $OBJ/sshd_proxy | ||
20 | echo "Ciphers=$cipher" >> $OBJ/sshd_proxy | ||
17 | rm -f ${LOG} | 21 | rm -f ${LOG} |
18 | opts="-oKexAlgorithms=$kex -oCiphers=$cipher" | 22 | opts="-oKexAlgorithms=$kex -oCiphers=$cipher" |
19 | groupsz="1024<$bits<8192" | 23 | groupsz="1024<$bits<8192" |
diff --git a/regress/forwarding.sh b/regress/forwarding.sh index 94873f22c..f799d4951 100644 --- a/regress/forwarding.sh +++ b/regress/forwarding.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: forwarding.sh,v 1.11 2013/06/10 21:56:43 dtucker Exp $ | 1 | # $OpenBSD: forwarding.sh,v 1.12 2014/07/15 15:54:15 millert Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="local and remote forwarding" | 4 | tid="local and remote forwarding" |
@@ -28,7 +28,7 @@ for p in 1 2; do | |||
28 | trace "transfer over forwarded channels and check result" | 28 | trace "transfer over forwarded channels and check result" |
29 | ${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \ | 29 | ${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \ |
30 | somehost cat ${DATA} > ${COPY} | 30 | somehost cat ${DATA} > ${COPY} |
31 | test -f ${COPY} || fail "failed copy of ${DATA}" | 31 | test -s ${COPY} || fail "failed copy of ${DATA}" |
32 | cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" | 32 | cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" |
33 | 33 | ||
34 | sleep 10 | 34 | sleep 10 |
@@ -114,8 +114,24 @@ for p in 1 2; do | |||
114 | trace "config file: transfer over forwarded channels and check result" | 114 | trace "config file: transfer over forwarded channels and check result" |
115 | ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \ | 115 | ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \ |
116 | somehost cat ${DATA} > ${COPY} | 116 | somehost cat ${DATA} > ${COPY} |
117 | test -f ${COPY} || fail "failed copy of ${DATA}" | 117 | test -s ${COPY} || fail "failed copy of ${DATA}" |
118 | cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" | 118 | cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" |
119 | 119 | ||
120 | wait | 120 | wait |
121 | done | 121 | done |
122 | |||
123 | for p in 2; do | ||
124 | trace "transfer over chained unix domain socket forwards and check result" | ||
125 | rm -f $OBJ/unix-[123].fwd | ||
126 | ${SSH} -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost sleep 10 | ||
127 | ${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost sleep 10 | ||
128 | ${SSH} -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost sleep 10 | ||
129 | ${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost sleep 10 | ||
130 | ${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=4' \ | ||
131 | somehost cat ${DATA} > ${COPY} | ||
132 | test -s ${COPY} || fail "failed copy ${DATA}" | ||
133 | cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" | ||
134 | |||
135 | #wait | ||
136 | sleep 10 | ||
137 | done | ||
diff --git a/regress/integrity.sh b/regress/integrity.sh index 852d82690..d3a489ff7 100644 --- a/regress/integrity.sh +++ b/regress/integrity.sh | |||
@@ -1,7 +1,8 @@ | |||
1 | # $OpenBSD: integrity.sh,v 1.12 2013/11/21 03:18:51 djm Exp $ | 1 | # $OpenBSD: integrity.sh,v 1.14 2014/05/21 07:04:21 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="integrity" | 4 | tid="integrity" |
5 | cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak | ||
5 | 6 | ||
6 | # start at byte 2900 (i.e. after kex) and corrupt at different offsets | 7 | # start at byte 2900 (i.e. after kex) and corrupt at different offsets |
7 | # XXX the test hangs if we modify the low bytes of the packet length | 8 | # XXX the test hangs if we modify the low bytes of the packet length |
@@ -34,11 +35,15 @@ for m in $macs; do | |||
34 | # avoid modifying the high bytes of the length | 35 | # avoid modifying the high bytes of the length |
35 | continue | 36 | continue |
36 | fi | 37 | fi |
38 | cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy | ||
37 | # modify output from sshd at offset $off | 39 | # modify output from sshd at offset $off |
38 | pxy="proxycommand=$cmd | $OBJ/modpipe -wm xor:$off:1" | 40 | pxy="proxycommand=$cmd | $OBJ/modpipe -wm xor:$off:1" |
39 | if ssh -Q cipher-auth | grep "^${m}\$" >/dev/null 2>&1 ; then | 41 | if ssh -Q cipher-auth | grep "^${m}\$" >/dev/null 2>&1 ; then |
42 | echo "Ciphers=$m" >> $OBJ/sshd_proxy | ||
40 | macopt="-c $m" | 43 | macopt="-c $m" |
41 | else | 44 | else |
45 | echo "Ciphers=aes128-ctr" >> $OBJ/sshd_proxy | ||
46 | echo "MACs=$m" >> $OBJ/sshd_proxy | ||
42 | macopt="-m $m -c aes128-ctr" | 47 | macopt="-m $m -c aes128-ctr" |
43 | fi | 48 | fi |
44 | verbose "test $tid: $m @$off" | 49 | verbose "test $tid: $m @$off" |
@@ -49,14 +54,14 @@ for m in $macs; do | |||
49 | fail "ssh -m $m succeeds with bit-flip at $off" | 54 | fail "ssh -m $m succeeds with bit-flip at $off" |
50 | fi | 55 | fi |
51 | ecnt=`expr $ecnt + 1` | 56 | ecnt=`expr $ecnt + 1` |
52 | output=$(tail -2 $TEST_SSH_LOGFILE | egrep -v "^debug" | \ | 57 | out=$(tail -2 $TEST_SSH_LOGFILE | egrep -v "^debug" | \ |
53 | tr -s '\r\n' '.') | 58 | tr -s '\r\n' '.') |
54 | case "$output" in | 59 | case "$out" in |
55 | Bad?packet*) elen=`expr $elen + 1`; skip=3;; | 60 | Bad?packet*) elen=`expr $elen + 1`; skip=3;; |
56 | Corrupted?MAC* | Decryption?integrity?check?failed*) | 61 | Corrupted?MAC* | Decryption?integrity?check?failed*) |
57 | emac=`expr $emac + 1`; skip=0;; | 62 | emac=`expr $emac + 1`; skip=0;; |
58 | padding*) epad=`expr $epad + 1`; skip=0;; | 63 | padding*) epad=`expr $epad + 1`; skip=0;; |
59 | *) fail "unexpected error mac $m at $off";; | 64 | *) fail "unexpected error mac $m at $off: $out";; |
60 | esac | 65 | esac |
61 | done | 66 | done |
62 | verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen" | 67 | verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen" |
diff --git a/regress/kextype.sh b/regress/kextype.sh index 8c2ac09d6..6f952f4e4 100644 --- a/regress/kextype.sh +++ b/regress/kextype.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: kextype.sh,v 1.4 2013/11/07 04:26:56 dtucker Exp $ | 1 | # $OpenBSD: kextype.sh,v 1.5 2014/04/21 22:15:37 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="login with different key exchange algorithms" | 4 | tid="login with different key exchange algorithms" |
@@ -7,6 +7,11 @@ TIME=/usr/bin/time | |||
7 | cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak | 7 | cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak |
8 | cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak | 8 | cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak |
9 | 9 | ||
10 | # Make server accept all key exchanges. | ||
11 | ALLKEX=`ssh -Q kex` | ||
12 | KEXOPT=`echo $ALLKEX | tr ' ' ,` | ||
13 | echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy | ||
14 | |||
10 | tries="1 2 3 4" | 15 | tries="1 2 3 4" |
11 | for k in `${SSH} -Q kex`; do | 16 | for k in `${SSH} -Q kex`; do |
12 | verbose "kex $k" | 17 | verbose "kex $k" |
diff --git a/regress/krl.sh b/regress/krl.sh index 09246371c..287384b4a 100644 --- a/regress/krl.sh +++ b/regress/krl.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: krl.sh,v 1.2 2013/11/21 03:15:46 djm Exp $ | 1 | # $OpenBSD: krl.sh,v 1.3 2014/06/24 01:04:43 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="key revocation lists" | 4 | tid="key revocation lists" |
@@ -37,6 +37,9 @@ serial: 700-797 | |||
37 | serial: 798 | 37 | serial: 798 |
38 | serial: 799 | 38 | serial: 799 |
39 | serial: 599-701 | 39 | serial: 599-701 |
40 | # Some multiple consecutive serial number ranges | ||
41 | serial: 10000-20000 | ||
42 | serial: 30000-40000 | ||
40 | EOF | 43 | EOF |
41 | 44 | ||
42 | # A specification that revokes some certificated by key ID. | 45 | # A specification that revokes some certificated by key ID. |
diff --git a/regress/login-timeout.sh b/regress/login-timeout.sh index d9b48f391..eb76f554b 100644 --- a/regress/login-timeout.sh +++ b/regress/login-timeout.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: login-timeout.sh,v 1.6 2014/02/27 20:04:16 djm Exp $ | 1 | # $OpenBSD: login-timeout.sh,v 1.7 2014/03/13 20:44:49 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="connect after login grace timeout" | 4 | tid="connect after login grace timeout" |
@@ -22,6 +22,7 @@ $SUDO kill `$SUDO cat $PIDFILE` | |||
22 | trace "test login grace without privsep" | 22 | trace "test login grace without privsep" |
23 | echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config | 23 | echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config |
24 | start_sshd | 24 | start_sshd |
25 | sleep 1 | ||
25 | 26 | ||
26 | (echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & | 27 | (echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & |
27 | sleep 15 | 28 | sleep 15 |
diff --git a/regress/multiplex.sh b/regress/multiplex.sh index 3e697e691..8ee140be6 100644 --- a/regress/multiplex.sh +++ b/regress/multiplex.sh | |||
@@ -1,10 +1,26 @@ | |||
1 | # $OpenBSD: multiplex.sh,v 1.21 2013/05/17 04:29:14 dtucker Exp $ | 1 | # $OpenBSD: multiplex.sh,v 1.25 2014/07/22 01:32:12 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | CTL=/tmp/openssh.regress.ctl-sock.$$ | 4 | CTL=/tmp/openssh.regress.ctl-sock.$$ |
5 | 5 | ||
6 | tid="connection multiplexing" | 6 | tid="connection multiplexing" |
7 | 7 | ||
8 | if have_prog nc ; then | ||
9 | if nc -h 2>&1 | grep -- -N >/dev/null; then | ||
10 | NC="nc -N"; | ||
11 | elif nc -h 2>&1 | grep -- "-U.*Use UNIX" >/dev/null ; then | ||
12 | NC="nc" | ||
13 | else | ||
14 | echo "nc is incompatible" | ||
15 | fi | ||
16 | fi | ||
17 | |||
18 | if test -z "$NC" ; then | ||
19 | echo "skipped (no compatible nc found)" | ||
20 | exit 0 | ||
21 | fi | ||
22 | |||
23 | trace "will use ProxyCommand $proxycmd" | ||
8 | if config_defined DISABLE_FD_PASSING ; then | 24 | if config_defined DISABLE_FD_PASSING ; then |
9 | echo "skipped (not supported on this platform)" | 25 | echo "skipped (not supported on this platform)" |
10 | exit 0 | 26 | exit 0 |
@@ -29,7 +45,8 @@ start_mux_master() | |||
29 | trace "start master, fork to background" | 45 | trace "start master, fork to background" |
30 | ${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \ | 46 | ${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \ |
31 | -E $TEST_REGRESS_LOGFILE 2>&1 & | 47 | -E $TEST_REGRESS_LOGFILE 2>&1 & |
32 | MASTER_PID=$! | 48 | # NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors. |
49 | SSH_PID=$! | ||
33 | wait_for_mux_master_ready | 50 | wait_for_mux_master_ready |
34 | } | 51 | } |
35 | 52 | ||
@@ -71,6 +88,25 @@ test -f ${COPY} || fail "scp: failed copy ${DATA}" | |||
71 | cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}" | 88 | cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}" |
72 | 89 | ||
73 | rm -f ${COPY} | 90 | rm -f ${COPY} |
91 | verbose "test $tid: forward" | ||
92 | trace "forward over TCP/IP and check result" | ||
93 | $NC -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} & | ||
94 | netcat_pid=$! | ||
95 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1 | ||
96 | $NC -d 127.0.0.1 $((${PORT} + 2)) > ${COPY} < /dev/null | ||
97 | cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" | ||
98 | kill $netcat_pid 2>/dev/null | ||
99 | rm -f ${COPY} $OBJ/unix-[123].fwd | ||
100 | |||
101 | trace "forward over UNIX and check result" | ||
102 | $NC -Ul $OBJ/unix-1.fwd < ${DATA} & | ||
103 | netcat_pid=$! | ||
104 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 | ||
105 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 | ||
106 | $NC -d -U $OBJ/unix-3.fwd > ${COPY} </dev/null | ||
107 | cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" | ||
108 | kill $netcat_pid 2>/dev/null | ||
109 | rm -f ${COPY} $OBJ/unix-[123].fwd | ||
74 | 110 | ||
75 | for s in 0 1 4 5 44; do | 111 | for s in 0 1 4 5 44; do |
76 | trace "exit status $s over multiplexed connection" | 112 | trace "exit status $s over multiplexed connection" |
@@ -95,7 +131,7 @@ verbose "test $tid: cmd check" | |||
95 | ${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ | 131 | ${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ |
96 | || fail "check command failed" | 132 | || fail "check command failed" |
97 | 133 | ||
98 | verbose "test $tid: cmd forward local" | 134 | verbose "test $tid: cmd forward local (TCP)" |
99 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \ | 135 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \ |
100 | || fail "request local forward failed" | 136 | || fail "request local forward failed" |
101 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ | 137 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ |
@@ -105,7 +141,7 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \ | |||
105 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ | 141 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ |
106 | && fail "local forward port still listening" | 142 | && fail "local forward port still listening" |
107 | 143 | ||
108 | verbose "test $tid: cmd forward remote" | 144 | verbose "test $tid: cmd forward remote (TCP)" |
109 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \ | 145 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \ |
110 | || fail "request remote forward failed" | 146 | || fail "request remote forward failed" |
111 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ | 147 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ |
@@ -115,13 +151,35 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \ | |||
115 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ | 151 | ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ |
116 | && fail "remote forward port still listening" | 152 | && fail "remote forward port still listening" |
117 | 153 | ||
154 | verbose "test $tid: cmd forward local (UNIX)" | ||
155 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \ | ||
156 | || fail "request local forward failed" | ||
157 | echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \ | ||
158 | || fail "connect to local forward path failed" | ||
159 | ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \ | ||
160 | || fail "cancel local forward failed" | ||
161 | N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l) | ||
162 | test ${N} -eq 0 || fail "local forward path still listening" | ||
163 | rm -f $OBJ/unix-1.fwd | ||
164 | |||
165 | verbose "test $tid: cmd forward remote (UNIX)" | ||
166 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \ | ||
167 | || fail "request remote forward failed" | ||
168 | echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \ | ||
169 | || fail "connect to remote forwarded path failed" | ||
170 | ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \ | ||
171 | || fail "cancel remote forward failed" | ||
172 | N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l) | ||
173 | test ${N} -eq 0 || fail "remote forward path still listening" | ||
174 | rm -f $OBJ/unix-1.fwd | ||
175 | |||
118 | verbose "test $tid: cmd exit" | 176 | verbose "test $tid: cmd exit" |
119 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ | 177 | ${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ |
120 | || fail "send exit command failed" | 178 | || fail "send exit command failed" |
121 | 179 | ||
122 | # Wait for master to exit | 180 | # Wait for master to exit |
123 | wait $MASTER_PID | 181 | wait $SSH_PID |
124 | kill -0 $MASTER_PID >/dev/null 2>&1 && fail "exit command failed" | 182 | kill -0 $SSH_PID >/dev/null 2>&1 && fail "exit command failed" |
125 | 183 | ||
126 | # Restart master and test -O stop command with master using -N | 184 | # Restart master and test -O stop command with master using -N |
127 | verbose "test $tid: cmd stop" | 185 | verbose "test $tid: cmd stop" |
@@ -138,6 +196,8 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 | |||
138 | # wait until both long-running command and master have exited. | 196 | # wait until both long-running command and master have exited. |
139 | wait $SLEEP_PID | 197 | wait $SLEEP_PID |
140 | [ $! != 0 ] || fail "waiting for concurrent command" | 198 | [ $! != 0 ] || fail "waiting for concurrent command" |
141 | wait $MASTER_PID | 199 | wait $SSH_PID |
142 | [ $! != 0 ] || fail "waiting for master stop" | 200 | [ $! != 0 ] || fail "waiting for master stop" |
143 | kill -0 $MASTER_PID >/dev/null 2>&1 && fail "stop command failed" | 201 | kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed" |
202 | SSH_PID="" # Already gone, so don't kill in cleanup | ||
203 | |||
diff --git a/regress/proxy-connect.sh b/regress/proxy-connect.sh index 76e602dd6..023ba7367 100644 --- a/regress/proxy-connect.sh +++ b/regress/proxy-connect.sh | |||
@@ -1,26 +1,31 @@ | |||
1 | # $OpenBSD: proxy-connect.sh,v 1.6 2013/03/07 00:20:34 djm Exp $ | 1 | # $OpenBSD: proxy-connect.sh,v 1.7 2014/05/03 18:46:14 dtucker Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="proxy connect" | 4 | tid="proxy connect" |
5 | 5 | ||
6 | verbose "plain username" | 6 | mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig |
7 | for p in 1 2; do | 7 | |
8 | ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true | 8 | for ps in no yes; do |
9 | if [ $? -ne 0 ]; then | 9 | cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy |
10 | fail "ssh proxyconnect protocol $p failed" | 10 | echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy |
11 | fi | 11 | |
12 | SSH_CONNECTION=`${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 'echo $SSH_CONNECTION'` | 12 | for p in 1 2; do |
13 | for c in no yes; do | ||
14 | verbose "plain username protocol $p privsep=$ps comp=$c" | ||
15 | opts="-$p -oCompression=$c -F $OBJ/ssh_proxy" | ||
16 | SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'` | ||
13 | if [ $? -ne 0 ]; then | 17 | if [ $? -ne 0 ]; then |
14 | fail "ssh proxyconnect protocol $p failed" | 18 | fail "ssh proxyconnect protocol $p privsep=$ps comp=$c failed" |
15 | fi | 19 | fi |
16 | if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then | 20 | if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then |
17 | fail "bad SSH_CONNECTION" | 21 | fail "bad SSH_CONNECTION protocol $p privsep=$ps comp=$c" |
18 | fi | 22 | fi |
23 | done | ||
24 | done | ||
19 | done | 25 | done |
20 | 26 | ||
21 | verbose "username with style" | ||
22 | for p in 1 2; do | 27 | for p in 1 2; do |
28 | verbose "username with style protocol $p" | ||
23 | ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ | 29 | ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ |
24 | fail "ssh proxyconnect protocol $p failed" | 30 | fail "ssh proxyconnect protocol $p failed" |
25 | done | 31 | done |
26 | |||
diff --git a/regress/rekey.sh b/regress/rekey.sh index cf9401ea0..fd452b034 100644 --- a/regress/rekey.sh +++ b/regress/rekey.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: rekey.sh,v 1.14 2013/11/21 03:18:51 djm Exp $ | 1 | # $OpenBSD: rekey.sh,v 1.15 2014/04/21 22:15:37 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="rekey" | 4 | tid="rekey" |
@@ -6,14 +6,22 @@ tid="rekey" | |||
6 | LOG=${TEST_SSH_LOGFILE} | 6 | LOG=${TEST_SSH_LOGFILE} |
7 | 7 | ||
8 | rm -f ${LOG} | 8 | rm -f ${LOG} |
9 | cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak | ||
9 | 10 | ||
10 | # Test rekeying based on data volume only. | 11 | # Test rekeying based on data volume only. |
11 | # Arguments will be passed to ssh. | 12 | # Arguments will be passed to ssh. |
12 | ssh_data_rekeying() | 13 | ssh_data_rekeying() |
13 | { | 14 | { |
15 | _kexopt=$1 ; shift | ||
16 | _opts="$@" | ||
17 | if ! test -z "$_kexopts" ; then | ||
18 | cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy | ||
19 | echo "$_kexopt" >> $OBJ/sshd_proxy | ||
20 | _opts="$_opts -o$_kexopt" | ||
21 | fi | ||
14 | rm -f ${COPY} ${LOG} | 22 | rm -f ${COPY} ${LOG} |
15 | ${SSH} <${DATA} -oCompression=no $@ -v -F $OBJ/ssh_proxy somehost \ | 23 | _opts="$_opts -oCompression=no" |
16 | "cat > ${COPY}" | 24 | ${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}" |
17 | if [ $? -ne 0 ]; then | 25 | if [ $? -ne 0 ]; then |
18 | fail "ssh failed ($@)" | 26 | fail "ssh failed ($@)" |
19 | fi | 27 | fi |
@@ -41,7 +49,7 @@ done | |||
41 | 49 | ||
42 | for opt in $opts; do | 50 | for opt in $opts; do |
43 | verbose "client rekey $opt" | 51 | verbose "client rekey $opt" |
44 | ssh_data_rekeying -oRekeyLimit=256k -o$opt | 52 | ssh_data_rekeying "$opt" -oRekeyLimit=256k |
45 | done | 53 | done |
46 | 54 | ||
47 | # AEAD ciphers are magical so test with all KexAlgorithms | 55 | # AEAD ciphers are magical so test with all KexAlgorithms |
@@ -49,14 +57,14 @@ if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then | |||
49 | for c in `${SSH} -Q cipher-auth`; do | 57 | for c in `${SSH} -Q cipher-auth`; do |
50 | for kex in `${SSH} -Q kex`; do | 58 | for kex in `${SSH} -Q kex`; do |
51 | verbose "client rekey $c $kex" | 59 | verbose "client rekey $c $kex" |
52 | ssh_data_rekeying -oRekeyLimit=256k -oCiphers=$c -oKexAlgorithms=$kex | 60 | ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c |
53 | done | 61 | done |
54 | done | 62 | done |
55 | fi | 63 | fi |
56 | 64 | ||
57 | for s in 16 1k 128k 256k; do | 65 | for s in 16 1k 128k 256k; do |
58 | verbose "client rekeylimit ${s}" | 66 | verbose "client rekeylimit ${s}" |
59 | ssh_data_rekeying -oCompression=no -oRekeyLimit=$s | 67 | ssh_data_rekeying "" -oCompression=no -oRekeyLimit=$s |
60 | done | 68 | done |
61 | 69 | ||
62 | for s in 5 10; do | 70 | for s in 5 10; do |
diff --git a/regress/test-exec.sh b/regress/test-exec.sh index aac8aa5c2..a1bab832f 100644 --- a/regress/test-exec.sh +++ b/regress/test-exec.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: test-exec.sh,v 1.47 2013/11/09 05:41:34 dtucker Exp $ | 1 | # $OpenBSD: test-exec.sh,v 1.48 2014/07/06 07:42:03 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | #SUDO=sudo | 4 | #SUDO=sudo |
@@ -240,13 +240,20 @@ md5 () { | |||
240 | # helper | 240 | # helper |
241 | cleanup () | 241 | cleanup () |
242 | { | 242 | { |
243 | if [ "x$SSH_PID" != "x" ]; then | ||
244 | if [ $SSH_PID -lt 2 ]; then | ||
245 | echo bad pid for ssh: $SSH_PID | ||
246 | else | ||
247 | kill $SSH_PID | ||
248 | fi | ||
249 | fi | ||
243 | if [ -f $PIDFILE ]; then | 250 | if [ -f $PIDFILE ]; then |
244 | pid=`$SUDO cat $PIDFILE` | 251 | pid=`$SUDO cat $PIDFILE` |
245 | if [ "X$pid" = "X" ]; then | 252 | if [ "X$pid" = "X" ]; then |
246 | echo no sshd running | 253 | echo no sshd running |
247 | else | 254 | else |
248 | if [ $pid -lt 2 ]; then | 255 | if [ $pid -lt 2 ]; then |
249 | echo bad pid for ssh: $pid | 256 | echo bad pid for sshd: $pid |
250 | else | 257 | else |
251 | $SUDO kill $pid | 258 | $SUDO kill $pid |
252 | trace "wait for sshd to exit" | 259 | trace "wait for sshd to exit" |
diff --git a/regress/try-ciphers.sh b/regress/try-ciphers.sh index ac34cedbf..2881ce16c 100644 --- a/regress/try-ciphers.sh +++ b/regress/try-ciphers.sh | |||
@@ -1,13 +1,18 @@ | |||
1 | # $OpenBSD: try-ciphers.sh,v 1.22 2013/11/21 03:18:51 djm Exp $ | 1 | # $OpenBSD: try-ciphers.sh,v 1.23 2014/04/21 22:15:37 djm Exp $ |
2 | # Placed in the Public Domain. | 2 | # Placed in the Public Domain. |
3 | 3 | ||
4 | tid="try ciphers" | 4 | tid="try ciphers" |
5 | 5 | ||
6 | cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak | ||
7 | |||
6 | for c in `${SSH} -Q cipher`; do | 8 | for c in `${SSH} -Q cipher`; do |
7 | n=0 | 9 | n=0 |
8 | for m in `${SSH} -Q mac`; do | 10 | for m in `${SSH} -Q mac`; do |
9 | trace "proto 2 cipher $c mac $m" | 11 | trace "proto 2 cipher $c mac $m" |
10 | verbose "test $tid: proto 2 cipher $c mac $m" | 12 | verbose "test $tid: proto 2 cipher $c mac $m" |
13 | cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy | ||
14 | echo "Ciphers=$c" >> $OBJ/sshd_proxy | ||
15 | echo "MACs=$m" >> $OBJ/sshd_proxy | ||
11 | ${SSH} -F $OBJ/ssh_proxy -2 -m $m -c $c somehost true | 16 | ${SSH} -F $OBJ/ssh_proxy -2 -m $m -c $c somehost true |
12 | if [ $? -ne 0 ]; then | 17 | if [ $? -ne 0 ]; then |
13 | fail "ssh -2 failed with mac $m cipher $c" | 18 | fail "ssh -2 failed with mac $m cipher $c" |
diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile new file mode 100644 index 000000000..bdb4574e2 --- /dev/null +++ b/regress/unittests/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $ | ||
2 | |||
3 | SUBDIR= test_helper sshbuf sshkey | ||
4 | |||
5 | .include <bsd.subdir.mk> | ||
diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc new file mode 100644 index 000000000..4c3363749 --- /dev/null +++ b/regress/unittests/Makefile.inc | |||
@@ -0,0 +1,59 @@ | |||
1 | # $OpenBSD: Makefile.inc,v 1.1 2014/04/30 05:32:00 djm Exp $ | ||
2 | |||
3 | .include <bsd.own.mk> | ||
4 | .include <bsd.obj.mk> | ||
5 | |||
6 | # enable warnings | ||
7 | WARNINGS=Yes | ||
8 | |||
9 | DEBUG=-g | ||
10 | CFLAGS+= -fstack-protector-all | ||
11 | CDIAGFLAGS= -Wall | ||
12 | CDIAGFLAGS+= -Wextra | ||
13 | CDIAGFLAGS+= -Werror | ||
14 | CDIAGFLAGS+= -Wchar-subscripts | ||
15 | CDIAGFLAGS+= -Wcomment | ||
16 | CDIAGFLAGS+= -Wformat | ||
17 | CDIAGFLAGS+= -Wformat-security | ||
18 | CDIAGFLAGS+= -Wimplicit | ||
19 | CDIAGFLAGS+= -Winline | ||
20 | CDIAGFLAGS+= -Wmissing-declarations | ||
21 | CDIAGFLAGS+= -Wmissing-prototypes | ||
22 | CDIAGFLAGS+= -Wparentheses | ||
23 | CDIAGFLAGS+= -Wpointer-arith | ||
24 | CDIAGFLAGS+= -Wpointer-sign | ||
25 | CDIAGFLAGS+= -Wreturn-type | ||
26 | CDIAGFLAGS+= -Wshadow | ||
27 | CDIAGFLAGS+= -Wsign-compare | ||
28 | CDIAGFLAGS+= -Wstrict-aliasing | ||
29 | CDIAGFLAGS+= -Wstrict-prototypes | ||
30 | CDIAGFLAGS+= -Wswitch | ||
31 | CDIAGFLAGS+= -Wtrigraphs | ||
32 | CDIAGFLAGS+= -Wuninitialized | ||
33 | CDIAGFLAGS+= -Wunused | ||
34 | .if ${COMPILER_VERSION} == "gcc4" | ||
35 | CDIAGFLAGS+= -Wold-style-definition | ||
36 | .endif | ||
37 | |||
38 | SSHREL=../../../../../usr.bin/ssh | ||
39 | |||
40 | CFLAGS+=-I${.CURDIR}/../test_helper -I${.CURDIR}/${SSHREL} | ||
41 | |||
42 | .if exists(${.CURDIR}/../test_helper/${__objdir}) | ||
43 | LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper | ||
44 | DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a | ||
45 | .else | ||
46 | LDADD+=-L${.CURDIR}/../test_helper -ltest_helper | ||
47 | DPADD+=${.CURDIR}/../test_helper/libtest_helper.a | ||
48 | .endif | ||
49 | |||
50 | .if exists(${.CURDIR}/${SSHREL}/lib/${__objdir}) | ||
51 | LDADD+=-L${.CURDIR}/${SSHREL}/lib/${__objdir} -lssh | ||
52 | DPADD+=${.CURDIR}/${SSHREL}/lib/${__objdir}/libssh.a | ||
53 | .else | ||
54 | LDADD+=-L${.CURDIR}/${SSHREL}/lib -lssh | ||
55 | DPADD+=${.CURDIR}/${SSHREL}/lib/libssh.a | ||
56 | .endif | ||
57 | |||
58 | LDADD+= -lcrypto | ||
59 | DPADD+= ${LIBCRYPTO} | ||
diff --git a/regress/unittests/sshbuf/Makefile b/regress/unittests/sshbuf/Makefile new file mode 100644 index 000000000..85f99ac38 --- /dev/null +++ b/regress/unittests/sshbuf/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $ | ||
2 | |||
3 | PROG=test_sshbuf | ||
4 | SRCS=tests.c | ||
5 | SRCS+=test_sshbuf.c | ||
6 | SRCS+=test_sshbuf_getput_basic.c | ||
7 | SRCS+=test_sshbuf_getput_crypto.c | ||
8 | SRCS+=test_sshbuf_misc.c | ||
9 | SRCS+=test_sshbuf_fuzz.c | ||
10 | SRCS+=test_sshbuf_getput_fuzz.c | ||
11 | SRCS+=test_sshbuf_fixed.c | ||
12 | |||
13 | .include <bsd.regress.mk> | ||
14 | |||
diff --git a/regress/unittests/sshbuf/test_sshbuf.c b/regress/unittests/sshbuf/test_sshbuf.c new file mode 100644 index 000000000..ee77d6934 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* $OpenBSD: test_sshbuf.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #define SSHBUF_INTERNAL 1 /* access internals for testing */ | ||
9 | #include "includes.h" | ||
10 | |||
11 | #include <sys/types.h> | ||
12 | #include <sys/param.h> | ||
13 | #include <stdio.h> | ||
14 | #ifdef HAVE_STDINT_H | ||
15 | # include <stdint.h> | ||
16 | #endif | ||
17 | #include <stdlib.h> | ||
18 | #include <string.h> | ||
19 | |||
20 | #include "../test_helper/test_helper.h" | ||
21 | |||
22 | #include "ssherr.h" | ||
23 | #include "sshbuf.h" | ||
24 | |||
25 | void sshbuf_tests(void); | ||
26 | |||
27 | void | ||
28 | sshbuf_tests(void) | ||
29 | { | ||
30 | struct sshbuf *p1; | ||
31 | const u_char *cdp; | ||
32 | u_char *dp; | ||
33 | size_t sz; | ||
34 | int r; | ||
35 | |||
36 | TEST_START("allocate sshbuf"); | ||
37 | p1 = sshbuf_new(); | ||
38 | ASSERT_PTR_NE(p1, NULL); | ||
39 | TEST_DONE(); | ||
40 | |||
41 | TEST_START("max size on fresh buffer"); | ||
42 | ASSERT_SIZE_T_GT(sshbuf_max_size(p1), 0); | ||
43 | TEST_DONE(); | ||
44 | |||
45 | TEST_START("available on fresh buffer"); | ||
46 | ASSERT_SIZE_T_GT(sshbuf_avail(p1), 0); | ||
47 | TEST_DONE(); | ||
48 | |||
49 | TEST_START("len = 0 on empty buffer"); | ||
50 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
51 | TEST_DONE(); | ||
52 | |||
53 | TEST_START("set valid max size"); | ||
54 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 65536), 0); | ||
55 | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 65536); | ||
56 | TEST_DONE(); | ||
57 | |||
58 | TEST_START("available on limited buffer"); | ||
59 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 65536); | ||
60 | TEST_DONE(); | ||
61 | |||
62 | TEST_START("free"); | ||
63 | sshbuf_free(p1); | ||
64 | TEST_DONE(); | ||
65 | |||
66 | TEST_START("consume on empty buffer"); | ||
67 | p1 = sshbuf_new(); | ||
68 | ASSERT_PTR_NE(p1, NULL); | ||
69 | ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0); | ||
70 | ASSERT_INT_EQ(sshbuf_consume(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE); | ||
71 | sshbuf_free(p1); | ||
72 | TEST_DONE(); | ||
73 | |||
74 | TEST_START("consume_end on empty buffer"); | ||
75 | p1 = sshbuf_new(); | ||
76 | ASSERT_PTR_NE(p1, NULL); | ||
77 | ASSERT_INT_EQ(sshbuf_consume_end(p1, 0), 0); | ||
78 | ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE); | ||
79 | sshbuf_free(p1); | ||
80 | TEST_DONE(); | ||
81 | |||
82 | TEST_START("reserve space"); | ||
83 | p1 = sshbuf_new(); | ||
84 | ASSERT_PTR_NE(p1, NULL); | ||
85 | r = sshbuf_reserve(p1, 1, &dp); | ||
86 | ASSERT_INT_EQ(r, 0); | ||
87 | ASSERT_PTR_NE(dp, NULL); | ||
88 | *dp = 0x11; | ||
89 | r = sshbuf_reserve(p1, 3, &dp); | ||
90 | ASSERT_INT_EQ(r, 0); | ||
91 | ASSERT_PTR_NE(dp, NULL); | ||
92 | *dp++ = 0x22; | ||
93 | *dp++ = 0x33; | ||
94 | *dp++ = 0x44; | ||
95 | TEST_DONE(); | ||
96 | |||
97 | TEST_START("sshbuf_len on filled buffer"); | ||
98 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
99 | TEST_DONE(); | ||
100 | |||
101 | TEST_START("sshbuf_ptr on filled buffer"); | ||
102 | cdp = sshbuf_ptr(p1); | ||
103 | ASSERT_PTR_NE(cdp, NULL); | ||
104 | ASSERT_U8_EQ(cdp[0], 0x11); | ||
105 | ASSERT_U8_EQ(cdp[1], 0x22); | ||
106 | ASSERT_U8_EQ(cdp[2], 0x33); | ||
107 | ASSERT_U8_EQ(cdp[3], 0x44); | ||
108 | TEST_DONE(); | ||
109 | |||
110 | TEST_START("consume on filled buffer"); | ||
111 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
112 | ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0); | ||
113 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
114 | r = sshbuf_consume(p1, 64); | ||
115 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
116 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
117 | ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0); | ||
118 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3); | ||
119 | cdp = sshbuf_ptr(p1); | ||
120 | ASSERT_PTR_NE(p1, NULL); | ||
121 | ASSERT_U8_EQ(cdp[0], 0x22); | ||
122 | ASSERT_INT_EQ(sshbuf_consume(p1, 2), 0); | ||
123 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
124 | cdp = sshbuf_ptr(p1); | ||
125 | ASSERT_PTR_NE(p1, NULL); | ||
126 | ASSERT_U8_EQ(cdp[0], 0x44); | ||
127 | r = sshbuf_consume(p1, 2); | ||
128 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
129 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
130 | ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0); | ||
131 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
132 | r = sshbuf_consume(p1, 1); | ||
133 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
134 | sshbuf_free(p1); | ||
135 | TEST_DONE(); | ||
136 | |||
137 | TEST_START("consume_end on filled buffer"); | ||
138 | p1 = sshbuf_new(); | ||
139 | ASSERT_PTR_NE(p1, NULL); | ||
140 | r = sshbuf_reserve(p1, 4, &dp); | ||
141 | ASSERT_INT_EQ(r, 0); | ||
142 | ASSERT_PTR_NE(dp, NULL); | ||
143 | *dp++ = 0x11; | ||
144 | *dp++ = 0x22; | ||
145 | *dp++ = 0x33; | ||
146 | *dp++ = 0x44; | ||
147 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
148 | r = sshbuf_consume_end(p1, 5); | ||
149 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
150 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
151 | ASSERT_INT_EQ(sshbuf_consume_end(p1, 3), 0); | ||
152 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
153 | cdp = sshbuf_ptr(p1); | ||
154 | ASSERT_PTR_NE(cdp, NULL); | ||
155 | ASSERT_U8_EQ(*cdp, 0x11); | ||
156 | r = sshbuf_consume_end(p1, 2); | ||
157 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
158 | ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0); | ||
159 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
160 | sshbuf_free(p1); | ||
161 | TEST_DONE(); | ||
162 | |||
163 | TEST_START("fill limited buffer"); | ||
164 | p1 = sshbuf_new(); | ||
165 | ASSERT_PTR_NE(p1, NULL); | ||
166 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0); | ||
167 | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); | ||
168 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223); | ||
169 | r = sshbuf_reserve(p1, 1223, &dp); | ||
170 | ASSERT_INT_EQ(r, 0); | ||
171 | ASSERT_PTR_NE(dp, NULL); | ||
172 | memset(dp, 0xd7, 1223); | ||
173 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223); | ||
174 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0); | ||
175 | r = sshbuf_reserve(p1, 1, &dp); | ||
176 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
177 | ASSERT_PTR_EQ(dp, NULL); | ||
178 | TEST_DONE(); | ||
179 | |||
180 | TEST_START("consume and force compaction"); | ||
181 | ASSERT_INT_EQ(sshbuf_consume(p1, 223), 0); | ||
182 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000); | ||
183 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223); | ||
184 | r = sshbuf_reserve(p1, 224, &dp); | ||
185 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
186 | ASSERT_PTR_EQ(dp, NULL); | ||
187 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000); | ||
188 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223); | ||
189 | r = sshbuf_reserve(p1, 223, &dp); | ||
190 | ASSERT_INT_EQ(r, 0); | ||
191 | ASSERT_PTR_NE(dp, NULL); | ||
192 | memset(dp, 0x7d, 223); | ||
193 | cdp = sshbuf_ptr(p1); | ||
194 | ASSERT_PTR_NE(cdp, NULL); | ||
195 | ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000); | ||
196 | ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223); | ||
197 | TEST_DONE(); | ||
198 | |||
199 | TEST_START("resize full buffer"); | ||
200 | r = sshbuf_set_max_size(p1, 1000); | ||
201 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
202 | sz = roundup(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC); | ||
203 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, sz), 0); | ||
204 | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); | ||
205 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - 1223); | ||
206 | ASSERT_INT_EQ(sshbuf_len(p1), 1223); | ||
207 | TEST_DONE(); | ||
208 | |||
209 | /* NB. uses sshbuf internals */ | ||
210 | TEST_START("alloc chunking"); | ||
211 | r = sshbuf_reserve(p1, 1, &dp); | ||
212 | ASSERT_INT_EQ(r, 0); | ||
213 | ASSERT_PTR_NE(dp, NULL); | ||
214 | *dp = 0xff; | ||
215 | cdp = sshbuf_ptr(p1); | ||
216 | ASSERT_PTR_NE(cdp, NULL); | ||
217 | ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000); | ||
218 | ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223); | ||
219 | ASSERT_MEM_FILLED_EQ(cdp + 1223, 0xff, 1); | ||
220 | ASSERT_SIZE_T_EQ(sshbuf_alloc(p1) % SSHBUF_SIZE_INC, 0); | ||
221 | sshbuf_free(p1); | ||
222 | TEST_DONE(); | ||
223 | |||
224 | TEST_START("reset buffer"); | ||
225 | p1 = sshbuf_new(); | ||
226 | ASSERT_PTR_NE(p1, NULL); | ||
227 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0); | ||
228 | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); | ||
229 | r = sshbuf_reserve(p1, 1223, &dp); | ||
230 | ASSERT_INT_EQ(r, 0); | ||
231 | ASSERT_PTR_NE(dp, NULL); | ||
232 | memset(dp, 0xd7, 1223); | ||
233 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223); | ||
234 | sshbuf_reset(p1); | ||
235 | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); | ||
236 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
237 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223); | ||
238 | sshbuf_free(p1); | ||
239 | TEST_DONE(); | ||
240 | } | ||
diff --git a/regress/unittests/sshbuf/test_sshbuf_fixed.c b/regress/unittests/sshbuf/test_sshbuf_fixed.c new file mode 100644 index 000000000..df4925f7c --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_fixed.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* $OpenBSD: test_sshbuf_fixed.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #define SSHBUF_INTERNAL 1 /* access internals for testing */ | ||
9 | #include "includes.h" | ||
10 | |||
11 | #include <sys/types.h> | ||
12 | #include <sys/param.h> | ||
13 | #include <stdio.h> | ||
14 | #ifdef HAVE_STDINT_H | ||
15 | # include <stdint.h> | ||
16 | #endif | ||
17 | #include <stdlib.h> | ||
18 | #include <string.h> | ||
19 | |||
20 | #include "../test_helper/test_helper.h" | ||
21 | |||
22 | #include "sshbuf.h" | ||
23 | #include "ssherr.h" | ||
24 | |||
25 | void sshbuf_fixed(void); | ||
26 | |||
27 | const u_char test_buf[] = "\x01\x12\x34\x56\x78\x00\x00\x00\x05hello"; | ||
28 | |||
29 | void | ||
30 | sshbuf_fixed(void) | ||
31 | { | ||
32 | struct sshbuf *p1, *p2, *p3; | ||
33 | u_char c; | ||
34 | char *s; | ||
35 | u_int i; | ||
36 | size_t l; | ||
37 | |||
38 | TEST_START("sshbuf_from"); | ||
39 | p1 = sshbuf_from(test_buf, sizeof(test_buf)); | ||
40 | ASSERT_PTR_NE(p1, NULL); | ||
41 | ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL); | ||
42 | ASSERT_INT_EQ(sshbuf_check_reserve(p1, 1), SSH_ERR_BUFFER_READ_ONLY); | ||
43 | ASSERT_INT_EQ(sshbuf_reserve(p1, 1, NULL), SSH_ERR_BUFFER_READ_ONLY); | ||
44 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 200), SSH_ERR_BUFFER_READ_ONLY); | ||
45 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), SSH_ERR_BUFFER_READ_ONLY); | ||
46 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0); | ||
47 | ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf); | ||
48 | sshbuf_free(p1); | ||
49 | TEST_DONE(); | ||
50 | |||
51 | TEST_START("sshbuf_from data"); | ||
52 | p1 = sshbuf_from(test_buf, sizeof(test_buf) - 1); | ||
53 | ASSERT_PTR_NE(p1, NULL); | ||
54 | ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf); | ||
55 | ASSERT_INT_EQ(sshbuf_get_u8(p1, &c), 0); | ||
56 | ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 1); | ||
57 | ASSERT_U8_EQ(c, 1); | ||
58 | ASSERT_INT_EQ(sshbuf_get_u32(p1, &i), 0); | ||
59 | ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 5); | ||
60 | ASSERT_U32_EQ(i, 0x12345678); | ||
61 | ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s, &l), 0); | ||
62 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
63 | ASSERT_STRING_EQ(s, "hello"); | ||
64 | ASSERT_SIZE_T_EQ(l, 5); | ||
65 | sshbuf_free(p1); | ||
66 | free(s); | ||
67 | TEST_DONE(); | ||
68 | |||
69 | TEST_START("sshbuf_fromb "); | ||
70 | p1 = sshbuf_new(); | ||
71 | ASSERT_PTR_NE(p1, NULL); | ||
72 | ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1); | ||
73 | ASSERT_PTR_EQ(sshbuf_parent(p1), NULL); | ||
74 | ASSERT_INT_EQ(sshbuf_put(p1, test_buf, sizeof(test_buf) - 1), 0); | ||
75 | p2 = sshbuf_fromb(p1); | ||
76 | ASSERT_PTR_NE(p2, NULL); | ||
77 | ASSERT_U_INT_EQ(sshbuf_refcount(p1), 2); | ||
78 | ASSERT_PTR_EQ(sshbuf_parent(p1), NULL); | ||
79 | ASSERT_PTR_EQ(sshbuf_parent(p2), p1); | ||
80 | ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1)); | ||
81 | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | ||
82 | ASSERT_PTR_NE(sshbuf_ptr(p2), NULL); | ||
83 | ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL); | ||
84 | ASSERT_PTR_EQ(sshbuf_mutable_ptr(p2), NULL); | ||
85 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sshbuf_len(p2)); | ||
86 | ASSERT_INT_EQ(sshbuf_get_u8(p2, &c), 0); | ||
87 | ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 1); | ||
88 | ASSERT_U8_EQ(c, 1); | ||
89 | ASSERT_INT_EQ(sshbuf_get_u32(p2, &i), 0); | ||
90 | ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 5); | ||
91 | ASSERT_U32_EQ(i, 0x12345678); | ||
92 | ASSERT_INT_EQ(sshbuf_get_cstring(p2, &s, &l), 0); | ||
93 | ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0); | ||
94 | ASSERT_STRING_EQ(s, "hello"); | ||
95 | ASSERT_SIZE_T_EQ(l, 5); | ||
96 | sshbuf_free(p1); | ||
97 | ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1); | ||
98 | sshbuf_free(p2); | ||
99 | free(s); | ||
100 | TEST_DONE(); | ||
101 | |||
102 | TEST_START("sshbuf_froms"); | ||
103 | p1 = sshbuf_new(); | ||
104 | ASSERT_PTR_NE(p1, NULL); | ||
105 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x01), 0); | ||
106 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); | ||
107 | ASSERT_INT_EQ(sshbuf_put_cstring(p1, "hello"), 0); | ||
108 | p2 = sshbuf_new(); | ||
109 | ASSERT_PTR_NE(p2, NULL); | ||
110 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(test_buf) - 1); | ||
111 | ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0); | ||
112 | ASSERT_SIZE_T_EQ(sshbuf_len(p2), sizeof(test_buf) + 4 - 1); | ||
113 | ASSERT_INT_EQ(sshbuf_froms(p2, &p3), 0); | ||
114 | ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0); | ||
115 | ASSERT_PTR_NE(p3, NULL); | ||
116 | ASSERT_PTR_NE(sshbuf_ptr(p3), NULL); | ||
117 | ASSERT_SIZE_T_EQ(sshbuf_len(p3), sizeof(test_buf) - 1); | ||
118 | ASSERT_MEM_EQ(sshbuf_ptr(p3), test_buf, sizeof(test_buf) - 1); | ||
119 | sshbuf_free(p3); | ||
120 | ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0); | ||
121 | ASSERT_INT_EQ(sshbuf_consume_end(p2, 1), 0); | ||
122 | ASSERT_INT_EQ(sshbuf_froms(p2, &p3), SSH_ERR_MESSAGE_INCOMPLETE); | ||
123 | ASSERT_PTR_EQ(p3, NULL); | ||
124 | sshbuf_free(p2); | ||
125 | sshbuf_free(p1); | ||
126 | } | ||
diff --git a/regress/unittests/sshbuf/test_sshbuf_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_fuzz.c new file mode 100644 index 000000000..c52376b53 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_fuzz.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* $OpenBSD: test_sshbuf_fuzz.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <stdio.h> | ||
13 | #ifdef HAVE_STDINT_H | ||
14 | # include <stdint.h> | ||
15 | #endif | ||
16 | #include <stdlib.h> | ||
17 | #include <string.h> | ||
18 | |||
19 | #include "../test_helper/test_helper.h" | ||
20 | |||
21 | #include "ssherr.h" | ||
22 | #include "sshbuf.h" | ||
23 | |||
24 | #define NUM_FUZZ_TESTS (1 << 18) | ||
25 | |||
26 | void sshbuf_fuzz_tests(void); | ||
27 | |||
28 | void | ||
29 | sshbuf_fuzz_tests(void) | ||
30 | { | ||
31 | struct sshbuf *p1; | ||
32 | u_char *dp; | ||
33 | size_t sz, sz2, i; | ||
34 | u_int32_t r; | ||
35 | int ret; | ||
36 | |||
37 | /* NB. uses sshbuf internals */ | ||
38 | TEST_START("fuzz alloc/dealloc"); | ||
39 | p1 = sshbuf_new(); | ||
40 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0); | ||
41 | ASSERT_PTR_NE(p1, NULL); | ||
42 | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | ||
43 | ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); | ||
44 | for (i = 0; i < NUM_FUZZ_TESTS; i++) { | ||
45 | r = arc4random_uniform(10); | ||
46 | if (r == 0) { | ||
47 | /* 10% chance: small reserve */ | ||
48 | r = arc4random_uniform(10); | ||
49 | fuzz_reserve: | ||
50 | sz = sshbuf_avail(p1); | ||
51 | sz2 = sshbuf_len(p1); | ||
52 | ret = sshbuf_reserve(p1, r, &dp); | ||
53 | if (ret < 0) { | ||
54 | ASSERT_PTR_EQ(dp, NULL); | ||
55 | ASSERT_SIZE_T_LT(sz, r); | ||
56 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); | ||
57 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); | ||
58 | } else { | ||
59 | ASSERT_PTR_NE(dp, NULL); | ||
60 | ASSERT_SIZE_T_GE(sz, r); | ||
61 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r); | ||
62 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r); | ||
63 | memset(dp, arc4random_uniform(255) + 1, r); | ||
64 | } | ||
65 | } else if (r < 3) { | ||
66 | /* 20% chance: big reserve */ | ||
67 | r = arc4random_uniform(8 * 1024); | ||
68 | goto fuzz_reserve; | ||
69 | } else if (r == 3) { | ||
70 | /* 10% chance: small consume */ | ||
71 | r = arc4random_uniform(10); | ||
72 | fuzz_consume: | ||
73 | sz = sshbuf_avail(p1); | ||
74 | sz2 = sshbuf_len(p1); | ||
75 | /* 50% change consume from end, otherwise start */ | ||
76 | ret = ((arc4random() & 1) ? | ||
77 | sshbuf_consume : sshbuf_consume_end)(p1, r); | ||
78 | if (ret < 0) { | ||
79 | ASSERT_SIZE_T_LT(sz2, r); | ||
80 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); | ||
81 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); | ||
82 | } else { | ||
83 | ASSERT_SIZE_T_GE(sz2, r); | ||
84 | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r); | ||
85 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r); | ||
86 | } | ||
87 | } else if (r < 8) { | ||
88 | /* 40% chance: big consume */ | ||
89 | r = arc4random_uniform(2 * 1024); | ||
90 | goto fuzz_consume; | ||
91 | } else if (r == 8) { | ||
92 | /* 10% chance: reset max size */ | ||
93 | r = arc4random_uniform(16 * 1024); | ||
94 | sz = sshbuf_max_size(p1); | ||
95 | if (sshbuf_set_max_size(p1, r) < 0) | ||
96 | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); | ||
97 | else | ||
98 | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r); | ||
99 | } else { | ||
100 | if (arc4random_uniform(8192) == 0) { | ||
101 | /* tiny chance: new buffer */ | ||
102 | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | ||
103 | ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); | ||
104 | sshbuf_free(p1); | ||
105 | p1 = sshbuf_new(); | ||
106 | ASSERT_PTR_NE(p1, NULL); | ||
107 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, | ||
108 | 16 * 1024), 0); | ||
109 | } else { | ||
110 | /* Almost 10%: giant reserve */ | ||
111 | /* use arc4random_buf for r > 2^32 on 64 bit */ | ||
112 | arc4random_buf(&r, sizeof(r)); | ||
113 | while (r < SSHBUF_SIZE_MAX / 2) { | ||
114 | r <<= 1; | ||
115 | r |= arc4random() & 1; | ||
116 | } | ||
117 | goto fuzz_reserve; | ||
118 | } | ||
119 | } | ||
120 | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | ||
121 | ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024); | ||
122 | } | ||
123 | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | ||
124 | ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); | ||
125 | sshbuf_free(p1); | ||
126 | TEST_DONE(); | ||
127 | } | ||
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_basic.c b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c new file mode 100644 index 000000000..966e8432b --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c | |||
@@ -0,0 +1,484 @@ | |||
1 | /* $OpenBSD: test_sshbuf_getput_basic.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <stdio.h> | ||
13 | #ifdef HAVE_STDINT_H | ||
14 | # include <stdint.h> | ||
15 | #endif | ||
16 | #include <stdlib.h> | ||
17 | #include <string.h> | ||
18 | |||
19 | #include "../test_helper/test_helper.h" | ||
20 | #include "ssherr.h" | ||
21 | #include "sshbuf.h" | ||
22 | |||
23 | void sshbuf_getput_basic_tests(void); | ||
24 | |||
25 | void | ||
26 | sshbuf_getput_basic_tests(void) | ||
27 | { | ||
28 | struct sshbuf *p1, *p2; | ||
29 | const u_char *cd; | ||
30 | u_char *d, d2[32], x[] = { | ||
31 | 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x99 | ||
32 | }; | ||
33 | u_int64_t v64; | ||
34 | u_int32_t v32; | ||
35 | u_int16_t v16; | ||
36 | u_char v8; | ||
37 | size_t s; | ||
38 | char *s2; | ||
39 | int r; | ||
40 | u_char bn1[] = { 0x00, 0x00, 0x00 }; | ||
41 | u_char bn2[] = { 0x00, 0x00, 0x01, 0x02 }; | ||
42 | u_char bn3[] = { 0x00, 0x80, 0x09 }; | ||
43 | u_char bn_exp1[] = { 0x00, 0x00, 0x00, 0x00 }; | ||
44 | u_char bn_exp2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 0x02 }; | ||
45 | u_char bn_exp3[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0x09 }; | ||
46 | |||
47 | TEST_START("PEEK_U64"); | ||
48 | ASSERT_U64_EQ(PEEK_U64(x), 0x1122334455667788ULL); | ||
49 | TEST_DONE(); | ||
50 | |||
51 | TEST_START("PEEK_U32"); | ||
52 | ASSERT_U32_EQ(PEEK_U32(x), 0x11223344); | ||
53 | TEST_DONE(); | ||
54 | |||
55 | TEST_START("PEEK_U16"); | ||
56 | ASSERT_U16_EQ(PEEK_U16(x), 0x1122); | ||
57 | TEST_DONE(); | ||
58 | |||
59 | TEST_START("POKE_U64"); | ||
60 | bzero(d2, sizeof(d2)); | ||
61 | POKE_U64(d2, 0x1122334455667788ULL); | ||
62 | ASSERT_MEM_EQ(d2, x, 8); | ||
63 | TEST_DONE(); | ||
64 | |||
65 | TEST_START("POKE_U32"); | ||
66 | bzero(d2, sizeof(d2)); | ||
67 | POKE_U32(d2, 0x11223344); | ||
68 | ASSERT_MEM_EQ(d2, x, 4); | ||
69 | TEST_DONE(); | ||
70 | |||
71 | TEST_START("POKE_U16"); | ||
72 | bzero(d2, sizeof(d2)); | ||
73 | POKE_U16(d2, 0x1122); | ||
74 | ASSERT_MEM_EQ(d2, x, 2); | ||
75 | TEST_DONE(); | ||
76 | |||
77 | TEST_START("sshbuf_put"); | ||
78 | p1 = sshbuf_new(); | ||
79 | ASSERT_PTR_NE(p1, NULL); | ||
80 | ASSERT_INT_EQ(sshbuf_put(p1, x, 5), 0); | ||
81 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5); | ||
82 | cd = sshbuf_ptr(p1); | ||
83 | ASSERT_PTR_NE(cd, NULL); | ||
84 | ASSERT_U8_EQ(cd[0], 0x11); | ||
85 | ASSERT_U8_EQ(cd[1], 0x22); | ||
86 | ASSERT_U8_EQ(cd[2], 0x33); | ||
87 | ASSERT_U8_EQ(cd[3], 0x44); | ||
88 | ASSERT_U8_EQ(cd[4], 0x55); | ||
89 | TEST_DONE(); | ||
90 | |||
91 | TEST_START("sshbuf_get"); | ||
92 | ASSERT_INT_EQ(sshbuf_get(p1, d2, 4), 0); | ||
93 | ASSERT_MEM_EQ(d2, x, 4); | ||
94 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
95 | ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55); | ||
96 | TEST_DONE(); | ||
97 | |||
98 | TEST_START("sshbuf_get truncated"); | ||
99 | r = sshbuf_get(p1, d2, 4); | ||
100 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
101 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
102 | ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55); | ||
103 | TEST_DONE(); | ||
104 | |||
105 | TEST_START("sshbuf_put truncated"); | ||
106 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0); | ||
107 | r = sshbuf_put(p1, x, 5); | ||
108 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
109 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
110 | sshbuf_free(p1); | ||
111 | TEST_DONE(); | ||
112 | |||
113 | TEST_START("sshbuf_get_u64"); | ||
114 | p1 = sshbuf_new(); | ||
115 | ASSERT_PTR_NE(p1, NULL); | ||
116 | ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0); | ||
117 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10); | ||
118 | ASSERT_INT_EQ(sshbuf_get_u64(p1, &v64), 0); | ||
119 | ASSERT_U64_EQ(v64, 0x1122334455667788ULL); | ||
120 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
121 | TEST_DONE(); | ||
122 | |||
123 | TEST_START("sshbuf_get_u64 truncated"); | ||
124 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
125 | r = sshbuf_get_u64(p1, &v64); | ||
126 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
127 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
128 | sshbuf_free(p1); | ||
129 | TEST_DONE(); | ||
130 | |||
131 | TEST_START("sshbuf_get_u32"); | ||
132 | p1 = sshbuf_new(); | ||
133 | ASSERT_PTR_NE(p1, NULL); | ||
134 | ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0); | ||
135 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10); | ||
136 | ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0); | ||
137 | ASSERT_U32_EQ(v32, 0x11223344); | ||
138 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 6); | ||
139 | ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0); | ||
140 | ASSERT_U32_EQ(v32, 0x55667788); | ||
141 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
142 | TEST_DONE(); | ||
143 | |||
144 | TEST_START("sshbuf_get_u32 truncated"); | ||
145 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
146 | r = sshbuf_get_u32(p1, &v32); | ||
147 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
148 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
149 | sshbuf_free(p1); | ||
150 | TEST_DONE(); | ||
151 | |||
152 | TEST_START("sshbuf_get_u16"); | ||
153 | p1 = sshbuf_new(); | ||
154 | ASSERT_PTR_NE(p1, NULL); | ||
155 | ASSERT_INT_EQ(sshbuf_put(p1, x, 9), 0); | ||
156 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 9); | ||
157 | ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); | ||
158 | ASSERT_U16_EQ(v16, 0x1122); | ||
159 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 7); | ||
160 | ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); | ||
161 | ASSERT_U16_EQ(v16, 0x3344); | ||
162 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5); | ||
163 | ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); | ||
164 | ASSERT_U16_EQ(v16, 0x5566); | ||
165 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3); | ||
166 | ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); | ||
167 | ASSERT_U16_EQ(v16, 0x7788); | ||
168 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
169 | TEST_DONE(); | ||
170 | |||
171 | TEST_START("sshbuf_get_u16 truncated"); | ||
172 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
173 | r = sshbuf_get_u16(p1, &v16); | ||
174 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
175 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
176 | sshbuf_free(p1); | ||
177 | TEST_DONE(); | ||
178 | |||
179 | TEST_START("sshbuf_get_u8"); | ||
180 | p1 = sshbuf_new(); | ||
181 | ASSERT_PTR_NE(p1, NULL); | ||
182 | ASSERT_INT_EQ(sshbuf_put(p1, x, 2), 0); | ||
183 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
184 | ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0); | ||
185 | ASSERT_U8_EQ(v8, 0x11); | ||
186 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
187 | ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0); | ||
188 | ASSERT_U8_EQ(v8, 0x22); | ||
189 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
190 | TEST_DONE(); | ||
191 | |||
192 | TEST_START("sshbuf_get_u8 truncated"); | ||
193 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
194 | r = sshbuf_get_u8(p1, &v8); | ||
195 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
196 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
197 | sshbuf_free(p1); | ||
198 | TEST_DONE(); | ||
199 | |||
200 | TEST_START("sshbuf_put_u64"); | ||
201 | p1 = sshbuf_new(); | ||
202 | ASSERT_PTR_NE(p1, NULL); | ||
203 | ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0); | ||
204 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8); | ||
205 | ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8); | ||
206 | sshbuf_free(p1); | ||
207 | TEST_DONE(); | ||
208 | |||
209 | TEST_START("sshbuf_put_u64 exact"); | ||
210 | p1 = sshbuf_new(); | ||
211 | ASSERT_PTR_NE(p1, NULL); | ||
212 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 8), 0); | ||
213 | ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0); | ||
214 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8); | ||
215 | ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8); | ||
216 | sshbuf_free(p1); | ||
217 | TEST_DONE(); | ||
218 | |||
219 | TEST_START("sshbuf_put_u64 limited"); | ||
220 | p1 = sshbuf_new(); | ||
221 | ASSERT_PTR_NE(p1, NULL); | ||
222 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 7), 0); | ||
223 | r = sshbuf_put_u64(p1, 0x1122334455667788ULL); | ||
224 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
225 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
226 | sshbuf_free(p1); | ||
227 | TEST_DONE(); | ||
228 | |||
229 | TEST_START("sshbuf_put_u32"); | ||
230 | p1 = sshbuf_new(); | ||
231 | ASSERT_PTR_NE(p1, NULL); | ||
232 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0); | ||
233 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
234 | ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4); | ||
235 | sshbuf_free(p1); | ||
236 | TEST_DONE(); | ||
237 | |||
238 | TEST_START("sshbuf_put_u32 exact"); | ||
239 | p1 = sshbuf_new(); | ||
240 | ASSERT_PTR_NE(p1, NULL); | ||
241 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0); | ||
242 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0); | ||
243 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
244 | ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4); | ||
245 | sshbuf_free(p1); | ||
246 | TEST_DONE(); | ||
247 | |||
248 | TEST_START("sshbuf_put_u32 limited"); | ||
249 | p1 = sshbuf_new(); | ||
250 | ASSERT_PTR_NE(p1, NULL); | ||
251 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 3), 0); | ||
252 | r = sshbuf_put_u32(p1, 0x11223344); | ||
253 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
254 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
255 | sshbuf_free(p1); | ||
256 | TEST_DONE(); | ||
257 | |||
258 | TEST_START("sshbuf_put_u16"); | ||
259 | p1 = sshbuf_new(); | ||
260 | ASSERT_PTR_NE(p1, NULL); | ||
261 | ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0); | ||
262 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
263 | ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2); | ||
264 | sshbuf_free(p1); | ||
265 | TEST_DONE(); | ||
266 | |||
267 | TEST_START("sshbuf_put_u16"); | ||
268 | p1 = sshbuf_new(); | ||
269 | ASSERT_PTR_NE(p1, NULL); | ||
270 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 2), 0); | ||
271 | ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0); | ||
272 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
273 | ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2); | ||
274 | sshbuf_free(p1); | ||
275 | TEST_DONE(); | ||
276 | |||
277 | TEST_START("sshbuf_put_u16 limited"); | ||
278 | p1 = sshbuf_new(); | ||
279 | ASSERT_PTR_NE(p1, NULL); | ||
280 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1), 0); | ||
281 | r = sshbuf_put_u16(p1, 0x1122); | ||
282 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
283 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
284 | sshbuf_free(p1); | ||
285 | TEST_DONE(); | ||
286 | |||
287 | TEST_START("sshbuf_get_string"); | ||
288 | p1 = sshbuf_new(); | ||
289 | ASSERT_PTR_NE(p1, NULL); | ||
290 | ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); | ||
291 | ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); | ||
292 | ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); | ||
293 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 + 4); | ||
294 | ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0); | ||
295 | ASSERT_SIZE_T_EQ(s, sizeof(x)); | ||
296 | ASSERT_MEM_EQ(d, x, sizeof(x)); | ||
297 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
298 | free(d); | ||
299 | sshbuf_free(p1); | ||
300 | TEST_DONE(); | ||
301 | |||
302 | TEST_START("sshbuf_get_string exact"); | ||
303 | p1 = sshbuf_new(); | ||
304 | ASSERT_PTR_NE(p1, NULL); | ||
305 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4), 0); | ||
306 | ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); | ||
307 | ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); | ||
308 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
309 | ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0); | ||
310 | ASSERT_SIZE_T_EQ(s, sizeof(x)); | ||
311 | ASSERT_MEM_EQ(d, x, sizeof(x)); | ||
312 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
313 | free(d); | ||
314 | sshbuf_free(p1); | ||
315 | TEST_DONE(); | ||
316 | |||
317 | TEST_START("sshbuf_get_string truncated"); | ||
318 | p1 = sshbuf_new(); | ||
319 | ASSERT_PTR_NE(p1, NULL); | ||
320 | ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); | ||
321 | ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); | ||
322 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
323 | ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0); | ||
324 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3); | ||
325 | r = sshbuf_get_string(p1, &d, &s); | ||
326 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
327 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3); | ||
328 | sshbuf_free(p1); | ||
329 | TEST_DONE(); | ||
330 | |||
331 | TEST_START("sshbuf_get_string giant"); | ||
332 | p1 = sshbuf_new(); | ||
333 | ASSERT_PTR_NE(p1, NULL); | ||
334 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0); | ||
335 | ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); | ||
336 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
337 | r = sshbuf_get_string(p1, &d, &s); | ||
338 | ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE); | ||
339 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
340 | sshbuf_free(p1); | ||
341 | TEST_DONE(); | ||
342 | |||
343 | TEST_START("sshbuf_get_cstring giant"); | ||
344 | p1 = sshbuf_new(); | ||
345 | ASSERT_PTR_NE(p1, NULL); | ||
346 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0); | ||
347 | ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); | ||
348 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
349 | r = sshbuf_get_cstring(p1, &s2, &s); | ||
350 | ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE); | ||
351 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
352 | sshbuf_free(p1); | ||
353 | TEST_DONE(); | ||
354 | |||
355 | TEST_START("sshbuf_get_cstring embedded \\0"); | ||
356 | p1 = sshbuf_new(); | ||
357 | ASSERT_PTR_NE(p1, NULL); | ||
358 | ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); | ||
359 | ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); | ||
360 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
361 | r = sshbuf_get_cstring(p1, &s2, NULL); | ||
362 | ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT); | ||
363 | sshbuf_free(p1); | ||
364 | TEST_DONE(); | ||
365 | |||
366 | TEST_START("sshbuf_get_cstring trailing \\0"); | ||
367 | p1 = sshbuf_new(); | ||
368 | ASSERT_PTR_NE(p1, NULL); | ||
369 | ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x) - 1), 0); | ||
370 | ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x) - 1), 0); | ||
371 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 - 1); | ||
372 | ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s2, &s), 0); | ||
373 | ASSERT_SIZE_T_EQ(s, sizeof(x) - 1); | ||
374 | ASSERT_MEM_EQ(s2, x, s); | ||
375 | free(s2); | ||
376 | sshbuf_free(p1); | ||
377 | TEST_DONE(); | ||
378 | |||
379 | TEST_START("sshbuf_put_string"); | ||
380 | p1 = sshbuf_new(); | ||
381 | ASSERT_PTR_NE(p1, NULL); | ||
382 | ASSERT_INT_EQ(sshbuf_put_string(p1, x, sizeof(x)), 0); | ||
383 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); | ||
384 | ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), sizeof(x)); | ||
385 | ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, x, sizeof(x)); | ||
386 | sshbuf_free(p1); | ||
387 | TEST_DONE(); | ||
388 | |||
389 | TEST_START("sshbuf_put_string limited"); | ||
390 | p1 = sshbuf_new(); | ||
391 | ASSERT_PTR_NE(p1, NULL); | ||
392 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4 - 1), 0); | ||
393 | r = sshbuf_put_string(p1, x, sizeof(x)); | ||
394 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
395 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
396 | sshbuf_free(p1); | ||
397 | TEST_DONE(); | ||
398 | |||
399 | TEST_START("sshbuf_put_string giant"); | ||
400 | p1 = sshbuf_new(); | ||
401 | ASSERT_PTR_NE(p1, NULL); | ||
402 | r = sshbuf_put_string(p1, (void *)0x01, 0xfffffffc); | ||
403 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
404 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
405 | sshbuf_free(p1); | ||
406 | TEST_DONE(); | ||
407 | |||
408 | TEST_START("sshbuf_putf"); | ||
409 | p1 = sshbuf_new(); | ||
410 | ASSERT_PTR_NE(p1, NULL); | ||
411 | r = sshbuf_putf(p1, "%s %d %x", "hello", 23, 0x5f); | ||
412 | ASSERT_INT_EQ(r, 0); | ||
413 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 11); | ||
414 | ASSERT_MEM_EQ(sshbuf_ptr(p1), "hello 23 5f", 11); | ||
415 | sshbuf_free(p1); | ||
416 | TEST_DONE(); | ||
417 | |||
418 | TEST_START("sshbuf_putb"); | ||
419 | p1 = sshbuf_new(); | ||
420 | ASSERT_PTR_NE(p1, NULL); | ||
421 | p2 = sshbuf_new(); | ||
422 | ASSERT_PTR_NE(p2, NULL); | ||
423 | ASSERT_INT_EQ(sshbuf_put(p1, "blahblahblah", 12), 0); | ||
424 | ASSERT_INT_EQ(sshbuf_putb(p2, p1), 0); | ||
425 | sshbuf_free(p1); | ||
426 | ASSERT_SIZE_T_EQ(sshbuf_len(p2), 12); | ||
427 | ASSERT_MEM_EQ(sshbuf_ptr(p2), "blahblahblah", 12); | ||
428 | sshbuf_free(p2); | ||
429 | TEST_DONE(); | ||
430 | |||
431 | TEST_START("sshbuf_put_bignum2_bytes empty buf"); | ||
432 | p1 = sshbuf_new(); | ||
433 | ASSERT_PTR_NE(p1, NULL); | ||
434 | ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, NULL, 0), 0); | ||
435 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1)); | ||
436 | ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1)); | ||
437 | sshbuf_free(p1); | ||
438 | TEST_DONE(); | ||
439 | |||
440 | TEST_START("sshbuf_put_bignum2_bytes all zeroes"); | ||
441 | p1 = sshbuf_new(); | ||
442 | ASSERT_PTR_NE(p1, NULL); | ||
443 | ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn1, sizeof(bn1)), 0); | ||
444 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1)); | ||
445 | ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1)); | ||
446 | sshbuf_free(p1); | ||
447 | TEST_DONE(); | ||
448 | |||
449 | TEST_START("sshbuf_put_bignum2_bytes simple"); | ||
450 | p1 = sshbuf_new(); | ||
451 | ASSERT_PTR_NE(p1, NULL); | ||
452 | ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2+2, sizeof(bn2)-2), 0); | ||
453 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2)); | ||
454 | ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2)); | ||
455 | sshbuf_free(p1); | ||
456 | TEST_DONE(); | ||
457 | |||
458 | TEST_START("sshbuf_put_bignum2_bytes leading zero"); | ||
459 | p1 = sshbuf_new(); | ||
460 | ASSERT_PTR_NE(p1, NULL); | ||
461 | ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2, sizeof(bn2)), 0); | ||
462 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2)); | ||
463 | ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2)); | ||
464 | sshbuf_free(p1); | ||
465 | TEST_DONE(); | ||
466 | |||
467 | TEST_START("sshbuf_put_bignum2_bytes neg"); | ||
468 | p1 = sshbuf_new(); | ||
469 | ASSERT_PTR_NE(p1, NULL); | ||
470 | ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3+1, sizeof(bn3)-1), 0); | ||
471 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3)); | ||
472 | ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3)); | ||
473 | sshbuf_free(p1); | ||
474 | TEST_DONE(); | ||
475 | |||
476 | TEST_START("sshbuf_put_bignum2_bytes neg and leading zero"); | ||
477 | p1 = sshbuf_new(); | ||
478 | ASSERT_PTR_NE(p1, NULL); | ||
479 | ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3, sizeof(bn3)), 0); | ||
480 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3)); | ||
481 | ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3)); | ||
482 | sshbuf_free(p1); | ||
483 | TEST_DONE(); | ||
484 | } | ||
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c new file mode 100644 index 000000000..0c4c71ecd --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c | |||
@@ -0,0 +1,409 @@ | |||
1 | /* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <stdio.h> | ||
13 | #ifdef HAVE_STDINT_H | ||
14 | # include <stdint.h> | ||
15 | #endif | ||
16 | #include <stdlib.h> | ||
17 | #include <string.h> | ||
18 | |||
19 | #include <openssl/bn.h> | ||
20 | #include <openssl/objects.h> | ||
21 | #ifdef OPENSSL_HAS_NISTP256 | ||
22 | # include <openssl/ec.h> | ||
23 | #endif | ||
24 | |||
25 | #include "../test_helper/test_helper.h" | ||
26 | #include "ssherr.h" | ||
27 | #include "sshbuf.h" | ||
28 | |||
29 | void sshbuf_getput_crypto_tests(void); | ||
30 | |||
31 | void | ||
32 | sshbuf_getput_crypto_tests(void) | ||
33 | { | ||
34 | struct sshbuf *p1; | ||
35 | const u_char *d; | ||
36 | size_t s; | ||
37 | BIGNUM *bn, *bn2; | ||
38 | /* This one has num_bits != num_bytes * 8 to test bignum1 encoding */ | ||
39 | const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10"; | ||
40 | /* This one has MSB set to test bignum2 encoding negative-avoidance */ | ||
41 | const char *hexbn2 = "f0e0d0c0b0a0908070605040302010007fff11"; | ||
42 | u_char expbn1[] = { | ||
43 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
44 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, | ||
45 | }; | ||
46 | u_char expbn2[] = { | ||
47 | 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, | ||
48 | 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, | ||
49 | 0x7f, 0xff, 0x11 | ||
50 | }; | ||
51 | #ifdef OPENSSL_HAS_NISTP256 | ||
52 | BIGNUM *bn_x, *bn_y; | ||
53 | int ec256_nid = NID_X9_62_prime256v1; | ||
54 | char *ec256_x = "0C828004839D0106AA59575216191357" | ||
55 | "34B451459DADB586677EF9DF55784999"; | ||
56 | char *ec256_y = "4D196B50F0B4E94B3C73E3A9D4CD9DF2" | ||
57 | "C8F9A35E42BDD047550F69D80EC23CD4"; | ||
58 | u_char expec256[] = { | ||
59 | 0x04, | ||
60 | 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06, | ||
61 | 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57, | ||
62 | 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86, | ||
63 | 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99, | ||
64 | 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b, | ||
65 | 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2, | ||
66 | 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47, | ||
67 | 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4 | ||
68 | }; | ||
69 | EC_KEY *eck; | ||
70 | EC_POINT *ecp; | ||
71 | #endif | ||
72 | int r; | ||
73 | |||
74 | #define MKBN(b, bnn) \ | ||
75 | do { \ | ||
76 | bnn = NULL; \ | ||
77 | ASSERT_INT_GT(BN_hex2bn(&bnn, b), 0); \ | ||
78 | } while (0) | ||
79 | |||
80 | TEST_START("sshbuf_put_bignum1"); | ||
81 | MKBN(hexbn1, bn); | ||
82 | p1 = sshbuf_new(); | ||
83 | ASSERT_PTR_NE(p1, NULL); | ||
84 | ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0); | ||
85 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 2); | ||
86 | ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn)); | ||
87 | ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn1, sizeof(expbn1)); | ||
88 | BN_free(bn); | ||
89 | sshbuf_free(p1); | ||
90 | TEST_DONE(); | ||
91 | |||
92 | TEST_START("sshbuf_put_bignum1 limited"); | ||
93 | MKBN(hexbn1, bn); | ||
94 | p1 = sshbuf_new(); | ||
95 | ASSERT_PTR_NE(p1, NULL); | ||
96 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0); | ||
97 | r = sshbuf_put_bignum1(p1, bn); | ||
98 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
99 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
100 | BN_free(bn); | ||
101 | sshbuf_free(p1); | ||
102 | TEST_DONE(); | ||
103 | |||
104 | TEST_START("sshbuf_put_bignum1 bn2"); | ||
105 | MKBN(hexbn2, bn); | ||
106 | p1 = sshbuf_new(); | ||
107 | ASSERT_PTR_NE(p1, NULL); | ||
108 | ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0); | ||
109 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 2); | ||
110 | ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn)); | ||
111 | ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn2, sizeof(expbn2)); | ||
112 | BN_free(bn); | ||
113 | sshbuf_free(p1); | ||
114 | TEST_DONE(); | ||
115 | |||
116 | TEST_START("sshbuf_put_bignum1 bn2 limited"); | ||
117 | MKBN(hexbn2, bn); | ||
118 | p1 = sshbuf_new(); | ||
119 | ASSERT_PTR_NE(p1, NULL); | ||
120 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0); | ||
121 | r = sshbuf_put_bignum1(p1, bn); | ||
122 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
123 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
124 | BN_free(bn); | ||
125 | sshbuf_free(p1); | ||
126 | TEST_DONE(); | ||
127 | |||
128 | TEST_START("sshbuf_put_bignum2"); | ||
129 | MKBN(hexbn1, bn); | ||
130 | p1 = sshbuf_new(); | ||
131 | ASSERT_PTR_NE(p1, NULL); | ||
132 | ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); | ||
133 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 4); | ||
134 | ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn)); | ||
135 | ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, expbn1, sizeof(expbn1)); | ||
136 | BN_free(bn); | ||
137 | sshbuf_free(p1); | ||
138 | TEST_DONE(); | ||
139 | |||
140 | TEST_START("sshbuf_put_bignum2 limited"); | ||
141 | MKBN(hexbn1, bn); | ||
142 | p1 = sshbuf_new(); | ||
143 | ASSERT_PTR_NE(p1, NULL); | ||
144 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 3), 0); | ||
145 | r = sshbuf_put_bignum2(p1, bn); | ||
146 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
147 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
148 | BN_free(bn); | ||
149 | sshbuf_free(p1); | ||
150 | TEST_DONE(); | ||
151 | |||
152 | TEST_START("sshbuf_put_bignum2 bn2"); | ||
153 | MKBN(hexbn2, bn); | ||
154 | p1 = sshbuf_new(); | ||
155 | ASSERT_PTR_NE(p1, NULL); | ||
156 | ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); | ||
157 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4 + 1); /* MSB */ | ||
158 | ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn) + 1); | ||
159 | ASSERT_U8_EQ(*(sshbuf_ptr(p1) + 4), 0x00); | ||
160 | ASSERT_MEM_EQ(sshbuf_ptr(p1) + 5, expbn2, sizeof(expbn2)); | ||
161 | BN_free(bn); | ||
162 | sshbuf_free(p1); | ||
163 | TEST_DONE(); | ||
164 | |||
165 | TEST_START("sshbuf_put_bignum2 bn2 limited"); | ||
166 | MKBN(hexbn2, bn); | ||
167 | p1 = sshbuf_new(); | ||
168 | ASSERT_PTR_NE(p1, NULL); | ||
169 | ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn2) + 3), 0); | ||
170 | r = sshbuf_put_bignum2(p1, bn); | ||
171 | ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); | ||
172 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); | ||
173 | BN_free(bn); | ||
174 | sshbuf_free(p1); | ||
175 | TEST_DONE(); | ||
176 | |||
177 | TEST_START("sshbuf_get_bignum1"); | ||
178 | MKBN(hexbn1, bn); | ||
179 | p1 = sshbuf_new(); | ||
180 | ASSERT_PTR_NE(p1, NULL); | ||
181 | ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); | ||
182 | ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0); | ||
183 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1)); | ||
184 | ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); | ||
185 | bn2 = BN_new(); | ||
186 | ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0); | ||
187 | ASSERT_BIGNUM_EQ(bn, bn2); | ||
188 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
189 | BN_free(bn); | ||
190 | BN_free(bn2); | ||
191 | sshbuf_free(p1); | ||
192 | TEST_DONE(); | ||
193 | |||
194 | TEST_START("sshbuf_get_bignum1 truncated"); | ||
195 | MKBN(hexbn1, bn); | ||
196 | p1 = sshbuf_new(); | ||
197 | ASSERT_PTR_NE(p1, NULL); | ||
198 | ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); | ||
199 | ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0); | ||
200 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1); | ||
201 | bn2 = BN_new(); | ||
202 | r = sshbuf_get_bignum1(p1, bn2); | ||
203 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
204 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1); | ||
205 | BN_free(bn); | ||
206 | BN_free(bn2); | ||
207 | sshbuf_free(p1); | ||
208 | TEST_DONE(); | ||
209 | |||
210 | TEST_START("sshbuf_get_bignum1 giant"); | ||
211 | MKBN(hexbn1, bn); | ||
212 | p1 = sshbuf_new(); | ||
213 | ASSERT_PTR_NE(p1, NULL); | ||
214 | ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xffff), 0); | ||
215 | ASSERT_INT_EQ(sshbuf_reserve(p1, (0xffff + 7) / 8, NULL), 0); | ||
216 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8)); | ||
217 | bn2 = BN_new(); | ||
218 | r = sshbuf_get_bignum1(p1, bn2); | ||
219 | ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE); | ||
220 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8)); | ||
221 | BN_free(bn); | ||
222 | BN_free(bn2); | ||
223 | sshbuf_free(p1); | ||
224 | TEST_DONE(); | ||
225 | |||
226 | TEST_START("sshbuf_get_bignum1 bn2"); | ||
227 | MKBN(hexbn2, bn); | ||
228 | p1 = sshbuf_new(); | ||
229 | ASSERT_PTR_NE(p1, NULL); | ||
230 | ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); | ||
231 | ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); | ||
232 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2)); | ||
233 | ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); | ||
234 | bn2 = BN_new(); | ||
235 | ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0); | ||
236 | ASSERT_BIGNUM_EQ(bn, bn2); | ||
237 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
238 | BN_free(bn); | ||
239 | BN_free(bn2); | ||
240 | sshbuf_free(p1); | ||
241 | TEST_DONE(); | ||
242 | |||
243 | TEST_START("sshbuf_get_bignum1 bn2 truncated"); | ||
244 | MKBN(hexbn2, bn); | ||
245 | p1 = sshbuf_new(); | ||
246 | ASSERT_PTR_NE(p1, NULL); | ||
247 | ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); | ||
248 | ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0); | ||
249 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1); | ||
250 | bn2 = BN_new(); | ||
251 | r = sshbuf_get_bignum1(p1, bn2); | ||
252 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
253 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1); | ||
254 | BN_free(bn); | ||
255 | BN_free(bn2); | ||
256 | sshbuf_free(p1); | ||
257 | TEST_DONE(); | ||
258 | |||
259 | TEST_START("sshbuf_get_bignum2"); | ||
260 | MKBN(hexbn1, bn); | ||
261 | p1 = sshbuf_new(); | ||
262 | ASSERT_PTR_NE(p1, NULL); | ||
263 | ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); | ||
264 | ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0); | ||
265 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + sizeof(expbn1)); | ||
266 | ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); | ||
267 | bn2 = BN_new(); | ||
268 | ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0); | ||
269 | ASSERT_BIGNUM_EQ(bn, bn2); | ||
270 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
271 | BN_free(bn); | ||
272 | BN_free(bn2); | ||
273 | sshbuf_free(p1); | ||
274 | TEST_DONE(); | ||
275 | |||
276 | TEST_START("sshbuf_get_bignum2 truncated"); | ||
277 | MKBN(hexbn1, bn); | ||
278 | p1 = sshbuf_new(); | ||
279 | ASSERT_PTR_NE(p1, NULL); | ||
280 | ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); | ||
281 | ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0); | ||
282 | bn2 = BN_new(); | ||
283 | r = sshbuf_get_bignum2(p1, bn2); | ||
284 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
285 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 3); | ||
286 | BN_free(bn); | ||
287 | BN_free(bn2); | ||
288 | sshbuf_free(p1); | ||
289 | TEST_DONE(); | ||
290 | |||
291 | TEST_START("sshbuf_get_bignum2 giant"); | ||
292 | MKBN(hexbn1, bn); | ||
293 | p1 = sshbuf_new(); | ||
294 | ASSERT_PTR_NE(p1, NULL); | ||
295 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 65536), 0); | ||
296 | ASSERT_INT_EQ(sshbuf_reserve(p1, 65536, NULL), 0); | ||
297 | bn2 = BN_new(); | ||
298 | r = sshbuf_get_bignum2(p1, bn2); | ||
299 | ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE); | ||
300 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 65536 + 4); | ||
301 | BN_free(bn); | ||
302 | BN_free(bn2); | ||
303 | sshbuf_free(p1); | ||
304 | TEST_DONE(); | ||
305 | |||
306 | TEST_START("sshbuf_get_bignum2 bn2"); | ||
307 | MKBN(hexbn2, bn); | ||
308 | p1 = sshbuf_new(); | ||
309 | ASSERT_PTR_NE(p1, NULL); | ||
310 | ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); /* MSB */ | ||
311 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); | ||
312 | ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); | ||
313 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + 1 + sizeof(expbn2)); | ||
314 | ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); | ||
315 | bn2 = BN_new(); | ||
316 | ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0); | ||
317 | ASSERT_BIGNUM_EQ(bn, bn2); | ||
318 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
319 | BN_free(bn); | ||
320 | BN_free(bn2); | ||
321 | sshbuf_free(p1); | ||
322 | TEST_DONE(); | ||
323 | |||
324 | TEST_START("sshbuf_get_bignum2 bn2 truncated"); | ||
325 | MKBN(hexbn2, bn); | ||
326 | p1 = sshbuf_new(); | ||
327 | ASSERT_PTR_NE(p1, NULL); | ||
328 | ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); | ||
329 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); | ||
330 | ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0); | ||
331 | bn2 = BN_new(); | ||
332 | r = sshbuf_get_bignum2(p1, bn2); | ||
333 | ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); | ||
334 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 1 + 4 - 1); | ||
335 | BN_free(bn); | ||
336 | BN_free(bn2); | ||
337 | sshbuf_free(p1); | ||
338 | TEST_DONE(); | ||
339 | |||
340 | TEST_START("sshbuf_get_bignum2 bn2 negative"); | ||
341 | MKBN(hexbn2, bn); | ||
342 | p1 = sshbuf_new(); | ||
343 | ASSERT_PTR_NE(p1, NULL); | ||
344 | ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); | ||
345 | ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); | ||
346 | bn2 = BN_new(); | ||
347 | r = sshbuf_get_bignum2(p1, bn2); | ||
348 | ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_IS_NEGATIVE); | ||
349 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4); | ||
350 | BN_free(bn); | ||
351 | BN_free(bn2); | ||
352 | sshbuf_free(p1); | ||
353 | TEST_DONE(); | ||
354 | |||
355 | #ifdef OPENSSL_HAS_NISTP256 | ||
356 | TEST_START("sshbuf_put_ec"); | ||
357 | eck = EC_KEY_new_by_curve_name(ec256_nid); | ||
358 | ASSERT_PTR_NE(eck, NULL); | ||
359 | ecp = EC_POINT_new(EC_KEY_get0_group(eck)); | ||
360 | ASSERT_PTR_NE(ecp, NULL); | ||
361 | MKBN(ec256_x, bn_x); | ||
362 | MKBN(ec256_y, bn_y); | ||
363 | ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp( | ||
364 | EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1); | ||
365 | ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1); | ||
366 | BN_free(bn_x); | ||
367 | BN_free(bn_y); | ||
368 | EC_POINT_free(ecp); | ||
369 | p1 = sshbuf_new(); | ||
370 | ASSERT_PTR_NE(p1, NULL); | ||
371 | ASSERT_INT_EQ(sshbuf_put_eckey(p1, eck), 0); | ||
372 | ASSERT_INT_EQ(sshbuf_get_string_direct(p1, &d, &s), 0); | ||
373 | ASSERT_SIZE_T_EQ(s, sizeof(expec256)); | ||
374 | ASSERT_MEM_EQ(d, expec256, sizeof(expec256)); | ||
375 | sshbuf_free(p1); | ||
376 | EC_KEY_free(eck); | ||
377 | TEST_DONE(); | ||
378 | |||
379 | TEST_START("sshbuf_get_ec"); | ||
380 | eck = EC_KEY_new_by_curve_name(ec256_nid); | ||
381 | ASSERT_PTR_NE(eck, NULL); | ||
382 | p1 = sshbuf_new(); | ||
383 | ASSERT_PTR_NE(p1, NULL); | ||
384 | ASSERT_INT_EQ(sshbuf_put_string(p1, expec256, sizeof(expec256)), 0); | ||
385 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expec256) + 4); | ||
386 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); | ||
387 | ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0); | ||
388 | bn_x = BN_new(); | ||
389 | bn_y = BN_new(); | ||
390 | ASSERT_PTR_NE(bn_x, NULL); | ||
391 | ASSERT_PTR_NE(bn_y, NULL); | ||
392 | ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp( | ||
393 | EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck), | ||
394 | bn_x, bn_y, NULL), 1); | ||
395 | MKBN(ec256_x, bn); | ||
396 | MKBN(ec256_y, bn2); | ||
397 | ASSERT_INT_EQ(BN_cmp(bn_x, bn), 0); | ||
398 | ASSERT_INT_EQ(BN_cmp(bn_y, bn2), 0); | ||
399 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
400 | sshbuf_free(p1); | ||
401 | EC_KEY_free(eck); | ||
402 | BN_free(bn_x); | ||
403 | BN_free(bn_y); | ||
404 | BN_free(bn); | ||
405 | BN_free(bn2); | ||
406 | TEST_DONE(); | ||
407 | #endif | ||
408 | } | ||
409 | |||
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c new file mode 100644 index 000000000..8c3269b13 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.2 2014/05/02 02:54:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <stdio.h> | ||
13 | #ifdef HAVE_STDINT_H | ||
14 | # include <stdint.h> | ||
15 | #endif | ||
16 | #include <stdlib.h> | ||
17 | #include <string.h> | ||
18 | |||
19 | #include <openssl/bn.h> | ||
20 | #include <openssl/objects.h> | ||
21 | #ifdef OPENSSL_HAS_NISTP256 | ||
22 | # include <openssl/ec.h> | ||
23 | #endif | ||
24 | |||
25 | #include "../test_helper/test_helper.h" | ||
26 | #include "ssherr.h" | ||
27 | #include "sshbuf.h" | ||
28 | |||
29 | void sshbuf_getput_fuzz_tests(void); | ||
30 | |||
31 | static void | ||
32 | attempt_parse_blob(u_char *blob, size_t len) | ||
33 | { | ||
34 | struct sshbuf *p1; | ||
35 | BIGNUM *bn; | ||
36 | #ifdef OPENSSL_HAS_NISTP256 | ||
37 | EC_KEY *eck; | ||
38 | #endif | ||
39 | u_char *s; | ||
40 | size_t l; | ||
41 | u_int8_t u8; | ||
42 | u_int16_t u16; | ||
43 | u_int32_t u32; | ||
44 | u_int64_t u64; | ||
45 | |||
46 | p1 = sshbuf_new(); | ||
47 | ASSERT_PTR_NE(p1, NULL); | ||
48 | ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0); | ||
49 | sshbuf_get_u8(p1, &u8); | ||
50 | sshbuf_get_u16(p1, &u16); | ||
51 | sshbuf_get_u32(p1, &u32); | ||
52 | sshbuf_get_u64(p1, &u64); | ||
53 | if (sshbuf_get_string(p1, &s, &l) == 0) { | ||
54 | bzero(s, l); | ||
55 | free(s); | ||
56 | } | ||
57 | bn = BN_new(); | ||
58 | sshbuf_get_bignum1(p1, bn); | ||
59 | BN_clear_free(bn); | ||
60 | bn = BN_new(); | ||
61 | sshbuf_get_bignum2(p1, bn); | ||
62 | BN_clear_free(bn); | ||
63 | #ifdef OPENSSL_HAS_NISTP256 | ||
64 | eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); | ||
65 | ASSERT_PTR_NE(eck, NULL); | ||
66 | sshbuf_get_eckey(p1, eck); | ||
67 | EC_KEY_free(eck); | ||
68 | #endif | ||
69 | sshbuf_free(p1); | ||
70 | } | ||
71 | |||
72 | |||
73 | static void | ||
74 | onerror(void *fuzz) | ||
75 | { | ||
76 | fprintf(stderr, "Failed during fuzz:\n"); | ||
77 | fuzz_dump((struct fuzz *)fuzz); | ||
78 | } | ||
79 | |||
80 | void | ||
81 | sshbuf_getput_fuzz_tests(void) | ||
82 | { | ||
83 | u_char blob[] = { | ||
84 | /* u8 */ | ||
85 | 0xd0, | ||
86 | /* u16 */ | ||
87 | 0xc0, 0xde, | ||
88 | /* u32 */ | ||
89 | 0xfa, 0xce, 0xde, 0xad, | ||
90 | /* u64 */ | ||
91 | 0xfe, 0xed, 0xac, 0x1d, 0x1f, 0x1c, 0xbe, 0xef, | ||
92 | /* string */ | ||
93 | 0x00, 0x00, 0x00, 0x09, | ||
94 | 'O', ' ', 'G', 'o', 'r', 'g', 'o', 'n', '!', | ||
95 | /* bignum1 */ | ||
96 | 0x79, | ||
97 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
98 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, | ||
99 | /* bignum2 */ | ||
100 | 0x00, 0x00, 0x00, 0x14, | ||
101 | 0x00, | ||
102 | 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, | ||
103 | 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, | ||
104 | 0x7f, 0xff, 0x11, | ||
105 | /* EC point (NIST-256 curve) */ | ||
106 | 0x00, 0x00, 0x00, 0x41, | ||
107 | 0x04, | ||
108 | 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06, | ||
109 | 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57, | ||
110 | 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86, | ||
111 | 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99, | ||
112 | 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b, | ||
113 | 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2, | ||
114 | 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47, | ||
115 | 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4, | ||
116 | }; | ||
117 | struct fuzz *fuzz; | ||
118 | |||
119 | TEST_START("fuzz blob parsing"); | ||
120 | fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | | ||
121 | FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | | ||
122 | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, blob, sizeof(blob)); | ||
123 | TEST_ONERROR(onerror, fuzz); | ||
124 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) | ||
125 | attempt_parse_blob(blob, sizeof(blob)); | ||
126 | fuzz_cleanup(fuzz); | ||
127 | TEST_DONE(); | ||
128 | TEST_ONERROR(NULL, NULL); | ||
129 | } | ||
130 | |||
diff --git a/regress/unittests/sshbuf/test_sshbuf_misc.c b/regress/unittests/sshbuf/test_sshbuf_misc.c new file mode 100644 index 000000000..f155491a0 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_misc.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* $OpenBSD: test_sshbuf_misc.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <stdio.h> | ||
13 | #ifdef HAVE_STDINT_H | ||
14 | # include <stdint.h> | ||
15 | #endif | ||
16 | #include <stdlib.h> | ||
17 | #include <string.h> | ||
18 | |||
19 | #include "../test_helper/test_helper.h" | ||
20 | |||
21 | #include "sshbuf.h" | ||
22 | |||
23 | void sshbuf_misc_tests(void); | ||
24 | |||
25 | void | ||
26 | sshbuf_misc_tests(void) | ||
27 | { | ||
28 | struct sshbuf *p1; | ||
29 | char tmp[512], *p; | ||
30 | FILE *out; | ||
31 | size_t sz; | ||
32 | |||
33 | TEST_START("sshbuf_dump"); | ||
34 | out = tmpfile(); | ||
35 | ASSERT_PTR_NE(out, NULL); | ||
36 | p1 = sshbuf_new(); | ||
37 | ASSERT_PTR_NE(p1, NULL); | ||
38 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); | ||
39 | sshbuf_dump(p1, out); | ||
40 | fflush(out); | ||
41 | rewind(out); | ||
42 | sz = fread(tmp, 1, sizeof(tmp), out); | ||
43 | ASSERT_INT_EQ(ferror(out), 0); | ||
44 | ASSERT_INT_NE(feof(out), 0); | ||
45 | ASSERT_SIZE_T_GT(sz, 0); | ||
46 | tmp[sz] = '\0'; | ||
47 | ASSERT_PTR_NE(strstr(tmp, "12 34 56 78"), NULL); | ||
48 | fclose(out); | ||
49 | sshbuf_free(p1); | ||
50 | TEST_DONE(); | ||
51 | |||
52 | TEST_START("sshbuf_dtob16"); | ||
53 | p1 = sshbuf_new(); | ||
54 | ASSERT_PTR_NE(p1, NULL); | ||
55 | ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); | ||
56 | p = sshbuf_dtob16(p1); | ||
57 | ASSERT_PTR_NE(p, NULL); | ||
58 | ASSERT_STRING_EQ(p, "12345678"); | ||
59 | free(p); | ||
60 | sshbuf_free(p1); | ||
61 | TEST_DONE(); | ||
62 | |||
63 | TEST_START("sshbuf_dtob64 len 1"); | ||
64 | p1 = sshbuf_new(); | ||
65 | ASSERT_PTR_NE(p1, NULL); | ||
66 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); | ||
67 | p = sshbuf_dtob64(p1); | ||
68 | ASSERT_PTR_NE(p, NULL); | ||
69 | ASSERT_STRING_EQ(p, "EQ=="); | ||
70 | free(p); | ||
71 | sshbuf_free(p1); | ||
72 | TEST_DONE(); | ||
73 | |||
74 | TEST_START("sshbuf_dtob64 len 2"); | ||
75 | p1 = sshbuf_new(); | ||
76 | ASSERT_PTR_NE(p1, NULL); | ||
77 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); | ||
78 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0); | ||
79 | p = sshbuf_dtob64(p1); | ||
80 | ASSERT_PTR_NE(p, NULL); | ||
81 | ASSERT_STRING_EQ(p, "ESI="); | ||
82 | free(p); | ||
83 | sshbuf_free(p1); | ||
84 | TEST_DONE(); | ||
85 | |||
86 | TEST_START("sshbuf_dtob64 len 3"); | ||
87 | p1 = sshbuf_new(); | ||
88 | ASSERT_PTR_NE(p1, NULL); | ||
89 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); | ||
90 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0); | ||
91 | ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x33), 0); | ||
92 | p = sshbuf_dtob64(p1); | ||
93 | ASSERT_PTR_NE(p, NULL); | ||
94 | ASSERT_STRING_EQ(p, "ESIz"); | ||
95 | free(p); | ||
96 | sshbuf_free(p1); | ||
97 | TEST_DONE(); | ||
98 | |||
99 | TEST_START("sshbuf_dtob64 len 8191"); | ||
100 | p1 = sshbuf_new(); | ||
101 | ASSERT_PTR_NE(p1, NULL); | ||
102 | ASSERT_INT_EQ(sshbuf_reserve(p1, 8192, NULL), 0); | ||
103 | bzero(sshbuf_mutable_ptr(p1), 8192); | ||
104 | p = sshbuf_dtob64(p1); | ||
105 | ASSERT_PTR_NE(p, NULL); | ||
106 | ASSERT_SIZE_T_EQ(strlen(p), ((8191 + 2) / 3) * 4); | ||
107 | free(p); | ||
108 | sshbuf_free(p1); | ||
109 | TEST_DONE(); | ||
110 | |||
111 | TEST_START("sshbuf_b64tod len 1"); | ||
112 | p1 = sshbuf_new(); | ||
113 | ASSERT_PTR_NE(p1, NULL); | ||
114 | ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A=="), 0); | ||
115 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); | ||
116 | ASSERT_U8_EQ(*sshbuf_ptr(p1), 0xd0); | ||
117 | sshbuf_free(p1); | ||
118 | TEST_DONE(); | ||
119 | |||
120 | TEST_START("sshbuf_b64tod len 2"); | ||
121 | p1 = sshbuf_new(); | ||
122 | ASSERT_PTR_NE(p1, NULL); | ||
123 | ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A8="), 0); | ||
124 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); | ||
125 | ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), 0xd00f); | ||
126 | sshbuf_free(p1); | ||
127 | TEST_DONE(); | ||
128 | |||
129 | TEST_START("sshbuf_b64tod len 4"); | ||
130 | p1 = sshbuf_new(); | ||
131 | ASSERT_PTR_NE(p1, NULL); | ||
132 | ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A/QDw=="), 0); | ||
133 | ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); | ||
134 | ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), 0xd00fd00f); | ||
135 | sshbuf_free(p1); | ||
136 | TEST_DONE(); | ||
137 | } | ||
138 | |||
diff --git a/regress/unittests/sshbuf/tests.c b/regress/unittests/sshbuf/tests.c new file mode 100644 index 000000000..1557e4342 --- /dev/null +++ b/regress/unittests/sshbuf/tests.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /* $OpenBSD: tests.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "../test_helper/test_helper.h" | ||
9 | |||
10 | void sshbuf_tests(void); | ||
11 | void sshbuf_getput_basic_tests(void); | ||
12 | void sshbuf_getput_crypto_tests(void); | ||
13 | void sshbuf_misc_tests(void); | ||
14 | void sshbuf_fuzz_tests(void); | ||
15 | void sshbuf_getput_fuzz_tests(void); | ||
16 | void sshbuf_fixed(void); | ||
17 | |||
18 | void | ||
19 | tests(void) | ||
20 | { | ||
21 | sshbuf_tests(); | ||
22 | sshbuf_getput_basic_tests(); | ||
23 | sshbuf_getput_crypto_tests(); | ||
24 | sshbuf_misc_tests(); | ||
25 | sshbuf_fuzz_tests(); | ||
26 | sshbuf_getput_fuzz_tests(); | ||
27 | sshbuf_fixed(); | ||
28 | } | ||
diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile new file mode 100644 index 000000000..1bcd26676 --- /dev/null +++ b/regress/unittests/sshkey/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # $OpenBSD: Makefile,v 1.1 2014/06/24 01:14:18 djm Exp $ | ||
2 | |||
3 | TEST_ENV= "MALLOC_OPTIONS=AFGJPRX" | ||
4 | |||
5 | PROG=test_sshkey | ||
6 | SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c | ||
7 | REGRESS_TARGETS=run-regress-${PROG} | ||
8 | |||
9 | run-regress-${PROG}: ${PROG} | ||
10 | env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata | ||
11 | |||
12 | .include <bsd.regress.mk> | ||
13 | |||
diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c new file mode 100644 index 000000000..0a4b3a90c --- /dev/null +++ b/regress/unittests/sshkey/common.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* $OpenBSD: common.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ | ||
2 | /* | ||
3 | * Helpers for key API tests | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <sys/stat.h> | ||
13 | #include <fcntl.h> | ||
14 | #include <stdio.h> | ||
15 | #ifdef HAVE_STDINT_H | ||
16 | #include <stdint.h> | ||
17 | #endif | ||
18 | #include <stdlib.h> | ||
19 | #include <string.h> | ||
20 | #include <unistd.h> | ||
21 | |||
22 | #include <openssl/bn.h> | ||
23 | #include <openssl/rsa.h> | ||
24 | #include <openssl/dsa.h> | ||
25 | #include <openssl/objects.h> | ||
26 | #ifdef OPENSSL_HAS_NISTP256 | ||
27 | # include <openssl/ec.h> | ||
28 | #endif | ||
29 | |||
30 | #include "../test_helper/test_helper.h" | ||
31 | |||
32 | #include "ssherr.h" | ||
33 | #include "authfile.h" | ||
34 | #include "sshkey.h" | ||
35 | #include "sshbuf.h" | ||
36 | |||
37 | #include "common.h" | ||
38 | |||
39 | struct sshbuf * | ||
40 | load_file(const char *name) | ||
41 | { | ||
42 | int fd; | ||
43 | struct sshbuf *ret; | ||
44 | |||
45 | ASSERT_PTR_NE(ret = sshbuf_new(), NULL); | ||
46 | ASSERT_INT_NE(fd = open(test_data_file(name), O_RDONLY), -1); | ||
47 | ASSERT_INT_EQ(sshkey_load_file(fd, name, ret), 0); | ||
48 | close(fd); | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | struct sshbuf * | ||
53 | load_text_file(const char *name) | ||
54 | { | ||
55 | struct sshbuf *ret = load_file(name); | ||
56 | const u_char *p; | ||
57 | |||
58 | /* Trim whitespace at EOL */ | ||
59 | for (p = sshbuf_ptr(ret); sshbuf_len(ret) > 0;) { | ||
60 | if (p[sshbuf_len(ret) - 1] == '\r' || | ||
61 | p[sshbuf_len(ret) - 1] == '\t' || | ||
62 | p[sshbuf_len(ret) - 1] == ' ' || | ||
63 | p[sshbuf_len(ret) - 1] == '\n') | ||
64 | ASSERT_INT_EQ(sshbuf_consume_end(ret, 1), 0); | ||
65 | else | ||
66 | break; | ||
67 | } | ||
68 | /* \0 terminate */ | ||
69 | ASSERT_INT_EQ(sshbuf_put_u8(ret, 0), 0); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | BIGNUM * | ||
74 | load_bignum(const char *name) | ||
75 | { | ||
76 | BIGNUM *ret = NULL; | ||
77 | struct sshbuf *buf; | ||
78 | |||
79 | buf = load_text_file(name); | ||
80 | ASSERT_INT_NE(BN_hex2bn(&ret, (const char *)sshbuf_ptr(buf)), 0); | ||
81 | sshbuf_free(buf); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
diff --git a/regress/unittests/sshkey/common.h b/regress/unittests/sshkey/common.h new file mode 100644 index 000000000..bf7d19dce --- /dev/null +++ b/regress/unittests/sshkey/common.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* $OpenBSD: common.h,v 1.1 2014/06/24 01:14:18 djm Exp $ */ | ||
2 | /* | ||
3 | * Helpers for key API tests | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | /* Load a binary file into a buffer */ | ||
9 | struct sshbuf *load_file(const char *name); | ||
10 | |||
11 | /* Load a text file into a buffer */ | ||
12 | struct sshbuf *load_text_file(const char *name); | ||
13 | |||
14 | /* Load a bignum from a file */ | ||
15 | BIGNUM *load_bignum(const char *name); | ||
16 | |||
diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh new file mode 100755 index 000000000..ee1fe3962 --- /dev/null +++ b/regress/unittests/sshkey/mktestdata.sh | |||
@@ -0,0 +1,190 @@ | |||
1 | #!/bin/sh | ||
2 | # $OpenBSD: mktestdata.sh,v 1.3 2014/07/22 23:57:40 dtucker Exp $ | ||
3 | |||
4 | PW=mekmitasdigoat | ||
5 | |||
6 | rsa1_params() { | ||
7 | _in="$1" | ||
8 | _outbase="$2" | ||
9 | set -e | ||
10 | ssh-keygen -f $_in -e -m pkcs8 | \ | ||
11 | openssl rsa -noout -text -pubin | \ | ||
12 | awk '/^Modulus:$/,/^Exponent:/' | \ | ||
13 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n | ||
14 | # XXX need conversion support in ssh-keygen for the other params | ||
15 | for x in n ; do | ||
16 | echo "" >> ${_outbase}.$x | ||
17 | echo ============ ${_outbase}.$x | ||
18 | cat ${_outbase}.$x | ||
19 | echo ============ | ||
20 | done | ||
21 | } | ||
22 | |||
23 | rsa_params() { | ||
24 | _in="$1" | ||
25 | _outbase="$2" | ||
26 | set -e | ||
27 | openssl rsa -noout -text -in $_in | \ | ||
28 | awk '/^modulus:$/,/^publicExponent:/' | \ | ||
29 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n | ||
30 | openssl rsa -noout -text -in $_in | \ | ||
31 | awk '/^prime1:$/,/^prime2:/' | \ | ||
32 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.p | ||
33 | openssl rsa -noout -text -in $_in | \ | ||
34 | awk '/^prime2:$/,/^exponent1:/' | \ | ||
35 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.q | ||
36 | for x in n p q ; do | ||
37 | echo "" >> ${_outbase}.$x | ||
38 | echo ============ ${_outbase}.$x | ||
39 | cat ${_outbase}.$x | ||
40 | echo ============ | ||
41 | done | ||
42 | } | ||
43 | |||
44 | dsa_params() { | ||
45 | _in="$1" | ||
46 | _outbase="$2" | ||
47 | set -e | ||
48 | openssl dsa -noout -text -in $_in | \ | ||
49 | awk '/^priv:$/,/^pub:/' | \ | ||
50 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv | ||
51 | openssl dsa -noout -text -in $_in | \ | ||
52 | awk '/^pub:/,/^P:/' | #\ | ||
53 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub | ||
54 | openssl dsa -noout -text -in $_in | \ | ||
55 | awk '/^G:/,0' | \ | ||
56 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.g | ||
57 | for x in priv pub g ; do | ||
58 | echo "" >> ${_outbase}.$x | ||
59 | echo ============ ${_outbase}.$x | ||
60 | cat ${_outbase}.$x | ||
61 | echo ============ | ||
62 | done | ||
63 | } | ||
64 | |||
65 | ecdsa_params() { | ||
66 | _in="$1" | ||
67 | _outbase="$2" | ||
68 | set -e | ||
69 | openssl ec -noout -text -in $_in | \ | ||
70 | awk '/^priv:$/,/^pub:/' | \ | ||
71 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv | ||
72 | openssl ec -noout -text -in $_in | \ | ||
73 | awk '/^pub:/,/^ASN1 OID:/' | #\ | ||
74 | grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub | ||
75 | openssl ec -noout -text -in $_in | \ | ||
76 | grep "ASN1 OID:" | tr -d '\n' | \ | ||
77 | sed 's/.*: //;s/ *$//' > ${_outbase}.curve | ||
78 | for x in priv pub curve ; do | ||
79 | echo "" >> ${_outbase}.$x | ||
80 | echo ============ ${_outbase}.$x | ||
81 | cat ${_outbase}.$x | ||
82 | echo ============ | ||
83 | done | ||
84 | } | ||
85 | |||
86 | set -ex | ||
87 | |||
88 | cd testdata | ||
89 | |||
90 | rm -f rsa1_1 rsa_1 dsa_1 ecdsa_1 ed25519_1 | ||
91 | rm -f rsa1_2 rsa_2 dsa_2 ecdsa_2 ed25519_2 | ||
92 | rm -f rsa_n dsa_n ecdsa_n # new-format keys | ||
93 | rm -f rsa1_1_pw rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw | ||
94 | rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw | ||
95 | rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb | ||
96 | |||
97 | ssh-keygen -t rsa1 -b 768 -C "RSA1 test key #1" -N "" -f rsa1_1 | ||
98 | ssh-keygen -t rsa -b 768 -C "RSA test key #1" -N "" -f rsa_1 | ||
99 | ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 | ||
100 | ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 | ||
101 | ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1 | ||
102 | |||
103 | ssh-keygen -t rsa1 -b 2048 -C "RSA1 test key #2" -N "" -f rsa1_2 | ||
104 | ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 | ||
105 | ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 | ||
106 | ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 | ||
107 | ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_2 | ||
108 | |||
109 | cp rsa_1 rsa_n | ||
110 | cp dsa_1 dsa_n | ||
111 | cp ecdsa_1 ecdsa_n | ||
112 | |||
113 | cp rsa1_1 rsa1_1_pw | ||
114 | cp rsa_1 rsa_1_pw | ||
115 | cp dsa_1 dsa_1_pw | ||
116 | cp ecdsa_1 ecdsa_1_pw | ||
117 | cp ed25519_1 ed25519_1_pw | ||
118 | cp rsa_1 rsa_n_pw | ||
119 | cp dsa_1 dsa_n_pw | ||
120 | cp ecdsa_1 ecdsa_n_pw | ||
121 | |||
122 | ssh-keygen -pf rsa1_1_pw -N "$PW" | ||
123 | ssh-keygen -pf rsa_1_pw -N "$PW" | ||
124 | ssh-keygen -pf dsa_1_pw -N "$PW" | ||
125 | ssh-keygen -pf ecdsa_1_pw -N "$PW" | ||
126 | ssh-keygen -pf ed25519_1_pw -N "$PW" | ||
127 | ssh-keygen -opf rsa_n_pw -N "$PW" | ||
128 | ssh-keygen -opf dsa_n_pw -N "$PW" | ||
129 | ssh-keygen -opf ecdsa_n_pw -N "$PW" | ||
130 | |||
131 | rsa1_params rsa1_1 rsa1_1.param | ||
132 | rsa1_params rsa1_2 rsa1_2.param | ||
133 | rsa_params rsa_1 rsa_1.param | ||
134 | rsa_params rsa_2 rsa_2.param | ||
135 | dsa_params dsa_1 dsa_1.param | ||
136 | dsa_params dsa_1 dsa_1.param | ||
137 | ecdsa_params ecdsa_1 ecdsa_1.param | ||
138 | ecdsa_params ecdsa_2 ecdsa_2.param | ||
139 | # XXX ed25519 params | ||
140 | |||
141 | ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ | ||
142 | -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ | ||
143 | -V 19990101:20110101 -z 1 rsa_1.pub | ||
144 | ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ | ||
145 | -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ | ||
146 | -V 19990101:20110101 -z 2 dsa_1.pub | ||
147 | ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ | ||
148 | -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ | ||
149 | -V 19990101:20110101 -z 3 ecdsa_1.pub | ||
150 | ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ | ||
151 | -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ | ||
152 | -V 19990101:20110101 -z 4 ed25519_1.pub | ||
153 | |||
154 | ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ | ||
155 | -V 19990101:20110101 -z 5 rsa_1.pub | ||
156 | ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ | ||
157 | -V 19990101:20110101 -z 6 dsa_1.pub | ||
158 | ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ | ||
159 | -V 19990101:20110101 -z 7 ecdsa_1.pub | ||
160 | ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ | ||
161 | -V 19990101:20110101 -z 8 ed25519_1.pub | ||
162 | |||
163 | ssh-keygen -lf rsa1_1 | awk '{print $2}' > rsa1_1.fp | ||
164 | ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp | ||
165 | ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp | ||
166 | ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp | ||
167 | ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp | ||
168 | ssh-keygen -lf rsa1_2 | awk '{print $2}' > rsa1_2.fp | ||
169 | ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp | ||
170 | ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp | ||
171 | ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp | ||
172 | ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp | ||
173 | |||
174 | ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp | ||
175 | ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp | ||
176 | ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp | ||
177 | ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp | ||
178 | |||
179 | ssh-keygen -Bf rsa1_1 | awk '{print $2}' > rsa1_1.fp.bb | ||
180 | ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb | ||
181 | ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb | ||
182 | ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb | ||
183 | ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb | ||
184 | ssh-keygen -Bf rsa1_2 | awk '{print $2}' > rsa1_2.fp.bb | ||
185 | ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb | ||
186 | ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb | ||
187 | ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb | ||
188 | ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb | ||
189 | |||
190 | echo "$PW" > pw | ||
diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c new file mode 100644 index 000000000..764f7fb76 --- /dev/null +++ b/regress/unittests/sshkey/test_file.c | |||
@@ -0,0 +1,457 @@ | |||
1 | /* $OpenBSD: test_file.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshkey.h key management API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <sys/stat.h> | ||
13 | #include <fcntl.h> | ||
14 | #include <stdio.h> | ||
15 | #ifdef HAVE_STDINT_H | ||
16 | #include <stdint.h> | ||
17 | #endif | ||
18 | #include <stdlib.h> | ||
19 | #include <string.h> | ||
20 | #include <unistd.h> | ||
21 | |||
22 | #include <openssl/bn.h> | ||
23 | #include <openssl/rsa.h> | ||
24 | #include <openssl/dsa.h> | ||
25 | #include <openssl/objects.h> | ||
26 | #ifdef OPENSSL_HAS_NISTP256 | ||
27 | # include <openssl/ec.h> | ||
28 | #endif | ||
29 | |||
30 | #include "../test_helper/test_helper.h" | ||
31 | |||
32 | #include "ssherr.h" | ||
33 | #include "authfile.h" | ||
34 | #include "sshkey.h" | ||
35 | #include "sshbuf.h" | ||
36 | |||
37 | #include "common.h" | ||
38 | |||
39 | void sshkey_file_tests(void); | ||
40 | |||
41 | void | ||
42 | sshkey_file_tests(void) | ||
43 | { | ||
44 | struct sshkey *k1, *k2; | ||
45 | struct sshbuf *buf, *pw; | ||
46 | BIGNUM *a, *b, *c; | ||
47 | char *cp; | ||
48 | |||
49 | TEST_START("load passphrase"); | ||
50 | pw = load_text_file("pw"); | ||
51 | TEST_DONE(); | ||
52 | |||
53 | TEST_START("parse RSA1 from private"); | ||
54 | buf = load_file("rsa1_1"); | ||
55 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa1_1", | ||
56 | &k1, NULL), 0); | ||
57 | sshbuf_free(buf); | ||
58 | ASSERT_PTR_NE(k1, NULL); | ||
59 | a = load_bignum("rsa1_1.param.n"); | ||
60 | ASSERT_BIGNUM_EQ(k1->rsa->n, a); | ||
61 | BN_free(a); | ||
62 | TEST_DONE(); | ||
63 | |||
64 | TEST_START("parse RSA1 from private w/ passphrase"); | ||
65 | buf = load_file("rsa1_1_pw"); | ||
66 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
67 | (const char *)sshbuf_ptr(pw), "rsa1_1_pw", &k2, NULL), 0); | ||
68 | sshbuf_free(buf); | ||
69 | ASSERT_PTR_NE(k2, NULL); | ||
70 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
71 | sshkey_free(k2); | ||
72 | TEST_DONE(); | ||
73 | |||
74 | TEST_START("load RSA1 from public"); | ||
75 | ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa1_1.pub"), &k2, | ||
76 | NULL), 0); | ||
77 | ASSERT_PTR_NE(k2, NULL); | ||
78 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
79 | sshkey_free(k2); | ||
80 | TEST_DONE(); | ||
81 | |||
82 | TEST_START("RSA1 key hex fingerprint"); | ||
83 | buf = load_text_file("rsa1_1.fp"); | ||
84 | cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); | ||
85 | ASSERT_PTR_NE(cp, NULL); | ||
86 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
87 | sshbuf_free(buf); | ||
88 | free(cp); | ||
89 | TEST_DONE(); | ||
90 | |||
91 | TEST_START("RSA1 key bubblebabble fingerprint"); | ||
92 | buf = load_text_file("rsa1_1.fp.bb"); | ||
93 | cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); | ||
94 | ASSERT_PTR_NE(cp, NULL); | ||
95 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
96 | sshbuf_free(buf); | ||
97 | free(cp); | ||
98 | TEST_DONE(); | ||
99 | |||
100 | sshkey_free(k1); | ||
101 | |||
102 | TEST_START("parse RSA from private"); | ||
103 | buf = load_file("rsa_1"); | ||
104 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa_1", | ||
105 | &k1, NULL), 0); | ||
106 | sshbuf_free(buf); | ||
107 | ASSERT_PTR_NE(k1, NULL); | ||
108 | a = load_bignum("rsa_1.param.n"); | ||
109 | b = load_bignum("rsa_1.param.p"); | ||
110 | c = load_bignum("rsa_1.param.q"); | ||
111 | ASSERT_BIGNUM_EQ(k1->rsa->n, a); | ||
112 | ASSERT_BIGNUM_EQ(k1->rsa->p, b); | ||
113 | ASSERT_BIGNUM_EQ(k1->rsa->q, c); | ||
114 | BN_free(a); | ||
115 | BN_free(b); | ||
116 | BN_free(c); | ||
117 | TEST_DONE(); | ||
118 | |||
119 | TEST_START("parse RSA from private w/ passphrase"); | ||
120 | buf = load_file("rsa_1_pw"); | ||
121 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
122 | (const char *)sshbuf_ptr(pw), "rsa_1_pw", &k2, NULL), 0); | ||
123 | sshbuf_free(buf); | ||
124 | ASSERT_PTR_NE(k2, NULL); | ||
125 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
126 | sshkey_free(k2); | ||
127 | TEST_DONE(); | ||
128 | |||
129 | TEST_START("parse RSA from new-format"); | ||
130 | buf = load_file("rsa_n"); | ||
131 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
132 | "", "rsa_n", &k2, NULL), 0); | ||
133 | sshbuf_free(buf); | ||
134 | ASSERT_PTR_NE(k2, NULL); | ||
135 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
136 | sshkey_free(k2); | ||
137 | TEST_DONE(); | ||
138 | |||
139 | TEST_START("parse RSA from new-format w/ passphrase"); | ||
140 | buf = load_file("rsa_n_pw"); | ||
141 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
142 | (const char *)sshbuf_ptr(pw), "rsa_n_pw", &k2, NULL), 0); | ||
143 | sshbuf_free(buf); | ||
144 | ASSERT_PTR_NE(k2, NULL); | ||
145 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
146 | sshkey_free(k2); | ||
147 | TEST_DONE(); | ||
148 | |||
149 | TEST_START("load RSA from public"); | ||
150 | ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, | ||
151 | NULL), 0); | ||
152 | ASSERT_PTR_NE(k2, NULL); | ||
153 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
154 | sshkey_free(k2); | ||
155 | TEST_DONE(); | ||
156 | |||
157 | TEST_START("load RSA cert"); | ||
158 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k2), 0); | ||
159 | ASSERT_PTR_NE(k2, NULL); | ||
160 | ASSERT_INT_EQ(k2->type, KEY_RSA_CERT); | ||
161 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); | ||
162 | ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); | ||
163 | TEST_DONE(); | ||
164 | |||
165 | TEST_START("RSA key hex fingerprint"); | ||
166 | buf = load_text_file("rsa_1.fp"); | ||
167 | cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); | ||
168 | ASSERT_PTR_NE(cp, NULL); | ||
169 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
170 | sshbuf_free(buf); | ||
171 | free(cp); | ||
172 | TEST_DONE(); | ||
173 | |||
174 | TEST_START("RSA cert hex fingerprint"); | ||
175 | buf = load_text_file("rsa_1-cert.fp"); | ||
176 | cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); | ||
177 | ASSERT_PTR_NE(cp, NULL); | ||
178 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
179 | sshbuf_free(buf); | ||
180 | free(cp); | ||
181 | sshkey_free(k2); | ||
182 | TEST_DONE(); | ||
183 | |||
184 | TEST_START("RSA key bubblebabble fingerprint"); | ||
185 | buf = load_text_file("rsa_1.fp.bb"); | ||
186 | cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); | ||
187 | ASSERT_PTR_NE(cp, NULL); | ||
188 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
189 | sshbuf_free(buf); | ||
190 | free(cp); | ||
191 | TEST_DONE(); | ||
192 | |||
193 | sshkey_free(k1); | ||
194 | |||
195 | TEST_START("parse DSA from private"); | ||
196 | buf = load_file("dsa_1"); | ||
197 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "dsa_1", | ||
198 | &k1, NULL), 0); | ||
199 | sshbuf_free(buf); | ||
200 | ASSERT_PTR_NE(k1, NULL); | ||
201 | a = load_bignum("dsa_1.param.g"); | ||
202 | b = load_bignum("dsa_1.param.priv"); | ||
203 | c = load_bignum("dsa_1.param.pub"); | ||
204 | ASSERT_BIGNUM_EQ(k1->dsa->g, a); | ||
205 | ASSERT_BIGNUM_EQ(k1->dsa->priv_key, b); | ||
206 | ASSERT_BIGNUM_EQ(k1->dsa->pub_key, c); | ||
207 | BN_free(a); | ||
208 | BN_free(b); | ||
209 | BN_free(c); | ||
210 | TEST_DONE(); | ||
211 | |||
212 | TEST_START("parse DSA from private w/ passphrase"); | ||
213 | buf = load_file("dsa_1_pw"); | ||
214 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
215 | (const char *)sshbuf_ptr(pw), "dsa_1_pw", &k2, NULL), 0); | ||
216 | sshbuf_free(buf); | ||
217 | ASSERT_PTR_NE(k2, NULL); | ||
218 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
219 | sshkey_free(k2); | ||
220 | TEST_DONE(); | ||
221 | |||
222 | TEST_START("parse DSA from new-format"); | ||
223 | buf = load_file("dsa_n"); | ||
224 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
225 | "", "dsa_n", &k2, NULL), 0); | ||
226 | sshbuf_free(buf); | ||
227 | ASSERT_PTR_NE(k2, NULL); | ||
228 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
229 | sshkey_free(k2); | ||
230 | TEST_DONE(); | ||
231 | |||
232 | TEST_START("parse DSA from new-format w/ passphrase"); | ||
233 | buf = load_file("dsa_n_pw"); | ||
234 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
235 | (const char *)sshbuf_ptr(pw), "dsa_n_pw", &k2, NULL), 0); | ||
236 | sshbuf_free(buf); | ||
237 | ASSERT_PTR_NE(k2, NULL); | ||
238 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
239 | sshkey_free(k2); | ||
240 | TEST_DONE(); | ||
241 | |||
242 | TEST_START("load DSA from public"); | ||
243 | ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_1.pub"), &k2, | ||
244 | NULL), 0); | ||
245 | ASSERT_PTR_NE(k2, NULL); | ||
246 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
247 | sshkey_free(k2); | ||
248 | TEST_DONE(); | ||
249 | |||
250 | TEST_START("load DSA cert"); | ||
251 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k2), 0); | ||
252 | ASSERT_PTR_NE(k2, NULL); | ||
253 | ASSERT_INT_EQ(k2->type, KEY_DSA_CERT); | ||
254 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); | ||
255 | ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); | ||
256 | TEST_DONE(); | ||
257 | |||
258 | TEST_START("DSA key hex fingerprint"); | ||
259 | buf = load_text_file("dsa_1.fp"); | ||
260 | cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); | ||
261 | ASSERT_PTR_NE(cp, NULL); | ||
262 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
263 | sshbuf_free(buf); | ||
264 | free(cp); | ||
265 | TEST_DONE(); | ||
266 | |||
267 | TEST_START("DSA cert hex fingerprint"); | ||
268 | buf = load_text_file("dsa_1-cert.fp"); | ||
269 | cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); | ||
270 | ASSERT_PTR_NE(cp, NULL); | ||
271 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
272 | sshbuf_free(buf); | ||
273 | free(cp); | ||
274 | sshkey_free(k2); | ||
275 | TEST_DONE(); | ||
276 | |||
277 | TEST_START("DSA key bubblebabble fingerprint"); | ||
278 | buf = load_text_file("dsa_1.fp.bb"); | ||
279 | cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); | ||
280 | ASSERT_PTR_NE(cp, NULL); | ||
281 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
282 | sshbuf_free(buf); | ||
283 | free(cp); | ||
284 | TEST_DONE(); | ||
285 | |||
286 | sshkey_free(k1); | ||
287 | |||
288 | #ifdef OPENSSL_HAS_ECC | ||
289 | TEST_START("parse ECDSA from private"); | ||
290 | buf = load_file("ecdsa_1"); | ||
291 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "ecdsa_1", | ||
292 | &k1, NULL), 0); | ||
293 | sshbuf_free(buf); | ||
294 | ASSERT_PTR_NE(k1, NULL); | ||
295 | buf = load_text_file("ecdsa_1.param.curve"); | ||
296 | ASSERT_STRING_EQ((const char *)sshbuf_ptr(buf), | ||
297 | OBJ_nid2sn(k1->ecdsa_nid)); | ||
298 | sshbuf_free(buf); | ||
299 | a = load_bignum("ecdsa_1.param.priv"); | ||
300 | b = load_bignum("ecdsa_1.param.pub"); | ||
301 | c = EC_POINT_point2bn(EC_KEY_get0_group(k1->ecdsa), | ||
302 | EC_KEY_get0_public_key(k1->ecdsa), POINT_CONVERSION_UNCOMPRESSED, | ||
303 | NULL, NULL); | ||
304 | ASSERT_PTR_NE(c, NULL); | ||
305 | ASSERT_BIGNUM_EQ(EC_KEY_get0_private_key(k1->ecdsa), a); | ||
306 | ASSERT_BIGNUM_EQ(b, c); | ||
307 | BN_free(a); | ||
308 | BN_free(b); | ||
309 | BN_free(c); | ||
310 | TEST_DONE(); | ||
311 | |||
312 | TEST_START("parse ECDSA from private w/ passphrase"); | ||
313 | buf = load_file("ecdsa_1_pw"); | ||
314 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
315 | (const char *)sshbuf_ptr(pw), "ecdsa_1_pw", &k2, NULL), 0); | ||
316 | sshbuf_free(buf); | ||
317 | ASSERT_PTR_NE(k2, NULL); | ||
318 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
319 | sshkey_free(k2); | ||
320 | TEST_DONE(); | ||
321 | |||
322 | TEST_START("parse ECDSA from new-format"); | ||
323 | buf = load_file("ecdsa_n"); | ||
324 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
325 | "", "ecdsa_n", &k2, NULL), 0); | ||
326 | sshbuf_free(buf); | ||
327 | ASSERT_PTR_NE(k2, NULL); | ||
328 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
329 | sshkey_free(k2); | ||
330 | TEST_DONE(); | ||
331 | |||
332 | TEST_START("parse ECDSA from new-format w/ passphrase"); | ||
333 | buf = load_file("ecdsa_n_pw"); | ||
334 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
335 | (const char *)sshbuf_ptr(pw), "ecdsa_n_pw", &k2, NULL), 0); | ||
336 | sshbuf_free(buf); | ||
337 | ASSERT_PTR_NE(k2, NULL); | ||
338 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
339 | sshkey_free(k2); | ||
340 | TEST_DONE(); | ||
341 | |||
342 | TEST_START("load ECDSA from public"); | ||
343 | ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_1.pub"), &k2, | ||
344 | NULL), 0); | ||
345 | ASSERT_PTR_NE(k2, NULL); | ||
346 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
347 | sshkey_free(k2); | ||
348 | TEST_DONE(); | ||
349 | |||
350 | TEST_START("load ECDSA cert"); | ||
351 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k2), 0); | ||
352 | ASSERT_PTR_NE(k2, NULL); | ||
353 | ASSERT_INT_EQ(k2->type, KEY_ECDSA_CERT); | ||
354 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); | ||
355 | ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); | ||
356 | TEST_DONE(); | ||
357 | |||
358 | TEST_START("ECDSA key hex fingerprint"); | ||
359 | buf = load_text_file("ecdsa_1.fp"); | ||
360 | cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); | ||
361 | ASSERT_PTR_NE(cp, NULL); | ||
362 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
363 | sshbuf_free(buf); | ||
364 | free(cp); | ||
365 | TEST_DONE(); | ||
366 | |||
367 | TEST_START("ECDSA cert hex fingerprint"); | ||
368 | buf = load_text_file("ecdsa_1-cert.fp"); | ||
369 | cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); | ||
370 | ASSERT_PTR_NE(cp, NULL); | ||
371 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
372 | sshbuf_free(buf); | ||
373 | free(cp); | ||
374 | sshkey_free(k2); | ||
375 | TEST_DONE(); | ||
376 | |||
377 | TEST_START("ECDSA key bubblebabble fingerprint"); | ||
378 | buf = load_text_file("ecdsa_1.fp.bb"); | ||
379 | cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); | ||
380 | ASSERT_PTR_NE(cp, NULL); | ||
381 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
382 | sshbuf_free(buf); | ||
383 | free(cp); | ||
384 | TEST_DONE(); | ||
385 | |||
386 | sshkey_free(k1); | ||
387 | #endif /* OPENSSL_HAS_ECC */ | ||
388 | |||
389 | TEST_START("parse Ed25519 from private"); | ||
390 | buf = load_file("ed25519_1"); | ||
391 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "ed25519_1", | ||
392 | &k1, NULL), 0); | ||
393 | sshbuf_free(buf); | ||
394 | ASSERT_PTR_NE(k1, NULL); | ||
395 | ASSERT_INT_EQ(k1->type, KEY_ED25519); | ||
396 | /* XXX check key contents */ | ||
397 | TEST_DONE(); | ||
398 | |||
399 | TEST_START("parse Ed25519 from private w/ passphrase"); | ||
400 | buf = load_file("ed25519_1_pw"); | ||
401 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, | ||
402 | (const char *)sshbuf_ptr(pw), "ed25519_1_pw", &k2, NULL), 0); | ||
403 | sshbuf_free(buf); | ||
404 | ASSERT_PTR_NE(k2, NULL); | ||
405 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
406 | sshkey_free(k2); | ||
407 | TEST_DONE(); | ||
408 | |||
409 | TEST_START("load Ed25519 from public"); | ||
410 | ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"), &k2, | ||
411 | NULL), 0); | ||
412 | ASSERT_PTR_NE(k2, NULL); | ||
413 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); | ||
414 | sshkey_free(k2); | ||
415 | TEST_DONE(); | ||
416 | |||
417 | TEST_START("load Ed25519 cert"); | ||
418 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k2), 0); | ||
419 | ASSERT_PTR_NE(k2, NULL); | ||
420 | ASSERT_INT_EQ(k2->type, KEY_ED25519_CERT); | ||
421 | ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); | ||
422 | ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); | ||
423 | TEST_DONE(); | ||
424 | |||
425 | TEST_START("Ed25519 key hex fingerprint"); | ||
426 | buf = load_text_file("ed25519_1.fp"); | ||
427 | cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); | ||
428 | ASSERT_PTR_NE(cp, NULL); | ||
429 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
430 | sshbuf_free(buf); | ||
431 | free(cp); | ||
432 | TEST_DONE(); | ||
433 | |||
434 | TEST_START("Ed25519 cert hex fingerprint"); | ||
435 | buf = load_text_file("ed25519_1-cert.fp"); | ||
436 | cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); | ||
437 | ASSERT_PTR_NE(cp, NULL); | ||
438 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
439 | sshbuf_free(buf); | ||
440 | free(cp); | ||
441 | sshkey_free(k2); | ||
442 | TEST_DONE(); | ||
443 | |||
444 | TEST_START("Ed25519 key bubblebabble fingerprint"); | ||
445 | buf = load_text_file("ed25519_1.fp.bb"); | ||
446 | cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); | ||
447 | ASSERT_PTR_NE(cp, NULL); | ||
448 | ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); | ||
449 | sshbuf_free(buf); | ||
450 | free(cp); | ||
451 | TEST_DONE(); | ||
452 | |||
453 | sshkey_free(k1); | ||
454 | |||
455 | sshbuf_free(pw); | ||
456 | |||
457 | } | ||
diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c new file mode 100644 index 000000000..a3f61a6df --- /dev/null +++ b/regress/unittests/sshkey/test_fuzz.c | |||
@@ -0,0 +1,406 @@ | |||
1 | /* $OpenBSD: test_fuzz.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ | ||
2 | /* | ||
3 | * Fuzz tests for key parsing | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <sys/stat.h> | ||
13 | #include <fcntl.h> | ||
14 | #include <stdio.h> | ||
15 | #ifdef HAVE_STDINT_H | ||
16 | #include <stdint.h> | ||
17 | #endif | ||
18 | #include <stdlib.h> | ||
19 | #include <string.h> | ||
20 | #include <unistd.h> | ||
21 | |||
22 | #include <openssl/bn.h> | ||
23 | #include <openssl/rsa.h> | ||
24 | #include <openssl/dsa.h> | ||
25 | #include <openssl/objects.h> | ||
26 | #ifdef OPENSSL_HAS_NISTP256 | ||
27 | # include <openssl/ec.h> | ||
28 | #endif | ||
29 | |||
30 | #include "../test_helper/test_helper.h" | ||
31 | |||
32 | #include "ssherr.h" | ||
33 | #include "authfile.h" | ||
34 | #include "sshkey.h" | ||
35 | #include "sshbuf.h" | ||
36 | |||
37 | #include "common.h" | ||
38 | |||
39 | void sshkey_fuzz_tests(void); | ||
40 | |||
41 | static void | ||
42 | onerror(void *fuzz) | ||
43 | { | ||
44 | fprintf(stderr, "Failed during fuzz:\n"); | ||
45 | fuzz_dump((struct fuzz *)fuzz); | ||
46 | } | ||
47 | |||
48 | static void | ||
49 | public_fuzz(struct sshkey *k) | ||
50 | { | ||
51 | struct sshkey *k1; | ||
52 | struct sshbuf *buf; | ||
53 | struct fuzz *fuzz; | ||
54 | |||
55 | ASSERT_PTR_NE(buf = sshbuf_new(), NULL); | ||
56 | ASSERT_INT_EQ(sshkey_to_blob_buf(k, buf), 0); | ||
57 | /* XXX need a way to run the tests in "slow, but complete" mode */ | ||
58 | fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */ | ||
59 | FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */ | ||
60 | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, | ||
61 | sshbuf_mutable_ptr(buf), sshbuf_len(buf)); | ||
62 | ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf), | ||
63 | &k1), 0); | ||
64 | sshkey_free(k1); | ||
65 | sshbuf_free(buf); | ||
66 | TEST_ONERROR(onerror, fuzz); | ||
67 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
68 | if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0) | ||
69 | sshkey_free(k1); | ||
70 | } | ||
71 | fuzz_cleanup(fuzz); | ||
72 | } | ||
73 | |||
74 | static void | ||
75 | sig_fuzz(struct sshkey *k) | ||
76 | { | ||
77 | struct fuzz *fuzz; | ||
78 | u_char *sig, c[] = "some junk to be signed"; | ||
79 | size_t l; | ||
80 | |||
81 | ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), 0), 0); | ||
82 | ASSERT_SIZE_T_GT(l, 0); | ||
83 | fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* too slow FUZZ_2_BIT_FLIP | */ | ||
84 | FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | | ||
85 | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sig, l); | ||
86 | ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), 0), 0); | ||
87 | free(sig); | ||
88 | TEST_ONERROR(onerror, fuzz); | ||
89 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
90 | sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz), | ||
91 | c, sizeof(c), 0); | ||
92 | } | ||
93 | fuzz_cleanup(fuzz); | ||
94 | } | ||
95 | |||
96 | void | ||
97 | sshkey_fuzz_tests(void) | ||
98 | { | ||
99 | struct sshkey *k1; | ||
100 | struct sshbuf *buf, *fuzzed; | ||
101 | struct fuzz *fuzz; | ||
102 | int r; | ||
103 | |||
104 | TEST_START("fuzz RSA1 private"); | ||
105 | buf = load_file("rsa1_1"); | ||
106 | fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | | ||
107 | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, | ||
108 | sshbuf_mutable_ptr(buf), sshbuf_len(buf)); | ||
109 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
110 | &k1, NULL), 0); | ||
111 | sshkey_free(k1); | ||
112 | sshbuf_free(buf); | ||
113 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
114 | TEST_ONERROR(onerror, fuzz); | ||
115 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
116 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
117 | ASSERT_INT_EQ(r, 0); | ||
118 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
119 | &k1, NULL) == 0) | ||
120 | sshkey_free(k1); | ||
121 | sshbuf_reset(fuzzed); | ||
122 | } | ||
123 | sshbuf_free(fuzzed); | ||
124 | fuzz_cleanup(fuzz); | ||
125 | TEST_DONE(); | ||
126 | |||
127 | TEST_START("fuzz RSA1 public"); | ||
128 | buf = load_file("rsa1_1_pw"); | ||
129 | fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | | ||
130 | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, | ||
131 | sshbuf_mutable_ptr(buf), sshbuf_len(buf)); | ||
132 | ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0); | ||
133 | sshkey_free(k1); | ||
134 | sshbuf_free(buf); | ||
135 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
136 | TEST_ONERROR(onerror, fuzz); | ||
137 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
138 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
139 | ASSERT_INT_EQ(r, 0); | ||
140 | if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0) | ||
141 | sshkey_free(k1); | ||
142 | sshbuf_reset(fuzzed); | ||
143 | } | ||
144 | sshbuf_free(fuzzed); | ||
145 | fuzz_cleanup(fuzz); | ||
146 | TEST_DONE(); | ||
147 | |||
148 | TEST_START("fuzz RSA private"); | ||
149 | buf = load_file("rsa_1"); | ||
150 | fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), | ||
151 | sshbuf_len(buf)); | ||
152 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
153 | &k1, NULL), 0); | ||
154 | sshkey_free(k1); | ||
155 | sshbuf_free(buf); | ||
156 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
157 | TEST_ONERROR(onerror, fuzz); | ||
158 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
159 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
160 | ASSERT_INT_EQ(r, 0); | ||
161 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
162 | &k1, NULL) == 0) | ||
163 | sshkey_free(k1); | ||
164 | sshbuf_reset(fuzzed); | ||
165 | } | ||
166 | sshbuf_free(fuzzed); | ||
167 | fuzz_cleanup(fuzz); | ||
168 | TEST_DONE(); | ||
169 | |||
170 | TEST_START("fuzz RSA new-format private"); | ||
171 | buf = load_file("rsa_n"); | ||
172 | fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), | ||
173 | sshbuf_len(buf)); | ||
174 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
175 | &k1, NULL), 0); | ||
176 | sshkey_free(k1); | ||
177 | sshbuf_free(buf); | ||
178 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
179 | TEST_ONERROR(onerror, fuzz); | ||
180 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
181 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
182 | ASSERT_INT_EQ(r, 0); | ||
183 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
184 | &k1, NULL) == 0) | ||
185 | sshkey_free(k1); | ||
186 | sshbuf_reset(fuzzed); | ||
187 | } | ||
188 | sshbuf_free(fuzzed); | ||
189 | fuzz_cleanup(fuzz); | ||
190 | TEST_DONE(); | ||
191 | |||
192 | TEST_START("fuzz DSA private"); | ||
193 | buf = load_file("dsa_1"); | ||
194 | fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), | ||
195 | sshbuf_len(buf)); | ||
196 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
197 | &k1, NULL), 0); | ||
198 | sshkey_free(k1); | ||
199 | sshbuf_free(buf); | ||
200 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
201 | TEST_ONERROR(onerror, fuzz); | ||
202 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
203 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
204 | ASSERT_INT_EQ(r, 0); | ||
205 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
206 | &k1, NULL) == 0) | ||
207 | sshkey_free(k1); | ||
208 | sshbuf_reset(fuzzed); | ||
209 | } | ||
210 | sshbuf_free(fuzzed); | ||
211 | fuzz_cleanup(fuzz); | ||
212 | TEST_DONE(); | ||
213 | |||
214 | TEST_START("fuzz DSA new-format private"); | ||
215 | buf = load_file("dsa_n"); | ||
216 | fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), | ||
217 | sshbuf_len(buf)); | ||
218 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
219 | &k1, NULL), 0); | ||
220 | sshkey_free(k1); | ||
221 | sshbuf_free(buf); | ||
222 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
223 | TEST_ONERROR(onerror, fuzz); | ||
224 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
225 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
226 | ASSERT_INT_EQ(r, 0); | ||
227 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
228 | &k1, NULL) == 0) | ||
229 | sshkey_free(k1); | ||
230 | sshbuf_reset(fuzzed); | ||
231 | } | ||
232 | sshbuf_free(fuzzed); | ||
233 | fuzz_cleanup(fuzz); | ||
234 | TEST_DONE(); | ||
235 | |||
236 | #ifdef OPENSSL_HAS_ECC | ||
237 | TEST_START("fuzz ECDSA private"); | ||
238 | buf = load_file("ecdsa_1"); | ||
239 | fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), | ||
240 | sshbuf_len(buf)); | ||
241 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
242 | &k1, NULL), 0); | ||
243 | sshkey_free(k1); | ||
244 | sshbuf_free(buf); | ||
245 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
246 | TEST_ONERROR(onerror, fuzz); | ||
247 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
248 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
249 | ASSERT_INT_EQ(r, 0); | ||
250 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
251 | &k1, NULL) == 0) | ||
252 | sshkey_free(k1); | ||
253 | sshbuf_reset(fuzzed); | ||
254 | } | ||
255 | sshbuf_free(fuzzed); | ||
256 | fuzz_cleanup(fuzz); | ||
257 | TEST_DONE(); | ||
258 | |||
259 | TEST_START("fuzz ECDSA new-format private"); | ||
260 | buf = load_file("ecdsa_n"); | ||
261 | fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), | ||
262 | sshbuf_len(buf)); | ||
263 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
264 | &k1, NULL), 0); | ||
265 | sshkey_free(k1); | ||
266 | sshbuf_free(buf); | ||
267 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
268 | TEST_ONERROR(onerror, fuzz); | ||
269 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
270 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
271 | ASSERT_INT_EQ(r, 0); | ||
272 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
273 | &k1, NULL) == 0) | ||
274 | sshkey_free(k1); | ||
275 | sshbuf_reset(fuzzed); | ||
276 | } | ||
277 | sshbuf_free(fuzzed); | ||
278 | fuzz_cleanup(fuzz); | ||
279 | TEST_DONE(); | ||
280 | #endif | ||
281 | |||
282 | TEST_START("fuzz Ed25519 private"); | ||
283 | buf = load_file("ed25519_1"); | ||
284 | fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), | ||
285 | sshbuf_len(buf)); | ||
286 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
287 | &k1, NULL), 0); | ||
288 | sshkey_free(k1); | ||
289 | sshbuf_free(buf); | ||
290 | ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); | ||
291 | TEST_ONERROR(onerror, fuzz); | ||
292 | for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { | ||
293 | r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); | ||
294 | ASSERT_INT_EQ(r, 0); | ||
295 | if (sshkey_parse_private_fileblob(fuzzed, "", "key", | ||
296 | &k1, NULL) == 0) | ||
297 | sshkey_free(k1); | ||
298 | sshbuf_reset(fuzzed); | ||
299 | } | ||
300 | sshbuf_free(fuzzed); | ||
301 | fuzz_cleanup(fuzz); | ||
302 | TEST_DONE(); | ||
303 | |||
304 | TEST_START("fuzz RSA public"); | ||
305 | buf = load_file("rsa_1"); | ||
306 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
307 | &k1, NULL), 0); | ||
308 | sshbuf_free(buf); | ||
309 | public_fuzz(k1); | ||
310 | sshkey_free(k1); | ||
311 | TEST_DONE(); | ||
312 | |||
313 | TEST_START("fuzz RSA cert"); | ||
314 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); | ||
315 | public_fuzz(k1); | ||
316 | sshkey_free(k1); | ||
317 | TEST_DONE(); | ||
318 | |||
319 | TEST_START("fuzz DSA public"); | ||
320 | buf = load_file("dsa_1"); | ||
321 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
322 | &k1, NULL), 0); | ||
323 | sshbuf_free(buf); | ||
324 | public_fuzz(k1); | ||
325 | sshkey_free(k1); | ||
326 | TEST_DONE(); | ||
327 | |||
328 | TEST_START("fuzz DSA cert"); | ||
329 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0); | ||
330 | public_fuzz(k1); | ||
331 | sshkey_free(k1); | ||
332 | TEST_DONE(); | ||
333 | |||
334 | #ifdef OPENSSL_HAS_ECC | ||
335 | TEST_START("fuzz ECDSA public"); | ||
336 | buf = load_file("ecdsa_1"); | ||
337 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
338 | &k1, NULL), 0); | ||
339 | sshbuf_free(buf); | ||
340 | public_fuzz(k1); | ||
341 | sshkey_free(k1); | ||
342 | TEST_DONE(); | ||
343 | |||
344 | TEST_START("fuzz ECDSA cert"); | ||
345 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0); | ||
346 | public_fuzz(k1); | ||
347 | sshkey_free(k1); | ||
348 | TEST_DONE(); | ||
349 | #endif | ||
350 | |||
351 | TEST_START("fuzz Ed25519 public"); | ||
352 | buf = load_file("ed25519_1"); | ||
353 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
354 | &k1, NULL), 0); | ||
355 | sshbuf_free(buf); | ||
356 | public_fuzz(k1); | ||
357 | sshkey_free(k1); | ||
358 | TEST_DONE(); | ||
359 | |||
360 | TEST_START("fuzz Ed25519 cert"); | ||
361 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0); | ||
362 | public_fuzz(k1); | ||
363 | sshkey_free(k1); | ||
364 | TEST_DONE(); | ||
365 | |||
366 | TEST_START("fuzz RSA sig"); | ||
367 | buf = load_file("rsa_1"); | ||
368 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
369 | &k1, NULL), 0); | ||
370 | sshbuf_free(buf); | ||
371 | sig_fuzz(k1); | ||
372 | sshkey_free(k1); | ||
373 | TEST_DONE(); | ||
374 | |||
375 | TEST_START("fuzz DSA sig"); | ||
376 | buf = load_file("dsa_1"); | ||
377 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
378 | &k1, NULL), 0); | ||
379 | sshbuf_free(buf); | ||
380 | sig_fuzz(k1); | ||
381 | sshkey_free(k1); | ||
382 | TEST_DONE(); | ||
383 | |||
384 | #ifdef OPENSSL_HAS_ECC | ||
385 | TEST_START("fuzz ECDSA sig"); | ||
386 | buf = load_file("ecdsa_1"); | ||
387 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
388 | &k1, NULL), 0); | ||
389 | sshbuf_free(buf); | ||
390 | sig_fuzz(k1); | ||
391 | sshkey_free(k1); | ||
392 | TEST_DONE(); | ||
393 | #endif | ||
394 | |||
395 | TEST_START("fuzz Ed25519 sig"); | ||
396 | buf = load_file("ed25519_1"); | ||
397 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", | ||
398 | &k1, NULL), 0); | ||
399 | sshbuf_free(buf); | ||
400 | sig_fuzz(k1); | ||
401 | sshkey_free(k1); | ||
402 | TEST_DONE(); | ||
403 | |||
404 | /* XXX fuzz decoded new-format blobs too */ | ||
405 | |||
406 | } | ||
diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c new file mode 100644 index 000000000..ef0c67956 --- /dev/null +++ b/regress/unittests/sshkey/test_sshkey.c | |||
@@ -0,0 +1,357 @@ | |||
1 | /* $OpenBSD: test_sshkey.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshkey.h key management API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <sys/param.h> | ||
12 | #include <stdio.h> | ||
13 | #ifdef HAVE_STDINT_H | ||
14 | #include <stdint.h> | ||
15 | #endif | ||
16 | #include <stdlib.h> | ||
17 | #include <string.h> | ||
18 | |||
19 | #include <openssl/bn.h> | ||
20 | #include <openssl/rsa.h> | ||
21 | #include <openssl/dsa.h> | ||
22 | #ifdef OPENSSL_HAS_NISTP256 | ||
23 | # include <openssl/ec.h> | ||
24 | #endif | ||
25 | |||
26 | #include "../test_helper/test_helper.h" | ||
27 | |||
28 | #include "ssherr.h" | ||
29 | #include "sshbuf.h" | ||
30 | #define SSHBUF_INTERNAL 1 /* access internals for testing */ | ||
31 | #include "sshkey.h" | ||
32 | |||
33 | #include "authfile.h" | ||
34 | #include "common.h" | ||
35 | #include "ssh2.h" | ||
36 | |||
37 | void sshkey_tests(void); | ||
38 | |||
39 | static void | ||
40 | build_cert(struct sshbuf *b, const struct sshkey *k, const char *type, | ||
41 | const struct sshkey *sign_key, const struct sshkey *ca_key) | ||
42 | { | ||
43 | struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts; | ||
44 | u_char *sigblob; | ||
45 | size_t siglen; | ||
46 | |||
47 | ca_buf = sshbuf_new(); | ||
48 | ASSERT_INT_EQ(sshkey_to_blob_buf(ca_key, ca_buf), 0); | ||
49 | |||
50 | /* | ||
51 | * Get the public key serialisation by rendering the key and skipping | ||
52 | * the type string. This is a bit of a hack :/ | ||
53 | */ | ||
54 | pk = sshbuf_new(); | ||
55 | ASSERT_INT_EQ(sshkey_plain_to_blob_buf(k, pk), 0); | ||
56 | ASSERT_INT_EQ(sshbuf_skip_string(pk), 0); | ||
57 | |||
58 | principals = sshbuf_new(); | ||
59 | ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0); | ||
60 | ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0); | ||
61 | |||
62 | critopts = sshbuf_new(); | ||
63 | /* XXX fill this in */ | ||
64 | |||
65 | exts = sshbuf_new(); | ||
66 | /* XXX fill this in */ | ||
67 | |||
68 | ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0); | ||
69 | ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */ | ||
70 | ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */ | ||
71 | ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */ | ||
72 | ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */ | ||
73 | ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */ | ||
74 | ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */ | ||
75 | ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */ | ||
76 | ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */ | ||
77 | ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */ | ||
78 | ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */ | ||
79 | ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ | ||
80 | ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ | ||
81 | ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, | ||
82 | sshbuf_ptr(b), sshbuf_len(b), 0), 0); | ||
83 | ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ | ||
84 | |||
85 | free(sigblob); | ||
86 | sshbuf_free(ca_buf); | ||
87 | sshbuf_free(exts); | ||
88 | sshbuf_free(critopts); | ||
89 | sshbuf_free(principals); | ||
90 | sshbuf_free(pk); | ||
91 | } | ||
92 | |||
93 | void | ||
94 | sshkey_tests(void) | ||
95 | { | ||
96 | struct sshkey *k1, *k2, *k3, *k4, *kr, *kd, *ke, *kf; | ||
97 | struct sshbuf *b; | ||
98 | |||
99 | TEST_START("new invalid"); | ||
100 | k1 = sshkey_new(-42); | ||
101 | ASSERT_PTR_EQ(k1, NULL); | ||
102 | TEST_DONE(); | ||
103 | |||
104 | TEST_START("new/free KEY_UNSPEC"); | ||
105 | k1 = sshkey_new(KEY_UNSPEC); | ||
106 | ASSERT_PTR_NE(k1, NULL); | ||
107 | sshkey_free(k1); | ||
108 | TEST_DONE(); | ||
109 | |||
110 | TEST_START("new/free KEY_RSA1"); | ||
111 | k1 = sshkey_new(KEY_RSA1); | ||
112 | ASSERT_PTR_NE(k1, NULL); | ||
113 | ASSERT_PTR_NE(k1->rsa, NULL); | ||
114 | ASSERT_PTR_NE(k1->rsa->n, NULL); | ||
115 | ASSERT_PTR_NE(k1->rsa->e, NULL); | ||
116 | ASSERT_PTR_EQ(k1->rsa->p, NULL); | ||
117 | sshkey_free(k1); | ||
118 | TEST_DONE(); | ||
119 | |||
120 | TEST_START("new/free KEY_RSA"); | ||
121 | k1 = sshkey_new(KEY_RSA); | ||
122 | ASSERT_PTR_NE(k1, NULL); | ||
123 | ASSERT_PTR_NE(k1->rsa, NULL); | ||
124 | ASSERT_PTR_NE(k1->rsa->n, NULL); | ||
125 | ASSERT_PTR_NE(k1->rsa->e, NULL); | ||
126 | ASSERT_PTR_EQ(k1->rsa->p, NULL); | ||
127 | sshkey_free(k1); | ||
128 | TEST_DONE(); | ||
129 | |||
130 | TEST_START("new/free KEY_DSA"); | ||
131 | k1 = sshkey_new(KEY_DSA); | ||
132 | ASSERT_PTR_NE(k1, NULL); | ||
133 | ASSERT_PTR_NE(k1->dsa, NULL); | ||
134 | ASSERT_PTR_NE(k1->dsa->g, NULL); | ||
135 | ASSERT_PTR_EQ(k1->dsa->priv_key, NULL); | ||
136 | sshkey_free(k1); | ||
137 | TEST_DONE(); | ||
138 | |||
139 | TEST_START("new/free KEY_ECDSA"); | ||
140 | k1 = sshkey_new(KEY_ECDSA); | ||
141 | ASSERT_PTR_NE(k1, NULL); | ||
142 | ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */ | ||
143 | sshkey_free(k1); | ||
144 | TEST_DONE(); | ||
145 | |||
146 | TEST_START("new/free KEY_ED25519"); | ||
147 | k1 = sshkey_new(KEY_ED25519); | ||
148 | ASSERT_PTR_NE(k1, NULL); | ||
149 | /* These should be blank until key loaded or generated */ | ||
150 | ASSERT_PTR_EQ(k1->ed25519_sk, NULL); | ||
151 | ASSERT_PTR_EQ(k1->ed25519_pk, NULL); | ||
152 | sshkey_free(k1); | ||
153 | TEST_DONE(); | ||
154 | |||
155 | TEST_START("new_private KEY_RSA"); | ||
156 | k1 = sshkey_new_private(KEY_RSA); | ||
157 | ASSERT_PTR_NE(k1, NULL); | ||
158 | ASSERT_PTR_NE(k1->rsa, NULL); | ||
159 | ASSERT_PTR_NE(k1->rsa->n, NULL); | ||
160 | ASSERT_PTR_NE(k1->rsa->e, NULL); | ||
161 | ASSERT_PTR_NE(k1->rsa->p, NULL); | ||
162 | ASSERT_INT_EQ(sshkey_add_private(k1), 0); | ||
163 | sshkey_free(k1); | ||
164 | TEST_DONE(); | ||
165 | |||
166 | TEST_START("new_private KEY_DSA"); | ||
167 | k1 = sshkey_new_private(KEY_DSA); | ||
168 | ASSERT_PTR_NE(k1, NULL); | ||
169 | ASSERT_PTR_NE(k1->dsa, NULL); | ||
170 | ASSERT_PTR_NE(k1->dsa->g, NULL); | ||
171 | ASSERT_PTR_NE(k1->dsa->priv_key, NULL); | ||
172 | ASSERT_INT_EQ(sshkey_add_private(k1), 0); | ||
173 | sshkey_free(k1); | ||
174 | TEST_DONE(); | ||
175 | |||
176 | TEST_START("generate KEY_RSA too small modulus"); | ||
177 | ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 128, &k1), | ||
178 | SSH_ERR_INVALID_ARGUMENT); | ||
179 | ASSERT_PTR_EQ(k1, NULL); | ||
180 | TEST_DONE(); | ||
181 | |||
182 | TEST_START("generate KEY_RSA too large modulus"); | ||
183 | ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1 << 20, &k1), | ||
184 | SSH_ERR_INVALID_ARGUMENT); | ||
185 | ASSERT_PTR_EQ(k1, NULL); | ||
186 | TEST_DONE(); | ||
187 | |||
188 | TEST_START("generate KEY_DSA wrong bits"); | ||
189 | ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1), | ||
190 | SSH_ERR_INVALID_ARGUMENT); | ||
191 | ASSERT_PTR_EQ(k1, NULL); | ||
192 | sshkey_free(k1); | ||
193 | TEST_DONE(); | ||
194 | |||
195 | TEST_START("generate KEY_ECDSA wrong bits"); | ||
196 | ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1), | ||
197 | SSH_ERR_INVALID_ARGUMENT); | ||
198 | ASSERT_PTR_EQ(k1, NULL); | ||
199 | sshkey_free(k1); | ||
200 | TEST_DONE(); | ||
201 | |||
202 | TEST_START("generate KEY_RSA"); | ||
203 | ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 768, &kr), 0); | ||
204 | ASSERT_PTR_NE(kr, NULL); | ||
205 | ASSERT_PTR_NE(kr->rsa, NULL); | ||
206 | ASSERT_PTR_NE(kr->rsa->n, NULL); | ||
207 | ASSERT_PTR_NE(kr->rsa->e, NULL); | ||
208 | ASSERT_PTR_NE(kr->rsa->p, NULL); | ||
209 | ASSERT_INT_EQ(BN_num_bits(kr->rsa->n), 768); | ||
210 | TEST_DONE(); | ||
211 | |||
212 | TEST_START("generate KEY_DSA"); | ||
213 | ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); | ||
214 | ASSERT_PTR_NE(kd, NULL); | ||
215 | ASSERT_PTR_NE(kd->dsa, NULL); | ||
216 | ASSERT_PTR_NE(kd->dsa->g, NULL); | ||
217 | ASSERT_PTR_NE(kd->dsa->priv_key, NULL); | ||
218 | TEST_DONE(); | ||
219 | |||
220 | #ifdef OPENSSL_HAS_ECC | ||
221 | TEST_START("generate KEY_ECDSA"); | ||
222 | ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0); | ||
223 | ASSERT_PTR_NE(ke, NULL); | ||
224 | ASSERT_PTR_NE(ke->ecdsa, NULL); | ||
225 | ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); | ||
226 | ASSERT_PTR_NE(EC_KEY_get0_private_key(ke->ecdsa), NULL); | ||
227 | TEST_DONE(); | ||
228 | #endif | ||
229 | |||
230 | TEST_START("generate KEY_ED25519"); | ||
231 | ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &kf), 0); | ||
232 | ASSERT_PTR_NE(kf, NULL); | ||
233 | ASSERT_INT_EQ(kf->type, KEY_ED25519); | ||
234 | ASSERT_PTR_NE(kf->ed25519_pk, NULL); | ||
235 | ASSERT_PTR_NE(kf->ed25519_sk, NULL); | ||
236 | TEST_DONE(); | ||
237 | |||
238 | TEST_START("demote KEY_RSA"); | ||
239 | ASSERT_INT_EQ(sshkey_demote(kr, &k1), 0); | ||
240 | ASSERT_PTR_NE(k1, NULL); | ||
241 | ASSERT_PTR_NE(kr, k1); | ||
242 | ASSERT_INT_EQ(k1->type, KEY_RSA); | ||
243 | ASSERT_PTR_NE(k1->rsa, NULL); | ||
244 | ASSERT_PTR_NE(k1->rsa->n, NULL); | ||
245 | ASSERT_PTR_NE(k1->rsa->e, NULL); | ||
246 | ASSERT_PTR_EQ(k1->rsa->p, NULL); | ||
247 | TEST_DONE(); | ||
248 | |||
249 | TEST_START("equal KEY_RSA/demoted KEY_RSA"); | ||
250 | ASSERT_INT_EQ(sshkey_equal(kr, k1), 1); | ||
251 | sshkey_free(k1); | ||
252 | TEST_DONE(); | ||
253 | |||
254 | TEST_START("demote KEY_DSA"); | ||
255 | ASSERT_INT_EQ(sshkey_demote(kd, &k1), 0); | ||
256 | ASSERT_PTR_NE(k1, NULL); | ||
257 | ASSERT_PTR_NE(kd, k1); | ||
258 | ASSERT_INT_EQ(k1->type, KEY_DSA); | ||
259 | ASSERT_PTR_NE(k1->dsa, NULL); | ||
260 | ASSERT_PTR_NE(k1->dsa->g, NULL); | ||
261 | ASSERT_PTR_EQ(k1->dsa->priv_key, NULL); | ||
262 | TEST_DONE(); | ||
263 | |||
264 | TEST_START("equal KEY_DSA/demoted KEY_DSA"); | ||
265 | ASSERT_INT_EQ(sshkey_equal(kd, k1), 1); | ||
266 | sshkey_free(k1); | ||
267 | TEST_DONE(); | ||
268 | |||
269 | #ifdef OPENSSL_HAS_ECC | ||
270 | TEST_START("demote KEY_ECDSA"); | ||
271 | ASSERT_INT_EQ(sshkey_demote(ke, &k1), 0); | ||
272 | ASSERT_PTR_NE(k1, NULL); | ||
273 | ASSERT_PTR_NE(ke, k1); | ||
274 | ASSERT_INT_EQ(k1->type, KEY_ECDSA); | ||
275 | ASSERT_PTR_NE(k1->ecdsa, NULL); | ||
276 | ASSERT_INT_EQ(k1->ecdsa_nid, ke->ecdsa_nid); | ||
277 | ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); | ||
278 | ASSERT_PTR_EQ(EC_KEY_get0_private_key(k1->ecdsa), NULL); | ||
279 | TEST_DONE(); | ||
280 | |||
281 | TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA"); | ||
282 | ASSERT_INT_EQ(sshkey_equal(ke, k1), 1); | ||
283 | sshkey_free(k1); | ||
284 | TEST_DONE(); | ||
285 | #endif | ||
286 | |||
287 | TEST_START("demote KEY_ED25519"); | ||
288 | ASSERT_INT_EQ(sshkey_demote(kf, &k1), 0); | ||
289 | ASSERT_PTR_NE(k1, NULL); | ||
290 | ASSERT_PTR_NE(kf, k1); | ||
291 | ASSERT_INT_EQ(k1->type, KEY_ED25519); | ||
292 | ASSERT_PTR_NE(k1->ed25519_pk, NULL); | ||
293 | ASSERT_PTR_EQ(k1->ed25519_sk, NULL); | ||
294 | TEST_DONE(); | ||
295 | |||
296 | TEST_START("equal KEY_ED25519/demoted KEY_ED25519"); | ||
297 | ASSERT_INT_EQ(sshkey_equal(kf, k1), 1); | ||
298 | sshkey_free(k1); | ||
299 | TEST_DONE(); | ||
300 | |||
301 | TEST_START("equal mismatched key types"); | ||
302 | ASSERT_INT_EQ(sshkey_equal(kd, kr), 0); | ||
303 | #ifdef OPENSSL_HAS_ECC | ||
304 | ASSERT_INT_EQ(sshkey_equal(kd, ke), 0); | ||
305 | ASSERT_INT_EQ(sshkey_equal(kr, ke), 0); | ||
306 | ASSERT_INT_EQ(sshkey_equal(ke, kf), 0); | ||
307 | #endif | ||
308 | ASSERT_INT_EQ(sshkey_equal(kd, kf), 0); | ||
309 | TEST_DONE(); | ||
310 | |||
311 | TEST_START("equal different keys"); | ||
312 | ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 768, &k1), 0); | ||
313 | ASSERT_INT_EQ(sshkey_equal(kr, k1), 0); | ||
314 | sshkey_free(k1); | ||
315 | ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &k1), 0); | ||
316 | ASSERT_INT_EQ(sshkey_equal(kd, k1), 0); | ||
317 | sshkey_free(k1); | ||
318 | #ifdef OPENSSL_HAS_ECC | ||
319 | ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &k1), 0); | ||
320 | ASSERT_INT_EQ(sshkey_equal(ke, k1), 0); | ||
321 | sshkey_free(k1); | ||
322 | #endif | ||
323 | ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &k1), 0); | ||
324 | ASSERT_INT_EQ(sshkey_equal(kf, k1), 0); | ||
325 | sshkey_free(k1); | ||
326 | TEST_DONE(); | ||
327 | |||
328 | sshkey_free(kr); | ||
329 | sshkey_free(kd); | ||
330 | #ifdef OPENSSL_HAS_ECC | ||
331 | sshkey_free(ke); | ||
332 | #endif | ||
333 | sshkey_free(kf); | ||
334 | |||
335 | /* XXX certify test */ | ||
336 | /* XXX sign test */ | ||
337 | /* XXX verify test */ | ||
338 | |||
339 | TEST_START("nested certificate"); | ||
340 | ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); | ||
341 | ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, | ||
342 | NULL), 0); | ||
343 | b = load_file("rsa_2"); | ||
344 | ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", "rsa_1", | ||
345 | &k3, NULL), 0); | ||
346 | sshbuf_reset(b); | ||
347 | build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1); | ||
348 | ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), | ||
349 | SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); | ||
350 | ASSERT_PTR_EQ(k4, NULL); | ||
351 | sshbuf_free(b); | ||
352 | sshkey_free(k1); | ||
353 | sshkey_free(k2); | ||
354 | sshkey_free(k3); | ||
355 | TEST_DONE(); | ||
356 | |||
357 | } | ||
diff --git a/regress/unittests/sshkey/testdata/dsa_1 b/regress/unittests/sshkey/testdata/dsa_1 new file mode 100644 index 000000000..34346869f --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1 | |||
@@ -0,0 +1,12 @@ | |||
1 | -----BEGIN DSA PRIVATE KEY----- | ||
2 | MIIBuwIBAAKBgQCxBNwH8TmLXqiZa0b9pxC6W+zS4Voqp8S+QwecYpNPTmhjaUYI | ||
3 | E/aJWAzFVtdbysLM89ukvw/z8qBkbMSefdypKmjUtgv51ZD4nfV4Wxb+G+1QExHr | ||
4 | M+kowOOL3XbcsdbPLUt8vxDJbBlQRch4zyai7CWjQR3JFXpR8sevUFJxSQIVAIdE | ||
5 | oncp2DEY2U/ZZnIyGCwApCzfAoGARW+eewZTv1Eosxv3ANKx372pf5+fQKwnWizI | ||
6 | j5z/GY3w3xobRCP9FiL4K3Nip2FvHLTGpRrlfm19RWYAg77VsNgztC4V9C8QrKWc | ||
7 | WJdkUkoQpZ3VoO25rO13hmIelkal3omKCF4ZE/edeF3d2B8DlzYs0aBcjTCMDrub | ||
8 | /CJILcYCgYEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j | ||
9 | 4hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1 | ||
10 | /EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gCFBl7Lc6V | ||
11 | hmTiTuhLXjoRdCZS/p/m | ||
12 | -----END DSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/regress/unittests/sshkey/testdata/dsa_1-cert.fp new file mode 100644 index 000000000..56ee1f89b --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1-cert.fp | |||
@@ -0,0 +1 @@ | |||
5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74 | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.pub b/regress/unittests/sshkey/testdata/dsa_1-cert.pub new file mode 100644 index 000000000..023edf136 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1-cert.pub | |||
@@ -0,0 +1 @@ | |||
ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgj8zueN51MSQ7jW3fFwqyJWA3DycAAavQ8WgMHqcUG7YAAACBALEE3AfxOYteqJlrRv2nELpb7NLhWiqnxL5DB5xik09OaGNpRggT9olYDMVW11vKwszz26S/D/PyoGRsxJ593KkqaNS2C/nVkPid9XhbFv4b7VATEesz6SjA44vddtyx1s8tS3y/EMlsGVBFyHjPJqLsJaNBHckVelHyx69QUnFJAAAAFQCHRKJ3KdgxGNlP2WZyMhgsAKQs3wAAAIBFb557BlO/USizG/cA0rHfval/n59ArCdaLMiPnP8ZjfDfGhtEI/0WIvgrc2KnYW8ctMalGuV+bX1FZgCDvtWw2DO0LhX0LxCspZxYl2RSShClndWg7bms7XeGYh6WRqXeiYoIXhkT9514Xd3YHwOXNizRoFyNMIwOu5v8IkgtxgAAAIEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j4hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1/EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gAAAAAAAAABgAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEA6qftqozw0ah9PG9obAg8iOPwQv6AsT9t/1G69eArSd9Am85OKIhAvYguI1Xtr9rw78X/Xk+6HtyAOF3QemaQD dsa_1.pub | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp b/regress/unittests/sshkey/testdata/dsa_1.fp new file mode 100644 index 000000000..56ee1f89b --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.fp | |||
@@ -0,0 +1 @@ | |||
5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74 | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp.bb b/regress/unittests/sshkey/testdata/dsa_1.fp.bb new file mode 100644 index 000000000..07dd9b418 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.fp.bb | |||
@@ -0,0 +1 @@ | |||
xosat-baneh-gocad-relek-kepur-mibip-motog-bykyb-hisug-mysus-tuxix | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.g b/regress/unittests/sshkey/testdata/dsa_1.param.g new file mode 100644 index 000000000..4b09f6d18 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.param.g | |||
@@ -0,0 +1 @@ | |||
456f9e7b0653bf5128b31bf700d2b1dfbda97f9f9f40ac275a2cc88f9cff198df0df1a1b4423fd1622f82b7362a7616f1cb4c6a51ae57e6d7d45660083bed5b0d833b42e15f42f10aca59c589764524a10a59dd5a0edb9aced7786621e9646a5de898a085e1913f79d785dddd81f0397362cd1a05c8d308c0ebb9bfc22482dc6 | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.priv b/regress/unittests/sshkey/testdata/dsa_1.param.priv new file mode 100644 index 000000000..2dd737cbe --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.param.priv | |||
@@ -0,0 +1 @@ | |||
197b2dce958664e24ee84b5e3a11742652fe9fe6 | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.pub b/regress/unittests/sshkey/testdata/dsa_1.param.pub new file mode 100644 index 000000000..b23d7207f --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.param.pub | |||
@@ -0,0 +1 @@ | |||
00809b7d8de7c6422e1297917c8778d8a39d8bca013cb0d632bab12530a566ca1152289d487e2f63e21369da3673bbb8e96568589dd5283da1ba81b441edf2f7a79927951a373f60f39ddeaee8d01d86b003596f895fd9f5fc430a52fd21f2b44523fddbf516351d55730501fb577b0d27a89e907f09a8ecb596208c68cca5c388 | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1.pub b/regress/unittests/sshkey/testdata/dsa_1.pub new file mode 100644 index 000000000..89681970c --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.pub | |||
@@ -0,0 +1 @@ | |||
ssh-dss AAAAB3NzaC1kc3MAAACBALEE3AfxOYteqJlrRv2nELpb7NLhWiqnxL5DB5xik09OaGNpRggT9olYDMVW11vKwszz26S/D/PyoGRsxJ593KkqaNS2C/nVkPid9XhbFv4b7VATEesz6SjA44vddtyx1s8tS3y/EMlsGVBFyHjPJqLsJaNBHckVelHyx69QUnFJAAAAFQCHRKJ3KdgxGNlP2WZyMhgsAKQs3wAAAIBFb557BlO/USizG/cA0rHfval/n59ArCdaLMiPnP8ZjfDfGhtEI/0WIvgrc2KnYW8ctMalGuV+bX1FZgCDvtWw2DO0LhX0LxCspZxYl2RSShClndWg7bms7XeGYh6WRqXeiYoIXhkT9514Xd3YHwOXNizRoFyNMIwOu5v8IkgtxgAAAIEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j4hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1/EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4g= DSA test key #1 | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_1_pw b/regress/unittests/sshkey/testdata/dsa_1_pw new file mode 100644 index 000000000..1402153a0 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1_pw | |||
@@ -0,0 +1,15 @@ | |||
1 | -----BEGIN DSA PRIVATE KEY----- | ||
2 | Proc-Type: 4,ENCRYPTED | ||
3 | DEK-Info: AES-128-CBC,9E668E24E7B9D658E3E7D0446B32B376 | ||
4 | |||
5 | hDjDLbfCAQutblxLuyNzSLxISSgXTgyzq8St9GE0lUtEc7i0xGNWwoWpFSbtD9y1 | ||
6 | yTG5UkhATQt56SY1ABfXZ21wieYuEEQeSJi0gwUQNNt2SwwITx4EdzDedWiHjikt | ||
7 | jbzH3v33agp/odw2X9wY6zu75y9CeW9o7SszRl286DliWIHJmhMlbb8r7jRqu62H | ||
8 | s5YYxD0xS1ipWauxklmIXMWNZHcARo8ZiJOuNdLshrSrl8DUW9P6F89FvxclQzKr | ||
9 | 44u3OBm7KbgPvPURDFLgNP6uCGBjzHvhHTpzVBxmQzCl3aGgsTKXiwJ1eupNjntB | ||
10 | ji0EnbznvoxR6qhXxw/WQ+MnWlWqTXka/2qaB6m3oJv+Zn7cPCJ5kvHnhr2JmNMl | ||
11 | igTh4Ov4LZLyNgO0Lbec4KyxW9QInRV5CY4Pu5lhqHteiPmOIGMWFtuh8Bb8Kg2q | ||
12 | VvXnPo5I3FjqV7UhDduO1Wn558sBZWQPqRbHVPN6wXJuM3HGkBl+aNjn0qddv9tr | ||
13 | VFJd/xdly2Ne81g3CB8jysE+3WEOrV9kdybocp/EhSOzP4i6pjWlyWdR5+CgbvRm | ||
14 | TUIeIaQbmPIB5251o5YK+Q== | ||
15 | -----END DSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/dsa_2 b/regress/unittests/sshkey/testdata/dsa_2 new file mode 100644 index 000000000..b189dc821 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2 | |||
@@ -0,0 +1,12 @@ | |||
1 | -----BEGIN DSA PRIVATE KEY----- | ||
2 | MIIBuwIBAAKBgQDoMxCTyBnLPSO7CRU3RyfJLANLKBZ3/LdcsyNaARctaRA5gzRb | ||
3 | XdTFFU+rWKfxv+otm0KyCOepLtWy8tjKRYb7Ni46USlGwtM0Adx/3vR4iWNfipDP | ||
4 | K2V4O97JyMe3wsbF7siC01U4b8Ki+J44iFG9nuRnOTHqUWI615mraQRwlQIVAMsX | ||
5 | nsPGH8QrU11F1ScAIfZC165dAoGACCXyOHFkxABpJDtJs6AE7Hl3XjI4dnlim/XH | ||
6 | Y60W6gcO7gHSE2r2ljCubJqoUXmxd5mLKgnu91jIG/4URwDM4V7pb2k99sXpAi8I | ||
7 | L52eQl88C0bRD9+lEJfR4PMT39EccDRPB4+E055RoYQZ/McIyad8sF3Qwt084Eq+ | ||
8 | IkUt2coCgYEAxZRpCY82sM9Mu4B0EcH6O8seRqIRScmelljhUtKxuvf2PChwIWkR | ||
9 | HK9lORHBE3iKyurC5Muf3abuHKwMFjrOjHKOTqXBRrDZ7RgLQA0aUAQD3lWc9OTP | ||
10 | NShjphpq5xr0HZB31eJg3/Mo6KxYlRpzMXbTyenZP0XLICSSAywvTDoCFG5whl2k | ||
11 | Y2FLGfi9V6ylUVH6jKgE | ||
12 | -----END DSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp b/regress/unittests/sshkey/testdata/dsa_2.fp new file mode 100644 index 000000000..ba9de82a8 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2.fp | |||
@@ -0,0 +1 @@ | |||
72:5f:50:6b:e5:64:c5:62:21:92:3f:8b:10:9b:9f:1a | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp.bb b/regress/unittests/sshkey/testdata/dsa_2.fp.bb new file mode 100644 index 000000000..37a5221a7 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2.fp.bb | |||
@@ -0,0 +1 @@ | |||
xesoh-mebaf-feced-lenuz-sicam-pevok-bosak-nogaz-ligen-fekef-fixex | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_2.pub b/regress/unittests/sshkey/testdata/dsa_2.pub new file mode 100644 index 000000000..6ed2736b1 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2.pub | |||
@@ -0,0 +1 @@ | |||
ssh-dss AAAAB3NzaC1kc3MAAACBAOgzEJPIGcs9I7sJFTdHJ8ksA0soFnf8t1yzI1oBFy1pEDmDNFtd1MUVT6tYp/G/6i2bQrII56ku1bLy2MpFhvs2LjpRKUbC0zQB3H/e9HiJY1+KkM8rZXg73snIx7fCxsXuyILTVThvwqL4njiIUb2e5Gc5MepRYjrXmatpBHCVAAAAFQDLF57Dxh/EK1NdRdUnACH2QteuXQAAAIAIJfI4cWTEAGkkO0mzoATseXdeMjh2eWKb9cdjrRbqBw7uAdITavaWMK5smqhRebF3mYsqCe73WMgb/hRHAMzhXulvaT32xekCLwgvnZ5CXzwLRtEP36UQl9Hg8xPf0RxwNE8Hj4TTnlGhhBn8xwjJp3ywXdDC3TzgSr4iRS3ZygAAAIEAxZRpCY82sM9Mu4B0EcH6O8seRqIRScmelljhUtKxuvf2PChwIWkRHK9lORHBE3iKyurC5Muf3abuHKwMFjrOjHKOTqXBRrDZ7RgLQA0aUAQD3lWc9OTPNShjphpq5xr0HZB31eJg3/Mo6KxYlRpzMXbTyenZP0XLICSSAywvTDo= DSA test key #2 | |||
diff --git a/regress/unittests/sshkey/testdata/dsa_n b/regress/unittests/sshkey/testdata/dsa_n new file mode 100644 index 000000000..34346869f --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_n | |||
@@ -0,0 +1,12 @@ | |||
1 | -----BEGIN DSA PRIVATE KEY----- | ||
2 | MIIBuwIBAAKBgQCxBNwH8TmLXqiZa0b9pxC6W+zS4Voqp8S+QwecYpNPTmhjaUYI | ||
3 | E/aJWAzFVtdbysLM89ukvw/z8qBkbMSefdypKmjUtgv51ZD4nfV4Wxb+G+1QExHr | ||
4 | M+kowOOL3XbcsdbPLUt8vxDJbBlQRch4zyai7CWjQR3JFXpR8sevUFJxSQIVAIdE | ||
5 | oncp2DEY2U/ZZnIyGCwApCzfAoGARW+eewZTv1Eosxv3ANKx372pf5+fQKwnWizI | ||
6 | j5z/GY3w3xobRCP9FiL4K3Nip2FvHLTGpRrlfm19RWYAg77VsNgztC4V9C8QrKWc | ||
7 | WJdkUkoQpZ3VoO25rO13hmIelkal3omKCF4ZE/edeF3d2B8DlzYs0aBcjTCMDrub | ||
8 | /CJILcYCgYEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j | ||
9 | 4hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1 | ||
10 | /EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gCFBl7Lc6V | ||
11 | hmTiTuhLXjoRdCZS/p/m | ||
12 | -----END DSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/dsa_n_pw b/regress/unittests/sshkey/testdata/dsa_n_pw new file mode 100644 index 000000000..42f70dd23 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_n_pw | |||
@@ -0,0 +1,22 @@ | |||
1 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
2 | b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABD5nB+Nkw | ||
3 | LNoPtAG7C3IdXmAAAAEAAAAAEAAAGyAAAAB3NzaC1kc3MAAACBALEE3AfxOYteqJlrRv2n | ||
4 | ELpb7NLhWiqnxL5DB5xik09OaGNpRggT9olYDMVW11vKwszz26S/D/PyoGRsxJ593KkqaN | ||
5 | S2C/nVkPid9XhbFv4b7VATEesz6SjA44vddtyx1s8tS3y/EMlsGVBFyHjPJqLsJaNBHckV | ||
6 | elHyx69QUnFJAAAAFQCHRKJ3KdgxGNlP2WZyMhgsAKQs3wAAAIBFb557BlO/USizG/cA0r | ||
7 | Hfval/n59ArCdaLMiPnP8ZjfDfGhtEI/0WIvgrc2KnYW8ctMalGuV+bX1FZgCDvtWw2DO0 | ||
8 | LhX0LxCspZxYl2RSShClndWg7bms7XeGYh6WRqXeiYoIXhkT9514Xd3YHwOXNizRoFyNMI | ||
9 | wOu5v8IkgtxgAAAIEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j | ||
10 | 4hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1/EMKUv | ||
11 | 0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gAAAHw8P1DtkBulOGv85qf | ||
12 | P+md2+LL+NKufVzHl9k2UKQFjeqY6uqs4HSDqvhXe7oiXd5mz6I7orxjtKU9hGjNF4ABUD | ||
13 | OawVGe/GCRUQ4WgpAgDnqQLeFcdIwtMSIrRZU6xjs314EI7TM7IIiG26JEuXDfZI1e7C3y | ||
14 | Cc38ZsP3zmg/UjgcCQar5c4n++vhOmeO36+fcUyZ1QlR05SaEtFYJA+otP3RmKTiDwob8Q | ||
15 | zRMr8Y57i2NTTtFjkmnnnQCibP62yz7N22Dve7RTOH8jiaW7p02Vn/6WmCarevN1rxtLLR | ||
16 | lkuWtPoKY8z/Ktcev8YE9f2+9H2TfXDRKYqIEfxgZLCJ4yP2gxDe6zurabS0hAO1CP+ej5 | ||
17 | htdJM3/rTqHAIevXX5uhIDmMvRHnLGldaIX1xux8TIJvSfMkYNIwscIP4kx7BGMk04vXtW | ||
18 | 5DLm6IZhzw9T3hjr8R0kBugmT6/h9vD5iN1D+wiHIhHYzQKMU9nOeFNsMBFWgJjU0l8VlF | ||
19 | gEjEMgAEfwynnmIoKB1iA/0em1tdU3naS59DBK+buE0trxUpTAAB5z8yPhAm6DdqrPE8cA | ||
20 | N3HlMoWrbCuak2A0uyOlEJjPg4UJUnv12ve2c9pAMsAu/4CAszCEM0prR+qd/RA4nn4M5u | ||
21 | Xrny2wNtt/DybCkA== | ||
22 | -----END OPENSSH PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1 b/regress/unittests/sshkey/testdata/ecdsa_1 new file mode 100644 index 000000000..aec73dd61 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1 | |||
@@ -0,0 +1,5 @@ | |||
1 | -----BEGIN EC PRIVATE KEY----- | ||
2 | MHcCAQEEIFghsFR1K95tz8qOl3+tX6fv8a/O6AfNbxOSFZX3ihxooAoGCCqGSM49 | ||
3 | AwEHoUQDQgAEalpgP0BOePHtTw0Pus4tdhTb8P9yWUZluvLf1D8vrHImT+G4vr/W | ||
4 | xo5iXGKQVEifuUVyLkAW2kDrq8J/szeRiQ== | ||
5 | -----END EC PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp new file mode 100644 index 000000000..a56dbc8d0 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp | |||
@@ -0,0 +1 @@ | |||
f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub new file mode 100644 index 000000000..29b06a4dd --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub | |||
@@ -0,0 +1 @@ | |||
ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgjpoHehzmM54xz776HOiTOLPhkOwSWyXOMYeqDhDEcLgAAAAIbmlzdHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYlxikFRIn7lFci5AFtpA66vCf7M3kYkAAAAAAAAABwAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYlxikFRIn7lFci5AFtpA66vCf7M3kYkAAABjAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIFZM1PXlXf0a3VuGs7MVdWSealDXprT1nN5hQTg+m+EYAAAAIGN1yNXWEY5V315NhOD3mBuh/xCpfDn5rZjF4YntA7du ecdsa_1.pub | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp b/regress/unittests/sshkey/testdata/ecdsa_1.fp new file mode 100644 index 000000000..a56dbc8d0 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp | |||
@@ -0,0 +1 @@ | |||
f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb new file mode 100644 index 000000000..f01a5dd44 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb | |||
@@ -0,0 +1 @@ | |||
xotah-hecal-zibyb-nadug-romuc-hator-venum-hobip-ruluh-ripus-naxix | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.curve b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve new file mode 100644 index 000000000..fa0400467 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve | |||
@@ -0,0 +1 @@ | |||
prime256v1 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.priv b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv new file mode 100644 index 000000000..3475f1fe9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv | |||
@@ -0,0 +1 @@ | |||
5821b054752bde6dcfca8e977fad5fa7eff1afcee807cd6f13921595f78a1c68 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.pub b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub new file mode 100644 index 000000000..11847a394 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub | |||
@@ -0,0 +1 @@ | |||
046a5a603f404e78f1ed4f0d0fbace2d7614dbf0ff72594665baf2dfd43f2fac72264fe1b8bebfd6c68e625c629054489fb945722e4016da40ebabc27fb3379189 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.pub b/regress/unittests/sshkey/testdata/ecdsa_1.pub new file mode 100644 index 000000000..eca1620bc --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.pub | |||
@@ -0,0 +1 @@ | |||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYlxikFRIn7lFci5AFtpA66vCf7M3kYk= ECDSA test key #1 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1_pw b/regress/unittests/sshkey/testdata/ecdsa_1_pw new file mode 100644 index 000000000..071154ab2 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1_pw | |||
@@ -0,0 +1,8 @@ | |||
1 | -----BEGIN EC PRIVATE KEY----- | ||
2 | Proc-Type: 4,ENCRYPTED | ||
3 | DEK-Info: AES-128-CBC,74C8AEA5BFAFCC2B1C8B13DE671F5610 | ||
4 | |||
5 | vUsgOvCqezxPmcZcFqrSy9Y1MMlVguY0h9cfSPFC7gUrRr+45uCOYX5bOwEXecKn | ||
6 | /9uCXZtlBwwqDS9iK5IPoUrjEHvzI5rVbHWUxDrEOVbsfiDuCxrQM19It6QIqC1v | ||
7 | OSQEdXuBWR5WmhKNc3dqLbWsU8u2s60YwKQmZrj9nM4= | ||
8 | -----END EC PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2 b/regress/unittests/sshkey/testdata/ecdsa_2 new file mode 100644 index 000000000..76ae07ad4 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2 | |||
@@ -0,0 +1,7 @@ | |||
1 | -----BEGIN EC PRIVATE KEY----- | ||
2 | MIHcAgEBBEIBg4kVxUfoo/RE/78/QBRqG6PZuHZ82eLnhmZVzBa7XREUiYI/Jw7r | ||
3 | Qwp4FTBVfXL76Pt5AyBMf+52aVeOUlLRERSgBwYFK4EEACOhgYkDgYYABACNTJ5O | ||
4 | uNo5dNgIQRLHzKU91m7immKFiutJ6BlDbkRkKr+Envj13J6HOgYvOTm0n7SPlKHS | ||
5 | STZ4/T36d/rzQOAbIwEnbbwD9HMj6IzE4WH9lJzH7Zy7Tcyu6dOM8L7nOxCp3DUk | ||
6 | F3aAnPSFJhD7NN0jBWOFsD6uy1OmaTklPfRAnCt1MQ== | ||
7 | -----END EC PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp b/regress/unittests/sshkey/testdata/ecdsa_2.fp new file mode 100644 index 000000000..eb4bbdf03 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp | |||
@@ -0,0 +1 @@ | |||
51:bd:ff:2b:6d:26:9b:90:f9:e1:4a:ca:a0:29:8e:70 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb new file mode 100644 index 000000000..267bc63fd --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb | |||
@@ -0,0 +1 @@ | |||
xuzaz-zuzuk-virop-vypah-zumel-gylak-selih-fevad-varag-zynif-haxox | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.curve b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve new file mode 100644 index 000000000..617ea2fb8 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve | |||
@@ -0,0 +1 @@ | |||
secp521r1 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.priv b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv new file mode 100644 index 000000000..537cdaac3 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv | |||
@@ -0,0 +1 @@ | |||
01838915c547e8a3f444ffbf3f40146a1ba3d9b8767cd9e2e7866655cc16bb5d111489823f270eeb430a781530557d72fbe8fb7903204c7fee7669578e5252d11114 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.pub b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub new file mode 100644 index 000000000..3352ac769 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub | |||
@@ -0,0 +1 @@ | |||
04008d4c9e4eb8da3974d8084112c7cca53dd66ee29a62858aeb49e819436e44642abf849ef8f5dc9e873a062f3939b49fb48f94a1d2493678fd3dfa77faf340e01b2301276dbc03f47323e88cc4e161fd949cc7ed9cbb4dccaee9d38cf0bee73b10a9dc35241776809cf4852610fb34dd23056385b03eaecb53a66939253df4409c2b7531 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.pub b/regress/unittests/sshkey/testdata/ecdsa_2.pub new file mode 100644 index 000000000..34e1881dd --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.pub | |||
@@ -0,0 +1 @@ | |||
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBACNTJ5OuNo5dNgIQRLHzKU91m7immKFiutJ6BlDbkRkKr+Envj13J6HOgYvOTm0n7SPlKHSSTZ4/T36d/rzQOAbIwEnbbwD9HMj6IzE4WH9lJzH7Zy7Tcyu6dOM8L7nOxCp3DUkF3aAnPSFJhD7NN0jBWOFsD6uy1OmaTklPfRAnCt1MQ== ECDSA test key #2 | |||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_n b/regress/unittests/sshkey/testdata/ecdsa_n new file mode 100644 index 000000000..aec73dd61 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_n | |||
@@ -0,0 +1,5 @@ | |||
1 | -----BEGIN EC PRIVATE KEY----- | ||
2 | MHcCAQEEIFghsFR1K95tz8qOl3+tX6fv8a/O6AfNbxOSFZX3ihxooAoGCCqGSM49 | ||
3 | AwEHoUQDQgAEalpgP0BOePHtTw0Pus4tdhTb8P9yWUZluvLf1D8vrHImT+G4vr/W | ||
4 | xo5iXGKQVEifuUVyLkAW2kDrq8J/szeRiQ== | ||
5 | -----END EC PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ecdsa_n_pw b/regress/unittests/sshkey/testdata/ecdsa_n_pw new file mode 100644 index 000000000..75d585908 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_n_pw | |||
@@ -0,0 +1,9 @@ | |||
1 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
2 | b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABBXqI6Z6o | ||
3 | uRM+jAwdhnDoIMAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz | ||
4 | dHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYl | ||
5 | xikFRIn7lFci5AFtpA66vCf7M3kYkAAACwYMnoCTqvUTG0ktSSMNsOZLCdal5J4avEpM1L | ||
6 | sV9SL/RVcwo3ChprhwsnQsaAtMiJCRcHerKgD9qy1MNNaE5VNfVJ0Ih/7ut04cbFKed8p6 | ||
7 | 0V+w8WP7WvFffBPoHn+GGbQd1FDGzHhXUB61pH8Qzd1bI/sld/XEtMk7iYjNGQe9Rt0RaK | ||
8 | Wi8trwaA0Fb2w/EFnrdsFFxrIhQEqYBdEQJo782IqAsMG9OwUaM0vy+8bcI= | ||
9 | -----END OPENSSH PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ed25519_1 b/regress/unittests/sshkey/testdata/ed25519_1 new file mode 100644 index 000000000..a537ae13d --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1 | |||
@@ -0,0 +1,7 @@ | |||
1 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
2 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW | ||
3 | QyNTUxOQAAACC5PeVeSdyylcfG3C0geNO90e3dGgL0fICaz751dA9zEAAAAJglsAcYJbAH | ||
4 | GAAAAAtzc2gtZWQyNTUxOQAAACC5PeVeSdyylcfG3C0geNO90e3dGgL0fICaz751dA9zEA | ||
5 | AAAED6HJ8Bh8tdQvhMd5o8IxtIwBv8/FV48FpBFWAbYdsIsLk95V5J3LKVx8bcLSB4073R | ||
6 | 7d0aAvR8gJrPvnV0D3MQAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== | ||
7 | -----END OPENSSH PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp new file mode 100644 index 000000000..e6d23d0b8 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp | |||
@@ -0,0 +1 @@ | |||
19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f | |||
diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.pub b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub new file mode 100644 index 000000000..ad0b9a888 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub | |||
@@ -0,0 +1 @@ | |||
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIHmdL66MkkOvncpc0W4MdvlJZMfQthHiOUv+XKm7gvzOAAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQAAAAAAAAAAgAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANouDYAAAAABNHeHgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACC5PeVeSdyylcfG3C0geNO90e3dGgL0fICaz751dA9zEAAAAFMAAAALc3NoLWVkMjU1MTkAAABAsUStKm1z3Rtvwy3eXE1DrgVp6kix2iEQXfB66IHX2UpAj5yl0eQGXWTSEDIxHDIb0SJvUH43OWX0PrEeAs0mAA== ed25519_1.pub | |||
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp b/regress/unittests/sshkey/testdata/ed25519_1.fp new file mode 100644 index 000000000..e6d23d0b8 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1.fp | |||
@@ -0,0 +1 @@ | |||
19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f | |||
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp.bb b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb new file mode 100644 index 000000000..591a711b4 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb | |||
@@ -0,0 +1 @@ | |||
xofip-nuhoh-botam-cypeg-panig-tunef-bimav-numeb-nikic-gocyf-paxax | |||
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.pub b/regress/unittests/sshkey/testdata/ed25519_1.pub new file mode 100644 index 000000000..633e05077 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1.pub | |||
@@ -0,0 +1 @@ | |||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQ ED25519 test key #1 | |||
diff --git a/regress/unittests/sshkey/testdata/ed25519_1_pw b/regress/unittests/sshkey/testdata/ed25519_1_pw new file mode 100644 index 000000000..9fc635208 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1_pw | |||
@@ -0,0 +1,8 @@ | |||
1 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
2 | b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABAlT1eewp | ||
3 | 9gl0gue+sSrBWKAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bc | ||
4 | LSB4073R7d0aAvR8gJrPvnV0D3MQAAAAoMrL9ixIQHoJ86DcKMGt26+bCeaoyGjW5hha2Y | ||
5 | IxAZ+rRvNjUuv3MGvbUxtUpPZkTP/vk2fVSCuCD9St5Lbt/LKdIk2MfWIFbjZ6iEfdzxz0 | ||
6 | DHmsSDMps8dbePqqIPULR8av447jEzQEkUc8GSR6WqFSJOjJ8OvrJat1KcEK7V2tjZnLS1 | ||
7 | GoLMqVAtCVhuXwUkeJiRQE/JRl172hxB+LAVw= | ||
8 | -----END OPENSSH PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ed25519_2 b/regress/unittests/sshkey/testdata/ed25519_2 new file mode 100644 index 000000000..a6e5f0040 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2 | |||
@@ -0,0 +1,7 @@ | |||
1 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
2 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW | ||
3 | QyNTUxOQAAACBXUfO5Kid+jhRnyVt+1r9wj2FN/mZ6RfgGdySeYoq4WAAAAJjGeKsZxnir | ||
4 | GQAAAAtzc2gtZWQyNTUxOQAAACBXUfO5Kid+jhRnyVt+1r9wj2FN/mZ6RfgGdySeYoq4WA | ||
5 | AAAEB+gn4gGClQl2WMeOkikY+w0A0kSw1KH4Oyami7hlypsFdR87kqJ36OFGfJW37Wv3CP | ||
6 | YU3+ZnpF+AZ3JJ5iirhYAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== | ||
7 | -----END OPENSSH PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp b/regress/unittests/sshkey/testdata/ed25519_2.fp new file mode 100644 index 000000000..02c684f36 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2.fp | |||
@@ -0,0 +1 @@ | |||
5c:c9:ae:a3:0c:aa:28:29:b8:fc:7c:64:ba:6e:e9:c9 | |||
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp.bb b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb new file mode 100644 index 000000000..ebe782e2c --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb | |||
@@ -0,0 +1 @@ | |||
xenoz-tovup-zecyt-hohar-motam-sugid-fecyz-tutyk-gosom-ginar-kixux | |||
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.pub b/regress/unittests/sshkey/testdata/ed25519_2.pub new file mode 100644 index 000000000..37b93352a --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2.pub | |||
@@ -0,0 +1 @@ | |||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdR87kqJ36OFGfJW37Wv3CPYU3+ZnpF+AZ3JJ5iirhY ED25519 test key #1 | |||
diff --git a/regress/unittests/sshkey/testdata/pw b/regress/unittests/sshkey/testdata/pw new file mode 100644 index 000000000..8a1dff98a --- /dev/null +++ b/regress/unittests/sshkey/testdata/pw | |||
@@ -0,0 +1 @@ | |||
mekmitasdigoat | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_1 b/regress/unittests/sshkey/testdata/rsa1_1 new file mode 100644 index 000000000..d22014e88 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_1 | |||
Binary files differ | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.fp b/regress/unittests/sshkey/testdata/rsa1_1.fp new file mode 100644 index 000000000..782ece0db --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_1.fp | |||
@@ -0,0 +1 @@ | |||
a8:82:9b:98:c5:e6:19:d6:83:39:9f:4d:3a:8f:7c:80 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.fp.bb b/regress/unittests/sshkey/testdata/rsa1_1.fp.bb new file mode 100644 index 000000000..caaf9511a --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_1.fp.bb | |||
@@ -0,0 +1 @@ | |||
xukib-cymuf-mylib-kecih-rogyb-sorid-belys-kytem-dinin-cicil-kyxex | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.param.n b/regress/unittests/sshkey/testdata/rsa1_1.param.n new file mode 100644 index 000000000..4ceb37362 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_1.param.n | |||
@@ -0,0 +1 @@ | |||
00cf68059e5c7743318d740d3ebb55eb577891c9c3098817703f4c3157285055c2daa50102509ebdcade324e541c965e2931fd3459052fe65d013722da805d7ec8ef5b97cc006789d0566c5578b23e7aaa5be2b055d85798030cdead2eb2cc4eb3 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.pub b/regress/unittests/sshkey/testdata/rsa1_1.pub new file mode 100644 index 000000000..56cf30d30 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_1.pub | |||
@@ -0,0 +1 @@ | |||
768 65537 1257820658919101781627826212425999371251377782154008557690434337796299274692579921603319269571889066123773172648045269780061837011867522525764583065919572648969392756890567918758763032103894830246827894023662422727333291801518558899 RSA1 test key #1 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_1_pw b/regress/unittests/sshkey/testdata/rsa1_1_pw new file mode 100644 index 000000000..3113dbc0f --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_1_pw | |||
Binary files differ | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_2 b/regress/unittests/sshkey/testdata/rsa1_2 new file mode 100644 index 000000000..e75e665ff --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_2 | |||
Binary files differ | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.fp b/regress/unittests/sshkey/testdata/rsa1_2.fp new file mode 100644 index 000000000..c3325371d --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_2.fp | |||
@@ -0,0 +1 @@ | |||
c0:83:1c:97:5f:32:77:7e:e4:e3:e9:29:b9:eb:76:9c | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.fp.bb b/regress/unittests/sshkey/testdata/rsa1_2.fp.bb new file mode 100644 index 000000000..cd8037140 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_2.fp.bb | |||
@@ -0,0 +1 @@ | |||
xifad-vevot-sozyl-fapeb-meryf-kylut-cydiv-firik-gavyb-lanad-kaxox | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.param.n b/regress/unittests/sshkey/testdata/rsa1_2.param.n new file mode 100644 index 000000000..f8143a4b9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_2.param.n | |||
@@ -0,0 +1 @@ | |||
00b08a9fa386aceaab2ec3e9cdc7e6cb4eac9e98620279eed6762e1f513739a417ac8a86231fad3b8727a9de994973a7aae674a132547341984ade91aa1c22f01d2f0204ea7fa121969c367a5d04bda384066cf94e0b56d1efc47f50ca28e90603547df41c0676550d82d369f699b457d4f0f077999d9e76ab679fbf4206d418dbabed1823f14e4ddf3aac987686e6b006f8a23ea6af13b4c0e5b1fb5b1eb4db2f47b229422c450574cae9c64db5dcfce050836b6bdfa8fb541b4d426444a5ea20ad51a25d3048414ced2e199da2997968273e8beb10f3a351e98a57b00dadfa8f00a39bb55be94dae898fda6021d728f32b2ec93edd16e51073be3ac7511e5085 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.pub b/regress/unittests/sshkey/testdata/rsa1_2.pub new file mode 100644 index 000000000..de1afbb8b --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa1_2.pub | |||
@@ -0,0 +1 @@ | |||
2048 65537 22286299513474010485021611215236051675183880694440075228245854420062562171290421803318459093678819161498086077099067169041536315773126601869537036602014639497662916952995546870691495931205282427606841521014293638607226118353743812583642616889028731910222603216563207637006843580936568089467160095319593442255227365472917576488012409542775346105980501967996562422764758836868135158147777193940857952623773420292946843206784104932927528915610322518810753953608862466374219925252817405397507396462117715293725218947744085154122395590957537510003558169729949140038634486299736757269280065662263306737701939154762092925061 RSA1 test key #2 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1 b/regress/unittests/sshkey/testdata/rsa_1 new file mode 100644 index 000000000..09e79a72e --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1 | |||
@@ -0,0 +1,12 @@ | |||
1 | -----BEGIN RSA PRIVATE KEY----- | ||
2 | MIIBywIBAAJhAM/6MDmVVm/uNQmZpOcthoAAgMDUg7G4H6ZLLyPEhboKaBBHvIdw | ||
3 | ZdDmB+0LDf3D1aWXyUd2/pCkCysiBzqd/523zAzjY7HayqL6A940AxKBBbWLn+X6 | ||
4 | i2yJR7dTOYkk6QIDAQABAmAgKanBjfWzE5yCIo+c7K5rJyjCKVtAZaAHYIMmveKM | ||
5 | VcWoFt/x9hDY0GoTX21HfDxLX8oDxnsmhsOrnvSmgUChFwkm45eSETqeVDWwIVFA | ||
6 | FGL1s38xQsciWZWBFNppAIECMQD7nslReAxwz/Ad++ACXswfJg1l2wUQ1gJA3zh3 | ||
7 | jln6a4s3aV1zxbKlIn8iqBv0BZkCMQDTmO4WqyNnin73XCZs0DWu7GsfcuaH8QnD | ||
8 | wqPjJgrclTZXedxHkeqO2oyZW4mLC9ECMBb/blsZ49kzyDiVWuYcj/+Q1MyodhAR | ||
9 | 32bagCi9RBAVYEYSRU5dlXRucLxULSnikQIxAJ5teY5Vcru6kZfJUifUuO0QrKAu | ||
10 | WnbcPVBqMmUHfchsm/RhFFIt6W4uKmlEhTYrkQIxAMAStb7QCU3yU6ZkN7uL22Zs | ||
11 | 498i4jY6y+VEXv+L9O09VdlEnXhbUisOhy1bhyS3yg== | ||
12 | -----END RSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.fp b/regress/unittests/sshkey/testdata/rsa_1-cert.fp new file mode 100644 index 000000000..bf9c2e362 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1-cert.fp | |||
@@ -0,0 +1 @@ | |||
be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.pub b/regress/unittests/sshkey/testdata/rsa_1-cert.pub new file mode 100644 index 000000000..51b1ce0dd --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1-cert.pub | |||
@@ -0,0 +1 @@ | |||
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg1i9Ueveqg9sFSGsEYmsQqlI+dpC3nqhucPfwBVo3DtcAAAADAQABAAAAYQDP+jA5lVZv7jUJmaTnLYaAAIDA1IOxuB+mSy8jxIW6CmgQR7yHcGXQ5gftCw39w9Wll8lHdv6QpAsrIgc6nf+dt8wM42Ox2sqi+gPeNAMSgQW1i5/l+otsiUe3UzmJJOkAAAAAAAAABQAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAED0TLf2Mv2F9TBt1Skf/1vviUgt7bt9xvL5HqugnVDfKaEg+RNKgfa5Rtpteb39EODkH8v4FJPWlmNG0F9w0cYF rsa_1.pub | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp b/regress/unittests/sshkey/testdata/rsa_1.fp new file mode 100644 index 000000000..bf9c2e362 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.fp | |||
@@ -0,0 +1 @@ | |||
be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp.bb b/regress/unittests/sshkey/testdata/rsa_1.fp.bb new file mode 100644 index 000000000..448133bad --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.fp.bb | |||
@@ -0,0 +1 @@ | |||
xetif-zuvul-nylyc-vykor-lumac-gyhyv-bacih-cimyk-sycen-gikym-pixax | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.n b/regress/unittests/sshkey/testdata/rsa_1.param.n new file mode 100644 index 000000000..2ffc2ba7e --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.param.n | |||
@@ -0,0 +1 @@ | |||
00cffa303995566fee350999a4e72d86800080c0d483b1b81fa64b2f23c485ba0a681047bc877065d0e607ed0b0dfdc3d5a597c94776fe90a40b2b22073a9dff9db7cc0ce363b1dacaa2fa03de3403128105b58b9fe5fa8b6c8947b753398924e9 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.p b/regress/unittests/sshkey/testdata/rsa_1.param.p new file mode 100644 index 000000000..4fcf148c3 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.param.p | |||
@@ -0,0 +1 @@ | |||
00fb9ec951780c70cff01dfbe0025ecc1f260d65db0510d60240df38778e59fa6b8b37695d73c5b2a5227f22a81bf40599 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.q b/regress/unittests/sshkey/testdata/rsa_1.param.q new file mode 100644 index 000000000..3473f5144 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.param.q | |||
@@ -0,0 +1 @@ | |||
00d398ee16ab23678a7ef75c266cd035aeec6b1f72e687f109c3c2a3e3260adc95365779dc4791ea8eda8c995b898b0bd1 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1.pub b/regress/unittests/sshkey/testdata/rsa_1.pub new file mode 100644 index 000000000..889fdae86 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.pub | |||
@@ -0,0 +1 @@ | |||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQDP+jA5lVZv7jUJmaTnLYaAAIDA1IOxuB+mSy8jxIW6CmgQR7yHcGXQ5gftCw39w9Wll8lHdv6QpAsrIgc6nf+dt8wM42Ox2sqi+gPeNAMSgQW1i5/l+otsiUe3UzmJJOk= RSA test key #1 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_1_pw b/regress/unittests/sshkey/testdata/rsa_1_pw new file mode 100644 index 000000000..71637a59b --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_pw | |||
@@ -0,0 +1,15 @@ | |||
1 | -----BEGIN RSA PRIVATE KEY----- | ||
2 | Proc-Type: 4,ENCRYPTED | ||
3 | DEK-Info: AES-128-CBC,1E851A01F12A49FDC256E7A665C61D4B | ||
4 | |||
5 | +sfWU7kg3idmHL6vShby5LXnfF4bZDPhJjv89uldae7qPEgEW8qS8o0Ssokxf7Au | ||
6 | /vTQnbSB+gy/qZaUOykOzqiV1YL7UfkbOkM2QYnzzrVeGzI5RZ0G9iH8HBn2owQ+ | ||
7 | Ejf1UKDUVZEea5X0IwQRfE0zaZqFS4tyEex0iKz8dI4FvyabKLZsCs1DBGO7A3ml | ||
8 | LgP947mh10yKWTP2fbq8LOhDUEWCXrh2NzuH6Rl5nNyC4MNQEkLzK1wL7J/WCNaL | ||
9 | sciYmuqEQRDikDDQQFZw2wjBD638fhK+IhuN3VGegiXFnu5C+p9kzUvqVk4X9g2r | ||
10 | BMmlP0pceFv/fEwtNNaeI2Tt7mIsWsZTmCqdzOUAYqGIiNjzykWw64nMO3TpVpbA | ||
11 | i4854RhblbeiyjENbMVPU6BAk4fx7OJvDElLxwN43CS3U0MldbI7A4uG3B3RTSCj | ||
12 | 1rGxRNAHWC3q3zzrn6gLwrUVje4iTedaKItLIHQeo1A091Tr8AqQdZi/Ck2Ju0Hl | ||
13 | 4Qdwzjw1Y5n1Akm+EWh31ydxtUQ0YBOz/W6DKwTNA1D8oH9bZBG4f0pnvVhtttAO | ||
14 | WKj+DUqMa+f3OOmQ9UXlitk2pEgjeMngTgfQnhZiCts= | ||
15 | -----END RSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/rsa_2 b/regress/unittests/sshkey/testdata/rsa_2 new file mode 100644 index 000000000..058cf777a --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2 | |||
@@ -0,0 +1,27 @@ | |||
1 | -----BEGIN RSA PRIVATE KEY----- | ||
2 | MIIEowIBAAKCAQEAlDS/ygeFfsR/mhZK/XMHU/gzRogPuMQIYUd17WDjMprA6dQb | ||
3 | ckTDrNm/mrf09I6YAhjgooEL16oWM1z6cesDE0KwaJsy6uTmXFMLO+Ha4mtFHhmu | ||
4 | tiyJcQ9MKKr0vC64384WQZygZk0OlVz7x9WSPiGXzal5MzsX4TYq5B05o2Cb+epA | ||
5 | FxK0c8cdYZD0Sy57gWRpRA3yJq4zh/hks98jzn0XA3HAJA39MKhUG5tf5e6z5BeP | ||
6 | Yi5FvdnDQ9WcasRiEvkmHbg59pbgg/Lbsl6OgZQruS8hKiJ3YBARt2euCCeg7qAF | ||
7 | KbXRR9TMwfphH3Ai4Oi/w6HPRAhdrwooA/gKkQIDAQABAoIBAH22OLB/rMaYmrvz | ||
8 | COzvM1oQgD3lj6Bj98+8M9WEh3MXPWeaGSXWGjx1/0aXn1oJ0fqFa5Wr7IWkqmwr | ||
9 | A+y5McSWntg8PPZt7tCFSFQlAetonhooIsA4CuUx2qHsUOeGoh6EyvAgkRX1atdb | ||
10 | Jd6d1AyLph43EK1aBKltrvgLqiZfs7mcuwyvKtN9ktdKY2FDhn6DHpm9pE9MEHJV | ||
11 | Xv1isNc6a0qNoRlKqxrSZHNEN4fbjLw31wBySzmmnIog5wVEwaHeASwLJT6TmuIZ | ||
12 | eZxnd7/jMwRZWH8ZIGKvkTMp4fYzK9QkehO7A2HFD3FPDBVrkSJjqRdkujF8vu1C | ||
13 | 0RwrD1kCgYEAxFXUoE1ero6vp9akvR/mw94kYjXE/YOz1yi0KTkZUs6gURc8Kzsm | ||
14 | MzlEZ31rnngE4jQHYAvuPEfiqcnUgylW3QuevMgo2hCLYO7aG5C0fk8TeOiuvnrF | ||
15 | YPO8rSJWk/BgdrPtzu45P7jmWsjkHn+y+t8cKvq1sZY40sn2YgIhYK8CgYEAwT6j | ||
16 | 5tReI6sxpHltPUbvOdpD04eL6ggBAKwzb5aBoa/Dj+sU1zg5uyY8diggQEEznlBW | ||
17 | iWTQmmmfy1ef9i6YAwNuZveKOrVwNMcdubQJ2X26XoFrmA59PjsbLtr1bdUb02gz | ||
18 | 6P5x6pcw5qzEq0mddgvHiU3RhL24xdc1LW8nmL8CgYEAmgaT1macPuklmNBlURGz | ||
19 | 4jll5b41GoW2EreWDzkCStpbHwLRa0DuCQWGSoI0aY/SlPsoRgtWDOiAQ59ZHsTR | ||
20 | pnw1PfjxQ5HzJkp7xWBSmTzEE/jHDhwWuKa+gD0OGuVbaARkLhDpzLnrzZEIlXyt | ||
21 | Fu7tlDI3VGh7j7Jtnhn5wXUCgYBKmPbGfcaVeFmih2lfFUn2CEbUmmetgUd5zf/R | ||
22 | HMWP9/zDStlxt3e5winm5tiEVWcqvxKY2T0Zzppr8biDXTs7NpDg2MAYp7/X7+GO | ||
23 | tWxz8/AE2WsCeN1qL4Dv1oCV1IV4V6pqUAcDqzeqZJlLEhDh5+wwGcU+u8pfPRN/ | ||
24 | JYCgmwKBgDa+kXPqzcc6vzD9cwEEk4ftn9/Vk2yBx0XOu8RdEkRhXj1QXGJckCqh | ||
25 | FkXzVbuurFhsBt+H0B4arw+51T9fVCZqfcaU34u+Qa/FQvTod4OJUSRxYUaDqygs | ||
26 | VTyuP+zGZlIw7JWktxjVazENsM/ef5wBH0Nf839OZbPVDLfn7K0j | ||
27 | -----END RSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp b/regress/unittests/sshkey/testdata/rsa_2.fp new file mode 100644 index 000000000..53939f413 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.fp | |||
@@ -0,0 +1 @@ | |||
fb:8f:7b:26:3d:42:40:ef:ed:f1:ed:ee:66:9e:ba:b0 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp.bb b/regress/unittests/sshkey/testdata/rsa_2.fp.bb new file mode 100644 index 000000000..e90a3571a --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.fp.bb | |||
@@ -0,0 +1 @@ | |||
xepev-gupub-vuvyg-femiv-gonat-defiv-hirak-betub-pahut-veryd-hexix | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.n b/regress/unittests/sshkey/testdata/rsa_2.param.n new file mode 100644 index 000000000..389de4226 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.param.n | |||
@@ -0,0 +1 @@ | |||
009434bfca07857ec47f9a164afd730753f83346880fb8c408614775ed60e3329ac0e9d41b7244c3acd9bf9ab7f4f48e980218e0a2810bd7aa16335cfa71eb031342b0689b32eae4e65c530b3be1dae26b451e19aeb62c89710f4c28aaf4bc2eb8dfce16419ca0664d0e955cfbc7d5923e2197cda979333b17e1362ae41d39a3609bf9ea401712b473c71d6190f44b2e7b816469440df226ae3387f864b3df23ce7d170371c0240dfd30a8541b9b5fe5eeb3e4178f622e45bdd9c343d59c6ac46212f9261db839f696e083f2dbb25e8e81942bb92f212a2277601011b767ae0827a0eea00529b5d147d4ccc1fa611f7022e0e8bfc3a1cf44085daf0a2803f80a91 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.p b/regress/unittests/sshkey/testdata/rsa_2.param.p new file mode 100644 index 000000000..c3c9a130a --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.param.p | |||
@@ -0,0 +1 @@ | |||
00c455d4a04d5eae8eafa7d6a4bd1fe6c3de246235c4fd83b3d728b429391952cea051173c2b3b26333944677d6b9e7804e23407600bee3c47e2a9c9d4832956dd0b9ebcc828da108b60eeda1b90b47e4f1378e8aebe7ac560f3bcad225693f06076b3edceee393fb8e65ac8e41e7fb2fadf1c2afab5b19638d2c9f662022160af | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.q b/regress/unittests/sshkey/testdata/rsa_2.param.q new file mode 100644 index 000000000..728c474b0 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.param.q | |||
@@ -0,0 +1 @@ | |||
00c13ea3e6d45e23ab31a4796d3d46ef39da43d3878bea080100ac336f9681a1afc38feb14d73839bb263c7628204041339e50568964d09a699fcb579ff62e9803036e66f78a3ab57034c71db9b409d97dba5e816b980e7d3e3b1b2edaf56dd51bd36833e8fe71ea9730e6acc4ab499d760bc7894dd184bdb8c5d7352d6f2798bf | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_2.pub b/regress/unittests/sshkey/testdata/rsa_2.pub new file mode 100644 index 000000000..ed9f78cad --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.pub | |||
@@ -0,0 +1 @@ | |||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUNL/KB4V+xH+aFkr9cwdT+DNGiA+4xAhhR3XtYOMymsDp1BtyRMOs2b+at/T0jpgCGOCigQvXqhYzXPpx6wMTQrBomzLq5OZcUws74dria0UeGa62LIlxD0woqvS8LrjfzhZBnKBmTQ6VXPvH1ZI+IZfNqXkzOxfhNirkHTmjYJv56kAXErRzxx1hkPRLLnuBZGlEDfImrjOH+GSz3yPOfRcDccAkDf0wqFQbm1/l7rPkF49iLkW92cND1ZxqxGIS+SYduDn2luCD8tuyXo6BlCu5LyEqIndgEBG3Z64IJ6DuoAUptdFH1MzB+mEfcCLg6L/Doc9ECF2vCigD+AqR RSA test key #2 | |||
diff --git a/regress/unittests/sshkey/testdata/rsa_n b/regress/unittests/sshkey/testdata/rsa_n new file mode 100644 index 000000000..09e79a72e --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_n | |||
@@ -0,0 +1,12 @@ | |||
1 | -----BEGIN RSA PRIVATE KEY----- | ||
2 | MIIBywIBAAJhAM/6MDmVVm/uNQmZpOcthoAAgMDUg7G4H6ZLLyPEhboKaBBHvIdw | ||
3 | ZdDmB+0LDf3D1aWXyUd2/pCkCysiBzqd/523zAzjY7HayqL6A940AxKBBbWLn+X6 | ||
4 | i2yJR7dTOYkk6QIDAQABAmAgKanBjfWzE5yCIo+c7K5rJyjCKVtAZaAHYIMmveKM | ||
5 | VcWoFt/x9hDY0GoTX21HfDxLX8oDxnsmhsOrnvSmgUChFwkm45eSETqeVDWwIVFA | ||
6 | FGL1s38xQsciWZWBFNppAIECMQD7nslReAxwz/Ad++ACXswfJg1l2wUQ1gJA3zh3 | ||
7 | jln6a4s3aV1zxbKlIn8iqBv0BZkCMQDTmO4WqyNnin73XCZs0DWu7GsfcuaH8QnD | ||
8 | wqPjJgrclTZXedxHkeqO2oyZW4mLC9ECMBb/blsZ49kzyDiVWuYcj/+Q1MyodhAR | ||
9 | 32bagCi9RBAVYEYSRU5dlXRucLxULSnikQIxAJ5teY5Vcru6kZfJUifUuO0QrKAu | ||
10 | WnbcPVBqMmUHfchsm/RhFFIt6W4uKmlEhTYrkQIxAMAStb7QCU3yU6ZkN7uL22Zs | ||
11 | 498i4jY6y+VEXv+L9O09VdlEnXhbUisOhy1bhyS3yg== | ||
12 | -----END RSA PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/testdata/rsa_n_pw b/regress/unittests/sshkey/testdata/rsa_n_pw new file mode 100644 index 000000000..0166fd5f1 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_n_pw | |||
@@ -0,0 +1,14 @@ | |||
1 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
2 | b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABClELgtaZ | ||
3 | qAmMwESpqXDN0uAAAAEAAAAAEAAAB3AAAAB3NzaC1yc2EAAAADAQABAAAAYQDP+jA5lVZv | ||
4 | 7jUJmaTnLYaAAIDA1IOxuB+mSy8jxIW6CmgQR7yHcGXQ5gftCw39w9Wll8lHdv6QpAsrIg | ||
5 | c6nf+dt8wM42Ox2sqi+gPeNAMSgQW1i5/l+otsiUe3UzmJJOkAAAGgwJpHy/nshQa9+Jbw | ||
6 | yomvgNMYvuuoD7Ll7iCY/RFFGXivTkki27C9q0qx3afauSLQQWFanGhjeJn7JPy98lMcVl | ||
7 | qnn5XOE5+xxZqA8ONOBD8eH0KBcTH17DH1A1z94p5zZ1VJKIWsBZ0krxgHIXcdv9ucAckj | ||
8 | N0vAEBm+0wsfy2TTOtuqXvcj65wFwknpyy/SSvU0QTr99FiYe9PIhIslBHO6wlqxfKj+Tm | ||
9 | E/nCb75dAVu6gTtS2P0pdOqV/V7VHX5C0z3BROqpKDJJcVeoc7vRkEl+MWfvvQrG66IPEW | ||
10 | luohFXPDPDrxu1zDduyRsmNwpBHChi2rFhxtsjxNK0svMwESeCCKAWmPxnzLJfvMbTCv00 | ||
11 | SpaCr7WhtzsGt73axqSkeOdynp5NNrN7MEdwruMZFirF4BcI2z2H9ugpS+qbLPuE2H5vln | ||
12 | h7NSwBUNwmZ+4TC8MXFH9KIpRg8dNhf66OU610LYiN4+ZfOYCmfQfgQuBGhMTYFMY6O4SB | ||
13 | NCdIavvWY6rDSBq7QC1f4rHpwiXxpkiE43Rd8fM32TaPlBPtA= | ||
14 | -----END OPENSSH PRIVATE KEY----- | ||
diff --git a/regress/unittests/sshkey/tests.c b/regress/unittests/sshkey/tests.c new file mode 100644 index 000000000..13f265cdb --- /dev/null +++ b/regress/unittests/sshkey/tests.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* $OpenBSD: tests.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ | ||
2 | /* | ||
3 | * Regress test for sshbuf.h buffer API | ||
4 | * | ||
5 | * Placed in the public domain | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <openssl/evp.h> | ||
11 | |||
12 | #include "../test_helper/test_helper.h" | ||
13 | |||
14 | void sshkey_tests(void); | ||
15 | void sshkey_file_tests(void); | ||
16 | void sshkey_fuzz_tests(void); | ||
17 | |||
18 | void | ||
19 | tests(void) | ||
20 | { | ||
21 | OpenSSL_add_all_algorithms(); | ||
22 | ERR_load_CRYPTO_strings(); | ||
23 | |||
24 | sshkey_tests(); | ||
25 | sshkey_file_tests(); | ||
26 | sshkey_fuzz_tests(); | ||
27 | } | ||
diff --git a/regress/unittests/test_helper/Makefile b/regress/unittests/test_helper/Makefile new file mode 100644 index 000000000..3e90903ef --- /dev/null +++ b/regress/unittests/test_helper/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $ | ||
2 | |||
3 | LIB= test_helper | ||
4 | SRCS= test_helper.c fuzz.c | ||
5 | |||
6 | DEBUGLIBS= no | ||
7 | NOPROFILE= yes | ||
8 | NOPIC= yes | ||
9 | |||
10 | install: | ||
11 | @echo -n | ||
12 | |||
13 | .include <bsd.lib.mk> | ||
diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c new file mode 100644 index 000000000..77c6e7cad --- /dev/null +++ b/regress/unittests/test_helper/fuzz.c | |||
@@ -0,0 +1,378 @@ | |||
1 | /* $OpenBSD: fuzz.c,v 1.3 2014/05/02 09:41:32 andre Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller <djm@mindrot.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | /* Utility functions/framework for fuzz tests */ | ||
19 | |||
20 | #include "includes.h" | ||
21 | |||
22 | #include <sys/types.h> | ||
23 | |||
24 | #include <assert.h> | ||
25 | #include <ctype.h> | ||
26 | #include <stdio.h> | ||
27 | #ifdef HAVE_STDINT_H | ||
28 | # include <stdint.h> | ||
29 | #endif | ||
30 | #include <stdlib.h> | ||
31 | #include <string.h> | ||
32 | #include <assert.h> | ||
33 | |||
34 | #include "test_helper.h" | ||
35 | |||
36 | /* #define FUZZ_DEBUG */ | ||
37 | |||
38 | #ifdef FUZZ_DEBUG | ||
39 | # define FUZZ_DBG(x) do { \ | ||
40 | printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ | ||
41 | printf x; \ | ||
42 | printf("\n"); \ | ||
43 | fflush(stdout); \ | ||
44 | } while (0) | ||
45 | #else | ||
46 | # define FUZZ_DBG(x) | ||
47 | #endif | ||
48 | |||
49 | /* For brevity later */ | ||
50 | typedef unsigned long long fuzz_ullong; | ||
51 | |||
52 | /* For base-64 fuzzing */ | ||
53 | static const char fuzz_b64chars[] = | ||
54 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
55 | |||
56 | struct fuzz { | ||
57 | /* Fuzz method currently in use */ | ||
58 | int strategy; | ||
59 | |||
60 | /* Fuzz methods remaining */ | ||
61 | int strategies; | ||
62 | |||
63 | /* Original seed data blob */ | ||
64 | void *seed; | ||
65 | size_t slen; | ||
66 | |||
67 | /* Current working copy of seed with fuzz mutations applied */ | ||
68 | u_char *fuzzed; | ||
69 | |||
70 | /* Used by fuzz methods */ | ||
71 | size_t o1, o2; | ||
72 | }; | ||
73 | |||
74 | static const char * | ||
75 | fuzz_ntop(u_int n) | ||
76 | { | ||
77 | switch (n) { | ||
78 | case 0: | ||
79 | return "NONE"; | ||
80 | case FUZZ_1_BIT_FLIP: | ||
81 | return "FUZZ_1_BIT_FLIP"; | ||
82 | case FUZZ_2_BIT_FLIP: | ||
83 | return "FUZZ_2_BIT_FLIP"; | ||
84 | case FUZZ_1_BYTE_FLIP: | ||
85 | return "FUZZ_1_BYTE_FLIP"; | ||
86 | case FUZZ_2_BYTE_FLIP: | ||
87 | return "FUZZ_2_BYTE_FLIP"; | ||
88 | case FUZZ_TRUNCATE_START: | ||
89 | return "FUZZ_TRUNCATE_START"; | ||
90 | case FUZZ_TRUNCATE_END: | ||
91 | return "FUZZ_TRUNCATE_END"; | ||
92 | case FUZZ_BASE64: | ||
93 | return "FUZZ_BASE64"; | ||
94 | default: | ||
95 | abort(); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | void | ||
100 | fuzz_dump(struct fuzz *fuzz) | ||
101 | { | ||
102 | u_char *p = fuzz_ptr(fuzz); | ||
103 | size_t i, j, len = fuzz_len(fuzz); | ||
104 | |||
105 | switch (fuzz->strategy) { | ||
106 | case FUZZ_1_BIT_FLIP: | ||
107 | fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n", | ||
108 | fuzz_ntop(fuzz->strategy), | ||
109 | fuzz->o1, fuzz->slen * 8, fuzz->o1); | ||
110 | break; | ||
111 | case FUZZ_2_BIT_FLIP: | ||
112 | fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n", | ||
113 | fuzz_ntop(fuzz->strategy), | ||
114 | (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, | ||
115 | ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, | ||
116 | fuzz->o1, fuzz->o2); | ||
117 | break; | ||
118 | case FUZZ_1_BYTE_FLIP: | ||
119 | fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n", | ||
120 | fuzz_ntop(fuzz->strategy), | ||
121 | fuzz->o1, fuzz->slen, fuzz->o1); | ||
122 | break; | ||
123 | case FUZZ_2_BYTE_FLIP: | ||
124 | fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n", | ||
125 | fuzz_ntop(fuzz->strategy), | ||
126 | (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, | ||
127 | ((fuzz_ullong)fuzz->slen) * fuzz->slen, | ||
128 | fuzz->o1, fuzz->o2); | ||
129 | break; | ||
130 | case FUZZ_TRUNCATE_START: | ||
131 | fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", | ||
132 | fuzz_ntop(fuzz->strategy), | ||
133 | fuzz->o1, fuzz->slen, fuzz->o1); | ||
134 | break; | ||
135 | case FUZZ_TRUNCATE_END: | ||
136 | fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", | ||
137 | fuzz_ntop(fuzz->strategy), | ||
138 | fuzz->o1, fuzz->slen, fuzz->o1); | ||
139 | break; | ||
140 | case FUZZ_BASE64: | ||
141 | assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); | ||
142 | fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n", | ||
143 | fuzz_ntop(fuzz->strategy), | ||
144 | (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, | ||
145 | fuzz->slen * (fuzz_ullong)64, fuzz->o1, | ||
146 | fuzz_b64chars[fuzz->o2]); | ||
147 | break; | ||
148 | default: | ||
149 | abort(); | ||
150 | } | ||
151 | |||
152 | fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len); | ||
153 | for (i = 0; i < len; i += 16) { | ||
154 | fprintf(stderr, "%.4zd: ", i); | ||
155 | for (j = i; j < i + 16; j++) { | ||
156 | if (j < len) | ||
157 | fprintf(stderr, "%02x ", p[j]); | ||
158 | else | ||
159 | fprintf(stderr, " "); | ||
160 | } | ||
161 | fprintf(stderr, " "); | ||
162 | for (j = i; j < i + 16; j++) { | ||
163 | if (j < len) { | ||
164 | if (isascii(p[j]) && isprint(p[j])) | ||
165 | fprintf(stderr, "%c", p[j]); | ||
166 | else | ||
167 | fprintf(stderr, "."); | ||
168 | } | ||
169 | } | ||
170 | fprintf(stderr, "\n"); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | struct fuzz * | ||
175 | fuzz_begin(u_int strategies, const void *p, size_t l) | ||
176 | { | ||
177 | struct fuzz *ret = calloc(sizeof(*ret), 1); | ||
178 | |||
179 | assert(p != NULL); | ||
180 | assert(ret != NULL); | ||
181 | ret->seed = malloc(l); | ||
182 | assert(ret->seed != NULL); | ||
183 | memcpy(ret->seed, p, l); | ||
184 | ret->slen = l; | ||
185 | ret->strategies = strategies; | ||
186 | |||
187 | assert(ret->slen < SIZE_MAX / 8); | ||
188 | assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1))); | ||
189 | |||
190 | FUZZ_DBG(("begin, ret = %p", ret)); | ||
191 | |||
192 | fuzz_next(ret); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | void | ||
197 | fuzz_cleanup(struct fuzz *fuzz) | ||
198 | { | ||
199 | FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); | ||
200 | assert(fuzz != NULL); | ||
201 | assert(fuzz->seed != NULL); | ||
202 | assert(fuzz->fuzzed != NULL); | ||
203 | free(fuzz->seed); | ||
204 | free(fuzz->fuzzed); | ||
205 | free(fuzz); | ||
206 | } | ||
207 | |||
208 | static int | ||
209 | fuzz_strategy_done(struct fuzz *fuzz) | ||
210 | { | ||
211 | FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu", | ||
212 | fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen)); | ||
213 | |||
214 | switch (fuzz->strategy) { | ||
215 | case FUZZ_1_BIT_FLIP: | ||
216 | return fuzz->o1 >= fuzz->slen * 8; | ||
217 | case FUZZ_2_BIT_FLIP: | ||
218 | return fuzz->o2 >= fuzz->slen * 8; | ||
219 | case FUZZ_2_BYTE_FLIP: | ||
220 | return fuzz->o2 >= fuzz->slen; | ||
221 | case FUZZ_1_BYTE_FLIP: | ||
222 | case FUZZ_TRUNCATE_START: | ||
223 | case FUZZ_TRUNCATE_END: | ||
224 | case FUZZ_BASE64: | ||
225 | return fuzz->o1 >= fuzz->slen; | ||
226 | default: | ||
227 | abort(); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | void | ||
232 | fuzz_next(struct fuzz *fuzz) | ||
233 | { | ||
234 | u_int i; | ||
235 | |||
236 | FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, " | ||
237 | "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), | ||
238 | (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); | ||
239 | |||
240 | if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) { | ||
241 | /* If we are just starting out, we need to allocate too */ | ||
242 | if (fuzz->fuzzed == NULL) { | ||
243 | FUZZ_DBG(("alloc")); | ||
244 | fuzz->fuzzed = calloc(fuzz->slen, 1); | ||
245 | } | ||
246 | /* Pick next strategy */ | ||
247 | FUZZ_DBG(("advance")); | ||
248 | for (i = 1; i <= FUZZ_MAX; i <<= 1) { | ||
249 | if ((fuzz->strategies & i) != 0) { | ||
250 | fuzz->strategy = i; | ||
251 | break; | ||
252 | } | ||
253 | } | ||
254 | FUZZ_DBG(("selected = %u", fuzz->strategy)); | ||
255 | if (fuzz->strategy == 0) { | ||
256 | FUZZ_DBG(("done, no more strategies")); | ||
257 | return; | ||
258 | } | ||
259 | fuzz->strategies &= ~(fuzz->strategy); | ||
260 | fuzz->o1 = fuzz->o2 = 0; | ||
261 | } | ||
262 | |||
263 | assert(fuzz->fuzzed != NULL); | ||
264 | |||
265 | switch (fuzz->strategy) { | ||
266 | case FUZZ_1_BIT_FLIP: | ||
267 | assert(fuzz->o1 / 8 < fuzz->slen); | ||
268 | memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); | ||
269 | fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); | ||
270 | fuzz->o1++; | ||
271 | break; | ||
272 | case FUZZ_2_BIT_FLIP: | ||
273 | assert(fuzz->o1 / 8 < fuzz->slen); | ||
274 | assert(fuzz->o2 / 8 < fuzz->slen); | ||
275 | memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); | ||
276 | fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); | ||
277 | fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8); | ||
278 | fuzz->o1++; | ||
279 | if (fuzz->o1 >= fuzz->slen * 8) { | ||
280 | fuzz->o1 = 0; | ||
281 | fuzz->o2++; | ||
282 | } | ||
283 | break; | ||
284 | case FUZZ_1_BYTE_FLIP: | ||
285 | assert(fuzz->o1 < fuzz->slen); | ||
286 | memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); | ||
287 | fuzz->fuzzed[fuzz->o1] ^= 0xff; | ||
288 | fuzz->o1++; | ||
289 | break; | ||
290 | case FUZZ_2_BYTE_FLIP: | ||
291 | assert(fuzz->o1 < fuzz->slen); | ||
292 | assert(fuzz->o2 < fuzz->slen); | ||
293 | memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); | ||
294 | fuzz->fuzzed[fuzz->o1] ^= 0xff; | ||
295 | fuzz->fuzzed[fuzz->o2] ^= 0xff; | ||
296 | fuzz->o1++; | ||
297 | if (fuzz->o1 >= fuzz->slen) { | ||
298 | fuzz->o1 = 0; | ||
299 | fuzz->o2++; | ||
300 | } | ||
301 | break; | ||
302 | case FUZZ_TRUNCATE_START: | ||
303 | case FUZZ_TRUNCATE_END: | ||
304 | assert(fuzz->o1 < fuzz->slen); | ||
305 | memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); | ||
306 | fuzz->o1++; | ||
307 | break; | ||
308 | case FUZZ_BASE64: | ||
309 | assert(fuzz->o1 < fuzz->slen); | ||
310 | assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); | ||
311 | memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); | ||
312 | fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2]; | ||
313 | fuzz->o2++; | ||
314 | if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) { | ||
315 | fuzz->o2 = 0; | ||
316 | fuzz->o1++; | ||
317 | } | ||
318 | break; | ||
319 | default: | ||
320 | abort(); | ||
321 | } | ||
322 | |||
323 | FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, " | ||
324 | "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), | ||
325 | (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); | ||
326 | } | ||
327 | |||
328 | int | ||
329 | fuzz_done(struct fuzz *fuzz) | ||
330 | { | ||
331 | FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz, | ||
332 | (u_long)fuzz->strategies)); | ||
333 | |||
334 | return fuzz_strategy_done(fuzz) && fuzz->strategies == 0; | ||
335 | } | ||
336 | |||
337 | size_t | ||
338 | fuzz_len(struct fuzz *fuzz) | ||
339 | { | ||
340 | assert(fuzz->fuzzed != NULL); | ||
341 | switch (fuzz->strategy) { | ||
342 | case FUZZ_1_BIT_FLIP: | ||
343 | case FUZZ_2_BIT_FLIP: | ||
344 | case FUZZ_1_BYTE_FLIP: | ||
345 | case FUZZ_2_BYTE_FLIP: | ||
346 | case FUZZ_BASE64: | ||
347 | return fuzz->slen; | ||
348 | case FUZZ_TRUNCATE_START: | ||
349 | case FUZZ_TRUNCATE_END: | ||
350 | assert(fuzz->o1 <= fuzz->slen); | ||
351 | return fuzz->slen - fuzz->o1; | ||
352 | default: | ||
353 | abort(); | ||
354 | } | ||
355 | } | ||
356 | |||
357 | u_char * | ||
358 | fuzz_ptr(struct fuzz *fuzz) | ||
359 | { | ||
360 | assert(fuzz->fuzzed != NULL); | ||
361 | switch (fuzz->strategy) { | ||
362 | case FUZZ_1_BIT_FLIP: | ||
363 | case FUZZ_2_BIT_FLIP: | ||
364 | case FUZZ_1_BYTE_FLIP: | ||
365 | case FUZZ_2_BYTE_FLIP: | ||
366 | case FUZZ_BASE64: | ||
367 | return fuzz->fuzzed; | ||
368 | case FUZZ_TRUNCATE_START: | ||
369 | assert(fuzz->o1 <= fuzz->slen); | ||
370 | return fuzz->fuzzed + fuzz->o1; | ||
371 | case FUZZ_TRUNCATE_END: | ||
372 | assert(fuzz->o1 <= fuzz->slen); | ||
373 | return fuzz->fuzzed; | ||
374 | default: | ||
375 | abort(); | ||
376 | } | ||
377 | } | ||
378 | |||
diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c new file mode 100644 index 000000000..d0bc67833 --- /dev/null +++ b/regress/unittests/test_helper/test_helper.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /* $OpenBSD: test_helper.c,v 1.2 2014/05/02 09:41:32 andre Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller <djm@mindrot.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | /* Utility functions/framework for regress tests */ | ||
19 | |||
20 | #include "includes.h" | ||
21 | |||
22 | #include <sys/types.h> | ||
23 | #include <sys/param.h> | ||
24 | |||
25 | #include <fcntl.h> | ||
26 | #include <stdio.h> | ||
27 | #ifdef HAVE_STDINT_H | ||
28 | # include <stdint.h> | ||
29 | #endif | ||
30 | #include <stdlib.h> | ||
31 | #include <string.h> | ||
32 | #include <assert.h> | ||
33 | #include <unistd.h> | ||
34 | |||
35 | #include <openssl/bn.h> | ||
36 | |||
37 | #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) | ||
38 | # include <vis.h> | ||
39 | #endif | ||
40 | |||
41 | #include "test_helper.h" | ||
42 | |||
43 | #define TEST_CHECK_INT(r, pred) do { \ | ||
44 | switch (pred) { \ | ||
45 | case TEST_EQ: \ | ||
46 | if (r == 0) \ | ||
47 | return; \ | ||
48 | break; \ | ||
49 | case TEST_NE: \ | ||
50 | if (r != 0) \ | ||
51 | return; \ | ||
52 | break; \ | ||
53 | case TEST_LT: \ | ||
54 | if (r < 0) \ | ||
55 | return; \ | ||
56 | break; \ | ||
57 | case TEST_LE: \ | ||
58 | if (r <= 0) \ | ||
59 | return; \ | ||
60 | break; \ | ||
61 | case TEST_GT: \ | ||
62 | if (r > 0) \ | ||
63 | return; \ | ||
64 | break; \ | ||
65 | case TEST_GE: \ | ||
66 | if (r >= 0) \ | ||
67 | return; \ | ||
68 | break; \ | ||
69 | default: \ | ||
70 | abort(); \ | ||
71 | } \ | ||
72 | } while (0) | ||
73 | |||
74 | #define TEST_CHECK(x1, x2, pred) do { \ | ||
75 | switch (pred) { \ | ||
76 | case TEST_EQ: \ | ||
77 | if (x1 == x2) \ | ||
78 | return; \ | ||
79 | break; \ | ||
80 | case TEST_NE: \ | ||
81 | if (x1 != x2) \ | ||
82 | return; \ | ||
83 | break; \ | ||
84 | case TEST_LT: \ | ||
85 | if (x1 < x2) \ | ||
86 | return; \ | ||
87 | break; \ | ||
88 | case TEST_LE: \ | ||
89 | if (x1 <= x2) \ | ||
90 | return; \ | ||
91 | break; \ | ||
92 | case TEST_GT: \ | ||
93 | if (x1 > x2) \ | ||
94 | return; \ | ||
95 | break; \ | ||
96 | case TEST_GE: \ | ||
97 | if (x1 >= x2) \ | ||
98 | return; \ | ||
99 | break; \ | ||
100 | default: \ | ||
101 | abort(); \ | ||
102 | } \ | ||
103 | } while (0) | ||
104 | |||
105 | extern char *__progname; | ||
106 | |||
107 | static int verbose_mode = 0; | ||
108 | static int quiet_mode = 0; | ||
109 | static char *active_test_name = NULL; | ||
110 | static u_int test_number = 0; | ||
111 | static test_onerror_func_t *test_onerror = NULL; | ||
112 | static void *onerror_ctx = NULL; | ||
113 | static const char *data_dir = NULL; | ||
114 | |||
115 | int | ||
116 | main(int argc, char **argv) | ||
117 | { | ||
118 | int ch; | ||
119 | |||
120 | /* Handle systems without __progname */ | ||
121 | if (__progname == NULL) { | ||
122 | __progname = strrchr(argv[0], '/'); | ||
123 | if (__progname == NULL || __progname[1] == '\0') | ||
124 | __progname = argv[0]; | ||
125 | else | ||
126 | __progname++; | ||
127 | if ((__progname = strdup(__progname)) == NULL) { | ||
128 | fprintf(stderr, "strdup failed\n"); | ||
129 | exit(1); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | while ((ch = getopt(argc, argv, "vqd:")) != -1) { | ||
134 | switch (ch) { | ||
135 | case 'd': | ||
136 | data_dir = optarg; | ||
137 | break; | ||
138 | case 'q': | ||
139 | verbose_mode = 0; | ||
140 | quiet_mode = 1; | ||
141 | break; | ||
142 | case 'v': | ||
143 | verbose_mode = 1; | ||
144 | quiet_mode = 0; | ||
145 | break; | ||
146 | default: | ||
147 | fprintf(stderr, "Unrecognised command line option\n"); | ||
148 | fprintf(stderr, "Usage: %s [-v]\n", __progname); | ||
149 | exit(1); | ||
150 | } | ||
151 | } | ||
152 | setvbuf(stdout, NULL, _IONBF, 0); | ||
153 | if (!quiet_mode) | ||
154 | printf("%s: ", __progname); | ||
155 | if (verbose_mode) | ||
156 | printf("\n"); | ||
157 | |||
158 | tests(); | ||
159 | |||
160 | if (!quiet_mode) | ||
161 | printf(" %u tests ok\n", test_number); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | const char * | ||
166 | test_data_file(const char *name) | ||
167 | { | ||
168 | static char ret[PATH_MAX]; | ||
169 | |||
170 | if (data_dir != NULL) | ||
171 | snprintf(ret, sizeof(ret), "%s/%s", data_dir, name); | ||
172 | else | ||
173 | strlcpy(ret, name, sizeof(ret)); | ||
174 | if (access(ret, F_OK) != 0) { | ||
175 | fprintf(stderr, "Cannot access data file %s: %s\n", | ||
176 | ret, strerror(errno)); | ||
177 | exit(1); | ||
178 | } | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | void | ||
183 | test_start(const char *n) | ||
184 | { | ||
185 | assert(active_test_name == NULL); | ||
186 | assert((active_test_name = strdup(n)) != NULL); | ||
187 | if (verbose_mode) | ||
188 | printf("test %u - \"%s\": ", test_number, active_test_name); | ||
189 | test_number++; | ||
190 | } | ||
191 | |||
192 | void | ||
193 | set_onerror_func(test_onerror_func_t *f, void *ctx) | ||
194 | { | ||
195 | test_onerror = f; | ||
196 | onerror_ctx = ctx; | ||
197 | } | ||
198 | |||
199 | void | ||
200 | test_done(void) | ||
201 | { | ||
202 | assert(active_test_name != NULL); | ||
203 | free(active_test_name); | ||
204 | active_test_name = NULL; | ||
205 | if (verbose_mode) | ||
206 | printf("OK\n"); | ||
207 | else if (!quiet_mode) { | ||
208 | printf("."); | ||
209 | fflush(stdout); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | void | ||
214 | ssl_err_check(const char *file, int line) | ||
215 | { | ||
216 | long openssl_error = ERR_get_error(); | ||
217 | |||
218 | if (openssl_error == 0) | ||
219 | return; | ||
220 | |||
221 | fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s", | ||
222 | file, line, ERR_error_string(openssl_error, NULL)); | ||
223 | abort(); | ||
224 | } | ||
225 | |||
226 | static const char * | ||
227 | pred_name(enum test_predicate p) | ||
228 | { | ||
229 | switch (p) { | ||
230 | case TEST_EQ: | ||
231 | return "EQ"; | ||
232 | case TEST_NE: | ||
233 | return "NE"; | ||
234 | case TEST_LT: | ||
235 | return "LT"; | ||
236 | case TEST_LE: | ||
237 | return "LE"; | ||
238 | case TEST_GT: | ||
239 | return "GT"; | ||
240 | case TEST_GE: | ||
241 | return "GE"; | ||
242 | default: | ||
243 | return "UNKNOWN"; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | static void | ||
248 | test_die(void) | ||
249 | { | ||
250 | if (test_onerror != NULL) | ||
251 | test_onerror(onerror_ctx); | ||
252 | abort(); | ||
253 | } | ||
254 | |||
255 | static void | ||
256 | test_header(const char *file, int line, const char *a1, const char *a2, | ||
257 | const char *name, enum test_predicate pred) | ||
258 | { | ||
259 | fprintf(stderr, "\n%s:%d test #%u \"%s\"\n", | ||
260 | file, line, test_number, active_test_name); | ||
261 | fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n", | ||
262 | name, pred_name(pred), a1, | ||
263 | a2 != NULL ? ", " : "", a2 != NULL ? a2 : ""); | ||
264 | } | ||
265 | |||
266 | void | ||
267 | assert_bignum(const char *file, int line, const char *a1, const char *a2, | ||
268 | const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred) | ||
269 | { | ||
270 | int r = BN_cmp(aa1, aa2); | ||
271 | |||
272 | TEST_CHECK_INT(r, pred); | ||
273 | test_header(file, line, a1, a2, "BIGNUM", pred); | ||
274 | fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1)); | ||
275 | fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2)); | ||
276 | test_die(); | ||
277 | } | ||
278 | |||
279 | void | ||
280 | assert_string(const char *file, int line, const char *a1, const char *a2, | ||
281 | const char *aa1, const char *aa2, enum test_predicate pred) | ||
282 | { | ||
283 | int r = strcmp(aa1, aa2); | ||
284 | |||
285 | TEST_CHECK_INT(r, pred); | ||
286 | test_header(file, line, a1, a2, "STRING", pred); | ||
287 | fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1)); | ||
288 | fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2)); | ||
289 | test_die(); | ||
290 | } | ||
291 | |||
292 | static char * | ||
293 | tohex(const void *_s, size_t l) | ||
294 | { | ||
295 | u_int8_t *s = (u_int8_t *)_s; | ||
296 | size_t i, j; | ||
297 | const char *hex = "0123456789abcdef"; | ||
298 | char *r = malloc((l * 2) + 1); | ||
299 | |||
300 | assert(r != NULL); | ||
301 | for (i = j = 0; i < l; i++) { | ||
302 | r[j++] = hex[(s[i] >> 4) & 0xf]; | ||
303 | r[j++] = hex[s[i] & 0xf]; | ||
304 | } | ||
305 | r[j] = '\0'; | ||
306 | return r; | ||
307 | } | ||
308 | |||
309 | void | ||
310 | assert_mem(const char *file, int line, const char *a1, const char *a2, | ||
311 | const void *aa1, const void *aa2, size_t l, enum test_predicate pred) | ||
312 | { | ||
313 | int r = memcmp(aa1, aa2, l); | ||
314 | |||
315 | TEST_CHECK_INT(r, pred); | ||
316 | test_header(file, line, a1, a2, "STRING", pred); | ||
317 | fprintf(stderr, "%12s = %s (len %zu)\n", a1, tohex(aa1, MIN(l, 256)), l); | ||
318 | fprintf(stderr, "%12s = %s (len %zu)\n", a2, tohex(aa2, MIN(l, 256)), l); | ||
319 | test_die(); | ||
320 | } | ||
321 | |||
322 | static int | ||
323 | memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where) | ||
324 | { | ||
325 | size_t i; | ||
326 | |||
327 | for (i = 0; i < l; i++) { | ||
328 | if (s[i] != v) { | ||
329 | *where = i; | ||
330 | return 1; | ||
331 | } | ||
332 | } | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | void | ||
337 | assert_mem_filled(const char *file, int line, const char *a1, | ||
338 | const void *aa1, u_char v, size_t l, enum test_predicate pred) | ||
339 | { | ||
340 | size_t where = -1; | ||
341 | int r = memvalcmp(aa1, v, l, &where); | ||
342 | char tmp[64]; | ||
343 | |||
344 | if (l == 0) | ||
345 | return; | ||
346 | TEST_CHECK_INT(r, pred); | ||
347 | test_header(file, line, a1, NULL, "MEM_ZERO", pred); | ||
348 | fprintf(stderr, "%20s = %s%s (len %zu)\n", a1, | ||
349 | tohex(aa1, MIN(l, 20)), l > 20 ? "..." : "", l); | ||
350 | snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where); | ||
351 | fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp, | ||
352 | ((u_char *)aa1)[where], v); | ||
353 | test_die(); | ||
354 | } | ||
355 | |||
356 | void | ||
357 | assert_int(const char *file, int line, const char *a1, const char *a2, | ||
358 | int aa1, int aa2, enum test_predicate pred) | ||
359 | { | ||
360 | TEST_CHECK(aa1, aa2, pred); | ||
361 | test_header(file, line, a1, a2, "INT", pred); | ||
362 | fprintf(stderr, "%12s = %d\n", a1, aa1); | ||
363 | fprintf(stderr, "%12s = %d\n", a2, aa2); | ||
364 | test_die(); | ||
365 | } | ||
366 | |||
367 | void | ||
368 | assert_size_t(const char *file, int line, const char *a1, const char *a2, | ||
369 | size_t aa1, size_t aa2, enum test_predicate pred) | ||
370 | { | ||
371 | TEST_CHECK(aa1, aa2, pred); | ||
372 | test_header(file, line, a1, a2, "SIZE_T", pred); | ||
373 | fprintf(stderr, "%12s = %zu\n", a1, aa1); | ||
374 | fprintf(stderr, "%12s = %zu\n", a2, aa2); | ||
375 | test_die(); | ||
376 | } | ||
377 | |||
378 | void | ||
379 | assert_u_int(const char *file, int line, const char *a1, const char *a2, | ||
380 | u_int aa1, u_int aa2, enum test_predicate pred) | ||
381 | { | ||
382 | TEST_CHECK(aa1, aa2, pred); | ||
383 | test_header(file, line, a1, a2, "U_INT", pred); | ||
384 | fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1); | ||
385 | fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2); | ||
386 | test_die(); | ||
387 | } | ||
388 | |||
389 | void | ||
390 | assert_long_long(const char *file, int line, const char *a1, const char *a2, | ||
391 | long long aa1, long long aa2, enum test_predicate pred) | ||
392 | { | ||
393 | TEST_CHECK(aa1, aa2, pred); | ||
394 | test_header(file, line, a1, a2, "LONG LONG", pred); | ||
395 | fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1); | ||
396 | fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2); | ||
397 | test_die(); | ||
398 | } | ||
399 | |||
400 | void | ||
401 | assert_char(const char *file, int line, const char *a1, const char *a2, | ||
402 | char aa1, char aa2, enum test_predicate pred) | ||
403 | { | ||
404 | char buf[8]; | ||
405 | |||
406 | TEST_CHECK(aa1, aa2, pred); | ||
407 | test_header(file, line, a1, a2, "CHAR", pred); | ||
408 | fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, | ||
409 | vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1); | ||
410 | fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, | ||
411 | vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2); | ||
412 | test_die(); | ||
413 | } | ||
414 | |||
415 | void | ||
416 | assert_u8(const char *file, int line, const char *a1, const char *a2, | ||
417 | u_int8_t aa1, u_int8_t aa2, enum test_predicate pred) | ||
418 | { | ||
419 | TEST_CHECK(aa1, aa2, pred); | ||
420 | test_header(file, line, a1, a2, "U8", pred); | ||
421 | fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1); | ||
422 | fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2); | ||
423 | test_die(); | ||
424 | } | ||
425 | |||
426 | void | ||
427 | assert_u16(const char *file, int line, const char *a1, const char *a2, | ||
428 | u_int16_t aa1, u_int16_t aa2, enum test_predicate pred) | ||
429 | { | ||
430 | TEST_CHECK(aa1, aa2, pred); | ||
431 | test_header(file, line, a1, a2, "U16", pred); | ||
432 | fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1); | ||
433 | fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2); | ||
434 | test_die(); | ||
435 | } | ||
436 | |||
437 | void | ||
438 | assert_u32(const char *file, int line, const char *a1, const char *a2, | ||
439 | u_int32_t aa1, u_int32_t aa2, enum test_predicate pred) | ||
440 | { | ||
441 | TEST_CHECK(aa1, aa2, pred); | ||
442 | test_header(file, line, a1, a2, "U32", pred); | ||
443 | fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1); | ||
444 | fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2); | ||
445 | test_die(); | ||
446 | } | ||
447 | |||
448 | void | ||
449 | assert_u64(const char *file, int line, const char *a1, const char *a2, | ||
450 | u_int64_t aa1, u_int64_t aa2, enum test_predicate pred) | ||
451 | { | ||
452 | TEST_CHECK(aa1, aa2, pred); | ||
453 | test_header(file, line, a1, a2, "U64", pred); | ||
454 | fprintf(stderr, "%12s = 0x%016llx %llu\n", a1, | ||
455 | (unsigned long long)aa1, (unsigned long long)aa1); | ||
456 | fprintf(stderr, "%12s = 0x%016llx %llu\n", a2, | ||
457 | (unsigned long long)aa2, (unsigned long long)aa2); | ||
458 | test_die(); | ||
459 | } | ||
460 | |||
461 | void | ||
462 | assert_ptr(const char *file, int line, const char *a1, const char *a2, | ||
463 | const void *aa1, const void *aa2, enum test_predicate pred) | ||
464 | { | ||
465 | TEST_CHECK(aa1, aa2, pred); | ||
466 | test_header(file, line, a1, a2, "PTR", pred); | ||
467 | fprintf(stderr, "%12s = %p\n", a1, aa1); | ||
468 | fprintf(stderr, "%12s = %p\n", a2, aa2); | ||
469 | test_die(); | ||
470 | } | ||
471 | |||
diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h new file mode 100644 index 000000000..a398c615f --- /dev/null +++ b/regress/unittests/test_helper/test_helper.h | |||
@@ -0,0 +1,292 @@ | |||
1 | /* $OpenBSD: test_helper.h,v 1.3 2014/05/02 09:41:32 andre Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller <djm@mindrot.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | /* Utility functions/framework for regress tests */ | ||
19 | |||
20 | #ifndef _TEST_HELPER_H | ||
21 | #define _TEST_HELPER_H | ||
22 | |||
23 | #include "includes.h" | ||
24 | |||
25 | #include <sys/types.h> | ||
26 | #ifdef HAVE_STDINT_H | ||
27 | # include <stdint.h> | ||
28 | #endif | ||
29 | |||
30 | #include <openssl/bn.h> | ||
31 | #include <openssl/err.h> | ||
32 | |||
33 | enum test_predicate { | ||
34 | TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE | ||
35 | }; | ||
36 | typedef void (test_onerror_func_t)(void *); | ||
37 | |||
38 | /* Supplied by test suite */ | ||
39 | void tests(void); | ||
40 | |||
41 | const char *test_data_file(const char *name); | ||
42 | void test_start(const char *n); | ||
43 | void set_onerror_func(test_onerror_func_t *f, void *ctx); | ||
44 | void test_done(void); | ||
45 | void ssl_err_check(const char *file, int line); | ||
46 | void assert_bignum(const char *file, int line, | ||
47 | const char *a1, const char *a2, | ||
48 | const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred); | ||
49 | void assert_string(const char *file, int line, | ||
50 | const char *a1, const char *a2, | ||
51 | const char *aa1, const char *aa2, enum test_predicate pred); | ||
52 | void assert_mem(const char *file, int line, | ||
53 | const char *a1, const char *a2, | ||
54 | const void *aa1, const void *aa2, size_t l, enum test_predicate pred); | ||
55 | void assert_mem_filled(const char *file, int line, | ||
56 | const char *a1, | ||
57 | const void *aa1, u_char v, size_t l, enum test_predicate pred); | ||
58 | void assert_int(const char *file, int line, | ||
59 | const char *a1, const char *a2, | ||
60 | int aa1, int aa2, enum test_predicate pred); | ||
61 | void assert_size_t(const char *file, int line, | ||
62 | const char *a1, const char *a2, | ||
63 | size_t aa1, size_t aa2, enum test_predicate pred); | ||
64 | void assert_u_int(const char *file, int line, | ||
65 | const char *a1, const char *a2, | ||
66 | u_int aa1, u_int aa2, enum test_predicate pred); | ||
67 | void assert_long_long(const char *file, int line, | ||
68 | const char *a1, const char *a2, | ||
69 | long long aa1, long long aa2, enum test_predicate pred); | ||
70 | void assert_char(const char *file, int line, | ||
71 | const char *a1, const char *a2, | ||
72 | char aa1, char aa2, enum test_predicate pred); | ||
73 | void assert_ptr(const char *file, int line, | ||
74 | const char *a1, const char *a2, | ||
75 | const void *aa1, const void *aa2, enum test_predicate pred); | ||
76 | void assert_u8(const char *file, int line, | ||
77 | const char *a1, const char *a2, | ||
78 | u_int8_t aa1, u_int8_t aa2, enum test_predicate pred); | ||
79 | void assert_u16(const char *file, int line, | ||
80 | const char *a1, const char *a2, | ||
81 | u_int16_t aa1, u_int16_t aa2, enum test_predicate pred); | ||
82 | void assert_u32(const char *file, int line, | ||
83 | const char *a1, const char *a2, | ||
84 | u_int32_t aa1, u_int32_t aa2, enum test_predicate pred); | ||
85 | void assert_u64(const char *file, int line, | ||
86 | const char *a1, const char *a2, | ||
87 | u_int64_t aa1, u_int64_t aa2, enum test_predicate pred); | ||
88 | |||
89 | #define TEST_START(n) test_start(n) | ||
90 | #define TEST_DONE() test_done() | ||
91 | #define TEST_ONERROR(f, c) set_onerror_func(f, c) | ||
92 | #define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__) | ||
93 | |||
94 | #define ASSERT_BIGNUM_EQ(a1, a2) \ | ||
95 | assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
96 | #define ASSERT_STRING_EQ(a1, a2) \ | ||
97 | assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
98 | #define ASSERT_MEM_EQ(a1, a2, l) \ | ||
99 | assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ) | ||
100 | #define ASSERT_MEM_FILLED_EQ(a1, c, l) \ | ||
101 | assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ) | ||
102 | #define ASSERT_MEM_ZERO_EQ(a1, l) \ | ||
103 | assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ) | ||
104 | #define ASSERT_INT_EQ(a1, a2) \ | ||
105 | assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
106 | #define ASSERT_SIZE_T_EQ(a1, a2) \ | ||
107 | assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
108 | #define ASSERT_U_INT_EQ(a1, a2) \ | ||
109 | assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
110 | #define ASSERT_LONG_LONG_EQ(a1, a2) \ | ||
111 | assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
112 | #define ASSERT_CHAR_EQ(a1, a2) \ | ||
113 | assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
114 | #define ASSERT_PTR_EQ(a1, a2) \ | ||
115 | assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
116 | #define ASSERT_U8_EQ(a1, a2) \ | ||
117 | assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
118 | #define ASSERT_U16_EQ(a1, a2) \ | ||
119 | assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
120 | #define ASSERT_U32_EQ(a1, a2) \ | ||
121 | assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
122 | #define ASSERT_U64_EQ(a1, a2) \ | ||
123 | assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) | ||
124 | |||
125 | #define ASSERT_BIGNUM_NE(a1, a2) \ | ||
126 | assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
127 | #define ASSERT_STRING_NE(a1, a2) \ | ||
128 | assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
129 | #define ASSERT_MEM_NE(a1, a2, l) \ | ||
130 | assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE) | ||
131 | #define ASSERT_MEM_ZERO_NE(a1, l) \ | ||
132 | assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE) | ||
133 | #define ASSERT_INT_NE(a1, a2) \ | ||
134 | assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
135 | #define ASSERT_SIZE_T_NE(a1, a2) \ | ||
136 | assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
137 | #define ASSERT_U_INT_NE(a1, a2) \ | ||
138 | assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
139 | #define ASSERT_LONG_LONG_NE(a1, a2) \ | ||
140 | assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
141 | #define ASSERT_CHAR_NE(a1, a2) \ | ||
142 | assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
143 | #define ASSERT_PTR_NE(a1, a2) \ | ||
144 | assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
145 | #define ASSERT_U8_NE(a1, a2) \ | ||
146 | assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
147 | #define ASSERT_U16_NE(a1, a2) \ | ||
148 | assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
149 | #define ASSERT_U32_NE(a1, a2) \ | ||
150 | assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
151 | #define ASSERT_U64_NE(a1, a2) \ | ||
152 | assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) | ||
153 | |||
154 | #define ASSERT_BIGNUM_LT(a1, a2) \ | ||
155 | assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
156 | #define ASSERT_STRING_LT(a1, a2) \ | ||
157 | assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
158 | #define ASSERT_MEM_LT(a1, a2, l) \ | ||
159 | assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT) | ||
160 | #define ASSERT_INT_LT(a1, a2) \ | ||
161 | assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
162 | #define ASSERT_SIZE_T_LT(a1, a2) \ | ||
163 | assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
164 | #define ASSERT_U_INT_LT(a1, a2) \ | ||
165 | assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
166 | #define ASSERT_LONG_LONG_LT(a1, a2) \ | ||
167 | assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
168 | #define ASSERT_CHAR_LT(a1, a2) \ | ||
169 | assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
170 | #define ASSERT_PTR_LT(a1, a2) \ | ||
171 | assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
172 | #define ASSERT_U8_LT(a1, a2) \ | ||
173 | assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
174 | #define ASSERT_U16_LT(a1, a2) \ | ||
175 | assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
176 | #define ASSERT_U32_LT(a1, a2) \ | ||
177 | assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
178 | #define ASSERT_U64_LT(a1, a2) \ | ||
179 | assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) | ||
180 | |||
181 | #define ASSERT_BIGNUM_LE(a1, a2) \ | ||
182 | assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
183 | #define ASSERT_STRING_LE(a1, a2) \ | ||
184 | assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
185 | #define ASSERT_MEM_LE(a1, a2, l) \ | ||
186 | assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE) | ||
187 | #define ASSERT_INT_LE(a1, a2) \ | ||
188 | assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
189 | #define ASSERT_SIZE_T_LE(a1, a2) \ | ||
190 | assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
191 | #define ASSERT_U_INT_LE(a1, a2) \ | ||
192 | assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
193 | #define ASSERT_LONG_LONG_LE(a1, a2) \ | ||
194 | assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
195 | #define ASSERT_CHAR_LE(a1, a2) \ | ||
196 | assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
197 | #define ASSERT_PTR_LE(a1, a2) \ | ||
198 | assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
199 | #define ASSERT_U8_LE(a1, a2) \ | ||
200 | assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
201 | #define ASSERT_U16_LE(a1, a2) \ | ||
202 | assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
203 | #define ASSERT_U32_LE(a1, a2) \ | ||
204 | assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
205 | #define ASSERT_U64_LE(a1, a2) \ | ||
206 | assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) | ||
207 | |||
208 | #define ASSERT_BIGNUM_GT(a1, a2) \ | ||
209 | assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
210 | #define ASSERT_STRING_GT(a1, a2) \ | ||
211 | assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
212 | #define ASSERT_MEM_GT(a1, a2, l) \ | ||
213 | assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT) | ||
214 | #define ASSERT_INT_GT(a1, a2) \ | ||
215 | assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
216 | #define ASSERT_SIZE_T_GT(a1, a2) \ | ||
217 | assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
218 | #define ASSERT_U_INT_GT(a1, a2) \ | ||
219 | assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
220 | #define ASSERT_LONG_LONG_GT(a1, a2) \ | ||
221 | assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
222 | #define ASSERT_CHAR_GT(a1, a2) \ | ||
223 | assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
224 | #define ASSERT_PTR_GT(a1, a2) \ | ||
225 | assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
226 | #define ASSERT_U8_GT(a1, a2) \ | ||
227 | assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
228 | #define ASSERT_U16_GT(a1, a2) \ | ||
229 | assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
230 | #define ASSERT_U32_GT(a1, a2) \ | ||
231 | assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
232 | #define ASSERT_U64_GT(a1, a2) \ | ||
233 | assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) | ||
234 | |||
235 | #define ASSERT_BIGNUM_GE(a1, a2) \ | ||
236 | assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
237 | #define ASSERT_STRING_GE(a1, a2) \ | ||
238 | assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
239 | #define ASSERT_MEM_GE(a1, a2, l) \ | ||
240 | assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE) | ||
241 | #define ASSERT_INT_GE(a1, a2) \ | ||
242 | assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
243 | #define ASSERT_SIZE_T_GE(a1, a2) \ | ||
244 | assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
245 | #define ASSERT_U_INT_GE(a1, a2) \ | ||
246 | assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
247 | #define ASSERT_LONG_LONG_GE(a1, a2) \ | ||
248 | assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
249 | #define ASSERT_CHAR_GE(a1, a2) \ | ||
250 | assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
251 | #define ASSERT_PTR_GE(a1, a2) \ | ||
252 | assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
253 | #define ASSERT_U8_GE(a1, a2) \ | ||
254 | assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
255 | #define ASSERT_U16_GE(a1, a2) \ | ||
256 | assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
257 | #define ASSERT_U32_GE(a1, a2) \ | ||
258 | assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
259 | #define ASSERT_U64_GE(a1, a2) \ | ||
260 | assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) | ||
261 | |||
262 | /* Fuzzing support */ | ||
263 | |||
264 | struct fuzz; | ||
265 | #define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */ | ||
266 | #define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */ | ||
267 | #define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */ | ||
268 | #define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */ | ||
269 | #define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */ | ||
270 | #define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */ | ||
271 | #define FUZZ_BASE64 0x00000040 /* Try all base64 chars */ | ||
272 | #define FUZZ_MAX FUZZ_BASE64 | ||
273 | |||
274 | /* Start fuzzing a blob of data with selected strategies (bitmask) */ | ||
275 | struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l); | ||
276 | |||
277 | /* Free a fuzz context */ | ||
278 | void fuzz_cleanup(struct fuzz *fuzz); | ||
279 | |||
280 | /* Prepare the next fuzz case in the series */ | ||
281 | void fuzz_next(struct fuzz *fuzz); | ||
282 | |||
283 | /* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */ | ||
284 | int fuzz_done(struct fuzz *fuzz); | ||
285 | |||
286 | /* Return the length and a pointer to the current fuzzed case */ | ||
287 | size_t fuzz_len(struct fuzz *fuzz); | ||
288 | u_char *fuzz_ptr(struct fuzz *fuzz); | ||
289 | |||
290 | /* Dump the current fuzz case to stderr */ | ||
291 | void fuzz_dump(struct fuzz *fuzz); | ||
292 | #endif /* _TEST_HELPER_H */ | ||
diff --git a/rijndael.c b/rijndael.c index 7432ea2e4..cde90789e 100644 --- a/rijndael.c +++ b/rijndael.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: rijndael.c,v 1.16 2004/06/23 00:39:38 mouring Exp $ */ | 1 | /* $OpenBSD: rijndael.c,v 1.18 2014/04/29 15:42:07 markus Exp $ */ |
2 | 2 | ||
3 | /** | 3 | /** |
4 | * rijndael-alg-fst.c | 4 | * rijndael-alg-fst.c |
@@ -25,6 +25,7 @@ | |||
25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ | 27 | */ |
28 | |||
28 | #include "includes.h" | 29 | #include "includes.h" |
29 | 30 | ||
30 | #include <stdlib.h> | 31 | #include <stdlib.h> |
@@ -32,7 +33,7 @@ | |||
32 | 33 | ||
33 | #include "rijndael.h" | 34 | #include "rijndael.h" |
34 | 35 | ||
35 | #define FULL_UNROLL | 36 | #undef FULL_UNROLL |
36 | 37 | ||
37 | /* | 38 | /* |
38 | Te0[x] = S [x].[02, 01, 01, 03]; | 39 | Te0[x] = S [x].[02, 01, 01, 03]; |
@@ -247,7 +248,6 @@ static const u32 Te2[256] = { | |||
247 | 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, | 248 | 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, |
248 | }; | 249 | }; |
249 | static const u32 Te3[256] = { | 250 | static const u32 Te3[256] = { |
250 | |||
251 | 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, | 251 | 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, |
252 | 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, | 252 | 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, |
253 | 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, | 253 | 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, |
@@ -532,7 +532,6 @@ static const u32 Td2[256] = { | |||
532 | 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, | 532 | 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, |
533 | 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, | 533 | 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, |
534 | 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, | 534 | 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, |
535 | |||
536 | 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, | 535 | 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, |
537 | 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, | 536 | 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, |
538 | 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, | 537 | 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, |
@@ -724,8 +723,10 @@ static const u32 rcon[] = { | |||
724 | * | 723 | * |
725 | * @return the number of rounds for the given cipher key size. | 724 | * @return the number of rounds for the given cipher key size. |
726 | */ | 725 | */ |
727 | static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { | 726 | int |
728 | int i = 0; | 727 | rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) |
728 | { | ||
729 | int i = 0; | ||
729 | u32 temp; | 730 | u32 temp; |
730 | 731 | ||
731 | rk[0] = GETU32(cipherKey ); | 732 | rk[0] = GETU32(cipherKey ); |
@@ -786,9 +787,9 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int | |||
786 | rk[ 9] = rk[ 1] ^ rk[ 8]; | 787 | rk[ 9] = rk[ 1] ^ rk[ 8]; |
787 | rk[10] = rk[ 2] ^ rk[ 9]; | 788 | rk[10] = rk[ 2] ^ rk[ 9]; |
788 | rk[11] = rk[ 3] ^ rk[10]; | 789 | rk[11] = rk[ 3] ^ rk[10]; |
789 | if (++i == 7) { | 790 | if (++i == 7) { |
790 | return 14; | 791 | return 14; |
791 | } | 792 | } |
792 | temp = rk[11]; | 793 | temp = rk[11]; |
793 | rk[12] = rk[ 4] ^ | 794 | rk[12] = rk[ 4] ^ |
794 | (Te4[(temp >> 24) ] & 0xff000000) ^ | 795 | (Te4[(temp >> 24) ] & 0xff000000) ^ |
@@ -797,7 +798,7 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int | |||
797 | (Te4[(temp ) & 0xff] & 0x000000ff); | 798 | (Te4[(temp ) & 0xff] & 0x000000ff); |
798 | rk[13] = rk[ 5] ^ rk[12]; | 799 | rk[13] = rk[ 5] ^ rk[12]; |
799 | rk[14] = rk[ 6] ^ rk[13]; | 800 | rk[14] = rk[ 6] ^ rk[13]; |
800 | rk[15] = rk[ 7] ^ rk[14]; | 801 | rk[15] = rk[ 7] ^ rk[14]; |
801 | rk += 8; | 802 | rk += 8; |
802 | } | 803 | } |
803 | } | 804 | } |
@@ -809,18 +810,21 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int | |||
809 | * | 810 | * |
810 | * @return the number of rounds for the given cipher key size. | 811 | * @return the number of rounds for the given cipher key size. |
811 | */ | 812 | */ |
812 | static int | 813 | int |
813 | rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits, | 814 | rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits, |
814 | int have_encrypt) { | 815 | int have_encrypt) |
816 | { | ||
815 | int Nr, i, j; | 817 | int Nr, i, j; |
816 | u32 temp; | 818 | u32 temp; |
817 | 819 | ||
818 | if (have_encrypt) { | 820 | /* expand the cipher key: */ |
821 | if (have_encrypt > 0) { | ||
822 | /* Already done */ | ||
819 | Nr = have_encrypt; | 823 | Nr = have_encrypt; |
820 | } else { | 824 | } else { |
821 | /* expand the cipher key: */ | ||
822 | Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); | 825 | Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); |
823 | } | 826 | } |
827 | |||
824 | /* invert the order of the round keys: */ | 828 | /* invert the order of the round keys: */ |
825 | for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { | 829 | for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { |
826 | temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; | 830 | temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; |
@@ -855,7 +859,10 @@ rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits, | |||
855 | return Nr; | 859 | return Nr; |
856 | } | 860 | } |
857 | 861 | ||
858 | static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { | 862 | void |
863 | rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], | ||
864 | u8 ct[16]) | ||
865 | { | ||
859 | u32 s0, s1, s2, s3, t0, t1, t2, t3; | 866 | u32 s0, s1, s2, s3, t0, t1, t2, t3; |
860 | #ifndef FULL_UNROLL | 867 | #ifndef FULL_UNROLL |
861 | int r; | 868 | int r; |
@@ -871,50 +878,50 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16 | |||
871 | s3 = GETU32(pt + 12) ^ rk[3]; | 878 | s3 = GETU32(pt + 12) ^ rk[3]; |
872 | #ifdef FULL_UNROLL | 879 | #ifdef FULL_UNROLL |
873 | /* round 1: */ | 880 | /* round 1: */ |
874 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; | 881 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; |
875 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; | 882 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; |
876 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; | 883 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; |
877 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; | 884 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; |
878 | /* round 2: */ | 885 | /* round 2: */ |
879 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; | 886 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; |
880 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; | 887 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; |
881 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; | 888 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; |
882 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; | 889 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; |
883 | /* round 3: */ | 890 | /* round 3: */ |
884 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; | 891 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; |
885 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; | 892 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; |
886 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; | 893 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; |
887 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; | 894 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; |
888 | /* round 4: */ | 895 | /* round 4: */ |
889 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; | 896 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; |
890 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; | 897 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; |
891 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; | 898 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; |
892 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; | 899 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; |
893 | /* round 5: */ | 900 | /* round 5: */ |
894 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; | 901 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; |
895 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; | 902 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; |
896 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; | 903 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; |
897 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; | 904 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; |
898 | /* round 6: */ | 905 | /* round 6: */ |
899 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; | 906 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; |
900 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; | 907 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; |
901 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; | 908 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; |
902 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; | 909 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; |
903 | /* round 7: */ | 910 | /* round 7: */ |
904 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; | 911 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; |
905 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; | 912 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; |
906 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; | 913 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; |
907 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; | 914 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; |
908 | /* round 8: */ | 915 | /* round 8: */ |
909 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; | 916 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; |
910 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; | 917 | s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; |
911 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; | 918 | s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; |
912 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; | 919 | s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; |
913 | /* round 9: */ | 920 | /* round 9: */ |
914 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; | 921 | t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; |
915 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; | 922 | t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; |
916 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; | 923 | t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; |
917 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; | 924 | t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; |
918 | if (Nr > 10) { | 925 | if (Nr > 10) { |
919 | /* round 10: */ | 926 | /* round 10: */ |
920 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; | 927 | s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; |
@@ -1036,7 +1043,10 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16 | |||
1036 | PUTU32(ct + 12, s3); | 1043 | PUTU32(ct + 12, s3); |
1037 | } | 1044 | } |
1038 | 1045 | ||
1039 | static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { | 1046 | static void |
1047 | rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], | ||
1048 | u8 pt[16]) | ||
1049 | { | ||
1040 | u32 s0, s1, s2, s3, t0, t1, t2, t3; | 1050 | u32 s0, s1, s2, s3, t0, t1, t2, t3; |
1041 | #ifndef FULL_UNROLL | 1051 | #ifndef FULL_UNROLL |
1042 | int r; | 1052 | int r; |
@@ -1187,33 +1197,33 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16 | |||
1187 | * apply last round and | 1197 | * apply last round and |
1188 | * map cipher state to byte array block: | 1198 | * map cipher state to byte array block: |
1189 | */ | 1199 | */ |
1190 | s0 = | 1200 | s0 = |
1191 | (Td4[(t0 >> 24) ] & 0xff000000) ^ | 1201 | (Td4[(t0 >> 24) ] & 0xff000000) ^ |
1192 | (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ | 1202 | (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ |
1193 | (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ | 1203 | (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ |
1194 | (Td4[(t1 ) & 0xff] & 0x000000ff) ^ | 1204 | (Td4[(t1 ) & 0xff] & 0x000000ff) ^ |
1195 | rk[0]; | 1205 | rk[0]; |
1196 | PUTU32(pt , s0); | 1206 | PUTU32(pt , s0); |
1197 | s1 = | 1207 | s1 = |
1198 | (Td4[(t1 >> 24) ] & 0xff000000) ^ | 1208 | (Td4[(t1 >> 24) ] & 0xff000000) ^ |
1199 | (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ | 1209 | (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ |
1200 | (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ | 1210 | (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ |
1201 | (Td4[(t2 ) & 0xff] & 0x000000ff) ^ | 1211 | (Td4[(t2 ) & 0xff] & 0x000000ff) ^ |
1202 | rk[1]; | 1212 | rk[1]; |
1203 | PUTU32(pt + 4, s1); | 1213 | PUTU32(pt + 4, s1); |
1204 | s2 = | 1214 | s2 = |
1205 | (Td4[(t2 >> 24) ] & 0xff000000) ^ | 1215 | (Td4[(t2 >> 24) ] & 0xff000000) ^ |
1206 | (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ | 1216 | (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ |
1207 | (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ | 1217 | (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ |
1208 | (Td4[(t3 ) & 0xff] & 0x000000ff) ^ | 1218 | (Td4[(t3 ) & 0xff] & 0x000000ff) ^ |
1209 | rk[2]; | 1219 | rk[2]; |
1210 | PUTU32(pt + 8, s2); | 1220 | PUTU32(pt + 8, s2); |
1211 | s3 = | 1221 | s3 = |
1212 | (Td4[(t3 >> 24) ] & 0xff000000) ^ | 1222 | (Td4[(t3 >> 24) ] & 0xff000000) ^ |
1213 | (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ | 1223 | (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ |
1214 | (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ | 1224 | (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ |
1215 | (Td4[(t0 ) & 0xff] & 0x000000ff) ^ | 1225 | (Td4[(t0 ) & 0xff] & 0x000000ff) ^ |
1216 | rk[3]; | 1226 | rk[3]; |
1217 | PUTU32(pt + 12, s3); | 1227 | PUTU32(pt + 12, s3); |
1218 | } | 1228 | } |
1219 | 1229 | ||
diff --git a/rijndael.h b/rijndael.h index c614bb188..53e74e0a8 100644 --- a/rijndael.h +++ b/rijndael.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: rijndael.h,v 1.12 2001/12/19 07:18:56 deraadt Exp $ */ | 1 | /* $OpenBSD: rijndael.h,v 1.14 2014/04/29 15:42:07 markus Exp $ */ |
2 | 2 | ||
3 | /** | 3 | /** |
4 | * rijndael-alg-fst.h | 4 | * rijndael-alg-fst.h |
@@ -25,27 +25,32 @@ | |||
25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ | 27 | */ |
28 | #ifndef __RIJNDAEL_H | 28 | #ifndef _PRIVATE_RIJNDAEL_H |
29 | #define __RIJNDAEL_H | 29 | #define _PRIVATE_RIJNDAEL_H |
30 | 30 | ||
31 | #define MAXKC (256/32) | 31 | #define AES_MAXKEYBITS (256) |
32 | #define MAXKB (256/8) | 32 | #define AES_MAXKEYBYTES (AES_MAXKEYBITS/8) |
33 | #define MAXNR 14 | 33 | /* for 256-bit keys, fewer for less */ |
34 | #define AES_MAXROUNDS 14 | ||
34 | 35 | ||
35 | typedef unsigned char u8; | 36 | typedef unsigned char u8; |
36 | typedef unsigned short u16; | 37 | typedef unsigned short u16; |
37 | typedef unsigned int u32; | 38 | typedef unsigned int u32; |
38 | 39 | ||
40 | int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int); | ||
41 | void rijndaelEncrypt(const unsigned int [], int, const unsigned char [], | ||
42 | unsigned char []); | ||
43 | |||
39 | /* The structure for key information */ | 44 | /* The structure for key information */ |
40 | typedef struct { | 45 | typedef struct { |
41 | int decrypt; | 46 | int decrypt; |
42 | int Nr; /* key-length-dependent number of rounds */ | 47 | int Nr; /* key-length-dependent number of rounds */ |
43 | u32 ek[4*(MAXNR + 1)]; /* encrypt key schedule */ | 48 | u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ |
44 | u32 dk[4*(MAXNR + 1)]; /* decrypt key schedule */ | 49 | u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */ |
45 | } rijndael_ctx; | 50 | } rijndael_ctx; |
46 | 51 | ||
47 | void rijndael_set_key(rijndael_ctx *, u_char *, int, int); | 52 | void rijndael_set_key(rijndael_ctx *, u_char *, int, int); |
48 | void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *); | 53 | void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *); |
49 | void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *); | 54 | void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *); |
50 | 55 | ||
51 | #endif /* __RIJNDAEL_H */ | 56 | #endif /* _PRIVATE_RIJNDAEL_H */ |
diff --git a/roaming_client.c b/roaming_client.c index de049cdc1..5e5c28b2b 100644 --- a/roaming_client.c +++ b/roaming_client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: roaming_client.c,v 1.7 2014/01/09 23:20:00 djm Exp $ */ | 1 | /* $OpenBSD: roaming_client.c,v 1.8 2014/04/29 18:01:49 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2004-2009 AppGate Network Security AB | 3 | * Copyright (c) 2004-2009 AppGate Network Security AB |
4 | * | 4 | * |
@@ -28,9 +28,6 @@ | |||
28 | #include <string.h> | 28 | #include <string.h> |
29 | #include <unistd.h> | 29 | #include <unistd.h> |
30 | 30 | ||
31 | #include <openssl/crypto.h> | ||
32 | #include <openssl/sha.h> | ||
33 | |||
34 | #include "xmalloc.h" | 31 | #include "xmalloc.h" |
35 | #include "buffer.h" | 32 | #include "buffer.h" |
36 | #include "channels.h" | 33 | #include "channels.h" |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: rsa.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -67,85 +67,122 @@ | |||
67 | #include <stdarg.h> | 67 | #include <stdarg.h> |
68 | #include <string.h> | 68 | #include <string.h> |
69 | 69 | ||
70 | #include "xmalloc.h" | ||
71 | #include "rsa.h" | 70 | #include "rsa.h" |
72 | #include "log.h" | 71 | #include "log.h" |
72 | #include "ssherr.h" | ||
73 | 73 | ||
74 | void | 74 | int |
75 | rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) | 75 | rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) |
76 | { | 76 | { |
77 | u_char *inbuf, *outbuf; | 77 | u_char *inbuf = NULL, *outbuf = NULL; |
78 | int len, ilen, olen; | 78 | int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; |
79 | 79 | ||
80 | if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) | 80 | if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) |
81 | fatal("rsa_public_encrypt() exponent too small or not odd"); | 81 | return SSH_ERR_INVALID_ARGUMENT; |
82 | 82 | ||
83 | olen = BN_num_bytes(key->n); | 83 | olen = BN_num_bytes(key->n); |
84 | outbuf = xmalloc(olen); | 84 | if ((outbuf = malloc(olen)) == NULL) { |
85 | r = SSH_ERR_ALLOC_FAIL; | ||
86 | goto out; | ||
87 | } | ||
85 | 88 | ||
86 | ilen = BN_num_bytes(in); | 89 | ilen = BN_num_bytes(in); |
87 | inbuf = xmalloc(ilen); | 90 | if ((inbuf = malloc(ilen)) == NULL) { |
91 | r = SSH_ERR_ALLOC_FAIL; | ||
92 | goto out; | ||
93 | } | ||
88 | BN_bn2bin(in, inbuf); | 94 | BN_bn2bin(in, inbuf); |
89 | 95 | ||
90 | if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, | 96 | if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, |
91 | RSA_PKCS1_PADDING)) <= 0) | 97 | RSA_PKCS1_PADDING)) <= 0) { |
92 | fatal("rsa_public_encrypt() failed"); | 98 | r = SSH_ERR_LIBCRYPTO_ERROR; |
99 | goto out; | ||
100 | } | ||
93 | 101 | ||
94 | if (BN_bin2bn(outbuf, len, out) == NULL) | 102 | if (BN_bin2bn(outbuf, len, out) == NULL) { |
95 | fatal("rsa_public_encrypt: BN_bin2bn failed"); | 103 | r = SSH_ERR_LIBCRYPTO_ERROR; |
104 | goto out; | ||
105 | } | ||
106 | r = 0; | ||
96 | 107 | ||
97 | explicit_bzero(outbuf, olen); | 108 | out: |
98 | explicit_bzero(inbuf, ilen); | 109 | if (outbuf != NULL) { |
99 | free(outbuf); | 110 | explicit_bzero(outbuf, olen); |
100 | free(inbuf); | 111 | free(outbuf); |
112 | } | ||
113 | if (inbuf != NULL) { | ||
114 | explicit_bzero(inbuf, ilen); | ||
115 | free(inbuf); | ||
116 | } | ||
117 | return r; | ||
101 | } | 118 | } |
102 | 119 | ||
103 | int | 120 | int |
104 | rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) | 121 | rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) |
105 | { | 122 | { |
106 | u_char *inbuf, *outbuf; | 123 | u_char *inbuf = NULL, *outbuf = NULL; |
107 | int len, ilen, olen; | 124 | int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; |
108 | 125 | ||
109 | olen = BN_num_bytes(key->n); | 126 | olen = BN_num_bytes(key->n); |
110 | outbuf = xmalloc(olen); | 127 | if ((outbuf = malloc(olen)) == NULL) { |
128 | r = SSH_ERR_ALLOC_FAIL; | ||
129 | goto out; | ||
130 | } | ||
111 | 131 | ||
112 | ilen = BN_num_bytes(in); | 132 | ilen = BN_num_bytes(in); |
113 | inbuf = xmalloc(ilen); | 133 | if ((inbuf = malloc(ilen)) == NULL) { |
134 | r = SSH_ERR_ALLOC_FAIL; | ||
135 | goto out; | ||
136 | } | ||
114 | BN_bn2bin(in, inbuf); | 137 | BN_bn2bin(in, inbuf); |
115 | 138 | ||
116 | if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, | 139 | if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, |
117 | RSA_PKCS1_PADDING)) <= 0) { | 140 | RSA_PKCS1_PADDING)) <= 0) { |
118 | error("rsa_private_decrypt() failed"); | 141 | r = SSH_ERR_LIBCRYPTO_ERROR; |
119 | } else { | 142 | goto out; |
120 | if (BN_bin2bn(outbuf, len, out) == NULL) | 143 | } else if (BN_bin2bn(outbuf, len, out) == NULL) { |
121 | fatal("rsa_private_decrypt: BN_bin2bn failed"); | 144 | r = SSH_ERR_LIBCRYPTO_ERROR; |
145 | goto out; | ||
146 | } | ||
147 | r = 0; | ||
148 | out: | ||
149 | if (outbuf != NULL) { | ||
150 | explicit_bzero(outbuf, olen); | ||
151 | free(outbuf); | ||
152 | } | ||
153 | if (inbuf != NULL) { | ||
154 | explicit_bzero(inbuf, ilen); | ||
155 | free(inbuf); | ||
122 | } | 156 | } |
123 | explicit_bzero(outbuf, olen); | 157 | return r; |
124 | explicit_bzero(inbuf, ilen); | ||
125 | free(outbuf); | ||
126 | free(inbuf); | ||
127 | return len; | ||
128 | } | 158 | } |
129 | 159 | ||
130 | /* calculate p-1 and q-1 */ | 160 | /* calculate p-1 and q-1 */ |
131 | void | 161 | int |
132 | rsa_generate_additional_parameters(RSA *rsa) | 162 | rsa_generate_additional_parameters(RSA *rsa) |
133 | { | 163 | { |
134 | BIGNUM *aux; | 164 | BIGNUM *aux = NULL; |
135 | BN_CTX *ctx; | 165 | BN_CTX *ctx = NULL; |
166 | int r; | ||
136 | 167 | ||
137 | if ((aux = BN_new()) == NULL) | ||
138 | fatal("rsa_generate_additional_parameters: BN_new failed"); | ||
139 | if ((ctx = BN_CTX_new()) == NULL) | 168 | if ((ctx = BN_CTX_new()) == NULL) |
140 | fatal("rsa_generate_additional_parameters: BN_CTX_new failed"); | 169 | return SSH_ERR_ALLOC_FAIL; |
170 | if ((aux = BN_new()) == NULL) { | ||
171 | r = SSH_ERR_ALLOC_FAIL; | ||
172 | goto out; | ||
173 | } | ||
141 | 174 | ||
142 | if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || | 175 | if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || |
143 | (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || | 176 | (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || |
144 | (BN_sub(aux, rsa->p, BN_value_one()) == 0) || | 177 | (BN_sub(aux, rsa->p, BN_value_one()) == 0) || |
145 | (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) | 178 | (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) { |
146 | fatal("rsa_generate_additional_parameters: BN_sub/mod failed"); | 179 | r = SSH_ERR_LIBCRYPTO_ERROR; |
147 | 180 | goto out; | |
181 | } | ||
182 | r = 0; | ||
183 | out: | ||
148 | BN_clear_free(aux); | 184 | BN_clear_free(aux); |
149 | BN_CTX_free(ctx); | 185 | BN_CTX_free(ctx); |
186 | return r; | ||
150 | } | 187 | } |
151 | 188 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: rsa.h,v 1.16 2006/03/25 22:22:43 djm Exp $ */ | 1 | /* $OpenBSD: rsa.h,v 1.17 2014/06/24 01:13:21 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -19,8 +19,8 @@ | |||
19 | #include <openssl/bn.h> | 19 | #include <openssl/bn.h> |
20 | #include <openssl/rsa.h> | 20 | #include <openssl/rsa.h> |
21 | 21 | ||
22 | void rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); | 22 | int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); |
23 | int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); | 23 | int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); |
24 | void rsa_generate_additional_parameters(RSA *); | 24 | int rsa_generate_additional_parameters(RSA *); |
25 | 25 | ||
26 | #endif /* RSA_H */ | 26 | #endif /* RSA_H */ |
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c index c0c17c2fc..b6f6258f2 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c | |||
@@ -25,6 +25,8 @@ | |||
25 | */ | 25 | */ |
26 | /* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ | 26 | /* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ |
27 | 27 | ||
28 | /* XXX it should be possible to do logging via the log socket safely */ | ||
29 | |||
28 | #ifdef SANDBOX_SECCOMP_FILTER_DEBUG | 30 | #ifdef SANDBOX_SECCOMP_FILTER_DEBUG |
29 | /* Use the kernel headers in case of an older toolchain. */ | 31 | /* Use the kernel headers in case of an older toolchain. */ |
30 | # include <asm/siginfo.h> | 32 | # include <asm/siginfo.h> |
@@ -89,6 +91,7 @@ static const struct sock_filter preauth_insns[] = { | |||
89 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, | 91 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, |
90 | offsetof(struct seccomp_data, nr)), | 92 | offsetof(struct seccomp_data, nr)), |
91 | SC_DENY(open, EACCES), | 93 | SC_DENY(open, EACCES), |
94 | SC_DENY(stat, EACCES), | ||
92 | SC_ALLOW(getpid), | 95 | SC_ALLOW(getpid), |
93 | SC_ALLOW(gettimeofday), | 96 | SC_ALLOW(gettimeofday), |
94 | SC_ALLOW(clock_gettime), | 97 | SC_ALLOW(clock_gettime), |
@@ -115,6 +118,10 @@ static const struct sock_filter preauth_insns[] = { | |||
115 | #ifdef __NR_mmap | 118 | #ifdef __NR_mmap |
116 | SC_ALLOW(mmap), | 119 | SC_ALLOW(mmap), |
117 | #endif | 120 | #endif |
121 | #ifdef __dietlibc__ | ||
122 | SC_ALLOW(mremap), | ||
123 | SC_ALLOW(exit), | ||
124 | #endif | ||
118 | SC_ALLOW(munmap), | 125 | SC_ALLOW(munmap), |
119 | SC_ALLOW(exit_group), | 126 | SC_ALLOW(exit_group), |
120 | #ifdef __NR_rt_sigprocmask | 127 | #ifdef __NR_rt_sigprocmask |
diff --git a/sandbox-systrace.c b/sandbox-systrace.c index 6706c9a80..aaa3d8f0a 100644 --- a/sandbox-systrace.c +++ b/sandbox-systrace.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sandbox-systrace.c,v 1.9 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: sandbox-systrace.c,v 1.13 2014/07/17 00:10:56 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 Damien Miller <djm@mindrot.org> | 3 | * Copyright (c) 2011 Damien Miller <djm@mindrot.org> |
4 | * | 4 | * |
@@ -52,7 +52,17 @@ struct sandbox_policy { | |||
52 | static const struct sandbox_policy preauth_policy[] = { | 52 | static const struct sandbox_policy preauth_policy[] = { |
53 | { SYS_open, SYSTR_POLICY_NEVER }, | 53 | { SYS_open, SYSTR_POLICY_NEVER }, |
54 | 54 | ||
55 | #ifdef SYS_getentropy | ||
56 | /* OpenBSD 5.6 and newer use getentropy(2) to seed arc4random(3). */ | ||
57 | { SYS_getentropy, SYSTR_POLICY_PERMIT }, | ||
58 | #else | ||
59 | /* Previous releases used sysctl(3)'s kern.arnd variable. */ | ||
55 | { SYS___sysctl, SYSTR_POLICY_PERMIT }, | 60 | { SYS___sysctl, SYSTR_POLICY_PERMIT }, |
61 | #endif | ||
62 | |||
63 | #ifdef SYS_sendsyslog | ||
64 | { SYS_sendsyslog, SYSTR_POLICY_PERMIT }, | ||
65 | #endif | ||
56 | { SYS_close, SYSTR_POLICY_PERMIT }, | 66 | { SYS_close, SYSTR_POLICY_PERMIT }, |
57 | { SYS_exit, SYSTR_POLICY_PERMIT }, | 67 | { SYS_exit, SYSTR_POLICY_PERMIT }, |
58 | { SYS_getpid, SYSTR_POLICY_PERMIT }, | 68 | { SYS_getpid, SYSTR_POLICY_PERMIT }, |
@@ -1,4 +1,4 @@ | |||
1 | SCP(1) OpenBSD Reference Manual SCP(1) | 1 | SCP(1) General Commands Manual SCP(1) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | scp - secure copy (remote file copy program) | 4 | scp - secure copy (remote file copy program) |
@@ -11,8 +11,8 @@ SYNOPSIS | |||
11 | DESCRIPTION | 11 | DESCRIPTION |
12 | scp copies files between hosts on a network. It uses ssh(1) for data | 12 | scp copies files between hosts on a network. It uses ssh(1) for data |
13 | transfer, and uses the same authentication and provides the same security | 13 | transfer, and uses the same authentication and provides the same security |
14 | as ssh(1). Unlike rcp(1), scp will ask for passwords or passphrases if | 14 | as ssh(1). scp will ask for passwords or passphrases if they are needed |
15 | they are needed for authentication. | 15 | for authentication. |
16 | 16 | ||
17 | File names may contain a user and host specification to indicate that the | 17 | File names may contain a user and host specification to indicate that the |
18 | file is to be copied to/from that host. Local file names can be made | 18 | file is to be copied to/from that host. Local file names can be made |
@@ -125,8 +125,7 @@ DESCRIPTION | |||
125 | -P port | 125 | -P port |
126 | Specifies the port to connect to on the remote host. Note that | 126 | Specifies the port to connect to on the remote host. Note that |
127 | this option is written with a capital `P', because -p is already | 127 | this option is written with a capital `P', because -p is already |
128 | reserved for preserving the times and modes of the file in | 128 | reserved for preserving the times and modes of the file. |
129 | rcp(1). | ||
130 | 129 | ||
131 | -p Preserves modification times, access times, and modes from the | 130 | -p Preserves modification times, access times, and modes from the |
132 | original file. | 131 | original file. |
@@ -149,15 +148,15 @@ EXIT STATUS | |||
149 | The scp utility exits 0 on success, and >0 if an error occurs. | 148 | The scp utility exits 0 on success, and >0 if an error occurs. |
150 | 149 | ||
151 | SEE ALSO | 150 | SEE ALSO |
152 | rcp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), | 151 | sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh_config(5), |
153 | ssh_config(5), sshd(8) | 152 | sshd(8) |
154 | 153 | ||
155 | HISTORY | 154 | HISTORY |
156 | scp is based on the rcp(1) program in BSD source code from the Regents of | 155 | scp is based on the rcp program in BSD source code from the Regents of |
157 | the University of California. | 156 | the University of California. |
158 | 157 | ||
159 | AUTHORS | 158 | AUTHORS |
160 | Timo Rinne <tri@iki.fi> | 159 | Timo Rinne <tri@iki.fi> |
161 | Tatu Ylonen <ylo@cs.hut.fi> | 160 | Tatu Ylonen <ylo@cs.hut.fi> |
162 | 161 | ||
163 | OpenBSD 5.5 October 20, 2013 OpenBSD 5.5 | 162 | OpenBSD 5.6 March 19, 2014 OpenBSD 5.6 |
@@ -8,9 +8,9 @@ | |||
8 | .\" | 8 | .\" |
9 | .\" Created: Sun May 7 00:14:37 1995 ylo | 9 | .\" Created: Sun May 7 00:14:37 1995 ylo |
10 | .\" | 10 | .\" |
11 | .\" $OpenBSD: scp.1,v 1.61 2013/10/20 09:51:26 djm Exp $ | 11 | .\" $OpenBSD: scp.1,v 1.62 2014/03/19 14:42:44 tedu Exp $ |
12 | .\" | 12 | .\" |
13 | .Dd $Mdocdate: October 20 2013 $ | 13 | .Dd $Mdocdate: March 19 2014 $ |
14 | .Dt SCP 1 | 14 | .Dt SCP 1 |
15 | .Os | 15 | .Os |
16 | .Sh NAME | 16 | .Sh NAME |
@@ -49,8 +49,6 @@ It uses | |||
49 | for data transfer, and uses the same authentication and provides the | 49 | for data transfer, and uses the same authentication and provides the |
50 | same security as | 50 | same security as |
51 | .Xr ssh 1 . | 51 | .Xr ssh 1 . |
52 | Unlike | ||
53 | .Xr rcp 1 , | ||
54 | .Nm | 52 | .Nm |
55 | will ask for passwords or passphrases if they are needed for | 53 | will ask for passwords or passphrases if they are needed for |
56 | authentication. | 54 | authentication. |
@@ -191,8 +189,7 @@ Note that this option is written with a capital | |||
191 | .Sq P , | 189 | .Sq P , |
192 | because | 190 | because |
193 | .Fl p | 191 | .Fl p |
194 | is already reserved for preserving the times and modes of the file in | 192 | is already reserved for preserving the times and modes of the file. |
195 | .Xr rcp 1 . | ||
196 | .It Fl p | 193 | .It Fl p |
197 | Preserves modification times, access times, and modes from the | 194 | Preserves modification times, access times, and modes from the |
198 | original file. | 195 | original file. |
@@ -225,7 +222,6 @@ debugging connection, authentication, and configuration problems. | |||
225 | .Sh EXIT STATUS | 222 | .Sh EXIT STATUS |
226 | .Ex -std scp | 223 | .Ex -std scp |
227 | .Sh SEE ALSO | 224 | .Sh SEE ALSO |
228 | .Xr rcp 1 , | ||
229 | .Xr sftp 1 , | 225 | .Xr sftp 1 , |
230 | .Xr ssh 1 , | 226 | .Xr ssh 1 , |
231 | .Xr ssh-add 1 , | 227 | .Xr ssh-add 1 , |
@@ -235,9 +231,7 @@ debugging connection, authentication, and configuration problems. | |||
235 | .Xr sshd 8 | 231 | .Xr sshd 8 |
236 | .Sh HISTORY | 232 | .Sh HISTORY |
237 | .Nm | 233 | .Nm |
238 | is based on the | 234 | is based on the rcp program in |
239 | .Xr rcp 1 | ||
240 | program in | ||
241 | .Bx | 235 | .Bx |
242 | source code from the Regents of the University of California. | 236 | source code from the Regents of the University of California. |
243 | .Sh AUTHORS | 237 | .Sh AUTHORS |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: scp.c,v 1.179 2013/11/20 20:53:10 deraadt Exp $ */ | 1 | /* $OpenBSD: scp.c,v 1.180 2014/06/24 02:21:01 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * scp - secure remote copy. This is basically patched BSD rcp which | 3 | * scp - secure remote copy. This is basically patched BSD rcp which |
4 | * uses ssh to do the data transfer (instead of using rcmd). | 4 | * uses ssh to do the data transfer (instead of using rcmd). |
@@ -755,7 +755,7 @@ source(int argc, char **argv) | |||
755 | static BUF buffer; | 755 | static BUF buffer; |
756 | BUF *bp; | 756 | BUF *bp; |
757 | off_t i, statbytes; | 757 | off_t i, statbytes; |
758 | size_t amt; | 758 | size_t amt, nr; |
759 | int fd = -1, haderr, indx; | 759 | int fd = -1, haderr, indx; |
760 | char *last, *name, buf[2048], encname[MAXPATHLEN]; | 760 | char *last, *name, buf[2048], encname[MAXPATHLEN]; |
761 | int len; | 761 | int len; |
@@ -828,12 +828,16 @@ next: if (fd != -1) { | |||
828 | if (i + (off_t)amt > stb.st_size) | 828 | if (i + (off_t)amt > stb.st_size) |
829 | amt = stb.st_size - i; | 829 | amt = stb.st_size - i; |
830 | if (!haderr) { | 830 | if (!haderr) { |
831 | if (atomicio(read, fd, bp->buf, amt) != amt) | 831 | if ((nr = atomicio(read, fd, |
832 | bp->buf, amt)) != amt) { | ||
832 | haderr = errno; | 833 | haderr = errno; |
834 | memset(bp->buf + nr, 0, amt - nr); | ||
835 | } | ||
833 | } | 836 | } |
834 | /* Keep writing after error to retain sync */ | 837 | /* Keep writing after error to retain sync */ |
835 | if (haderr) { | 838 | if (haderr) { |
836 | (void)atomicio(vwrite, remout, bp->buf, amt); | 839 | (void)atomicio(vwrite, remout, bp->buf, amt); |
840 | memset(bp->buf, 0, amt); | ||
837 | continue; | 841 | continue; |
838 | } | 842 | } |
839 | if (atomicio6(vwrite, remout, bp->buf, amt, scpio, | 843 | if (atomicio6(vwrite, remout, bp->buf, amt, scpio, |
diff --git a/servconf.c b/servconf.c index 37fd2de6d..6c7741ab2 100644 --- a/servconf.c +++ b/servconf.c | |||
@@ -1,5 +1,5 @@ | |||
1 | 1 | ||
2 | /* $OpenBSD: servconf.c,v 1.249 2014/01/29 06:18:35 djm Exp $ */ | 2 | /* $OpenBSD: servconf.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */ |
3 | /* | 3 | /* |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
5 | * All rights reserved | 5 | * All rights reserved |
@@ -39,10 +39,10 @@ | |||
39 | #include "ssh.h" | 39 | #include "ssh.h" |
40 | #include "log.h" | 40 | #include "log.h" |
41 | #include "buffer.h" | 41 | #include "buffer.h" |
42 | #include "misc.h" | ||
42 | #include "servconf.h" | 43 | #include "servconf.h" |
43 | #include "compat.h" | 44 | #include "compat.h" |
44 | #include "pathnames.h" | 45 | #include "pathnames.h" |
45 | #include "misc.h" | ||
46 | #include "cipher.h" | 46 | #include "cipher.h" |
47 | #include "key.h" | 47 | #include "key.h" |
48 | #include "kex.h" | 48 | #include "kex.h" |
@@ -93,6 +93,7 @@ initialize_server_options(ServerOptions *options) | |||
93 | options->x11_display_offset = -1; | 93 | options->x11_display_offset = -1; |
94 | options->x11_use_localhost = -1; | 94 | options->x11_use_localhost = -1; |
95 | options->permit_tty = -1; | 95 | options->permit_tty = -1; |
96 | options->permit_user_rc = -1; | ||
96 | options->xauth_location = NULL; | 97 | options->xauth_location = NULL; |
97 | options->strict_modes = -1; | 98 | options->strict_modes = -1; |
98 | options->tcp_keep_alive = -1; | 99 | options->tcp_keep_alive = -1; |
@@ -122,6 +123,7 @@ initialize_server_options(ServerOptions *options) | |||
122 | options->rekey_limit = -1; | 123 | options->rekey_limit = -1; |
123 | options->rekey_interval = -1; | 124 | options->rekey_interval = -1; |
124 | options->allow_tcp_forwarding = -1; | 125 | options->allow_tcp_forwarding = -1; |
126 | options->allow_streamlocal_forwarding = -1; | ||
125 | options->allow_agent_forwarding = -1; | 127 | options->allow_agent_forwarding = -1; |
126 | options->num_allow_users = 0; | 128 | options->num_allow_users = 0; |
127 | options->num_deny_users = 0; | 129 | options->num_deny_users = 0; |
@@ -131,7 +133,9 @@ initialize_server_options(ServerOptions *options) | |||
131 | options->macs = NULL; | 133 | options->macs = NULL; |
132 | options->kex_algorithms = NULL; | 134 | options->kex_algorithms = NULL; |
133 | options->protocol = SSH_PROTO_UNKNOWN; | 135 | options->protocol = SSH_PROTO_UNKNOWN; |
134 | options->gateway_ports = -1; | 136 | options->fwd_opts.gateway_ports = -1; |
137 | options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; | ||
138 | options->fwd_opts.streamlocal_bind_unlink = -1; | ||
135 | options->num_subsystems = 0; | 139 | options->num_subsystems = 0; |
136 | options->max_startups_begin = -1; | 140 | options->max_startups_begin = -1; |
137 | options->max_startups_rate = -1; | 141 | options->max_startups_rate = -1; |
@@ -220,6 +224,8 @@ fill_default_server_options(ServerOptions *options) | |||
220 | options->xauth_location = _PATH_XAUTH; | 224 | options->xauth_location = _PATH_XAUTH; |
221 | if (options->permit_tty == -1) | 225 | if (options->permit_tty == -1) |
222 | options->permit_tty = 1; | 226 | options->permit_tty = 1; |
227 | if (options->permit_user_rc == -1) | ||
228 | options->permit_user_rc = 1; | ||
223 | if (options->strict_modes == -1) | 229 | if (options->strict_modes == -1) |
224 | options->strict_modes = 1; | 230 | options->strict_modes = 1; |
225 | if (options->tcp_keep_alive == -1) | 231 | if (options->tcp_keep_alive == -1) |
@@ -276,10 +282,12 @@ fill_default_server_options(ServerOptions *options) | |||
276 | options->rekey_interval = 0; | 282 | options->rekey_interval = 0; |
277 | if (options->allow_tcp_forwarding == -1) | 283 | if (options->allow_tcp_forwarding == -1) |
278 | options->allow_tcp_forwarding = FORWARD_ALLOW; | 284 | options->allow_tcp_forwarding = FORWARD_ALLOW; |
285 | if (options->allow_streamlocal_forwarding == -1) | ||
286 | options->allow_streamlocal_forwarding = FORWARD_ALLOW; | ||
279 | if (options->allow_agent_forwarding == -1) | 287 | if (options->allow_agent_forwarding == -1) |
280 | options->allow_agent_forwarding = 1; | 288 | options->allow_agent_forwarding = 1; |
281 | if (options->gateway_ports == -1) | 289 | if (options->fwd_opts.gateway_ports == -1) |
282 | options->gateway_ports = 0; | 290 | options->fwd_opts.gateway_ports = 0; |
283 | if (options->max_startups == -1) | 291 | if (options->max_startups == -1) |
284 | options->max_startups = 100; | 292 | options->max_startups = 100; |
285 | if (options->max_startups_rate == -1) | 293 | if (options->max_startups_rate == -1) |
@@ -310,6 +318,10 @@ fill_default_server_options(ServerOptions *options) | |||
310 | options->ip_qos_bulk = IPTOS_THROUGHPUT; | 318 | options->ip_qos_bulk = IPTOS_THROUGHPUT; |
311 | if (options->version_addendum == NULL) | 319 | if (options->version_addendum == NULL) |
312 | options->version_addendum = xstrdup(""); | 320 | options->version_addendum = xstrdup(""); |
321 | if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) | ||
322 | options->fwd_opts.streamlocal_bind_mask = 0177; | ||
323 | if (options->fwd_opts.streamlocal_bind_unlink == -1) | ||
324 | options->fwd_opts.streamlocal_bind_unlink = 0; | ||
313 | if (options->debian_banner == -1) | 325 | if (options->debian_banner == -1) |
314 | options->debian_banner = 1; | 326 | options->debian_banner = 1; |
315 | /* Turn privilege separation on by default */ | 327 | /* Turn privilege separation on by default */ |
@@ -361,7 +373,9 @@ typedef enum { | |||
361 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, | 373 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
362 | sKexAlgorithms, sIPQoS, sVersionAddendum, | 374 | sKexAlgorithms, sIPQoS, sVersionAddendum, |
363 | sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, | 375 | sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, |
364 | sAuthenticationMethods, sHostKeyAgent, | 376 | sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, |
377 | sStreamLocalBindMask, sStreamLocalBindUnlink, | ||
378 | sAllowStreamLocalForwarding, | ||
365 | sDebianBanner, | 379 | sDebianBanner, |
366 | sDeprecated, sUnsupported | 380 | sDeprecated, sUnsupported |
367 | } ServerOpCodes; | 381 | } ServerOpCodes; |
@@ -486,6 +500,7 @@ static struct { | |||
486 | { "acceptenv", sAcceptEnv, SSHCFG_ALL }, | 500 | { "acceptenv", sAcceptEnv, SSHCFG_ALL }, |
487 | { "permittunnel", sPermitTunnel, SSHCFG_ALL }, | 501 | { "permittunnel", sPermitTunnel, SSHCFG_ALL }, |
488 | { "permittty", sPermitTTY, SSHCFG_ALL }, | 502 | { "permittty", sPermitTTY, SSHCFG_ALL }, |
503 | { "permituserrc", sPermitUserRC, SSHCFG_ALL }, | ||
489 | { "match", sMatch, SSHCFG_ALL }, | 504 | { "match", sMatch, SSHCFG_ALL }, |
490 | { "permitopen", sPermitOpen, SSHCFG_ALL }, | 505 | { "permitopen", sPermitOpen, SSHCFG_ALL }, |
491 | { "forcecommand", sForceCommand, SSHCFG_ALL }, | 506 | { "forcecommand", sForceCommand, SSHCFG_ALL }, |
@@ -500,6 +515,9 @@ static struct { | |||
500 | { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, | 515 | { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
501 | { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, | 516 | { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, |
502 | { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, | 517 | { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, |
518 | { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, | ||
519 | { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, | ||
520 | { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, | ||
503 | { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, | 521 | { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, |
504 | { NULL, sBadOption, 0 } | 522 | { NULL, sBadOption, 0 } |
505 | }; | 523 | }; |
@@ -1169,6 +1187,10 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1169 | intptr = &options->permit_tty; | 1187 | intptr = &options->permit_tty; |
1170 | goto parse_flag; | 1188 | goto parse_flag; |
1171 | 1189 | ||
1190 | case sPermitUserRC: | ||
1191 | intptr = &options->permit_user_rc; | ||
1192 | goto parse_flag; | ||
1193 | |||
1172 | case sStrictModes: | 1194 | case sStrictModes: |
1173 | intptr = &options->strict_modes; | 1195 | intptr = &options->strict_modes; |
1174 | goto parse_flag; | 1196 | goto parse_flag; |
@@ -1226,7 +1248,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1226 | break; | 1248 | break; |
1227 | 1249 | ||
1228 | case sGatewayPorts: | 1250 | case sGatewayPorts: |
1229 | intptr = &options->gateway_ports; | 1251 | intptr = &options->fwd_opts.gateway_ports; |
1230 | multistate_ptr = multistate_gatewayports; | 1252 | multistate_ptr = multistate_gatewayports; |
1231 | goto parse_multistate; | 1253 | goto parse_multistate; |
1232 | 1254 | ||
@@ -1261,6 +1283,11 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1261 | multistate_ptr = multistate_tcpfwd; | 1283 | multistate_ptr = multistate_tcpfwd; |
1262 | goto parse_multistate; | 1284 | goto parse_multistate; |
1263 | 1285 | ||
1286 | case sAllowStreamLocalForwarding: | ||
1287 | intptr = &options->allow_streamlocal_forwarding; | ||
1288 | multistate_ptr = multistate_tcpfwd; | ||
1289 | goto parse_multistate; | ||
1290 | |||
1264 | case sAllowAgentForwarding: | 1291 | case sAllowAgentForwarding: |
1265 | intptr = &options->allow_agent_forwarding; | 1292 | intptr = &options->allow_agent_forwarding; |
1266 | goto parse_flag; | 1293 | goto parse_flag; |
@@ -1659,6 +1686,22 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1659 | } | 1686 | } |
1660 | return 0; | 1687 | return 0; |
1661 | 1688 | ||
1689 | case sStreamLocalBindMask: | ||
1690 | arg = strdelim(&cp); | ||
1691 | if (!arg || *arg == '\0') | ||
1692 | fatal("%s line %d: missing StreamLocalBindMask argument.", | ||
1693 | filename, linenum); | ||
1694 | /* Parse mode in octal format */ | ||
1695 | value = strtol(arg, &p, 8); | ||
1696 | if (arg == p || value < 0 || value > 0777) | ||
1697 | fatal("%s line %d: Bad mask.", filename, linenum); | ||
1698 | options->fwd_opts.streamlocal_bind_mask = (mode_t)value; | ||
1699 | break; | ||
1700 | |||
1701 | case sStreamLocalBindUnlink: | ||
1702 | intptr = &options->fwd_opts.streamlocal_bind_unlink; | ||
1703 | goto parse_flag; | ||
1704 | |||
1662 | case sDebianBanner: | 1705 | case sDebianBanner: |
1663 | intptr = &options->debian_banner; | 1706 | intptr = &options->debian_banner; |
1664 | goto parse_int; | 1707 | goto parse_int; |
@@ -1802,13 +1845,15 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) | |||
1802 | M_CP_INTOPT(permit_empty_passwd); | 1845 | M_CP_INTOPT(permit_empty_passwd); |
1803 | 1846 | ||
1804 | M_CP_INTOPT(allow_tcp_forwarding); | 1847 | M_CP_INTOPT(allow_tcp_forwarding); |
1848 | M_CP_INTOPT(allow_streamlocal_forwarding); | ||
1805 | M_CP_INTOPT(allow_agent_forwarding); | 1849 | M_CP_INTOPT(allow_agent_forwarding); |
1806 | M_CP_INTOPT(permit_tun); | 1850 | M_CP_INTOPT(permit_tun); |
1807 | M_CP_INTOPT(gateway_ports); | 1851 | M_CP_INTOPT(fwd_opts.gateway_ports); |
1808 | M_CP_INTOPT(x11_display_offset); | 1852 | M_CP_INTOPT(x11_display_offset); |
1809 | M_CP_INTOPT(x11_forwarding); | 1853 | M_CP_INTOPT(x11_forwarding); |
1810 | M_CP_INTOPT(x11_use_localhost); | 1854 | M_CP_INTOPT(x11_use_localhost); |
1811 | M_CP_INTOPT(permit_tty); | 1855 | M_CP_INTOPT(permit_tty); |
1856 | M_CP_INTOPT(permit_user_rc); | ||
1812 | M_CP_INTOPT(max_sessions); | 1857 | M_CP_INTOPT(max_sessions); |
1813 | M_CP_INTOPT(max_authtries); | 1858 | M_CP_INTOPT(max_authtries); |
1814 | M_CP_INTOPT(ip_qos_interactive); | 1859 | M_CP_INTOPT(ip_qos_interactive); |
@@ -1901,6 +1946,8 @@ fmt_intarg(ServerOpCodes code, int val) | |||
1901 | return fmt_multistate_int(val, multistate_privsep); | 1946 | return fmt_multistate_int(val, multistate_privsep); |
1902 | case sAllowTcpForwarding: | 1947 | case sAllowTcpForwarding: |
1903 | return fmt_multistate_int(val, multistate_tcpfwd); | 1948 | return fmt_multistate_int(val, multistate_tcpfwd); |
1949 | case sAllowStreamLocalForwarding: | ||
1950 | return fmt_multistate_int(val, multistate_tcpfwd); | ||
1904 | case sProtocol: | 1951 | case sProtocol: |
1905 | switch (val) { | 1952 | switch (val) { |
1906 | case SSH_PROTO_1: | 1953 | case SSH_PROTO_1: |
@@ -2053,15 +2100,17 @@ dump_config(ServerOptions *o) | |||
2053 | dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); | 2100 | dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); |
2054 | dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); | 2101 | dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); |
2055 | dump_cfg_fmtint(sPermitTTY, o->permit_tty); | 2102 | dump_cfg_fmtint(sPermitTTY, o->permit_tty); |
2103 | dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); | ||
2056 | dump_cfg_fmtint(sStrictModes, o->strict_modes); | 2104 | dump_cfg_fmtint(sStrictModes, o->strict_modes); |
2057 | dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); | 2105 | dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); |
2058 | dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); | 2106 | dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); |
2059 | dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); | 2107 | dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); |
2060 | dump_cfg_fmtint(sUseLogin, o->use_login); | 2108 | dump_cfg_fmtint(sUseLogin, o->use_login); |
2061 | dump_cfg_fmtint(sCompression, o->compression); | 2109 | dump_cfg_fmtint(sCompression, o->compression); |
2062 | dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); | 2110 | dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); |
2063 | dump_cfg_fmtint(sUseDNS, o->use_dns); | 2111 | dump_cfg_fmtint(sUseDNS, o->use_dns); |
2064 | dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); | 2112 | dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); |
2113 | dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); | ||
2065 | dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); | 2114 | dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); |
2066 | 2115 | ||
2067 | /* string arguments */ | 2116 | /* string arguments */ |
diff --git a/servconf.h b/servconf.h index dcd1c2ab8..fa48804ec 100644 --- a/servconf.h +++ b/servconf.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: servconf.h,v 1.112 2014/01/29 06:18:35 djm Exp $ */ | 1 | /* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -83,6 +83,7 @@ typedef struct { | |||
83 | int x11_use_localhost; /* If true, use localhost for fake X11 server. */ | 83 | int x11_use_localhost; /* If true, use localhost for fake X11 server. */ |
84 | char *xauth_location; /* Location of xauth program */ | 84 | char *xauth_location; /* Location of xauth program */ |
85 | int permit_tty; /* If false, deny pty allocation */ | 85 | int permit_tty; /* If false, deny pty allocation */ |
86 | int permit_user_rc; /* If false, deny ~/.ssh/rc execution */ | ||
86 | int strict_modes; /* If true, require string home dir modes. */ | 87 | int strict_modes; /* If true, require string home dir modes. */ |
87 | int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */ | 88 | int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */ |
88 | int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ | 89 | int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ |
@@ -91,7 +92,7 @@ typedef struct { | |||
91 | char *macs; /* Supported SSH2 macs. */ | 92 | char *macs; /* Supported SSH2 macs. */ |
92 | char *kex_algorithms; /* SSH2 kex methods in order of preference. */ | 93 | char *kex_algorithms; /* SSH2 kex methods in order of preference. */ |
93 | int protocol; /* Supported protocol versions. */ | 94 | int protocol; /* Supported protocol versions. */ |
94 | int gateway_ports; /* If true, allow remote connects to forwarded ports. */ | 95 | struct ForwardOptions fwd_opts; /* forwarding options */ |
95 | SyslogFacility log_facility; /* Facility for system logging. */ | 96 | SyslogFacility log_facility; /* Facility for system logging. */ |
96 | LogLevel log_level; /* Level for system logging. */ | 97 | LogLevel log_level; /* Level for system logging. */ |
97 | int rhosts_rsa_authentication; /* If true, permit rhosts RSA | 98 | int rhosts_rsa_authentication; /* If true, permit rhosts RSA |
@@ -126,6 +127,7 @@ typedef struct { | |||
126 | int use_login; /* If true, login(1) is used */ | 127 | int use_login; /* If true, login(1) is used */ |
127 | int compression; /* If true, compression is allowed */ | 128 | int compression; /* If true, compression is allowed */ |
128 | int allow_tcp_forwarding; /* One of FORWARD_* */ | 129 | int allow_tcp_forwarding; /* One of FORWARD_* */ |
130 | int allow_streamlocal_forwarding; /* One of FORWARD_* */ | ||
129 | int allow_agent_forwarding; | 131 | int allow_agent_forwarding; |
130 | u_int num_allow_users; | 132 | u_int num_allow_users; |
131 | char *allow_users[MAX_ALLOW_USERS]; | 133 | char *allow_users[MAX_ALLOW_USERS]; |
diff --git a/serverloop.c b/serverloop.c index 441d73b4d..813e5bf38 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: serverloop.c,v 1.170 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: serverloop.c,v 1.172 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -61,6 +61,7 @@ | |||
61 | #include "packet.h" | 61 | #include "packet.h" |
62 | #include "buffer.h" | 62 | #include "buffer.h" |
63 | #include "log.h" | 63 | #include "log.h" |
64 | #include "misc.h" | ||
64 | #include "servconf.h" | 65 | #include "servconf.h" |
65 | #include "canohost.h" | 66 | #include "canohost.h" |
66 | #include "sshpty.h" | 67 | #include "sshpty.h" |
@@ -77,7 +78,6 @@ | |||
77 | #include "dispatch.h" | 78 | #include "dispatch.h" |
78 | #include "auth-options.h" | 79 | #include "auth-options.h" |
79 | #include "serverloop.h" | 80 | #include "serverloop.h" |
80 | #include "misc.h" | ||
81 | #include "roaming.h" | 81 | #include "roaming.h" |
82 | 82 | ||
83 | extern ServerOptions options; | 83 | extern ServerOptions options; |
@@ -970,7 +970,7 @@ server_request_direct_tcpip(void) | |||
970 | /* XXX fine grained permissions */ | 970 | /* XXX fine grained permissions */ |
971 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && | 971 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && |
972 | !no_port_forwarding_flag) { | 972 | !no_port_forwarding_flag) { |
973 | c = channel_connect_to(target, target_port, | 973 | c = channel_connect_to_port(target, target_port, |
974 | "direct-tcpip", "direct-tcpip"); | 974 | "direct-tcpip", "direct-tcpip"); |
975 | } else { | 975 | } else { |
976 | logit("refused local port forward: " | 976 | logit("refused local port forward: " |
@@ -985,6 +985,38 @@ server_request_direct_tcpip(void) | |||
985 | } | 985 | } |
986 | 986 | ||
987 | static Channel * | 987 | static Channel * |
988 | server_request_direct_streamlocal(void) | ||
989 | { | ||
990 | Channel *c = NULL; | ||
991 | char *target, *originator; | ||
992 | u_short originator_port; | ||
993 | |||
994 | target = packet_get_string(NULL); | ||
995 | originator = packet_get_string(NULL); | ||
996 | originator_port = packet_get_int(); | ||
997 | packet_check_eom(); | ||
998 | |||
999 | debug("server_request_direct_streamlocal: originator %s port %d, target %s", | ||
1000 | originator, originator_port, target); | ||
1001 | |||
1002 | /* XXX fine grained permissions */ | ||
1003 | if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && | ||
1004 | !no_port_forwarding_flag) { | ||
1005 | c = channel_connect_to_path(target, | ||
1006 | "direct-streamlocal@openssh.com", "direct-streamlocal"); | ||
1007 | } else { | ||
1008 | logit("refused streamlocal port forward: " | ||
1009 | "originator %s port %d, target %s", | ||
1010 | originator, originator_port, target); | ||
1011 | } | ||
1012 | |||
1013 | free(originator); | ||
1014 | free(target); | ||
1015 | |||
1016 | return c; | ||
1017 | } | ||
1018 | |||
1019 | static Channel * | ||
988 | server_request_tun(void) | 1020 | server_request_tun(void) |
989 | { | 1021 | { |
990 | Channel *c = NULL; | 1022 | Channel *c = NULL; |
@@ -1081,6 +1113,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
1081 | c = server_request_session(); | 1113 | c = server_request_session(); |
1082 | } else if (strcmp(ctype, "direct-tcpip") == 0) { | 1114 | } else if (strcmp(ctype, "direct-tcpip") == 0) { |
1083 | c = server_request_direct_tcpip(); | 1115 | c = server_request_direct_tcpip(); |
1116 | } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { | ||
1117 | c = server_request_direct_streamlocal(); | ||
1084 | } else if (strcmp(ctype, "tun@openssh.com") == 0) { | 1118 | } else if (strcmp(ctype, "tun@openssh.com") == 0) { |
1085 | c = server_request_tun(); | 1119 | c = server_request_tun(); |
1086 | } | 1120 | } |
@@ -1125,47 +1159,74 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) | |||
1125 | /* -R style forwarding */ | 1159 | /* -R style forwarding */ |
1126 | if (strcmp(rtype, "tcpip-forward") == 0) { | 1160 | if (strcmp(rtype, "tcpip-forward") == 0) { |
1127 | struct passwd *pw; | 1161 | struct passwd *pw; |
1128 | char *listen_address; | 1162 | struct Forward fwd; |
1129 | u_short listen_port; | ||
1130 | 1163 | ||
1131 | pw = the_authctxt->pw; | 1164 | pw = the_authctxt->pw; |
1132 | if (pw == NULL || !the_authctxt->valid) | 1165 | if (pw == NULL || !the_authctxt->valid) |
1133 | fatal("server_input_global_request: no/invalid user"); | 1166 | fatal("server_input_global_request: no/invalid user"); |
1134 | listen_address = packet_get_string(NULL); | 1167 | memset(&fwd, 0, sizeof(fwd)); |
1135 | listen_port = (u_short)packet_get_int(); | 1168 | fwd.listen_host = packet_get_string(NULL); |
1169 | fwd.listen_port = (u_short)packet_get_int(); | ||
1136 | debug("server_input_global_request: tcpip-forward listen %s port %d", | 1170 | debug("server_input_global_request: tcpip-forward listen %s port %d", |
1137 | listen_address, listen_port); | 1171 | fwd.listen_host, fwd.listen_port); |
1138 | 1172 | ||
1139 | /* check permissions */ | 1173 | /* check permissions */ |
1140 | if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || | 1174 | if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || |
1141 | no_port_forwarding_flag || | 1175 | no_port_forwarding_flag || |
1142 | (!want_reply && listen_port == 0) | 1176 | (!want_reply && fwd.listen_port == 0) |
1143 | #ifndef NO_IPPORT_RESERVED_CONCEPT | 1177 | #ifndef NO_IPPORT_RESERVED_CONCEPT |
1144 | || (listen_port != 0 && listen_port < IPPORT_RESERVED && | 1178 | || (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED && |
1145 | pw->pw_uid != 0) | 1179 | pw->pw_uid != 0) |
1146 | #endif | 1180 | #endif |
1147 | ) { | 1181 | ) { |
1148 | success = 0; | 1182 | success = 0; |
1149 | packet_send_debug("Server has disabled port forwarding."); | 1183 | packet_send_debug("Server has disabled port forwarding."); |
1150 | } else { | 1184 | } else { |
1151 | /* Start listening on the port */ | 1185 | /* Start listening on the port */ |
1152 | success = channel_setup_remote_fwd_listener( | 1186 | success = channel_setup_remote_fwd_listener(&fwd, |
1153 | listen_address, listen_port, | 1187 | &allocated_listen_port, &options.fwd_opts); |
1154 | &allocated_listen_port, options.gateway_ports); | ||
1155 | } | 1188 | } |
1156 | free(listen_address); | 1189 | free(fwd.listen_host); |
1157 | } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { | 1190 | } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { |
1158 | char *cancel_address; | 1191 | struct Forward fwd; |
1159 | u_short cancel_port; | ||
1160 | 1192 | ||
1161 | cancel_address = packet_get_string(NULL); | 1193 | memset(&fwd, 0, sizeof(fwd)); |
1162 | cancel_port = (u_short)packet_get_int(); | 1194 | fwd.listen_host = packet_get_string(NULL); |
1195 | fwd.listen_port = (u_short)packet_get_int(); | ||
1163 | debug("%s: cancel-tcpip-forward addr %s port %d", __func__, | 1196 | debug("%s: cancel-tcpip-forward addr %s port %d", __func__, |
1164 | cancel_address, cancel_port); | 1197 | fwd.listen_host, fwd.listen_port); |
1198 | |||
1199 | success = channel_cancel_rport_listener(&fwd); | ||
1200 | free(fwd.listen_host); | ||
1201 | } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { | ||
1202 | struct Forward fwd; | ||
1203 | |||
1204 | memset(&fwd, 0, sizeof(fwd)); | ||
1205 | fwd.listen_path = packet_get_string(NULL); | ||
1206 | debug("server_input_global_request: streamlocal-forward listen path %s", | ||
1207 | fwd.listen_path); | ||
1208 | |||
1209 | /* check permissions */ | ||
1210 | if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0 | ||
1211 | || no_port_forwarding_flag) { | ||
1212 | success = 0; | ||
1213 | packet_send_debug("Server has disabled port forwarding."); | ||
1214 | } else { | ||
1215 | /* Start listening on the socket */ | ||
1216 | success = channel_setup_remote_fwd_listener( | ||
1217 | &fwd, NULL, &options.fwd_opts); | ||
1218 | } | ||
1219 | free(fwd.listen_path); | ||
1220 | } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) { | ||
1221 | struct Forward fwd; | ||
1222 | |||
1223 | memset(&fwd, 0, sizeof(fwd)); | ||
1224 | fwd.listen_path = packet_get_string(NULL); | ||
1225 | debug("%s: cancel-streamlocal-forward path %s", __func__, | ||
1226 | fwd.listen_path); | ||
1165 | 1227 | ||
1166 | success = channel_cancel_rport_listener(cancel_address, | 1228 | success = channel_cancel_rport_listener(&fwd); |
1167 | cancel_port); | 1229 | free(fwd.listen_path); |
1168 | free(cancel_address); | ||
1169 | } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { | 1230 | } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { |
1170 | no_more_sessions = 1; | 1231 | no_more_sessions = 1; |
1171 | success = 1; | 1232 | success = 1; |
@@ -1204,7 +1265,7 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt) | |||
1204 | } else if ((c->type == SSH_CHANNEL_LARVAL || | 1265 | } else if ((c->type == SSH_CHANNEL_LARVAL || |
1205 | c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) | 1266 | c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) |
1206 | success = session_input_channel_req(c, rtype); | 1267 | success = session_input_channel_req(c, rtype); |
1207 | if (reply) { | 1268 | if (reply && !(c->flags & CHAN_CLOSE_SENT)) { |
1208 | packet_start(success ? | 1269 | packet_start(success ? |
1209 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); | 1270 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); |
1210 | packet_put_int(c->remote_id); | 1271 | packet_put_int(c->remote_id); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.c,v 1.270 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: session.c,v 1.274 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -49,6 +49,7 @@ | |||
49 | #include <errno.h> | 49 | #include <errno.h> |
50 | #include <fcntl.h> | 50 | #include <fcntl.h> |
51 | #include <grp.h> | 51 | #include <grp.h> |
52 | #include <netdb.h> | ||
52 | #ifdef HAVE_PATHS_H | 53 | #ifdef HAVE_PATHS_H |
53 | #include <paths.h> | 54 | #include <paths.h> |
54 | #endif | 55 | #endif |
@@ -83,11 +84,11 @@ | |||
83 | #include "authfd.h" | 84 | #include "authfd.h" |
84 | #include "pathnames.h" | 85 | #include "pathnames.h" |
85 | #include "log.h" | 86 | #include "log.h" |
87 | #include "misc.h" | ||
86 | #include "servconf.h" | 88 | #include "servconf.h" |
87 | #include "sshlogin.h" | 89 | #include "sshlogin.h" |
88 | #include "serverloop.h" | 90 | #include "serverloop.h" |
89 | #include "canohost.h" | 91 | #include "canohost.h" |
90 | #include "misc.h" | ||
91 | #include "session.h" | 92 | #include "session.h" |
92 | #include "kex.h" | 93 | #include "kex.h" |
93 | #include "monitor_wrap.h" | 94 | #include "monitor_wrap.h" |
@@ -183,7 +184,6 @@ auth_input_request_forwarding(struct passwd * pw) | |||
183 | { | 184 | { |
184 | Channel *nc; | 185 | Channel *nc; |
185 | int sock = -1; | 186 | int sock = -1; |
186 | struct sockaddr_un sunaddr; | ||
187 | 187 | ||
188 | if (auth_sock_name != NULL) { | 188 | if (auth_sock_name != NULL) { |
189 | error("authentication forwarding requested twice."); | 189 | error("authentication forwarding requested twice."); |
@@ -209,33 +209,15 @@ auth_input_request_forwarding(struct passwd * pw) | |||
209 | xasprintf(&auth_sock_name, "%s/agent.%ld", | 209 | xasprintf(&auth_sock_name, "%s/agent.%ld", |
210 | auth_sock_dir, (long) getpid()); | 210 | auth_sock_dir, (long) getpid()); |
211 | 211 | ||
212 | /* Create the socket. */ | 212 | /* Start a Unix listener on auth_sock_name. */ |
213 | sock = socket(AF_UNIX, SOCK_STREAM, 0); | 213 | sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0); |
214 | if (sock < 0) { | ||
215 | error("socket: %.100s", strerror(errno)); | ||
216 | restore_uid(); | ||
217 | goto authsock_err; | ||
218 | } | ||
219 | |||
220 | /* Bind it to the name. */ | ||
221 | memset(&sunaddr, 0, sizeof(sunaddr)); | ||
222 | sunaddr.sun_family = AF_UNIX; | ||
223 | strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); | ||
224 | |||
225 | if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { | ||
226 | error("bind: %.100s", strerror(errno)); | ||
227 | restore_uid(); | ||
228 | goto authsock_err; | ||
229 | } | ||
230 | 214 | ||
231 | /* Restore the privileged uid. */ | 215 | /* Restore the privileged uid. */ |
232 | restore_uid(); | 216 | restore_uid(); |
233 | 217 | ||
234 | /* Start listening on the socket. */ | 218 | /* Check for socket/bind/listen failure. */ |
235 | if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { | 219 | if (sock < 0) |
236 | error("listen: %.100s", strerror(errno)); | ||
237 | goto authsock_err; | 220 | goto authsock_err; |
238 | } | ||
239 | 221 | ||
240 | /* Allocate a channel for the authentication agent socket. */ | 222 | /* Allocate a channel for the authentication agent socket. */ |
241 | nc = channel_new("auth socket", | 223 | nc = channel_new("auth socket", |
@@ -274,6 +256,7 @@ do_authenticated(Authctxt *authctxt) | |||
274 | setproctitle("%s", authctxt->pw->pw_name); | 256 | setproctitle("%s", authctxt->pw->pw_name); |
275 | 257 | ||
276 | /* setup the channel layer */ | 258 | /* setup the channel layer */ |
259 | /* XXX - streamlocal? */ | ||
277 | if (no_port_forwarding_flag || | 260 | if (no_port_forwarding_flag || |
278 | (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) | 261 | (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) |
279 | channel_disable_adm_local_opens(); | 262 | channel_disable_adm_local_opens(); |
@@ -393,7 +376,7 @@ do_authenticated1(Authctxt *authctxt) | |||
393 | } | 376 | } |
394 | debug("Received TCP/IP port forwarding request."); | 377 | debug("Received TCP/IP port forwarding request."); |
395 | if (channel_input_port_forward_request(s->pw->pw_uid == 0, | 378 | if (channel_input_port_forward_request(s->pw->pw_uid == 0, |
396 | options.gateway_ports) < 0) { | 379 | &options.fwd_opts) < 0) { |
397 | debug("Port forwarding failed."); | 380 | debug("Port forwarding failed."); |
398 | break; | 381 | break; |
399 | } | 382 | } |
@@ -1367,7 +1350,8 @@ do_rc_files(Session *s, const char *shell) | |||
1367 | 1350 | ||
1368 | /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ | 1351 | /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ |
1369 | if (!s->is_subsystem && options.adm_forced_command == NULL && | 1352 | if (!s->is_subsystem && options.adm_forced_command == NULL && |
1370 | !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) { | 1353 | !no_user_rc && options.permit_user_rc && |
1354 | stat(_PATH_SSH_USER_RC, &st) >= 0) { | ||
1371 | snprintf(cmd, sizeof cmd, "%s -c '%s %s'", | 1355 | snprintf(cmd, sizeof cmd, "%s -c '%s %s'", |
1372 | shell, _PATH_BSHELL, _PATH_SSH_USER_RC); | 1356 | shell, _PATH_BSHELL, _PATH_SSH_USER_RC); |
1373 | if (debug_flag) | 1357 | if (debug_flag) |
@@ -1514,6 +1498,9 @@ void | |||
1514 | do_setusercontext(struct passwd *pw, const char *role) | 1498 | do_setusercontext(struct passwd *pw, const char *role) |
1515 | { | 1499 | { |
1516 | char *chroot_path, *tmp; | 1500 | char *chroot_path, *tmp; |
1501 | #ifdef USE_LIBIAF | ||
1502 | int doing_chroot = 0; | ||
1503 | #endif | ||
1517 | 1504 | ||
1518 | platform_setusercontext(pw); | 1505 | platform_setusercontext(pw); |
1519 | 1506 | ||
@@ -1553,6 +1540,9 @@ do_setusercontext(struct passwd *pw, const char *role) | |||
1553 | /* Make sure we don't attempt to chroot again */ | 1540 | /* Make sure we don't attempt to chroot again */ |
1554 | free(options.chroot_directory); | 1541 | free(options.chroot_directory); |
1555 | options.chroot_directory = NULL; | 1542 | options.chroot_directory = NULL; |
1543 | #ifdef USE_LIBIAF | ||
1544 | doing_chroot = 1; | ||
1545 | #endif | ||
1556 | } | 1546 | } |
1557 | 1547 | ||
1558 | #ifdef HAVE_LOGIN_CAP | 1548 | #ifdef HAVE_LOGIN_CAP |
@@ -1567,7 +1557,14 @@ do_setusercontext(struct passwd *pw, const char *role) | |||
1567 | (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK); | 1557 | (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK); |
1568 | #else | 1558 | #else |
1569 | # ifdef USE_LIBIAF | 1559 | # ifdef USE_LIBIAF |
1570 | if (set_id(pw->pw_name) != 0) { | 1560 | /* In a chroot environment, the set_id() will always fail; typically |
1561 | * because of the lack of necessary authentication services and runtime | ||
1562 | * such as ./usr/lib/libiaf.so, ./usr/lib/libpam.so.1, and ./etc/passwd | ||
1563 | * We skip it in the internal sftp chroot case. | ||
1564 | * We'll lose auditing and ACLs but permanently_set_uid will | ||
1565 | * take care of the rest. | ||
1566 | */ | ||
1567 | if ((doing_chroot == 0) && set_id(pw->pw_name) != 0) { | ||
1571 | fatal("set_id(%s) Failed", pw->pw_name); | 1568 | fatal("set_id(%s) Failed", pw->pw_name); |
1572 | } | 1569 | } |
1573 | # endif /* USE_LIBIAF */ | 1570 | # endif /* USE_LIBIAF */ |
@@ -2653,7 +2650,7 @@ session_setup_x11fwd(Session *s) | |||
2653 | { | 2650 | { |
2654 | struct stat st; | 2651 | struct stat st; |
2655 | char display[512], auth_display[512]; | 2652 | char display[512], auth_display[512]; |
2656 | char hostname[MAXHOSTNAMELEN]; | 2653 | char hostname[NI_MAXHOST]; |
2657 | u_int i; | 2654 | u_int i; |
2658 | 2655 | ||
2659 | if (no_x11_forwarding_flag) { | 2656 | if (no_x11_forwarding_flag) { |
diff --git a/sftp-client.c b/sftp-client.c index 2f5907c85..990b58d14 100644 --- a/sftp-client.c +++ b/sftp-client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-client.c,v 1.114 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: sftp-client.c,v 1.115 2014/04/21 14:36:16 logan Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -1420,7 +1420,7 @@ download_dir(struct sftp_conn *conn, char *src, char *dst, | |||
1420 | 1420 | ||
1421 | int | 1421 | int |
1422 | do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | 1422 | do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, |
1423 | int preserve_flag, int fsync_flag) | 1423 | int preserve_flag, int resume, int fsync_flag) |
1424 | { | 1424 | { |
1425 | int local_fd; | 1425 | int local_fd; |
1426 | int status = SSH2_FX_OK; | 1426 | int status = SSH2_FX_OK; |
@@ -1429,7 +1429,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1429 | char *handle, *data; | 1429 | char *handle, *data; |
1430 | Buffer msg; | 1430 | Buffer msg; |
1431 | struct stat sb; | 1431 | struct stat sb; |
1432 | Attrib a; | 1432 | Attrib a, *c = NULL; |
1433 | u_int32_t startid; | 1433 | u_int32_t startid; |
1434 | u_int32_t ackid; | 1434 | u_int32_t ackid; |
1435 | struct outstanding_ack { | 1435 | struct outstanding_ack { |
@@ -1467,6 +1467,26 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1467 | if (!preserve_flag) | 1467 | if (!preserve_flag) |
1468 | a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; | 1468 | a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; |
1469 | 1469 | ||
1470 | if (resume) { | ||
1471 | /* Get remote file size if it exists */ | ||
1472 | if ((c = do_stat(conn, remote_path, 0)) == NULL) { | ||
1473 | close(local_fd); | ||
1474 | return -1; | ||
1475 | } | ||
1476 | |||
1477 | if ((off_t)c->size >= sb.st_size) { | ||
1478 | error("destination file bigger or same size as " | ||
1479 | "source file"); | ||
1480 | close(local_fd); | ||
1481 | return -1; | ||
1482 | } | ||
1483 | |||
1484 | if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { | ||
1485 | close(local_fd); | ||
1486 | return -1; | ||
1487 | } | ||
1488 | } | ||
1489 | |||
1470 | buffer_init(&msg); | 1490 | buffer_init(&msg); |
1471 | 1491 | ||
1472 | /* Send open request */ | 1492 | /* Send open request */ |
@@ -1474,7 +1494,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1474 | buffer_put_char(&msg, SSH2_FXP_OPEN); | 1494 | buffer_put_char(&msg, SSH2_FXP_OPEN); |
1475 | buffer_put_int(&msg, id); | 1495 | buffer_put_int(&msg, id); |
1476 | buffer_put_cstring(&msg, remote_path); | 1496 | buffer_put_cstring(&msg, remote_path); |
1477 | buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); | 1497 | buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| |
1498 | (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC)); | ||
1478 | encode_attrib(&msg, &a); | 1499 | encode_attrib(&msg, &a); |
1479 | send_msg(conn, &msg); | 1500 | send_msg(conn, &msg); |
1480 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); | 1501 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); |
@@ -1493,7 +1514,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1493 | data = xmalloc(conn->transfer_buflen); | 1514 | data = xmalloc(conn->transfer_buflen); |
1494 | 1515 | ||
1495 | /* Read from local and write to remote */ | 1516 | /* Read from local and write to remote */ |
1496 | offset = progress_counter = 0; | 1517 | offset = progress_counter = (resume ? c->size : 0); |
1497 | if (showprogress) | 1518 | if (showprogress) |
1498 | start_progress_meter(local_path, sb.st_size, | 1519 | start_progress_meter(local_path, sb.st_size, |
1499 | &progress_counter); | 1520 | &progress_counter); |
@@ -1608,7 +1629,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1608 | 1629 | ||
1609 | static int | 1630 | static int |
1610 | upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | 1631 | upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, |
1611 | int preserve_flag, int print_flag, int fsync_flag) | 1632 | int preserve_flag, int print_flag, int resume, int fsync_flag) |
1612 | { | 1633 | { |
1613 | int ret = 0, status; | 1634 | int ret = 0, status; |
1614 | DIR *dirp; | 1635 | DIR *dirp; |
@@ -1677,12 +1698,12 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | |||
1677 | continue; | 1698 | continue; |
1678 | 1699 | ||
1679 | if (upload_dir_internal(conn, new_src, new_dst, | 1700 | if (upload_dir_internal(conn, new_src, new_dst, |
1680 | depth + 1, preserve_flag, print_flag, | 1701 | depth + 1, preserve_flag, print_flag, resume, |
1681 | fsync_flag) == -1) | 1702 | fsync_flag) == -1) |
1682 | ret = -1; | 1703 | ret = -1; |
1683 | } else if (S_ISREG(sb.st_mode)) { | 1704 | } else if (S_ISREG(sb.st_mode)) { |
1684 | if (do_upload(conn, new_src, new_dst, | 1705 | if (do_upload(conn, new_src, new_dst, |
1685 | preserve_flag, fsync_flag) == -1) { | 1706 | preserve_flag, resume, fsync_flag) == -1) { |
1686 | error("Uploading of file %s to %s failed!", | 1707 | error("Uploading of file %s to %s failed!", |
1687 | new_src, new_dst); | 1708 | new_src, new_dst); |
1688 | ret = -1; | 1709 | ret = -1; |
@@ -1701,7 +1722,7 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | |||
1701 | 1722 | ||
1702 | int | 1723 | int |
1703 | upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, | 1724 | upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, |
1704 | int print_flag, int fsync_flag) | 1725 | int print_flag, int resume, int fsync_flag) |
1705 | { | 1726 | { |
1706 | char *dst_canon; | 1727 | char *dst_canon; |
1707 | int ret; | 1728 | int ret; |
@@ -1712,7 +1733,7 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, | |||
1712 | } | 1733 | } |
1713 | 1734 | ||
1714 | ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, | 1735 | ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, |
1715 | print_flag, fsync_flag); | 1736 | print_flag, resume, fsync_flag); |
1716 | 1737 | ||
1717 | free(dst_canon); | 1738 | free(dst_canon); |
1718 | return ret; | 1739 | return ret; |
diff --git a/sftp-client.h b/sftp-client.h index ba92ad01a..967840b9c 100644 --- a/sftp-client.h +++ b/sftp-client.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-client.h,v 1.24 2013/10/17 00:30:13 djm Exp $ */ | 1 | /* $OpenBSD: sftp-client.h,v 1.25 2014/04/21 14:36:16 logan Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 4 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
@@ -120,13 +120,13 @@ int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, | |||
120 | * Upload 'local_path' to 'remote_path'. Preserve permissions and times | 120 | * Upload 'local_path' to 'remote_path'. Preserve permissions and times |
121 | * if 'pflag' is set | 121 | * if 'pflag' is set |
122 | */ | 122 | */ |
123 | int do_upload(struct sftp_conn *, char *, char *, int, int); | 123 | int do_upload(struct sftp_conn *, char *, char *, int, int, int); |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * Recursively upload 'local_directory' to 'remote_directory'. Preserve | 126 | * Recursively upload 'local_directory' to 'remote_directory'. Preserve |
127 | * times if 'pflag' is set | 127 | * times if 'pflag' is set |
128 | */ | 128 | */ |
129 | int upload_dir(struct sftp_conn *, char *, char *, int, int, int); | 129 | int upload_dir(struct sftp_conn *, char *, char *, int, int, int, int); |
130 | 130 | ||
131 | /* Concatenate paths, taking care of slashes. Caller must free result. */ | 131 | /* Concatenate paths, taking care of slashes. Caller must free result. */ |
132 | char *path_append(char *, char *); | 132 | char *path_append(char *, char *); |
diff --git a/sftp-server.0 b/sftp-server.0 index ce7ddc07f..d811e252d 100644 --- a/sftp-server.0 +++ b/sftp-server.0 | |||
@@ -1,4 +1,4 @@ | |||
1 | SFTP-SERVER(8) OpenBSD System Manager's Manual SFTP-SERVER(8) | 1 | SFTP-SERVER(8) System Manager's Manual SFTP-SERVER(8) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | sftp-server - SFTP server subsystem | 4 | sftp-server - SFTP server subsystem |
@@ -76,9 +76,10 @@ DESCRIPTION | |||
76 | Sets an explicit umask(2) to be applied to newly-created files | 76 | Sets an explicit umask(2) to be applied to newly-created files |
77 | and directories, instead of the user's default mask. | 77 | and directories, instead of the user's default mask. |
78 | 78 | ||
79 | For logging to work, sftp-server must be able to access /dev/log. Use of | 79 | On some systems, sftp-server must be able to access /dev/log for logging |
80 | sftp-server in a chroot configuration therefore requires that syslogd(8) | 80 | to work, and use of sftp-server in a chroot configuration therefore |
81 | establish a logging socket inside the chroot directory. | 81 | requires that syslogd(8) establish a logging socket inside the chroot |
82 | directory. | ||
82 | 83 | ||
83 | SEE ALSO | 84 | SEE ALSO |
84 | sftp(1), ssh(1), sshd_config(5), sshd(8) | 85 | sftp(1), ssh(1), sshd_config(5), sshd(8) |
@@ -92,4 +93,4 @@ HISTORY | |||
92 | AUTHORS | 93 | AUTHORS |
93 | Markus Friedl <markus@openbsd.org> | 94 | Markus Friedl <markus@openbsd.org> |
94 | 95 | ||
95 | OpenBSD 5.5 October 14, 2013 OpenBSD 5.5 | 96 | OpenBSD 5.6 July 28, 2014 OpenBSD 5.6 |
diff --git a/sftp-server.8 b/sftp-server.8 index 1e0b277b4..75d8d8d53 100644 --- a/sftp-server.8 +++ b/sftp-server.8 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: sftp-server.8,v 1.25 2013/10/14 14:18:56 jmc Exp $ | 1 | .\" $OpenBSD: sftp-server.8,v 1.26 2014/07/28 15:40:08 schwarze Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | .\" Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | .\" | 4 | .\" |
@@ -22,7 +22,7 @@ | |||
22 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 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. | 23 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | .\" | 24 | .\" |
25 | .Dd $Mdocdate: October 14 2013 $ | 25 | .Dd $Mdocdate: July 28 2014 $ |
26 | .Dt SFTP-SERVER 8 | 26 | .Dt SFTP-SERVER 8 |
27 | .Os | 27 | .Os |
28 | .Sh NAME | 28 | .Sh NAME |
@@ -140,11 +140,11 @@ to be applied to newly-created files and directories, instead of the | |||
140 | user's default mask. | 140 | user's default mask. |
141 | .El | 141 | .El |
142 | .Pp | 142 | .Pp |
143 | For logging to work, | 143 | On some systems, |
144 | .Nm | 144 | .Nm |
145 | must be able to access | 145 | must be able to access |
146 | .Pa /dev/log . | 146 | .Pa /dev/log |
147 | Use of | 147 | for logging to work, and use of |
148 | .Nm | 148 | .Nm |
149 | in a chroot configuration therefore requires that | 149 | in a chroot configuration therefore requires that |
150 | .Xr syslogd 8 | 150 | .Xr syslogd 8 |
diff --git a/sftp-server.c b/sftp-server.c index b8eb59c36..0177130cf 100644 --- a/sftp-server.c +++ b/sftp-server.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #ifdef HAVE_SYS_STATVFS_H | 29 | #ifdef HAVE_SYS_STATVFS_H |
30 | #include <sys/statvfs.h> | 30 | #include <sys/statvfs.h> |
31 | #endif | 31 | #endif |
32 | #ifdef HAVE_SYS_PRCTL_H | ||
33 | #include <sys/prctl.h> | ||
34 | #endif | ||
32 | 35 | ||
33 | #include <dirent.h> | 36 | #include <dirent.h> |
34 | #include <errno.h> | 37 | #include <errno.h> |
@@ -1523,6 +1526,17 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) | |||
1523 | 1526 | ||
1524 | log_init(__progname, log_level, log_facility, log_stderr); | 1527 | log_init(__progname, log_level, log_facility, log_stderr); |
1525 | 1528 | ||
1529 | #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) | ||
1530 | /* | ||
1531 | * On Linux, we should try to avoid making /proc/self/{mem,maps} | ||
1532 | * available to the user so that sftp access doesn't automatically | ||
1533 | * imply arbitrary code execution access that will break | ||
1534 | * restricted configurations. | ||
1535 | */ | ||
1536 | if (prctl(PR_SET_DUMPABLE, 0) != 0) | ||
1537 | fatal("unable to make the process undumpable"); | ||
1538 | #endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */ | ||
1539 | |||
1526 | if ((cp = getenv("SSH_CONNECTION")) != NULL) { | 1540 | if ((cp = getenv("SSH_CONNECTION")) != NULL) { |
1527 | client_addr = xstrdup(cp); | 1541 | client_addr = xstrdup(cp); |
1528 | if ((cp = strchr(client_addr, ' ')) == NULL) { | 1542 | if ((cp = strchr(client_addr, ' ')) == NULL) { |
@@ -1,4 +1,4 @@ | |||
1 | SFTP(1) OpenBSD Reference Manual SFTP(1) | 1 | SFTP(1) General Commands Manual SFTP(1) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | sftp - secure file transfer program | 4 | sftp - secure file transfer program |
@@ -44,9 +44,9 @@ DESCRIPTION | |||
44 | 44 | ||
45 | -6 Forces sftp to use IPv6 addresses only. | 45 | -6 Forces sftp to use IPv6 addresses only. |
46 | 46 | ||
47 | -a Attempt to continue interrupted downloads rather than overwriting | 47 | -a Attempt to continue interrupted transfers rather than overwriting |
48 | existing partial or complete copies of files. If the remote file | 48 | existing partial or complete copies of files. If the partial |
49 | contents differ from the partial local copy then the resultant | 49 | contents differ from those being transferred, then the resultant |
50 | file is likely to be corrupt. | 50 | file is likely to be corrupt. |
51 | 51 | ||
52 | -B buffer_size | 52 | -B buffer_size |
@@ -60,10 +60,11 @@ DESCRIPTION | |||
60 | used in conjunction with non-interactive authentication. A | 60 | used in conjunction with non-interactive authentication. A |
61 | batchfile of `-' may be used to indicate standard input. sftp | 61 | batchfile of `-' may be used to indicate standard input. sftp |
62 | will abort if any of the following commands fail: get, put, | 62 | will abort if any of the following commands fail: get, put, |
63 | reget, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, chown, | 63 | reget, reput, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, |
64 | chgrp, lpwd, df, symlink, and lmkdir. Termination on error can | 64 | chown, chgrp, lpwd, df, symlink, and lmkdir. Termination on |
65 | be suppressed on a command by command basis by prefixing the | 65 | error can be suppressed on a command by command basis by |
66 | command with a `-' character (for example, -rm /tmp/blah*). | 66 | prefixing the command with a `-' character (for example, -rm |
67 | /tmp/blah*). | ||
67 | 68 | ||
68 | -C Enables compression (via ssh's -C flag). | 69 | -C Enables compression (via ssh's -C flag). |
69 | 70 | ||
@@ -310,7 +311,7 @@ INTERACTIVE COMMANDS | |||
310 | progress | 311 | progress |
311 | Toggle display of progress meter. | 312 | Toggle display of progress meter. |
312 | 313 | ||
313 | put [-fPpr] local-path [remote-path] | 314 | put [-afPpr] local-path [remote-path] |
314 | Upload local-path and store it on the remote machine. If the | 315 | Upload local-path and store it on the remote machine. If the |
315 | remote path name is not specified, it is given the same name it | 316 | remote path name is not specified, it is given the same name it |
316 | has on the local machine. local-path may contain glob(3) | 317 | has on the local machine. local-path may contain glob(3) |
@@ -318,6 +319,12 @@ INTERACTIVE COMMANDS | |||
318 | remote-path is specified, then remote-path must specify a | 319 | remote-path is specified, then remote-path must specify a |
319 | directory. | 320 | directory. |
320 | 321 | ||
322 | If the -a flag is specified, then attempt to resume partial | ||
323 | transfers of existing files. Note that resumption assumes that | ||
324 | any partial copy of the remote file matches the local copy. If | ||
325 | the local file contents differ from the remote local copy then | ||
326 | the resultant file is likely to be corrupt. | ||
327 | |||
321 | If the -f flag is specified, then a request will be sent to the | 328 | If the -f flag is specified, then a request will be sent to the |
322 | server to call fsync(2) after the file has been transferred. | 329 | server to call fsync(2) after the file has been transferred. |
323 | Note that this is only supported by servers that implement the | 330 | Note that this is only supported by servers that implement the |
@@ -338,6 +345,10 @@ INTERACTIVE COMMANDS | |||
338 | Resume download of remote-path. Equivalent to get with the -a | 345 | Resume download of remote-path. Equivalent to get with the -a |
339 | flag set. | 346 | flag set. |
340 | 347 | ||
348 | reput [-Ppr] [local-path] remote-path | ||
349 | Resume upload of [local-path]. Equivalent to put with the -a | ||
350 | flag set. | ||
351 | |||
341 | rename oldpath newpath | 352 | rename oldpath newpath |
342 | Rename remote file from oldpath to newpath. | 353 | Rename remote file from oldpath to newpath. |
343 | 354 | ||
@@ -367,4 +378,4 @@ SEE ALSO | |||
367 | T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- | 378 | T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- |
368 | filexfer-00.txt, January 2001, work in progress material. | 379 | filexfer-00.txt, January 2001, work in progress material. |
369 | 380 | ||
370 | OpenBSD 5.5 October 20, 2013 OpenBSD 5.5 | 381 | OpenBSD 5.6 April 22, 2014 OpenBSD 5.6 |
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: sftp.1,v 1.97 2013/10/20 09:51:26 djm Exp $ | 1 | .\" $OpenBSD: sftp.1,v 1.99 2014/04/22 14:16:30 jmc Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 2001 Damien Miller. All rights reserved. | 3 | .\" Copyright (c) 2001 Damien Miller. All rights reserved. |
4 | .\" | 4 | .\" |
@@ -22,7 +22,7 @@ | |||
22 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 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. | 23 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | .\" | 24 | .\" |
25 | .Dd $Mdocdate: October 20 2013 $ | 25 | .Dd $Mdocdate: April 22 2014 $ |
26 | .Dt SFTP 1 | 26 | .Dt SFTP 1 |
27 | .Os | 27 | .Os |
28 | .Sh NAME | 28 | .Sh NAME |
@@ -108,10 +108,10 @@ Forces | |||
108 | .Nm | 108 | .Nm |
109 | to use IPv6 addresses only. | 109 | to use IPv6 addresses only. |
110 | .It Fl a | 110 | .It Fl a |
111 | Attempt to continue interrupted downloads rather than overwriting existing | 111 | Attempt to continue interrupted transfers rather than overwriting |
112 | partial or complete copies of files. | 112 | existing partial or complete copies of files. |
113 | If the remote file contents differ from the partial local copy then the | 113 | If the partial contents differ from those being transferred, |
114 | resultant file is likely to be corrupt. | 114 | then the resultant file is likely to be corrupt. |
115 | .It Fl B Ar buffer_size | 115 | .It Fl B Ar buffer_size |
116 | Specify the size of the buffer that | 116 | Specify the size of the buffer that |
117 | .Nm | 117 | .Nm |
@@ -134,7 +134,7 @@ may be used to indicate standard input. | |||
134 | .Nm | 134 | .Nm |
135 | will abort if any of the following | 135 | will abort if any of the following |
136 | commands fail: | 136 | commands fail: |
137 | .Ic get , put , reget , rename , ln , | 137 | .Ic get , put , reget , reput, rename , ln , |
138 | .Ic rm , mkdir , chdir , ls , | 138 | .Ic rm , mkdir , chdir , ls , |
139 | .Ic lchdir , chmod , chown , | 139 | .Ic lchdir , chmod , chown , |
140 | .Ic chgrp , lpwd , df , symlink , | 140 | .Ic chgrp , lpwd , df , symlink , |
@@ -495,7 +495,7 @@ Create remote directory specified by | |||
495 | .It Ic progress | 495 | .It Ic progress |
496 | Toggle display of progress meter. | 496 | Toggle display of progress meter. |
497 | .It Xo Ic put | 497 | .It Xo Ic put |
498 | .Op Fl fPpr | 498 | .Op Fl afPpr |
499 | .Ar local-path | 499 | .Ar local-path |
500 | .Op Ar remote-path | 500 | .Op Ar remote-path |
501 | .Xc | 501 | .Xc |
@@ -515,6 +515,15 @@ is specified, then | |||
515 | must specify a directory. | 515 | must specify a directory. |
516 | .Pp | 516 | .Pp |
517 | If the | 517 | If the |
518 | .Fl a | ||
519 | flag is specified, then attempt to resume partial | ||
520 | transfers of existing files. | ||
521 | Note that resumption assumes that any partial copy of the remote file | ||
522 | matches the local copy. | ||
523 | If the local file contents differ from the remote local copy then | ||
524 | the resultant file is likely to be corrupt. | ||
525 | .Pp | ||
526 | If the | ||
518 | .Fl f | 527 | .Fl f |
519 | flag is specified, then a request will be sent to the server to call | 528 | flag is specified, then a request will be sent to the server to call |
520 | .Xr fsync 2 | 529 | .Xr fsync 2 |
@@ -552,6 +561,18 @@ Equivalent to | |||
552 | with the | 561 | with the |
553 | .Fl a | 562 | .Fl a |
554 | flag set. | 563 | flag set. |
564 | .It Xo Ic reput | ||
565 | .Op Fl Ppr | ||
566 | .Op Ar local-path | ||
567 | .Ar remote-path | ||
568 | .Xc | ||
569 | Resume upload of | ||
570 | .Op Ar local-path . | ||
571 | Equivalent to | ||
572 | .Ic put | ||
573 | with the | ||
574 | .Fl a | ||
575 | flag set. | ||
555 | .It Ic rename Ar oldpath Ar newpath | 576 | .It Ic rename Ar oldpath Ar newpath |
556 | Rename remote file from | 577 | Rename remote file from |
557 | .Ar oldpath | 578 | .Ar oldpath |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp.c,v 1.158 2013/11/20 20:54:10 deraadt Exp $ */ | 1 | /* $OpenBSD: sftp.c,v 1.164 2014/07/09 01:45:10 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -88,7 +88,7 @@ int showprogress = 1; | |||
88 | /* When this option is set, we always recursively download/upload directories */ | 88 | /* When this option is set, we always recursively download/upload directories */ |
89 | int global_rflag = 0; | 89 | int global_rflag = 0; |
90 | 90 | ||
91 | /* When this option is set, we resume download if possible */ | 91 | /* When this option is set, we resume download or upload if possible */ |
92 | int global_aflag = 0; | 92 | int global_aflag = 0; |
93 | 93 | ||
94 | /* When this option is set, the file transfers will always preserve times */ | 94 | /* When this option is set, the file transfers will always preserve times */ |
@@ -151,14 +151,15 @@ enum sftp_command { | |||
151 | I_PUT, | 151 | I_PUT, |
152 | I_PWD, | 152 | I_PWD, |
153 | I_QUIT, | 153 | I_QUIT, |
154 | I_REGET, | ||
154 | I_RENAME, | 155 | I_RENAME, |
156 | I_REPUT, | ||
155 | I_RM, | 157 | I_RM, |
156 | I_RMDIR, | 158 | I_RMDIR, |
157 | I_SHELL, | 159 | I_SHELL, |
158 | I_SYMLINK, | 160 | I_SYMLINK, |
159 | I_VERSION, | 161 | I_VERSION, |
160 | I_PROGRESS, | 162 | I_PROGRESS, |
161 | I_REGET, | ||
162 | }; | 163 | }; |
163 | 164 | ||
164 | struct CMD { | 165 | struct CMD { |
@@ -201,6 +202,7 @@ static const struct CMD cmds[] = { | |||
201 | { "quit", I_QUIT, NOARGS }, | 202 | { "quit", I_QUIT, NOARGS }, |
202 | { "reget", I_REGET, REMOTE }, | 203 | { "reget", I_REGET, REMOTE }, |
203 | { "rename", I_RENAME, REMOTE }, | 204 | { "rename", I_RENAME, REMOTE }, |
205 | { "reput", I_REPUT, LOCAL }, | ||
204 | { "rm", I_RM, REMOTE }, | 206 | { "rm", I_RM, REMOTE }, |
205 | { "rmdir", I_RMDIR, REMOTE }, | 207 | { "rmdir", I_RMDIR, REMOTE }, |
206 | { "symlink", I_SYMLINK, REMOTE }, | 208 | { "symlink", I_SYMLINK, REMOTE }, |
@@ -250,6 +252,7 @@ help(void) | |||
250 | "exit Quit sftp\n" | 252 | "exit Quit sftp\n" |
251 | "get [-Ppr] remote [local] Download file\n" | 253 | "get [-Ppr] remote [local] Download file\n" |
252 | "reget remote [local] Resume download file\n" | 254 | "reget remote [local] Resume download file\n" |
255 | "reput [local] remote Resume upload file\n" | ||
253 | "help Display this help text\n" | 256 | "help Display this help text\n" |
254 | "lcd path Change local directory to 'path'\n" | 257 | "lcd path Change local directory to 'path'\n" |
255 | "lls [ls-options [path]] Display local directory listing\n" | 258 | "lls [ls-options [path]] Display local directory listing\n" |
@@ -586,15 +589,19 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, | |||
586 | char *abs_dst = NULL; | 589 | char *abs_dst = NULL; |
587 | glob_t g; | 590 | glob_t g; |
588 | char *filename, *tmp=NULL; | 591 | char *filename, *tmp=NULL; |
589 | int i, err = 0; | 592 | int i, r, err = 0; |
590 | 593 | ||
591 | abs_src = xstrdup(src); | 594 | abs_src = xstrdup(src); |
592 | abs_src = make_absolute(abs_src, pwd); | 595 | abs_src = make_absolute(abs_src, pwd); |
593 | memset(&g, 0, sizeof(g)); | 596 | memset(&g, 0, sizeof(g)); |
594 | 597 | ||
595 | debug3("Looking up %s", abs_src); | 598 | debug3("Looking up %s", abs_src); |
596 | if (remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) { | 599 | if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) { |
597 | error("File \"%s\" not found.", abs_src); | 600 | if (r == GLOB_NOSPACE) { |
601 | error("Too many matches for \"%s\".", abs_src); | ||
602 | } else { | ||
603 | error("File \"%s\" not found.", abs_src); | ||
604 | } | ||
598 | err = -1; | 605 | err = -1; |
599 | goto out; | 606 | goto out; |
600 | } | 607 | } |
@@ -660,7 +667,7 @@ out: | |||
660 | 667 | ||
661 | static int | 668 | static int |
662 | process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, | 669 | process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, |
663 | int pflag, int rflag, int fflag) | 670 | int pflag, int rflag, int resume, int fflag) |
664 | { | 671 | { |
665 | char *tmp_dst = NULL; | 672 | char *tmp_dst = NULL; |
666 | char *abs_dst = NULL; | 673 | char *abs_dst = NULL; |
@@ -723,16 +730,20 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, | |||
723 | } | 730 | } |
724 | free(tmp); | 731 | free(tmp); |
725 | 732 | ||
726 | if (!quiet) | 733 | resume |= global_aflag; |
734 | if (!quiet && resume) | ||
735 | printf("Resuming upload of %s to %s\n", g.gl_pathv[i], | ||
736 | abs_dst); | ||
737 | else if (!quiet && !resume) | ||
727 | printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); | 738 | printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); |
728 | if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { | 739 | if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { |
729 | if (upload_dir(conn, g.gl_pathv[i], abs_dst, | 740 | if (upload_dir(conn, g.gl_pathv[i], abs_dst, |
730 | pflag || global_pflag, 1, | 741 | pflag || global_pflag, 1, resume, |
731 | fflag || global_fflag) == -1) | 742 | fflag || global_fflag) == -1) |
732 | err = -1; | 743 | err = -1; |
733 | } else { | 744 | } else { |
734 | if (do_upload(conn, g.gl_pathv[i], abs_dst, | 745 | if (do_upload(conn, g.gl_pathv[i], abs_dst, |
735 | pflag || global_pflag, | 746 | pflag || global_pflag, resume, |
736 | fflag || global_fflag) == -1) | 747 | fflag || global_fflag) == -1) |
737 | err = -1; | 748 | err = -1; |
738 | } | 749 | } |
@@ -855,19 +866,23 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, | |||
855 | { | 866 | { |
856 | char *fname, *lname; | 867 | char *fname, *lname; |
857 | glob_t g; | 868 | glob_t g; |
858 | int err; | 869 | int err, r; |
859 | struct winsize ws; | 870 | struct winsize ws; |
860 | u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; | 871 | u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; |
861 | 872 | ||
862 | memset(&g, 0, sizeof(g)); | 873 | memset(&g, 0, sizeof(g)); |
863 | 874 | ||
864 | if (remote_glob(conn, path, | 875 | if ((r = remote_glob(conn, path, |
865 | GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT, | 876 | GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT, |
866 | NULL, &g) || | 877 | NULL, &g)) != 0 || |
867 | (g.gl_pathc && !g.gl_matchc)) { | 878 | (g.gl_pathc && !g.gl_matchc)) { |
868 | if (g.gl_pathc) | 879 | if (g.gl_pathc) |
869 | globfree(&g); | 880 | globfree(&g); |
870 | error("Can't ls: \"%s\" not found", path); | 881 | if (r == GLOB_NOSPACE) { |
882 | error("Can't ls: Too many matches for \"%s\"", path); | ||
883 | } else { | ||
884 | error("Can't ls: \"%s\" not found", path); | ||
885 | } | ||
871 | return -1; | 886 | return -1; |
872 | } | 887 | } |
873 | 888 | ||
@@ -1186,8 +1201,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, | |||
1186 | } | 1201 | } |
1187 | 1202 | ||
1188 | static int | 1203 | static int |
1189 | parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, | 1204 | parse_args(const char **cpp, int *ignore_errors, int *aflag, |
1190 | int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag, | 1205 | int *fflag, int *hflag, int *iflag, int *lflag, int *pflag, |
1206 | int *rflag, int *sflag, | ||
1191 | unsigned long *n_arg, char **path1, char **path2) | 1207 | unsigned long *n_arg, char **path1, char **path2) |
1192 | { | 1208 | { |
1193 | const char *cmd, *cp = *cpp; | 1209 | const char *cmd, *cp = *cpp; |
@@ -1239,6 +1255,7 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, | |||
1239 | switch (cmdnum) { | 1255 | switch (cmdnum) { |
1240 | case I_GET: | 1256 | case I_GET: |
1241 | case I_REGET: | 1257 | case I_REGET: |
1258 | case I_REPUT: | ||
1242 | case I_PUT: | 1259 | case I_PUT: |
1243 | if ((optidx = parse_getput_flags(cmd, argv, argc, | 1260 | if ((optidx = parse_getput_flags(cmd, argv, argc, |
1244 | aflag, fflag, pflag, rflag)) == -1) | 1261 | aflag, fflag, pflag, rflag)) == -1) |
@@ -1256,11 +1273,6 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, | |||
1256 | /* Destination is not globbed */ | 1273 | /* Destination is not globbed */ |
1257 | undo_glob_escape(*path2); | 1274 | undo_glob_escape(*path2); |
1258 | } | 1275 | } |
1259 | if (*aflag && cmdnum == I_PUT) { | ||
1260 | /* XXX implement resume for uploads */ | ||
1261 | error("Resume is not supported for uploads"); | ||
1262 | return -1; | ||
1263 | } | ||
1264 | break; | 1276 | break; |
1265 | case I_LINK: | 1277 | case I_LINK: |
1266 | if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) | 1278 | if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) |
@@ -1382,7 +1394,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1382 | int err_abort) | 1394 | int err_abort) |
1383 | { | 1395 | { |
1384 | char *path1, *path2, *tmp; | 1396 | char *path1, *path2, *tmp; |
1385 | int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0; | 1397 | int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, |
1398 | iflag = 0; | ||
1386 | int lflag = 0, pflag = 0, rflag = 0, sflag = 0; | 1399 | int lflag = 0, pflag = 0, rflag = 0, sflag = 0; |
1387 | int cmdnum, i; | 1400 | int cmdnum, i; |
1388 | unsigned long n_arg = 0; | 1401 | unsigned long n_arg = 0; |
@@ -1415,9 +1428,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1415 | err = process_get(conn, path1, path2, *pwd, pflag, | 1428 | err = process_get(conn, path1, path2, *pwd, pflag, |
1416 | rflag, aflag, fflag); | 1429 | rflag, aflag, fflag); |
1417 | break; | 1430 | break; |
1431 | case I_REPUT: | ||
1432 | aflag = 1; | ||
1433 | /* FALLTHROUGH */ | ||
1418 | case I_PUT: | 1434 | case I_PUT: |
1419 | err = process_put(conn, path1, path2, *pwd, pflag, | 1435 | err = process_put(conn, path1, path2, *pwd, pflag, |
1420 | rflag, fflag); | 1436 | rflag, aflag, fflag); |
1421 | break; | 1437 | break; |
1422 | case I_RENAME: | 1438 | case I_RENAME: |
1423 | path1 = make_absolute(path1, *pwd); | 1439 | path1 = make_absolute(path1, *pwd); |
@@ -1834,6 +1850,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, | |||
1834 | pwdlen = tmplen + 1; /* track last seen '/' */ | 1850 | pwdlen = tmplen + 1; /* track last seen '/' */ |
1835 | } | 1851 | } |
1836 | free(tmp); | 1852 | free(tmp); |
1853 | tmp = NULL; | ||
1837 | 1854 | ||
1838 | if (g.gl_matchc == 0) | 1855 | if (g.gl_matchc == 0) |
1839 | goto out; | 1856 | goto out; |
@@ -1841,7 +1858,6 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, | |||
1841 | if (g.gl_matchc > 1) | 1858 | if (g.gl_matchc > 1) |
1842 | complete_display(g.gl_pathv, pwdlen); | 1859 | complete_display(g.gl_pathv, pwdlen); |
1843 | 1860 | ||
1844 | tmp = NULL; | ||
1845 | /* Don't try to extend globs */ | 1861 | /* Don't try to extend globs */ |
1846 | if (file == NULL || hadglob) | 1862 | if (file == NULL || hadglob) |
1847 | goto out; | 1863 | goto out; |
@@ -1904,7 +1920,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, | |||
1904 | lf = el_line(el); | 1920 | lf = el_line(el); |
1905 | if (g.gl_matchc == 1) { | 1921 | if (g.gl_matchc == 1) { |
1906 | i = 0; | 1922 | i = 0; |
1907 | if (!terminated) | 1923 | if (!terminated && quote != '\0') |
1908 | ins[i++] = quote; | 1924 | ins[i++] = quote; |
1909 | if (*(lf->cursor - 1) != '/' && | 1925 | if (*(lf->cursor - 1) != '/' && |
1910 | (lastarg || *(lf->cursor) != ' ')) | 1926 | (lastarg || *(lf->cursor) != ' ')) |
@@ -1,4 +1,4 @@ | |||
1 | SSH-ADD(1) OpenBSD Reference Manual SSH-ADD(1) | 1 | SSH-ADD(1) General Commands Manual SSH-ADD(1) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh-add - adds private key identities to the authentication agent | 4 | ssh-add - adds private key identities to the authentication agent |
@@ -120,4 +120,4 @@ AUTHORS | |||
120 | created OpenSSH. Markus Friedl contributed the support for SSH protocol | 120 | created OpenSSH. Markus Friedl contributed the support for SSH protocol |
121 | versions 1.5 and 2.0. | 121 | versions 1.5 and 2.0. |
122 | 122 | ||
123 | OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 | 123 | OpenBSD 5.6 December 7, 2013 OpenBSD 5.6 |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-add.c,v 1.109 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: ssh-add.c,v 1.113 2014/07/09 14:15:56 benno Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -62,6 +62,7 @@ | |||
62 | #include "authfile.h" | 62 | #include "authfile.h" |
63 | #include "pathnames.h" | 63 | #include "pathnames.h" |
64 | #include "misc.h" | 64 | #include "misc.h" |
65 | #include "ssherr.h" | ||
65 | 66 | ||
66 | /* argv0 */ | 67 | /* argv0 */ |
67 | extern char *__progname; | 68 | extern char *__progname; |
@@ -170,7 +171,7 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only) | |||
170 | Key *private, *cert; | 171 | Key *private, *cert; |
171 | char *comment = NULL; | 172 | char *comment = NULL; |
172 | char msg[1024], *certpath = NULL; | 173 | char msg[1024], *certpath = NULL; |
173 | int fd, perms_ok, ret = -1; | 174 | int r, fd, perms_ok, ret = -1; |
174 | Buffer keyblob; | 175 | Buffer keyblob; |
175 | 176 | ||
176 | if (strcmp(filename, "-") == 0) { | 177 | if (strcmp(filename, "-") == 0) { |
@@ -201,12 +202,18 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only) | |||
201 | close(fd); | 202 | close(fd); |
202 | 203 | ||
203 | /* At first, try empty passphrase */ | 204 | /* At first, try empty passphrase */ |
204 | private = key_parse_private(&keyblob, filename, "", &comment); | 205 | if ((r = sshkey_parse_private_fileblob(&keyblob, "", filename, |
206 | &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) | ||
207 | fatal("Cannot parse %s: %s", filename, ssh_err(r)); | ||
208 | /* try last */ | ||
209 | if (private == NULL && pass != NULL) { | ||
210 | if ((r = sshkey_parse_private_fileblob(&keyblob, pass, filename, | ||
211 | &private, &comment)) != 0 && | ||
212 | r != SSH_ERR_KEY_WRONG_PASSPHRASE) | ||
213 | fatal("Cannot parse %s: %s", filename, ssh_err(r)); | ||
214 | } | ||
205 | if (comment == NULL) | 215 | if (comment == NULL) |
206 | comment = xstrdup(filename); | 216 | comment = xstrdup(filename); |
207 | /* try last */ | ||
208 | if (private == NULL && pass != NULL) | ||
209 | private = key_parse_private(&keyblob, filename, pass, NULL); | ||
210 | if (private == NULL) { | 217 | if (private == NULL) { |
211 | /* clear passphrase since it did not work */ | 218 | /* clear passphrase since it did not work */ |
212 | clear_pass(); | 219 | clear_pass(); |
@@ -220,8 +227,11 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only) | |||
220 | buffer_free(&keyblob); | 227 | buffer_free(&keyblob); |
221 | return -1; | 228 | return -1; |
222 | } | 229 | } |
223 | private = key_parse_private(&keyblob, filename, pass, | 230 | if ((r = sshkey_parse_private_fileblob(&keyblob, |
224 | &comment); | 231 | pass, filename, &private, NULL)) != 0 && |
232 | r != SSH_ERR_KEY_WRONG_PASSPHRASE) | ||
233 | fatal("Cannot parse %s: %s", | ||
234 | filename, ssh_err(r)); | ||
225 | if (private != NULL) | 235 | if (private != NULL) |
226 | break; | 236 | break; |
227 | clear_pass(); | 237 | clear_pass(); |
@@ -427,6 +437,8 @@ main(int argc, char **argv) | |||
427 | 437 | ||
428 | OpenSSL_add_all_algorithms(); | 438 | OpenSSL_add_all_algorithms(); |
429 | 439 | ||
440 | setlinebuf(stdout); | ||
441 | |||
430 | /* At first, get a connection to the authentication agent. */ | 442 | /* At first, get a connection to the authentication agent. */ |
431 | ac = ssh_get_authentication_connection(); | 443 | ac = ssh_get_authentication_connection(); |
432 | if (ac == NULL) { | 444 | if (ac == NULL) { |
diff --git a/ssh-agent.0 b/ssh-agent.0 index c11523db3..cac40e048 100644 --- a/ssh-agent.0 +++ b/ssh-agent.0 | |||
@@ -1,4 +1,4 @@ | |||
1 | SSH-AGENT(1) OpenBSD Reference Manual SSH-AGENT(1) | 1 | SSH-AGENT(1) General Commands Manual SSH-AGENT(1) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh-agent - authentication agent | 4 | ssh-agent - authentication agent |
@@ -9,12 +9,18 @@ SYNOPSIS | |||
9 | 9 | ||
10 | DESCRIPTION | 10 | DESCRIPTION |
11 | ssh-agent is a program to hold private keys used for public key | 11 | ssh-agent is a program to hold private keys used for public key |
12 | authentication (RSA, DSA, ECDSA, ED25519). The idea is that ssh-agent is | 12 | authentication (RSA, DSA, ECDSA, ED25519). ssh-agent is usually started |
13 | started in the beginning of an X-session or a login session, and all | 13 | in the beginning of an X-session or a login session, and all other |
14 | other windows or programs are started as clients to the ssh-agent | 14 | windows or programs are started as clients to the ssh-agent program. |
15 | program. Through use of environment variables the agent can be located | 15 | Through use of environment variables the agent can be located and |
16 | and automatically used for authentication when logging in to other | 16 | automatically used for authentication when logging in to other machines |
17 | machines using ssh(1). | 17 | using ssh(1). |
18 | |||
19 | The agent initially does not have any private keys. Keys are added using | ||
20 | ssh-add(1). Multiple identities may be stored in ssh-agent concurrently | ||
21 | and ssh(1) will automatically use them if present. ssh-add(1) is also | ||
22 | used to remove keys from ssh-agent and to query the keys that are held in | ||
23 | one. | ||
18 | 24 | ||
19 | The options are as follows: | 25 | The options are as follows: |
20 | 26 | ||
@@ -44,17 +50,6 @@ DESCRIPTION | |||
44 | If a commandline is given, this is executed as a subprocess of the agent. | 50 | If a commandline is given, this is executed as a subprocess of the agent. |
45 | When the command dies, so does the agent. | 51 | When the command dies, so does the agent. |
46 | 52 | ||
47 | The agent initially does not have any private keys. Keys are added using | ||
48 | ssh-add(1). When executed without arguments, ssh-add(1) adds the files | ||
49 | ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and | ||
50 | ~/.ssh/identity. If the identity has a passphrase, ssh-add(1) asks for | ||
51 | the passphrase on the terminal if it has one or from a small X11 program | ||
52 | if running under X11. If neither of these is the case then the | ||
53 | authentication will fail. It then sends the identity to the agent. | ||
54 | Several identities can be stored in the agent; the agent can | ||
55 | automatically use any of these identities. ssh-add -l displays the | ||
56 | identities currently held by the agent. | ||
57 | |||
58 | The idea is that the agent is run in the user's local PC, laptop, or | 53 | The idea is that the agent is run in the user's local PC, laptop, or |
59 | terminal. Authentication data need not be stored on any other machine, | 54 | terminal. Authentication data need not be stored on any other machine, |
60 | and authentication passphrases never go over the network. However, the | 55 | and authentication passphrases never go over the network. However, the |
@@ -89,26 +84,6 @@ DESCRIPTION | |||
89 | terminates. | 84 | terminates. |
90 | 85 | ||
91 | FILES | 86 | FILES |
92 | ~/.ssh/identity | ||
93 | Contains the protocol version 1 RSA authentication identity of | ||
94 | the user. | ||
95 | |||
96 | ~/.ssh/id_dsa | ||
97 | Contains the protocol version 2 DSA authentication identity of | ||
98 | the user. | ||
99 | |||
100 | ~/.ssh/id_ecdsa | ||
101 | Contains the protocol version 2 ECDSA authentication identity of | ||
102 | the user. | ||
103 | |||
104 | ~/.ssh/id_ed25519 | ||
105 | Contains the protocol version 2 ED25519 authentication identity | ||
106 | of the user. | ||
107 | |||
108 | ~/.ssh/id_rsa | ||
109 | Contains the protocol version 2 RSA authentication identity of | ||
110 | the user. | ||
111 | |||
112 | $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid> | 87 | $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid> |
113 | UNIX-domain sockets used to contain the connection to the | 88 | UNIX-domain sockets used to contain the connection to the |
114 | authentication agent. These sockets should only be readable by | 89 | authentication agent. These sockets should only be readable by |
@@ -125,4 +100,4 @@ AUTHORS | |||
125 | created OpenSSH. Markus Friedl contributed the support for SSH protocol | 100 | created OpenSSH. Markus Friedl contributed the support for SSH protocol |
126 | versions 1.5 and 2.0. | 101 | versions 1.5 and 2.0. |
127 | 102 | ||
128 | OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 | 103 | OpenBSD 5.6 April 16, 2014 OpenBSD 5.6 |
diff --git a/ssh-agent.1 b/ssh-agent.1 index 38fd540bd..f2c408070 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-agent.1,v 1.54 2013/12/07 11:58:46 naddy Exp $ | 1 | .\" $OpenBSD: ssh-agent.1,v 1.55 2014/04/16 23:28:12 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -34,7 +34,7 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .Dd $Mdocdate: December 7 2013 $ | 37 | .Dd $Mdocdate: April 16 2014 $ |
38 | .Dt SSH-AGENT 1 | 38 | .Dt SSH-AGENT 1 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -54,9 +54,8 @@ | |||
54 | .Nm | 54 | .Nm |
55 | is a program to hold private keys used for public key authentication | 55 | is a program to hold private keys used for public key authentication |
56 | (RSA, DSA, ECDSA, ED25519). | 56 | (RSA, DSA, ECDSA, ED25519). |
57 | The idea is that | ||
58 | .Nm | 57 | .Nm |
59 | is started in the beginning of an X-session or a login session, and | 58 | is usually started in the beginning of an X-session or a login session, and |
60 | all other windows or programs are started as clients to the ssh-agent | 59 | all other windows or programs are started as clients to the ssh-agent |
61 | program. | 60 | program. |
62 | Through use of environment variables the agent can be located | 61 | Through use of environment variables the agent can be located |
@@ -64,6 +63,19 @@ and automatically used for authentication when logging in to other | |||
64 | machines using | 63 | machines using |
65 | .Xr ssh 1 . | 64 | .Xr ssh 1 . |
66 | .Pp | 65 | .Pp |
66 | The agent initially does not have any private keys. | ||
67 | Keys are added using | ||
68 | .Xr ssh-add 1 . | ||
69 | Multiple identities may be stored in | ||
70 | .Nm | ||
71 | concurrently and | ||
72 | .Xr ssh 1 | ||
73 | will automatically use them if present. | ||
74 | .Xr ssh-add 1 | ||
75 | is also used to remove keys from | ||
76 | .Nm | ||
77 | and to query the keys that are held in one. | ||
78 | .Pp | ||
67 | The options are as follows: | 79 | The options are as follows: |
68 | .Bl -tag -width Ds | 80 | .Bl -tag -width Ds |
69 | .It Fl a Ar bind_address | 81 | .It Fl a Ar bind_address |
@@ -107,29 +119,6 @@ Without this option the default maximum lifetime is forever. | |||
107 | If a commandline is given, this is executed as a subprocess of the agent. | 119 | If a commandline is given, this is executed as a subprocess of the agent. |
108 | When the command dies, so does the agent. | 120 | When the command dies, so does the agent. |
109 | .Pp | 121 | .Pp |
110 | The agent initially does not have any private keys. | ||
111 | Keys are added using | ||
112 | .Xr ssh-add 1 . | ||
113 | When executed without arguments, | ||
114 | .Xr ssh-add 1 | ||
115 | adds the files | ||
116 | .Pa ~/.ssh/id_rsa , | ||
117 | .Pa ~/.ssh/id_dsa , | ||
118 | .Pa ~/.ssh/id_ecdsa , | ||
119 | .Pa ~/.ssh/id_ed25519 | ||
120 | and | ||
121 | .Pa ~/.ssh/identity . | ||
122 | If the identity has a passphrase, | ||
123 | .Xr ssh-add 1 | ||
124 | asks for the passphrase on the terminal if it has one or from a small X11 | ||
125 | program if running under X11. | ||
126 | If neither of these is the case then the authentication will fail. | ||
127 | It then sends the identity to the agent. | ||
128 | Several identities can be stored in the | ||
129 | agent; the agent can automatically use any of these identities. | ||
130 | .Ic ssh-add -l | ||
131 | displays the identities currently held by the agent. | ||
132 | .Pp | ||
133 | The idea is that the agent is run in the user's local PC, laptop, or | 122 | The idea is that the agent is run in the user's local PC, laptop, or |
134 | terminal. | 123 | terminal. |
135 | Authentication data need not be stored on any other | 124 | Authentication data need not be stored on any other |
@@ -200,16 +189,6 @@ If you need to set any of these environment variables, you will need to do | |||
200 | so in the program executed by ssh-agent. | 189 | so in the program executed by ssh-agent. |
201 | .Sh FILES | 190 | .Sh FILES |
202 | .Bl -tag -width Ds | 191 | .Bl -tag -width Ds |
203 | .It Pa ~/.ssh/identity | ||
204 | Contains the protocol version 1 RSA authentication identity of the user. | ||
205 | .It Pa ~/.ssh/id_dsa | ||
206 | Contains the protocol version 2 DSA authentication identity of the user. | ||
207 | .It Pa ~/.ssh/id_ecdsa | ||
208 | Contains the protocol version 2 ECDSA authentication identity of the user. | ||
209 | .It Pa ~/.ssh/id_ed25519 | ||
210 | Contains the protocol version 2 ED25519 authentication identity of the user. | ||
211 | .It Pa ~/.ssh/id_rsa | ||
212 | Contains the protocol version 2 RSA authentication identity of the user. | ||
213 | .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt | 192 | .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt |
214 | .Ux Ns -domain | 193 | .Ux Ns -domain |
215 | sockets used to contain the connection to the authentication agent. | 194 | sockets used to contain the connection to the authentication agent. |
diff --git a/ssh-agent.c b/ssh-agent.c index ba2461211..25f10c549 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.183 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.190 2014/07/25 21:22:03 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -49,8 +49,10 @@ | |||
49 | #endif | 49 | #endif |
50 | #include "openbsd-compat/sys-queue.h" | 50 | #include "openbsd-compat/sys-queue.h" |
51 | 51 | ||
52 | #ifdef WITH_OPENSSL | ||
52 | #include <openssl/evp.h> | 53 | #include <openssl/evp.h> |
53 | #include "openbsd-compat/openssl-compat.h" | 54 | #include "openbsd-compat/openssl-compat.h" |
55 | #endif | ||
54 | 56 | ||
55 | #include <errno.h> | 57 | #include <errno.h> |
56 | #include <fcntl.h> | 58 | #include <fcntl.h> |
@@ -124,6 +126,9 @@ int max_fd = 0; | |||
124 | pid_t parent_pid = -1; | 126 | pid_t parent_pid = -1; |
125 | time_t parent_alive_interval = 0; | 127 | time_t parent_alive_interval = 0; |
126 | 128 | ||
129 | /* pid of process for which cleanup_socket is applicable */ | ||
130 | pid_t cleanup_pid = 0; | ||
131 | |||
127 | /* pathname and directory for AUTH_SOCKET */ | 132 | /* pathname and directory for AUTH_SOCKET */ |
128 | char socket_name[MAXPATHLEN]; | 133 | char socket_name[MAXPATHLEN]; |
129 | char socket_dir[MAXPATHLEN]; | 134 | char socket_dir[MAXPATHLEN]; |
@@ -221,9 +226,11 @@ process_request_identities(SocketEntry *e, int version) | |||
221 | buffer_put_int(&msg, tab->nentries); | 226 | buffer_put_int(&msg, tab->nentries); |
222 | TAILQ_FOREACH(id, &tab->idlist, next) { | 227 | TAILQ_FOREACH(id, &tab->idlist, next) { |
223 | if (id->key->type == KEY_RSA1) { | 228 | if (id->key->type == KEY_RSA1) { |
229 | #ifdef WITH_SSH1 | ||
224 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); | 230 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); |
225 | buffer_put_bignum(&msg, id->key->rsa->e); | 231 | buffer_put_bignum(&msg, id->key->rsa->e); |
226 | buffer_put_bignum(&msg, id->key->rsa->n); | 232 | buffer_put_bignum(&msg, id->key->rsa->n); |
233 | #endif | ||
227 | } else { | 234 | } else { |
228 | u_char *blob; | 235 | u_char *blob; |
229 | u_int blen; | 236 | u_int blen; |
@@ -238,6 +245,7 @@ process_request_identities(SocketEntry *e, int version) | |||
238 | buffer_free(&msg); | 245 | buffer_free(&msg); |
239 | } | 246 | } |
240 | 247 | ||
248 | #ifdef WITH_SSH1 | ||
241 | /* ssh1 only */ | 249 | /* ssh1 only */ |
242 | static void | 250 | static void |
243 | process_authentication_challenge1(SocketEntry *e) | 251 | process_authentication_challenge1(SocketEntry *e) |
@@ -273,7 +281,7 @@ process_authentication_challenge1(SocketEntry *e) | |||
273 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { | 281 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { |
274 | Key *private = id->key; | 282 | Key *private = id->key; |
275 | /* Decrypt the challenge using the private key. */ | 283 | /* Decrypt the challenge using the private key. */ |
276 | if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) | 284 | if (rsa_private_decrypt(challenge, challenge, private->rsa) != 0) |
277 | goto failure; | 285 | goto failure; |
278 | 286 | ||
279 | /* The response is MD5 of decrypted challenge plus session id. */ | 287 | /* The response is MD5 of decrypted challenge plus session id. */ |
@@ -308,6 +316,7 @@ send: | |||
308 | BN_clear_free(challenge); | 316 | BN_clear_free(challenge); |
309 | buffer_free(&msg); | 317 | buffer_free(&msg); |
310 | } | 318 | } |
319 | #endif | ||
311 | 320 | ||
312 | /* ssh2 only */ | 321 | /* ssh2 only */ |
313 | static void | 322 | static void |
@@ -359,12 +368,16 @@ process_sign_request2(SocketEntry *e) | |||
359 | static void | 368 | static void |
360 | process_remove_identity(SocketEntry *e, int version) | 369 | process_remove_identity(SocketEntry *e, int version) |
361 | { | 370 | { |
362 | u_int blen, bits; | 371 | u_int blen; |
363 | int success = 0; | 372 | int success = 0; |
364 | Key *key = NULL; | 373 | Key *key = NULL; |
365 | u_char *blob; | 374 | u_char *blob; |
375 | #ifdef WITH_SSH1 | ||
376 | u_int bits; | ||
377 | #endif /* WITH_SSH1 */ | ||
366 | 378 | ||
367 | switch (version) { | 379 | switch (version) { |
380 | #ifdef WITH_SSH1 | ||
368 | case 1: | 381 | case 1: |
369 | key = key_new(KEY_RSA1); | 382 | key = key_new(KEY_RSA1); |
370 | bits = buffer_get_int(&e->request); | 383 | bits = buffer_get_int(&e->request); |
@@ -375,6 +388,7 @@ process_remove_identity(SocketEntry *e, int version) | |||
375 | logit("Warning: identity keysize mismatch: actual %u, announced %u", | 388 | logit("Warning: identity keysize mismatch: actual %u, announced %u", |
376 | key_size(key), bits); | 389 | key_size(key), bits); |
377 | break; | 390 | break; |
391 | #endif /* WITH_SSH1 */ | ||
378 | case 2: | 392 | case 2: |
379 | blob = buffer_get_string(&e->request, &blen); | 393 | blob = buffer_get_string(&e->request, &blen); |
380 | key = key_from_blob(blob, blen); | 394 | key = key_from_blob(blob, blen); |
@@ -471,6 +485,7 @@ process_add_identity(SocketEntry *e, int version) | |||
471 | Key *k = NULL; | 485 | Key *k = NULL; |
472 | 486 | ||
473 | switch (version) { | 487 | switch (version) { |
488 | #ifdef WITH_SSH1 | ||
474 | case 1: | 489 | case 1: |
475 | k = key_new_private(KEY_RSA1); | 490 | k = key_new_private(KEY_RSA1); |
476 | (void) buffer_get_int(&e->request); /* ignored */ | 491 | (void) buffer_get_int(&e->request); /* ignored */ |
@@ -484,7 +499,9 @@ process_add_identity(SocketEntry *e, int version) | |||
484 | buffer_get_bignum(&e->request, k->rsa->p); /* q */ | 499 | buffer_get_bignum(&e->request, k->rsa->p); /* q */ |
485 | 500 | ||
486 | /* Generate additional parameters */ | 501 | /* Generate additional parameters */ |
487 | rsa_generate_additional_parameters(k->rsa); | 502 | if (rsa_generate_additional_parameters(k->rsa) != 0) |
503 | fatal("%s: rsa_generate_additional_parameters " | ||
504 | "error", __func__); | ||
488 | 505 | ||
489 | /* enable blinding */ | 506 | /* enable blinding */ |
490 | if (RSA_blinding_on(k->rsa, NULL) != 1) { | 507 | if (RSA_blinding_on(k->rsa, NULL) != 1) { |
@@ -493,6 +510,7 @@ process_add_identity(SocketEntry *e, int version) | |||
493 | goto send; | 510 | goto send; |
494 | } | 511 | } |
495 | break; | 512 | break; |
513 | #endif /* WITH_SSH1 */ | ||
496 | case 2: | 514 | case 2: |
497 | k = key_private_deserialize(&e->request); | 515 | k = key_private_deserialize(&e->request); |
498 | if (k == NULL) { | 516 | if (k == NULL) { |
@@ -501,11 +519,10 @@ process_add_identity(SocketEntry *e, int version) | |||
501 | } | 519 | } |
502 | break; | 520 | break; |
503 | } | 521 | } |
504 | comment = buffer_get_string(&e->request, NULL); | 522 | if (k == NULL) |
505 | if (k == NULL) { | ||
506 | free(comment); | ||
507 | goto send; | 523 | goto send; |
508 | } | 524 | comment = buffer_get_string(&e->request, NULL); |
525 | |||
509 | while (buffer_len(&e->request)) { | 526 | while (buffer_len(&e->request)) { |
510 | switch ((type = buffer_get_char(&e->request))) { | 527 | switch ((type = buffer_get_char(&e->request))) { |
511 | case SSH_AGENT_CONSTRAIN_LIFETIME: | 528 | case SSH_AGENT_CONSTRAIN_LIFETIME: |
@@ -733,6 +750,7 @@ process_message(SocketEntry *e) | |||
733 | case SSH_AGENTC_UNLOCK: | 750 | case SSH_AGENTC_UNLOCK: |
734 | process_lock_agent(e, type == SSH_AGENTC_LOCK); | 751 | process_lock_agent(e, type == SSH_AGENTC_LOCK); |
735 | break; | 752 | break; |
753 | #ifdef WITH_SSH1 | ||
736 | /* ssh1 */ | 754 | /* ssh1 */ |
737 | case SSH_AGENTC_RSA_CHALLENGE: | 755 | case SSH_AGENTC_RSA_CHALLENGE: |
738 | process_authentication_challenge1(e); | 756 | process_authentication_challenge1(e); |
@@ -750,6 +768,7 @@ process_message(SocketEntry *e) | |||
750 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: | 768 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: |
751 | process_remove_all_identities(e, 1); | 769 | process_remove_all_identities(e, 1); |
752 | break; | 770 | break; |
771 | #endif | ||
753 | /* ssh2 */ | 772 | /* ssh2 */ |
754 | case SSH2_AGENTC_SIGN_REQUEST: | 773 | case SSH2_AGENTC_SIGN_REQUEST: |
755 | process_sign_request2(e); | 774 | process_sign_request2(e); |
@@ -949,6 +968,7 @@ after_select(fd_set *readset, fd_set *writeset) | |||
949 | break; | 968 | break; |
950 | } | 969 | } |
951 | buffer_append(&sockets[i].input, buf, len); | 970 | buffer_append(&sockets[i].input, buf, len); |
971 | explicit_bzero(buf, sizeof(buf)); | ||
952 | process_message(&sockets[i]); | 972 | process_message(&sockets[i]); |
953 | } | 973 | } |
954 | break; | 974 | break; |
@@ -960,6 +980,9 @@ after_select(fd_set *readset, fd_set *writeset) | |||
960 | static void | 980 | static void |
961 | cleanup_socket(void) | 981 | cleanup_socket(void) |
962 | { | 982 | { |
983 | if (cleanup_pid != 0 && getpid() != cleanup_pid) | ||
984 | return; | ||
985 | debug("%s: cleanup", __func__); | ||
963 | if (socket_name[0]) | 986 | if (socket_name[0]) |
964 | unlink(socket_name); | 987 | unlink(socket_name); |
965 | if (socket_dir[0]) | 988 | if (socket_dir[0]) |
@@ -1001,15 +1024,10 @@ check_parent_exists(void) | |||
1001 | static void | 1024 | static void |
1002 | usage(void) | 1025 | usage(void) |
1003 | { | 1026 | { |
1004 | fprintf(stderr, "usage: %s [options] [command [arg ...]]\n", | 1027 | fprintf(stderr, |
1005 | __progname); | 1028 | "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n" |
1006 | fprintf(stderr, "Options:\n"); | 1029 | " [command [arg ...]]\n" |
1007 | fprintf(stderr, " -c Generate C-shell commands on stdout.\n"); | 1030 | " ssh-agent [-c | -s] -k\n"); |
1008 | fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n"); | ||
1009 | fprintf(stderr, " -k Kill the current agent.\n"); | ||
1010 | fprintf(stderr, " -d Debug mode.\n"); | ||
1011 | fprintf(stderr, " -a socket Bind agent socket to given name.\n"); | ||
1012 | fprintf(stderr, " -t life Default identity lifetime (seconds).\n"); | ||
1013 | exit(1); | 1031 | exit(1); |
1014 | } | 1032 | } |
1015 | 1033 | ||
@@ -1021,17 +1039,16 @@ main(int ac, char **av) | |||
1021 | u_int nalloc; | 1039 | u_int nalloc; |
1022 | char *shell, *format, *pidstr, *agentsocket = NULL; | 1040 | char *shell, *format, *pidstr, *agentsocket = NULL; |
1023 | fd_set *readsetp = NULL, *writesetp = NULL; | 1041 | fd_set *readsetp = NULL, *writesetp = NULL; |
1024 | struct sockaddr_un sunaddr; | ||
1025 | #ifdef HAVE_SETRLIMIT | 1042 | #ifdef HAVE_SETRLIMIT |
1026 | struct rlimit rlim; | 1043 | struct rlimit rlim; |
1027 | #endif | 1044 | #endif |
1028 | int prev_mask; | ||
1029 | extern int optind; | 1045 | extern int optind; |
1030 | extern char *optarg; | 1046 | extern char *optarg; |
1031 | pid_t pid; | 1047 | pid_t pid; |
1032 | char pidstrbuf[1 + 3 * sizeof pid]; | 1048 | char pidstrbuf[1 + 3 * sizeof pid]; |
1033 | struct timeval *tvp = NULL; | 1049 | struct timeval *tvp = NULL; |
1034 | size_t len; | 1050 | size_t len; |
1051 | mode_t prev_mask; | ||
1035 | 1052 | ||
1036 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 1053 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
1037 | sanitise_stdfd(); | 1054 | sanitise_stdfd(); |
@@ -1045,7 +1062,9 @@ main(int ac, char **av) | |||
1045 | prctl(PR_SET_DUMPABLE, 0); | 1062 | prctl(PR_SET_DUMPABLE, 0); |
1046 | #endif | 1063 | #endif |
1047 | 1064 | ||
1065 | #ifdef WITH_OPENSSL | ||
1048 | OpenSSL_add_all_algorithms(); | 1066 | OpenSSL_add_all_algorithms(); |
1067 | #endif | ||
1049 | 1068 | ||
1050 | __progname = ssh_get_progname(av[0]); | 1069 | __progname = ssh_get_progname(av[0]); |
1051 | seed_rng(); | 1070 | seed_rng(); |
@@ -1142,27 +1161,14 @@ main(int ac, char **av) | |||
1142 | * Create socket early so it will exist before command gets run from | 1161 | * Create socket early so it will exist before command gets run from |
1143 | * the parent. | 1162 | * the parent. |
1144 | */ | 1163 | */ |
1145 | sock = socket(AF_UNIX, SOCK_STREAM, 0); | ||
1146 | if (sock < 0) { | ||
1147 | perror("socket"); | ||
1148 | *socket_name = '\0'; /* Don't unlink any existing file */ | ||
1149 | cleanup_exit(1); | ||
1150 | } | ||
1151 | memset(&sunaddr, 0, sizeof(sunaddr)); | ||
1152 | sunaddr.sun_family = AF_UNIX; | ||
1153 | strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); | ||
1154 | prev_mask = umask(0177); | 1164 | prev_mask = umask(0177); |
1155 | if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { | 1165 | sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0); |
1156 | perror("bind"); | 1166 | if (sock < 0) { |
1167 | /* XXX - unix_listener() calls error() not perror() */ | ||
1157 | *socket_name = '\0'; /* Don't unlink any existing file */ | 1168 | *socket_name = '\0'; /* Don't unlink any existing file */ |
1158 | umask(prev_mask); | ||
1159 | cleanup_exit(1); | 1169 | cleanup_exit(1); |
1160 | } | 1170 | } |
1161 | umask(prev_mask); | 1171 | umask(prev_mask); |
1162 | if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { | ||
1163 | perror("listen"); | ||
1164 | cleanup_exit(1); | ||
1165 | } | ||
1166 | 1172 | ||
1167 | /* | 1173 | /* |
1168 | * Fork, and have the parent execute the command, if any, or present | 1174 | * Fork, and have the parent execute the command, if any, or present |
@@ -1231,6 +1237,8 @@ main(int ac, char **av) | |||
1231 | 1237 | ||
1232 | skip: | 1238 | skip: |
1233 | 1239 | ||
1240 | cleanup_pid = getpid(); | ||
1241 | |||
1234 | #ifdef ENABLE_PKCS11 | 1242 | #ifdef ENABLE_PKCS11 |
1235 | pkcs11_init(0); | 1243 | pkcs11_init(0); |
1236 | #endif | 1244 | #endif |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-dss.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: ssh-dss.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -28,162 +28,192 @@ | |||
28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
29 | 29 | ||
30 | #include <openssl/bn.h> | 30 | #include <openssl/bn.h> |
31 | #include <openssl/dsa.h> | ||
31 | #include <openssl/evp.h> | 32 | #include <openssl/evp.h> |
32 | 33 | ||
33 | #include <stdarg.h> | 34 | #include <stdarg.h> |
34 | #include <string.h> | 35 | #include <string.h> |
35 | 36 | ||
36 | #include "xmalloc.h" | 37 | #include "sshbuf.h" |
37 | #include "buffer.h" | ||
38 | #include "compat.h" | 38 | #include "compat.h" |
39 | #include "log.h" | 39 | #include "ssherr.h" |
40 | #include "key.h" | ||
41 | #include "digest.h" | 40 | #include "digest.h" |
41 | #define SSHKEY_INTERNAL | ||
42 | #include "sshkey.h" | ||
42 | 43 | ||
43 | #define INTBLOB_LEN 20 | 44 | #define INTBLOB_LEN 20 |
44 | #define SIGBLOB_LEN (2*INTBLOB_LEN) | 45 | #define SIGBLOB_LEN (2*INTBLOB_LEN) |
45 | 46 | ||
46 | int | 47 | int |
47 | ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp, | 48 | ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |
48 | const u_char *data, u_int datalen) | 49 | const u_char *data, size_t datalen, u_int compat) |
49 | { | 50 | { |
50 | DSA_SIG *sig; | 51 | DSA_SIG *sig = NULL; |
51 | u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; | 52 | u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; |
52 | u_int rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); | 53 | size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); |
53 | Buffer b; | 54 | struct sshbuf *b = NULL; |
54 | 55 | int ret = SSH_ERR_INVALID_ARGUMENT; | |
55 | if (key == NULL || key_type_plain(key->type) != KEY_DSA || | 56 | |
56 | key->dsa == NULL) { | 57 | if (lenp != NULL) |
57 | error("%s: no DSA key", __func__); | 58 | *lenp = 0; |
58 | return -1; | 59 | if (sigp != NULL) |
59 | } | 60 | *sigp = NULL; |
60 | 61 | ||
61 | if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, | 62 | if (key == NULL || key->dsa == NULL || |
62 | digest, sizeof(digest)) != 0) { | 63 | sshkey_type_plain(key->type) != KEY_DSA) |
63 | error("%s: ssh_digest_memory failed", __func__); | 64 | return SSH_ERR_INVALID_ARGUMENT; |
64 | return -1; | 65 | if (dlen == 0) |
65 | } | 66 | return SSH_ERR_INTERNAL_ERROR; |
66 | 67 | ||
67 | sig = DSA_do_sign(digest, dlen, key->dsa); | 68 | if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, |
68 | explicit_bzero(digest, sizeof(digest)); | 69 | digest, sizeof(digest))) != 0) |
69 | 70 | goto out; | |
70 | if (sig == NULL) { | 71 | |
71 | error("ssh_dss_sign: sign failed"); | 72 | if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { |
72 | return -1; | 73 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
74 | goto out; | ||
73 | } | 75 | } |
74 | 76 | ||
75 | rlen = BN_num_bytes(sig->r); | 77 | rlen = BN_num_bytes(sig->r); |
76 | slen = BN_num_bytes(sig->s); | 78 | slen = BN_num_bytes(sig->s); |
77 | if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { | 79 | if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { |
78 | error("bad sig size %u %u", rlen, slen); | 80 | ret = SSH_ERR_INTERNAL_ERROR; |
79 | DSA_SIG_free(sig); | 81 | goto out; |
80 | return -1; | ||
81 | } | 82 | } |
82 | explicit_bzero(sigblob, SIGBLOB_LEN); | 83 | explicit_bzero(sigblob, SIGBLOB_LEN); |
83 | BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); | 84 | BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); |
84 | BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); | 85 | BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen); |
85 | DSA_SIG_free(sig); | ||
86 | 86 | ||
87 | if (datafellows & SSH_BUG_SIGBLOB) { | 87 | if (compat & SSH_BUG_SIGBLOB) { |
88 | if (lenp != NULL) | ||
89 | *lenp = SIGBLOB_LEN; | ||
90 | if (sigp != NULL) { | 88 | if (sigp != NULL) { |
91 | *sigp = xmalloc(SIGBLOB_LEN); | 89 | if ((*sigp = malloc(SIGBLOB_LEN)) == NULL) { |
90 | ret = SSH_ERR_ALLOC_FAIL; | ||
91 | goto out; | ||
92 | } | ||
92 | memcpy(*sigp, sigblob, SIGBLOB_LEN); | 93 | memcpy(*sigp, sigblob, SIGBLOB_LEN); |
93 | } | 94 | } |
95 | if (lenp != NULL) | ||
96 | *lenp = SIGBLOB_LEN; | ||
97 | ret = 0; | ||
94 | } else { | 98 | } else { |
95 | /* ietf-drafts */ | 99 | /* ietf-drafts */ |
96 | buffer_init(&b); | 100 | if ((b = sshbuf_new()) == NULL) { |
97 | buffer_put_cstring(&b, "ssh-dss"); | 101 | ret = SSH_ERR_ALLOC_FAIL; |
98 | buffer_put_string(&b, sigblob, SIGBLOB_LEN); | 102 | goto out; |
99 | len = buffer_len(&b); | 103 | } |
100 | if (lenp != NULL) | 104 | if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || |
101 | *lenp = len; | 105 | (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0) |
106 | goto out; | ||
107 | len = sshbuf_len(b); | ||
102 | if (sigp != NULL) { | 108 | if (sigp != NULL) { |
103 | *sigp = xmalloc(len); | 109 | if ((*sigp = malloc(len)) == NULL) { |
104 | memcpy(*sigp, buffer_ptr(&b), len); | 110 | ret = SSH_ERR_ALLOC_FAIL; |
111 | goto out; | ||
112 | } | ||
113 | memcpy(*sigp, sshbuf_ptr(b), len); | ||
105 | } | 114 | } |
106 | buffer_free(&b); | 115 | if (lenp != NULL) |
116 | *lenp = len; | ||
117 | ret = 0; | ||
107 | } | 118 | } |
108 | return 0; | 119 | out: |
120 | explicit_bzero(digest, sizeof(digest)); | ||
121 | if (sig != NULL) | ||
122 | DSA_SIG_free(sig); | ||
123 | if (b != NULL) | ||
124 | sshbuf_free(b); | ||
125 | return ret; | ||
109 | } | 126 | } |
127 | |||
110 | int | 128 | int |
111 | ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, | 129 | ssh_dss_verify(const struct sshkey *key, |
112 | const u_char *data, u_int datalen) | 130 | const u_char *signature, size_t signaturelen, |
131 | const u_char *data, size_t datalen, u_int compat) | ||
113 | { | 132 | { |
114 | DSA_SIG *sig; | 133 | DSA_SIG *sig = NULL; |
115 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; | 134 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; |
116 | u_int len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); | 135 | size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); |
117 | int rlen, ret; | 136 | int ret = SSH_ERR_INTERNAL_ERROR; |
118 | Buffer b; | 137 | struct sshbuf *b = NULL; |
119 | 138 | char *ktype = NULL; | |
120 | if (key == NULL || key_type_plain(key->type) != KEY_DSA || | 139 | |
121 | key->dsa == NULL) { | 140 | if (key == NULL || key->dsa == NULL || |
122 | error("%s: no DSA key", __func__); | 141 | sshkey_type_plain(key->type) != KEY_DSA) |
123 | return -1; | 142 | return SSH_ERR_INVALID_ARGUMENT; |
124 | } | 143 | if (dlen == 0) |
144 | return SSH_ERR_INTERNAL_ERROR; | ||
125 | 145 | ||
126 | /* fetch signature */ | 146 | /* fetch signature */ |
127 | if (datafellows & SSH_BUG_SIGBLOB) { | 147 | if (compat & SSH_BUG_SIGBLOB) { |
128 | sigblob = xmalloc(signaturelen); | 148 | if ((sigblob = malloc(signaturelen)) == NULL) |
149 | return SSH_ERR_ALLOC_FAIL; | ||
129 | memcpy(sigblob, signature, signaturelen); | 150 | memcpy(sigblob, signature, signaturelen); |
130 | len = signaturelen; | 151 | len = signaturelen; |
131 | } else { | 152 | } else { |
132 | /* ietf-drafts */ | 153 | /* ietf-drafts */ |
133 | char *ktype; | 154 | if ((b = sshbuf_from(signature, signaturelen)) == NULL) |
134 | buffer_init(&b); | 155 | return SSH_ERR_ALLOC_FAIL; |
135 | buffer_append(&b, signature, signaturelen); | 156 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || |
136 | ktype = buffer_get_cstring(&b, NULL); | 157 | sshbuf_get_string(b, &sigblob, &len) != 0) { |
158 | ret = SSH_ERR_INVALID_FORMAT; | ||
159 | goto out; | ||
160 | } | ||
137 | if (strcmp("ssh-dss", ktype) != 0) { | 161 | if (strcmp("ssh-dss", ktype) != 0) { |
138 | error("%s: cannot handle type %s", __func__, ktype); | 162 | ret = SSH_ERR_KEY_TYPE_MISMATCH; |
139 | buffer_free(&b); | 163 | goto out; |
140 | free(ktype); | ||
141 | return -1; | ||
142 | } | 164 | } |
143 | free(ktype); | 165 | if (sshbuf_len(b) != 0) { |
144 | sigblob = buffer_get_string(&b, &len); | 166 | ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; |
145 | rlen = buffer_len(&b); | 167 | goto out; |
146 | buffer_free(&b); | ||
147 | if (rlen != 0) { | ||
148 | error("%s: remaining bytes in signature %d", | ||
149 | __func__, rlen); | ||
150 | free(sigblob); | ||
151 | return -1; | ||
152 | } | 168 | } |
153 | } | 169 | } |
154 | 170 | ||
155 | if (len != SIGBLOB_LEN) { | 171 | if (len != SIGBLOB_LEN) { |
156 | fatal("bad sigbloblen %u != SIGBLOB_LEN", len); | 172 | ret = SSH_ERR_INVALID_FORMAT; |
173 | goto out; | ||
157 | } | 174 | } |
158 | 175 | ||
159 | /* parse signature */ | 176 | /* parse signature */ |
160 | if ((sig = DSA_SIG_new()) == NULL) | 177 | if ((sig = DSA_SIG_new()) == NULL || |
161 | fatal("%s: DSA_SIG_new failed", __func__); | 178 | (sig->r = BN_new()) == NULL || |
162 | if ((sig->r = BN_new()) == NULL) | 179 | (sig->s = BN_new()) == NULL) { |
163 | fatal("%s: BN_new failed", __func__); | 180 | ret = SSH_ERR_ALLOC_FAIL; |
164 | if ((sig->s = BN_new()) == NULL) | 181 | goto out; |
165 | fatal("ssh_dss_verify: BN_new failed"); | 182 | } |
166 | if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || | 183 | if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || |
167 | (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) | 184 | (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) { |
168 | fatal("%s: BN_bin2bn failed", __func__); | 185 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
169 | 186 | goto out; | |
170 | /* clean up */ | 187 | } |
171 | explicit_bzero(sigblob, len); | ||
172 | free(sigblob); | ||
173 | 188 | ||
174 | /* sha1 the data */ | 189 | /* sha1 the data */ |
175 | if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, | 190 | if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, |
176 | digest, sizeof(digest)) != 0) { | 191 | digest, sizeof(digest))) != 0) |
177 | error("%s: digest_memory failed", __func__); | 192 | goto out; |
178 | return -1; | 193 | |
194 | switch (DSA_do_verify(digest, dlen, sig, key->dsa)) { | ||
195 | case 1: | ||
196 | ret = 0; | ||
197 | break; | ||
198 | case 0: | ||
199 | ret = SSH_ERR_SIGNATURE_INVALID; | ||
200 | goto out; | ||
201 | default: | ||
202 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
203 | goto out; | ||
179 | } | 204 | } |
180 | 205 | ||
181 | ret = DSA_do_verify(digest, dlen, sig, key->dsa); | 206 | out: |
182 | explicit_bzero(digest, sizeof(digest)); | 207 | explicit_bzero(digest, sizeof(digest)); |
183 | 208 | if (sig != NULL) | |
184 | DSA_SIG_free(sig); | 209 | DSA_SIG_free(sig); |
185 | 210 | if (b != NULL) | |
186 | debug("%s: signature %s", __func__, | 211 | sshbuf_free(b); |
187 | ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); | 212 | if (ktype != NULL) |
213 | free(ktype); | ||
214 | if (sigblob != NULL) { | ||
215 | explicit_bzero(sigblob, len); | ||
216 | free(sigblob); | ||
217 | } | ||
188 | return ret; | 218 | return ret; |
189 | } | 219 | } |
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c index 551c9c460..1119db045 100644 --- a/ssh-ecdsa.c +++ b/ssh-ecdsa.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-ecdsa.c,v 1.10 2014/02/03 23:28:00 djm Exp $ */ | 1 | /* $OpenBSD: ssh-ecdsa.c,v 1.11 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -37,141 +37,155 @@ | |||
37 | 37 | ||
38 | #include <string.h> | 38 | #include <string.h> |
39 | 39 | ||
40 | #include "xmalloc.h" | 40 | #include "sshbuf.h" |
41 | #include "buffer.h" | 41 | #include "ssherr.h" |
42 | #include "compat.h" | ||
43 | #include "log.h" | ||
44 | #include "key.h" | ||
45 | #include "digest.h" | 42 | #include "digest.h" |
43 | #define SSHKEY_INTERNAL | ||
44 | #include "sshkey.h" | ||
46 | 45 | ||
46 | /* ARGSUSED */ | ||
47 | int | 47 | int |
48 | ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, | 48 | ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |
49 | const u_char *data, u_int datalen) | 49 | const u_char *data, size_t datalen, u_int compat) |
50 | { | 50 | { |
51 | ECDSA_SIG *sig; | 51 | ECDSA_SIG *sig = NULL; |
52 | int hash_alg; | 52 | int hash_alg; |
53 | u_char digest[SSH_DIGEST_MAX_LENGTH]; | 53 | u_char digest[SSH_DIGEST_MAX_LENGTH]; |
54 | u_int len, dlen; | 54 | size_t len, dlen; |
55 | Buffer b, bb; | 55 | struct sshbuf *b = NULL, *bb = NULL; |
56 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
56 | 57 | ||
57 | if (key == NULL || key_type_plain(key->type) != KEY_ECDSA || | 58 | if (lenp != NULL) |
58 | key->ecdsa == NULL) { | 59 | *lenp = 0; |
59 | error("%s: no ECDSA key", __func__); | 60 | if (sigp != NULL) |
60 | return -1; | 61 | *sigp = NULL; |
62 | |||
63 | if (key == NULL || key->ecdsa == NULL || | ||
64 | sshkey_type_plain(key->type) != KEY_ECDSA) | ||
65 | return SSH_ERR_INVALID_ARGUMENT; | ||
66 | |||
67 | if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || | ||
68 | (dlen = ssh_digest_bytes(hash_alg)) == 0) | ||
69 | return SSH_ERR_INTERNAL_ERROR; | ||
70 | if ((ret = ssh_digest_memory(hash_alg, data, datalen, | ||
71 | digest, sizeof(digest))) != 0) | ||
72 | goto out; | ||
73 | |||
74 | if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) { | ||
75 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
76 | goto out; | ||
61 | } | 77 | } |
62 | 78 | ||
63 | hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); | 79 | if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { |
64 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { | 80 | ret = SSH_ERR_ALLOC_FAIL; |
65 | error("%s: bad hash algorithm %d", __func__, hash_alg); | 81 | goto out; |
66 | return -1; | ||
67 | } | ||
68 | if (ssh_digest_memory(hash_alg, data, datalen, | ||
69 | digest, sizeof(digest)) != 0) { | ||
70 | error("%s: digest_memory failed", __func__); | ||
71 | return -1; | ||
72 | } | 82 | } |
73 | 83 | if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 || | |
74 | sig = ECDSA_do_sign(digest, dlen, key->ecdsa); | 84 | (ret = sshbuf_put_bignum2(bb, sig->s)) != 0) |
75 | explicit_bzero(digest, sizeof(digest)); | 85 | goto out; |
76 | 86 | if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || | |
77 | if (sig == NULL) { | 87 | (ret = sshbuf_put_stringb(b, bb)) != 0) |
78 | error("%s: sign failed", __func__); | 88 | goto out; |
79 | return -1; | 89 | len = sshbuf_len(b); |
90 | if (sigp != NULL) { | ||
91 | if ((*sigp = malloc(len)) == NULL) { | ||
92 | ret = SSH_ERR_ALLOC_FAIL; | ||
93 | goto out; | ||
94 | } | ||
95 | memcpy(*sigp, sshbuf_ptr(b), len); | ||
80 | } | 96 | } |
81 | |||
82 | buffer_init(&bb); | ||
83 | buffer_put_bignum2(&bb, sig->r); | ||
84 | buffer_put_bignum2(&bb, sig->s); | ||
85 | ECDSA_SIG_free(sig); | ||
86 | |||
87 | buffer_init(&b); | ||
88 | buffer_put_cstring(&b, key_ssh_name_plain(key)); | ||
89 | buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb)); | ||
90 | buffer_free(&bb); | ||
91 | len = buffer_len(&b); | ||
92 | if (lenp != NULL) | 97 | if (lenp != NULL) |
93 | *lenp = len; | 98 | *lenp = len; |
94 | if (sigp != NULL) { | 99 | ret = 0; |
95 | *sigp = xmalloc(len); | 100 | out: |
96 | memcpy(*sigp, buffer_ptr(&b), len); | 101 | explicit_bzero(digest, sizeof(digest)); |
97 | } | 102 | if (b != NULL) |
98 | buffer_free(&b); | 103 | sshbuf_free(b); |
99 | 104 | if (bb != NULL) | |
100 | return 0; | 105 | sshbuf_free(bb); |
106 | if (sig != NULL) | ||
107 | ECDSA_SIG_free(sig); | ||
108 | return ret; | ||
101 | } | 109 | } |
110 | |||
111 | /* ARGSUSED */ | ||
102 | int | 112 | int |
103 | ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, | 113 | ssh_ecdsa_verify(const struct sshkey *key, |
104 | const u_char *data, u_int datalen) | 114 | const u_char *signature, size_t signaturelen, |
115 | const u_char *data, size_t datalen, u_int compat) | ||
105 | { | 116 | { |
106 | ECDSA_SIG *sig; | 117 | ECDSA_SIG *sig = NULL; |
107 | int hash_alg; | 118 | int hash_alg; |
108 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; | 119 | u_char digest[SSH_DIGEST_MAX_LENGTH]; |
109 | u_int len, dlen; | 120 | size_t dlen; |
110 | int rlen, ret; | 121 | int ret = SSH_ERR_INTERNAL_ERROR; |
111 | Buffer b, bb; | 122 | struct sshbuf *b = NULL, *sigbuf = NULL; |
112 | char *ktype; | 123 | char *ktype = NULL; |
113 | 124 | ||
114 | if (key == NULL || key_type_plain(key->type) != KEY_ECDSA || | 125 | if (key == NULL || key->ecdsa == NULL || |
115 | key->ecdsa == NULL) { | 126 | sshkey_type_plain(key->type) != KEY_ECDSA) |
116 | error("%s: no ECDSA key", __func__); | 127 | return SSH_ERR_INVALID_ARGUMENT; |
117 | return -1; | 128 | |
118 | } | 129 | if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || |
130 | (dlen = ssh_digest_bytes(hash_alg)) == 0) | ||
131 | return SSH_ERR_INTERNAL_ERROR; | ||
119 | 132 | ||
120 | /* fetch signature */ | 133 | /* fetch signature */ |
121 | buffer_init(&b); | 134 | if ((b = sshbuf_from(signature, signaturelen)) == NULL) |
122 | buffer_append(&b, signature, signaturelen); | 135 | return SSH_ERR_ALLOC_FAIL; |
123 | ktype = buffer_get_string(&b, NULL); | 136 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || |
124 | if (strcmp(key_ssh_name_plain(key), ktype) != 0) { | 137 | sshbuf_froms(b, &sigbuf) != 0) { |
125 | error("%s: cannot handle type %s", __func__, ktype); | 138 | ret = SSH_ERR_INVALID_FORMAT; |
126 | buffer_free(&b); | 139 | goto out; |
127 | free(ktype); | ||
128 | return -1; | ||
129 | } | 140 | } |
130 | free(ktype); | 141 | if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) { |
131 | sigblob = buffer_get_string(&b, &len); | 142 | ret = SSH_ERR_KEY_TYPE_MISMATCH; |
132 | rlen = buffer_len(&b); | 143 | goto out; |
133 | buffer_free(&b); | 144 | } |
134 | if (rlen != 0) { | 145 | if (sshbuf_len(b) != 0) { |
135 | error("%s: remaining bytes in signature %d", __func__, rlen); | 146 | ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; |
136 | free(sigblob); | 147 | goto out; |
137 | return -1; | ||
138 | } | 148 | } |
139 | 149 | ||
140 | /* parse signature */ | 150 | /* parse signature */ |
141 | if ((sig = ECDSA_SIG_new()) == NULL) | 151 | if ((sig = ECDSA_SIG_new()) == NULL) { |
142 | fatal("%s: ECDSA_SIG_new failed", __func__); | 152 | ret = SSH_ERR_ALLOC_FAIL; |
143 | 153 | goto out; | |
144 | buffer_init(&bb); | 154 | } |
145 | buffer_append(&bb, sigblob, len); | 155 | if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 || |
146 | buffer_get_bignum2(&bb, sig->r); | 156 | sshbuf_get_bignum2(sigbuf, sig->s) != 0) { |
147 | buffer_get_bignum2(&bb, sig->s); | 157 | ret = SSH_ERR_INVALID_FORMAT; |
148 | if (buffer_len(&bb) != 0) | 158 | goto out; |
149 | fatal("%s: remaining bytes in inner sigblob", __func__); | 159 | } |
150 | buffer_free(&bb); | 160 | if (sshbuf_len(sigbuf) != 0) { |
151 | 161 | ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; | |
152 | /* clean up */ | 162 | goto out; |
153 | explicit_bzero(sigblob, len); | ||
154 | free(sigblob); | ||
155 | |||
156 | /* hash the data */ | ||
157 | hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); | ||
158 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { | ||
159 | error("%s: bad hash algorithm %d", __func__, hash_alg); | ||
160 | return -1; | ||
161 | } | 163 | } |
162 | if (ssh_digest_memory(hash_alg, data, datalen, | 164 | if ((ret = ssh_digest_memory(hash_alg, data, datalen, |
163 | digest, sizeof(digest)) != 0) { | 165 | digest, sizeof(digest))) != 0) |
164 | error("%s: digest_memory failed", __func__); | 166 | goto out; |
165 | return -1; | 167 | |
168 | switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) { | ||
169 | case 1: | ||
170 | ret = 0; | ||
171 | break; | ||
172 | case 0: | ||
173 | ret = SSH_ERR_SIGNATURE_INVALID; | ||
174 | goto out; | ||
175 | default: | ||
176 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
177 | goto out; | ||
166 | } | 178 | } |
167 | 179 | ||
168 | ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa); | 180 | out: |
169 | explicit_bzero(digest, sizeof(digest)); | 181 | explicit_bzero(digest, sizeof(digest)); |
170 | 182 | if (sigbuf != NULL) | |
171 | ECDSA_SIG_free(sig); | 183 | sshbuf_free(sigbuf); |
172 | 184 | if (b != NULL) | |
173 | debug("%s: signature %s", __func__, | 185 | sshbuf_free(b); |
174 | ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); | 186 | if (sig != NULL) |
187 | ECDSA_SIG_free(sig); | ||
188 | free(ktype); | ||
175 | return ret; | 189 | return ret; |
176 | } | 190 | } |
177 | 191 | ||
diff --git a/ssh-ed25519.c b/ssh-ed25519.c index 160d1f23b..cb87d4790 100644 --- a/ssh-ed25519.c +++ b/ssh-ed25519.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-ed25519.c,v 1.3 2014/02/23 20:03:42 djm Exp $ */ | 1 | /* $OpenBSD: ssh-ed25519.c,v 1.4 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2013 Markus Friedl <markus@openbsd.org> | 3 | * Copyright (c) 2013 Markus Friedl <markus@openbsd.org> |
4 | * | 4 | * |
@@ -18,132 +18,149 @@ | |||
18 | #include "includes.h" | 18 | #include "includes.h" |
19 | 19 | ||
20 | #include <sys/types.h> | 20 | #include <sys/types.h> |
21 | #include <limits.h> | ||
21 | 22 | ||
22 | #include "crypto_api.h" | 23 | #include "crypto_api.h" |
23 | 24 | ||
24 | #include <limits.h> | ||
25 | #include <string.h> | 25 | #include <string.h> |
26 | #include <stdarg.h> | 26 | #include <stdarg.h> |
27 | 27 | ||
28 | #include "xmalloc.h" | 28 | #include "xmalloc.h" |
29 | #include "log.h" | 29 | #include "log.h" |
30 | #include "buffer.h" | 30 | #include "buffer.h" |
31 | #include "key.h" | 31 | #define SSHKEY_INTERNAL |
32 | #include "sshkey.h" | ||
33 | #include "ssherr.h" | ||
32 | #include "ssh.h" | 34 | #include "ssh.h" |
33 | 35 | ||
34 | int | 36 | int |
35 | ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp, | 37 | ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |
36 | const u_char *data, u_int datalen) | 38 | const u_char *data, size_t datalen, u_int compat) |
37 | { | 39 | { |
38 | u_char *sig; | 40 | u_char *sig = NULL; |
39 | u_int slen, len; | 41 | size_t slen = 0, len; |
40 | unsigned long long smlen; | 42 | unsigned long long smlen; |
41 | int ret; | 43 | int r, ret; |
42 | Buffer b; | 44 | struct sshbuf *b = NULL; |
43 | 45 | ||
44 | if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || | 46 | if (lenp != NULL) |
45 | key->ed25519_sk == NULL) { | 47 | *lenp = 0; |
46 | error("%s: no ED25519 key", __func__); | 48 | if (sigp != NULL) |
47 | return -1; | 49 | *sigp = NULL; |
48 | } | ||
49 | 50 | ||
50 | if (datalen >= UINT_MAX - crypto_sign_ed25519_BYTES) { | 51 | if (key == NULL || |
51 | error("%s: datalen %u too long", __func__, datalen); | 52 | sshkey_type_plain(key->type) != KEY_ED25519 || |
52 | return -1; | 53 | key->ed25519_sk == NULL || |
53 | } | 54 | datalen >= INT_MAX - crypto_sign_ed25519_BYTES) |
55 | return SSH_ERR_INVALID_ARGUMENT; | ||
54 | smlen = slen = datalen + crypto_sign_ed25519_BYTES; | 56 | smlen = slen = datalen + crypto_sign_ed25519_BYTES; |
55 | sig = xmalloc(slen); | 57 | if ((sig = malloc(slen)) == NULL) |
58 | return SSH_ERR_ALLOC_FAIL; | ||
56 | 59 | ||
57 | if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, | 60 | if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, |
58 | key->ed25519_sk)) != 0 || smlen <= datalen) { | 61 | key->ed25519_sk)) != 0 || smlen <= datalen) { |
59 | error("%s: crypto_sign_ed25519 failed: %d", __func__, ret); | 62 | r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ |
60 | free(sig); | 63 | goto out; |
61 | return -1; | ||
62 | } | 64 | } |
63 | /* encode signature */ | 65 | /* encode signature */ |
64 | buffer_init(&b); | 66 | if ((b = sshbuf_new()) == NULL) { |
65 | buffer_put_cstring(&b, "ssh-ed25519"); | 67 | r = SSH_ERR_ALLOC_FAIL; |
66 | buffer_put_string(&b, sig, smlen - datalen); | 68 | goto out; |
67 | len = buffer_len(&b); | 69 | } |
70 | if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 || | ||
71 | (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) | ||
72 | goto out; | ||
73 | len = sshbuf_len(b); | ||
74 | if (sigp != NULL) { | ||
75 | if ((*sigp = malloc(len)) == NULL) { | ||
76 | r = SSH_ERR_ALLOC_FAIL; | ||
77 | goto out; | ||
78 | } | ||
79 | memcpy(*sigp, sshbuf_ptr(b), len); | ||
80 | } | ||
68 | if (lenp != NULL) | 81 | if (lenp != NULL) |
69 | *lenp = len; | 82 | *lenp = len; |
70 | if (sigp != NULL) { | 83 | /* success */ |
71 | *sigp = xmalloc(len); | 84 | r = 0; |
72 | memcpy(*sigp, buffer_ptr(&b), len); | 85 | out: |
86 | sshbuf_free(b); | ||
87 | if (sig != NULL) { | ||
88 | explicit_bzero(sig, slen); | ||
89 | free(sig); | ||
73 | } | 90 | } |
74 | buffer_free(&b); | ||
75 | explicit_bzero(sig, slen); | ||
76 | free(sig); | ||
77 | 91 | ||
78 | return 0; | 92 | return r; |
79 | } | 93 | } |
80 | 94 | ||
81 | int | 95 | int |
82 | ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen, | 96 | ssh_ed25519_verify(const struct sshkey *key, |
83 | const u_char *data, u_int datalen) | 97 | const u_char *signature, size_t signaturelen, |
98 | const u_char *data, size_t datalen, u_int compat) | ||
84 | { | 99 | { |
85 | Buffer b; | 100 | struct sshbuf *b = NULL; |
86 | char *ktype; | 101 | char *ktype = NULL; |
87 | u_char *sigblob, *sm, *m; | 102 | const u_char *sigblob; |
88 | u_int len; | 103 | u_char *sm = NULL, *m = NULL; |
89 | unsigned long long smlen, mlen; | 104 | size_t len; |
90 | int rlen, ret; | 105 | unsigned long long smlen = 0, mlen = 0; |
106 | int r, ret; | ||
91 | 107 | ||
92 | if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || | 108 | if (key == NULL || |
93 | key->ed25519_pk == NULL) { | 109 | sshkey_type_plain(key->type) != KEY_ED25519 || |
94 | error("%s: no ED25519 key", __func__); | 110 | key->ed25519_pk == NULL || |
95 | return -1; | 111 | datalen >= INT_MAX - crypto_sign_ed25519_BYTES) |
96 | } | 112 | return SSH_ERR_INVALID_ARGUMENT; |
97 | buffer_init(&b); | 113 | |
98 | buffer_append(&b, signature, signaturelen); | 114 | if ((b = sshbuf_from(signature, signaturelen)) == NULL) |
99 | ktype = buffer_get_cstring(&b, NULL); | 115 | return SSH_ERR_ALLOC_FAIL; |
116 | if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || | ||
117 | (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0) | ||
118 | goto out; | ||
100 | if (strcmp("ssh-ed25519", ktype) != 0) { | 119 | if (strcmp("ssh-ed25519", ktype) != 0) { |
101 | error("%s: cannot handle type %s", __func__, ktype); | 120 | r = SSH_ERR_KEY_TYPE_MISMATCH; |
102 | buffer_free(&b); | 121 | goto out; |
103 | free(ktype); | ||
104 | return -1; | ||
105 | } | 122 | } |
106 | free(ktype); | 123 | if (sshbuf_len(b) != 0) { |
107 | sigblob = buffer_get_string(&b, &len); | 124 | r = SSH_ERR_UNEXPECTED_TRAILING_DATA; |
108 | rlen = buffer_len(&b); | 125 | goto out; |
109 | buffer_free(&b); | ||
110 | if (rlen != 0) { | ||
111 | error("%s: remaining bytes in signature %d", __func__, rlen); | ||
112 | free(sigblob); | ||
113 | return -1; | ||
114 | } | 126 | } |
115 | if (len > crypto_sign_ed25519_BYTES) { | 127 | if (len > crypto_sign_ed25519_BYTES) { |
116 | error("%s: len %u > crypto_sign_ed25519_BYTES %u", __func__, | 128 | r = SSH_ERR_INVALID_FORMAT; |
117 | len, crypto_sign_ed25519_BYTES); | 129 | goto out; |
118 | free(sigblob); | ||
119 | return -1; | ||
120 | } | 130 | } |
131 | if (datalen >= SIZE_MAX - len) | ||
132 | return SSH_ERR_INVALID_ARGUMENT; | ||
121 | smlen = len + datalen; | 133 | smlen = len + datalen; |
122 | sm = xmalloc(smlen); | 134 | mlen = smlen; |
135 | if ((sm = malloc(smlen)) == NULL || (m = xmalloc(mlen)) == NULL) { | ||
136 | r = SSH_ERR_ALLOC_FAIL; | ||
137 | goto out; | ||
138 | } | ||
123 | memcpy(sm, sigblob, len); | 139 | memcpy(sm, sigblob, len); |
124 | memcpy(sm+len, data, datalen); | 140 | memcpy(sm+len, data, datalen); |
125 | mlen = smlen; | ||
126 | m = xmalloc(mlen); | ||
127 | if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, | 141 | if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, |
128 | key->ed25519_pk)) != 0) { | 142 | key->ed25519_pk)) != 0) { |
129 | debug2("%s: crypto_sign_ed25519_open failed: %d", | 143 | debug2("%s: crypto_sign_ed25519_open failed: %d", |
130 | __func__, ret); | 144 | __func__, ret); |
131 | } | 145 | } |
132 | if (ret == 0 && mlen != datalen) { | 146 | if (ret != 0 || mlen != datalen) { |
133 | debug2("%s: crypto_sign_ed25519_open " | 147 | r = SSH_ERR_SIGNATURE_INVALID; |
134 | "mlen != datalen (%llu != %u)", __func__, mlen, datalen); | 148 | goto out; |
135 | ret = -1; | ||
136 | } | 149 | } |
137 | /* XXX compare 'm' and 'data' ? */ | 150 | /* XXX compare 'm' and 'data' ? */ |
138 | 151 | /* success */ | |
139 | explicit_bzero(sigblob, len); | 152 | r = 0; |
140 | explicit_bzero(sm, smlen); | 153 | out: |
141 | explicit_bzero(m, smlen); /* NB. mlen may be invalid if ret != 0 */ | 154 | if (sm != NULL) { |
142 | free(sigblob); | 155 | explicit_bzero(sm, smlen); |
143 | free(sm); | 156 | free(sm); |
144 | free(m); | 157 | } |
145 | debug("%s: signature %scorrect", __func__, (ret != 0) ? "in" : ""); | 158 | if (m != NULL) { |
146 | 159 | explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */ | |
147 | /* translate return code carefully */ | 160 | free(m); |
148 | return (ret == 0) ? 1 : -1; | 161 | } |
162 | sshbuf_free(b); | ||
163 | free(ktype); | ||
164 | return r; | ||
149 | } | 165 | } |
166 | |||
diff --git a/ssh-keygen.0 b/ssh-keygen.0 index c43678ff0..648f3017f 100644 --- a/ssh-keygen.0 +++ b/ssh-keygen.0 | |||
@@ -1,11 +1,11 @@ | |||
1 | SSH-KEYGEN(1) OpenBSD Reference Manual SSH-KEYGEN(1) | 1 | SSH-KEYGEN(1) General Commands Manual SSH-KEYGEN(1) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh-keygen - authentication key generation, management and conversion | 4 | ssh-keygen - authentication key generation, management and conversion |
5 | 5 | ||
6 | SYNOPSIS | 6 | SYNOPSIS |
7 | ssh-keygen [-q] [-b bits] [-t type] [-N new_passphrase] [-C comment] | 7 | ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] |
8 | [-f output_keyfile] | 8 | [-N new_passphrase] [-C comment] [-f output_keyfile] |
9 | ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile] | 9 | ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile] |
10 | ssh-keygen -i [-m key_format] [-f input_keyfile] | 10 | ssh-keygen -i [-m key_format] [-f input_keyfile] |
11 | ssh-keygen -e [-m key_format] [-f input_keyfile] | 11 | ssh-keygen -e [-m key_format] [-f input_keyfile] |
@@ -164,7 +164,9 @@ DESCRIPTION | |||
164 | 164 | ||
165 | -i This option will read an unencrypted private (or public) key file | 165 | -i This option will read an unencrypted private (or public) key file |
166 | in the format specified by the -m option and print an OpenSSH | 166 | in the format specified by the -m option and print an OpenSSH |
167 | compatible private (or public) key to stdout. | 167 | compatible private (or public) key to stdout. This option allows |
168 | importing keys from other software, including several commercial | ||
169 | SSH implementations. The default import format is ``RFC4716''. | ||
168 | 170 | ||
169 | -J num_lines | 171 | -J num_lines |
170 | Exit after screening the specified number of lines while | 172 | Exit after screening the specified number of lines while |
@@ -178,9 +180,7 @@ DESCRIPTION | |||
178 | Write the last line processed to the file checkpt while | 180 | Write the last line processed to the file checkpt while |
179 | performing DH candidate screening using the -T option. This will | 181 | performing DH candidate screening using the -T option. This will |
180 | be used to skip lines in the input file that have already been | 182 | be used to skip lines in the input file that have already been |
181 | processed if the job is restarted. This option allows importing | 183 | processed if the job is restarted. |
182 | keys from other software, including several commercial SSH | ||
183 | implementations. The default import format is ``RFC4716''. | ||
184 | 184 | ||
185 | -k Generate a KRL file. In this mode, ssh-keygen will generate a | 185 | -k Generate a KRL file. In this mode, ssh-keygen will generate a |
186 | KRL file at the location specified via the -f flag that revokes | 186 | KRL file at the location specified via the -f flag that revokes |
@@ -313,7 +313,7 @@ DESCRIPTION | |||
313 | Test DH group exchange candidate primes (generated using the -G | 313 | Test DH group exchange candidate primes (generated using the -G |
314 | option) for safety. | 314 | option) for safety. |
315 | 315 | ||
316 | -t type | 316 | -t dsa | ecdsa | ed25519 | rsa | rsa1 |
317 | Specifies the type of key to create. The possible values are | 317 | Specifies the type of key to create. The possible values are |
318 | ``rsa1'' for protocol version 1 and ``dsa'', ``ecdsa'', | 318 | ``rsa1'' for protocol version 1 and ``dsa'', ``ecdsa'', |
319 | ``ed25519'', or ``rsa'' for protocol version 2. | 319 | ``ed25519'', or ``rsa'' for protocol version 2. |
@@ -559,4 +559,4 @@ AUTHORS | |||
559 | created OpenSSH. Markus Friedl contributed the support for SSH protocol | 559 | created OpenSSH. Markus Friedl contributed the support for SSH protocol |
560 | versions 1.5 and 2.0. | 560 | versions 1.5 and 2.0. |
561 | 561 | ||
562 | OpenBSD 5.5 February 5, 2014 OpenBSD 5.5 | 562 | OpenBSD 5.6 March 31, 2014 OpenBSD 5.6 |
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index a71de7481..79b948c8b 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.120 2014/02/05 20:13:25 naddy Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.122 2014/03/31 13:39:34 jmc Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,7 +35,7 @@ | |||
35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | .\" | 37 | .\" |
38 | .Dd $Mdocdate: February 5 2014 $ | 38 | .Dd $Mdocdate: March 31 2014 $ |
39 | .Dt SSH-KEYGEN 1 | 39 | .Dt SSH-KEYGEN 1 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -46,7 +46,7 @@ | |||
46 | .Nm ssh-keygen | 46 | .Nm ssh-keygen |
47 | .Op Fl q | 47 | .Op Fl q |
48 | .Op Fl b Ar bits | 48 | .Op Fl b Ar bits |
49 | .Op Fl t Ar type | 49 | .Op Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1 |
50 | .Op Fl N Ar new_passphrase | 50 | .Op Fl N Ar new_passphrase |
51 | .Op Fl C Ar comment | 51 | .Op Fl C Ar comment |
52 | .Op Fl f Ar output_keyfile | 52 | .Op Fl f Ar output_keyfile |
@@ -328,6 +328,10 @@ in the format specified by the | |||
328 | .Fl m | 328 | .Fl m |
329 | option and print an OpenSSH compatible private | 329 | option and print an OpenSSH compatible private |
330 | (or public) key to stdout. | 330 | (or public) key to stdout. |
331 | This option allows importing keys from other software, including several | ||
332 | commercial SSH implementations. | ||
333 | The default import format is | ||
334 | .Dq RFC4716 . | ||
331 | .It Fl J Ar num_lines | 335 | .It Fl J Ar num_lines |
332 | Exit after screening the specified number of lines | 336 | Exit after screening the specified number of lines |
333 | while performing DH candidate screening using the | 337 | while performing DH candidate screening using the |
@@ -346,10 +350,6 @@ while performing DH candidate screening using the | |||
346 | option. | 350 | option. |
347 | This will be used to skip lines in the input file that have already been | 351 | This will be used to skip lines in the input file that have already been |
348 | processed if the job is restarted. | 352 | processed if the job is restarted. |
349 | This option allows importing keys from other software, including several | ||
350 | commercial SSH implementations. | ||
351 | The default import format is | ||
352 | .Dq RFC4716 . | ||
353 | .It Fl k | 353 | .It Fl k |
354 | Generate a KRL file. | 354 | Generate a KRL file. |
355 | In this mode, | 355 | In this mode, |
@@ -510,7 +510,7 @@ section for details. | |||
510 | Test DH group exchange candidate primes (generated using the | 510 | Test DH group exchange candidate primes (generated using the |
511 | .Fl G | 511 | .Fl G |
512 | option) for safety. | 512 | option) for safety. |
513 | .It Fl t Ar type | 513 | .It Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1 |
514 | Specifies the type of key to create. | 514 | Specifies the type of key to create. |
515 | The possible values are | 515 | The possible values are |
516 | .Dq rsa1 | 516 | .Dq rsa1 |
diff --git a/ssh-keygen.c b/ssh-keygen.c index 2a316bcea..23058ee99 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.241 2014/02/05 20:13:25 naddy Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.249 2014/07/03 03:47:27 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -165,7 +165,7 @@ int rounds = 0; | |||
165 | /* argv0 */ | 165 | /* argv0 */ |
166 | extern char *__progname; | 166 | extern char *__progname; |
167 | 167 | ||
168 | char hostname[MAXHOSTNAMELEN]; | 168 | char hostname[NI_MAXHOST]; |
169 | 169 | ||
170 | /* moduli.c */ | 170 | /* moduli.c */ |
171 | int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); | 171 | int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); |
@@ -195,6 +195,7 @@ type_bits_valid(int type, u_int32_t *bitsp) | |||
195 | fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); | 195 | fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); |
196 | exit(1); | 196 | exit(1); |
197 | } | 197 | } |
198 | #ifdef WITH_OPENSSL | ||
198 | if (type == KEY_DSA && *bitsp != 1024) | 199 | if (type == KEY_DSA && *bitsp != 1024) |
199 | fatal("DSA keys must be 1024 bits"); | 200 | fatal("DSA keys must be 1024 bits"); |
200 | else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768) | 201 | else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768) |
@@ -202,6 +203,7 @@ type_bits_valid(int type, u_int32_t *bitsp) | |||
202 | else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1) | 203 | else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1) |
203 | fatal("Invalid ECDSA key length - valid lengths are " | 204 | fatal("Invalid ECDSA key length - valid lengths are " |
204 | "256, 384 or 521 bits"); | 205 | "256, 384 or 521 bits"); |
206 | #endif | ||
205 | } | 207 | } |
206 | 208 | ||
207 | static void | 209 | static void |
@@ -278,6 +280,7 @@ load_identity(char *filename) | |||
278 | #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" | 280 | #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" |
279 | #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb | 281 | #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb |
280 | 282 | ||
283 | #ifdef WITH_OPENSSL | ||
281 | static void | 284 | static void |
282 | do_convert_to_ssh2(struct passwd *pw, Key *k) | 285 | do_convert_to_ssh2(struct passwd *pw, Key *k) |
283 | { | 286 | { |
@@ -408,7 +411,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) | |||
408 | Buffer b; | 411 | Buffer b; |
409 | Key *key = NULL; | 412 | Key *key = NULL; |
410 | char *type, *cipher; | 413 | char *type, *cipher; |
411 | u_char *sig, data[] = "abcde12345"; | 414 | u_char *sig = NULL, data[] = "abcde12345"; |
412 | int magic, rlen, ktype, i1, i2, i3, i4; | 415 | int magic, rlen, ktype, i1, i2, i3, i4; |
413 | u_int slen; | 416 | u_int slen; |
414 | u_long e; | 417 | u_long e; |
@@ -479,7 +482,9 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) | |||
479 | buffer_get_bignum_bits(&b, key->rsa->iqmp); | 482 | buffer_get_bignum_bits(&b, key->rsa->iqmp); |
480 | buffer_get_bignum_bits(&b, key->rsa->q); | 483 | buffer_get_bignum_bits(&b, key->rsa->q); |
481 | buffer_get_bignum_bits(&b, key->rsa->p); | 484 | buffer_get_bignum_bits(&b, key->rsa->p); |
482 | rsa_generate_additional_parameters(key->rsa); | 485 | if (rsa_generate_additional_parameters(key->rsa) != 0) |
486 | fatal("%s: rsa_generate_additional_parameters " | ||
487 | "error", __func__); | ||
483 | break; | 488 | break; |
484 | } | 489 | } |
485 | rlen = buffer_len(&b); | 490 | rlen = buffer_len(&b); |
@@ -711,6 +716,7 @@ do_convert_from(struct passwd *pw) | |||
711 | key_free(k); | 716 | key_free(k); |
712 | exit(0); | 717 | exit(0); |
713 | } | 718 | } |
719 | #endif | ||
714 | 720 | ||
715 | static void | 721 | static void |
716 | do_print_public(struct passwd *pw) | 722 | do_print_public(struct passwd *pw) |
@@ -981,7 +987,7 @@ do_gen_all_hostkeys(struct passwd *pw) | |||
981 | } | 987 | } |
982 | 988 | ||
983 | static void | 989 | static void |
984 | printhost(FILE *f, const char *name, Key *public, int ca, int hash) | 990 | printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash) |
985 | { | 991 | { |
986 | if (print_fingerprint) { | 992 | if (print_fingerprint) { |
987 | enum fp_rep rep; | 993 | enum fp_rep rep; |
@@ -1001,7 +1007,8 @@ printhost(FILE *f, const char *name, Key *public, int ca, int hash) | |||
1001 | } else { | 1007 | } else { |
1002 | if (hash && (name = host_hash(name, NULL, 0)) == NULL) | 1008 | if (hash && (name = host_hash(name, NULL, 0)) == NULL) |
1003 | fatal("hash_host failed"); | 1009 | fatal("hash_host failed"); |
1004 | fprintf(f, "%s%s%s ", ca ? CA_MARKER : "", ca ? " " : "", name); | 1010 | fprintf(f, "%s%s%s ", ca ? CA_MARKER " " : "", |
1011 | revoked ? REVOKE_MARKER " " : "" , name); | ||
1005 | if (!key_write(public, f)) | 1012 | if (!key_write(public, f)) |
1006 | fatal("key_write failed"); | 1013 | fatal("key_write failed"); |
1007 | fprintf(f, "\n"); | 1014 | fprintf(f, "\n"); |
@@ -1016,7 +1023,7 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
1016 | char *cp, *cp2, *kp, *kp2; | 1023 | char *cp, *cp2, *kp, *kp2; |
1017 | char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; | 1024 | char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; |
1018 | int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; | 1025 | int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; |
1019 | int ca; | 1026 | int ca, revoked; |
1020 | int found_key = 0; | 1027 | int found_key = 0; |
1021 | 1028 | ||
1022 | if (!have_identity) { | 1029 | if (!have_identity) { |
@@ -1030,6 +1037,7 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
1030 | if ((in = fopen(identity_file, "r")) == NULL) | 1037 | if ((in = fopen(identity_file, "r")) == NULL) |
1031 | fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); | 1038 | fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); |
1032 | 1039 | ||
1040 | /* XXX this code is a mess; refactor -djm */ | ||
1033 | /* | 1041 | /* |
1034 | * Find hosts goes to stdout, hash and deletions happen in-place | 1042 | * Find hosts goes to stdout, hash and deletions happen in-place |
1035 | * A corner case is ssh-keygen -HF foo, which should go to stdout | 1043 | * A corner case is ssh-keygen -HF foo, which should go to stdout |
@@ -1073,7 +1081,7 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
1073 | fprintf(out, "%s\n", cp); | 1081 | fprintf(out, "%s\n", cp); |
1074 | continue; | 1082 | continue; |
1075 | } | 1083 | } |
1076 | /* Check whether this is a CA key */ | 1084 | /* Check whether this is a CA key or revocation marker */ |
1077 | if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && | 1085 | if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && |
1078 | (cp[sizeof(CA_MARKER) - 1] == ' ' || | 1086 | (cp[sizeof(CA_MARKER) - 1] == ' ' || |
1079 | cp[sizeof(CA_MARKER) - 1] == '\t')) { | 1087 | cp[sizeof(CA_MARKER) - 1] == '\t')) { |
@@ -1081,6 +1089,14 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
1081 | cp += sizeof(CA_MARKER); | 1089 | cp += sizeof(CA_MARKER); |
1082 | } else | 1090 | } else |
1083 | ca = 0; | 1091 | ca = 0; |
1092 | if (strncasecmp(cp, REVOKE_MARKER, | ||
1093 | sizeof(REVOKE_MARKER) - 1) == 0 && | ||
1094 | (cp[sizeof(REVOKE_MARKER) - 1] == ' ' || | ||
1095 | cp[sizeof(REVOKE_MARKER) - 1] == '\t')) { | ||
1096 | revoked = 1; | ||
1097 | cp += sizeof(REVOKE_MARKER); | ||
1098 | } else | ||
1099 | revoked = 0; | ||
1084 | 1100 | ||
1085 | /* Find the end of the host name portion. */ | 1101 | /* Find the end of the host name portion. */ |
1086 | for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++) | 1102 | for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++) |
@@ -1124,20 +1140,23 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
1124 | printf("# Host %s found: " | 1140 | printf("# Host %s found: " |
1125 | "line %d type %s%s\n", name, | 1141 | "line %d type %s%s\n", name, |
1126 | num, key_type(pub), | 1142 | num, key_type(pub), |
1127 | ca ? " (CA key)" : ""); | 1143 | ca ? " (CA key)" : |
1128 | printhost(out, cp, pub, ca, 0); | 1144 | revoked? " (revoked)" : ""); |
1145 | printhost(out, cp, pub, ca, revoked, 0); | ||
1129 | found_key = 1; | 1146 | found_key = 1; |
1130 | } | 1147 | } |
1131 | if (delete_host) { | 1148 | if (delete_host) { |
1132 | if (!c && !ca) | 1149 | if (!c || ca || revoked) { |
1133 | printhost(out, cp, pub, ca, 0); | 1150 | printhost(out, cp, pub, |
1134 | else | 1151 | ca, revoked, 0); |
1152 | } else { | ||
1135 | printf("# Host %s found: " | 1153 | printf("# Host %s found: " |
1136 | "line %d type %s\n", name, | 1154 | "line %d type %s\n", name, |
1137 | num, key_type(pub)); | 1155 | num, key_type(pub)); |
1156 | } | ||
1138 | } | 1157 | } |
1139 | } else if (hash_hosts) | 1158 | } else if (hash_hosts) |
1140 | printhost(out, cp, pub, ca, 0); | 1159 | printhost(out, cp, pub, ca, revoked, 0); |
1141 | } else { | 1160 | } else { |
1142 | if (find_host || delete_host) { | 1161 | if (find_host || delete_host) { |
1143 | c = (match_hostname(name, cp, | 1162 | c = (match_hostname(name, cp, |
@@ -1148,38 +1167,43 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
1148 | "line %d type %s%s\n", name, | 1167 | "line %d type %s%s\n", name, |
1149 | num, key_type(pub), | 1168 | num, key_type(pub), |
1150 | ca ? " (CA key)" : ""); | 1169 | ca ? " (CA key)" : ""); |
1151 | printhost(out, name, pub, | 1170 | printhost(out, name, pub, ca, revoked, |
1152 | ca, hash_hosts && !ca); | 1171 | hash_hosts && !(ca || revoked)); |
1153 | found_key = 1; | 1172 | found_key = 1; |
1154 | } | 1173 | } |
1155 | if (delete_host) { | 1174 | if (delete_host) { |
1156 | if (!c && !ca) | 1175 | if (!c || ca || revoked) { |
1157 | printhost(out, cp, pub, ca, 0); | 1176 | printhost(out, cp, pub, |
1158 | else | 1177 | ca, revoked, 0); |
1178 | } else { | ||
1159 | printf("# Host %s found: " | 1179 | printf("# Host %s found: " |
1160 | "line %d type %s\n", name, | 1180 | "line %d type %s\n", name, |
1161 | num, key_type(pub)); | 1181 | num, key_type(pub)); |
1182 | } | ||
1162 | } | 1183 | } |
1184 | } else if (hash_hosts && (ca || revoked)) { | ||
1185 | /* Don't hash CA and revoked keys' hostnames */ | ||
1186 | printhost(out, cp, pub, ca, revoked, 0); | ||
1187 | has_unhashed = 1; | ||
1163 | } else if (hash_hosts) { | 1188 | } else if (hash_hosts) { |
1189 | /* Hash each hostname separately */ | ||
1164 | for (cp2 = strsep(&cp, ","); | 1190 | for (cp2 = strsep(&cp, ","); |
1165 | cp2 != NULL && *cp2 != '\0'; | 1191 | cp2 != NULL && *cp2 != '\0'; |
1166 | cp2 = strsep(&cp, ",")) { | 1192 | cp2 = strsep(&cp, ",")) { |
1167 | if (ca) { | 1193 | if (strcspn(cp2, "*?!") != |
1168 | fprintf(stderr, "Warning: " | ||
1169 | "ignoring CA key for host: " | ||
1170 | "%.64s\n", cp2); | ||
1171 | printhost(out, cp2, pub, ca, 0); | ||
1172 | } else if (strcspn(cp2, "*?!") != | ||
1173 | strlen(cp2)) { | 1194 | strlen(cp2)) { |
1174 | fprintf(stderr, "Warning: " | 1195 | fprintf(stderr, "Warning: " |
1175 | "ignoring host name with " | 1196 | "ignoring host name with " |
1176 | "metacharacters: %.64s\n", | 1197 | "metacharacters: %.64s\n", |
1177 | cp2); | 1198 | cp2); |
1178 | printhost(out, cp2, pub, ca, 0); | 1199 | printhost(out, cp2, pub, ca, |
1179 | } else | 1200 | revoked, 0); |
1180 | printhost(out, cp2, pub, ca, 1); | 1201 | has_unhashed = 1; |
1202 | } else { | ||
1203 | printhost(out, cp2, pub, ca, | ||
1204 | revoked, 1); | ||
1205 | } | ||
1181 | } | 1206 | } |
1182 | has_unhashed = 1; | ||
1183 | } | 1207 | } |
1184 | } | 1208 | } |
1185 | key_free(pub); | 1209 | key_free(pub); |
@@ -1589,7 +1613,9 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) | |||
1589 | } | 1613 | } |
1590 | } | 1614 | } |
1591 | 1615 | ||
1616 | #ifdef ENABLE_PKCS11 | ||
1592 | pkcs11_init(1); | 1617 | pkcs11_init(1); |
1618 | #endif | ||
1593 | tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); | 1619 | tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); |
1594 | if (pkcs11provider != NULL) { | 1620 | if (pkcs11provider != NULL) { |
1595 | if ((ca = load_pkcs11_key(tmp)) == NULL) | 1621 | if ((ca = load_pkcs11_key(tmp)) == NULL) |
@@ -1631,12 +1657,12 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) | |||
1631 | public->cert->valid_after = cert_valid_from; | 1657 | public->cert->valid_after = cert_valid_from; |
1632 | public->cert->valid_before = cert_valid_to; | 1658 | public->cert->valid_before = cert_valid_to; |
1633 | if (v00) { | 1659 | if (v00) { |
1634 | prepare_options_buf(&public->cert->critical, | 1660 | prepare_options_buf(public->cert->critical, |
1635 | OPTIONS_CRITICAL|OPTIONS_EXTENSIONS); | 1661 | OPTIONS_CRITICAL|OPTIONS_EXTENSIONS); |
1636 | } else { | 1662 | } else { |
1637 | prepare_options_buf(&public->cert->critical, | 1663 | prepare_options_buf(public->cert->critical, |
1638 | OPTIONS_CRITICAL); | 1664 | OPTIONS_CRITICAL); |
1639 | prepare_options_buf(&public->cert->extensions, | 1665 | prepare_options_buf(public->cert->extensions, |
1640 | OPTIONS_EXTENSIONS); | 1666 | OPTIONS_EXTENSIONS); |
1641 | } | 1667 | } |
1642 | public->cert->signature_key = key_from_private(ca); | 1668 | public->cert->signature_key = key_from_private(ca); |
@@ -1672,7 +1698,9 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) | |||
1672 | key_free(public); | 1698 | key_free(public); |
1673 | free(out); | 1699 | free(out); |
1674 | } | 1700 | } |
1701 | #ifdef ENABLE_PKCS11 | ||
1675 | pkcs11_terminate(); | 1702 | pkcs11_terminate(); |
1703 | #endif | ||
1676 | exit(0); | 1704 | exit(0); |
1677 | } | 1705 | } |
1678 | 1706 | ||
@@ -1820,8 +1848,8 @@ add_cert_option(char *opt) | |||
1820 | static void | 1848 | static void |
1821 | show_options(const Buffer *optbuf, int v00, int in_critical) | 1849 | show_options(const Buffer *optbuf, int v00, int in_critical) |
1822 | { | 1850 | { |
1823 | char *name; | 1851 | char *name, *arg; |
1824 | u_char *data; | 1852 | const u_char *data; |
1825 | u_int dlen; | 1853 | u_int dlen; |
1826 | Buffer options, option; | 1854 | Buffer options, option; |
1827 | 1855 | ||
@@ -1844,9 +1872,9 @@ show_options(const Buffer *optbuf, int v00, int in_critical) | |||
1844 | else if ((v00 || in_critical) && | 1872 | else if ((v00 || in_critical) && |
1845 | (strcmp(name, "force-command") == 0 || | 1873 | (strcmp(name, "force-command") == 0 || |
1846 | strcmp(name, "source-address") == 0)) { | 1874 | strcmp(name, "source-address") == 0)) { |
1847 | data = buffer_get_string(&option, NULL); | 1875 | arg = buffer_get_cstring(&option, NULL); |
1848 | printf(" %s\n", data); | 1876 | printf(" %s\n", arg); |
1849 | free(data); | 1877 | free(arg); |
1850 | } else { | 1878 | } else { |
1851 | printf(" UNKNOWN OPTION (len %u)\n", | 1879 | printf(" UNKNOWN OPTION (len %u)\n", |
1852 | buffer_len(&option)); | 1880 | buffer_len(&option)); |
@@ -1905,24 +1933,25 @@ do_show_cert(struct passwd *pw) | |||
1905 | printf("\n"); | 1933 | printf("\n"); |
1906 | } | 1934 | } |
1907 | printf(" Critical Options: "); | 1935 | printf(" Critical Options: "); |
1908 | if (buffer_len(&key->cert->critical) == 0) | 1936 | if (buffer_len(key->cert->critical) == 0) |
1909 | printf("(none)\n"); | 1937 | printf("(none)\n"); |
1910 | else { | 1938 | else { |
1911 | printf("\n"); | 1939 | printf("\n"); |
1912 | show_options(&key->cert->critical, v00, 1); | 1940 | show_options(key->cert->critical, v00, 1); |
1913 | } | 1941 | } |
1914 | if (!v00) { | 1942 | if (!v00) { |
1915 | printf(" Extensions: "); | 1943 | printf(" Extensions: "); |
1916 | if (buffer_len(&key->cert->extensions) == 0) | 1944 | if (buffer_len(key->cert->extensions) == 0) |
1917 | printf("(none)\n"); | 1945 | printf("(none)\n"); |
1918 | else { | 1946 | else { |
1919 | printf("\n"); | 1947 | printf("\n"); |
1920 | show_options(&key->cert->extensions, v00, 0); | 1948 | show_options(key->cert->extensions, v00, 0); |
1921 | } | 1949 | } |
1922 | } | 1950 | } |
1923 | exit(0); | 1951 | exit(0); |
1924 | } | 1952 | } |
1925 | 1953 | ||
1954 | #ifdef WITH_OPENSSL | ||
1926 | static void | 1955 | static void |
1927 | load_krl(const char *path, struct ssh_krl **krlp) | 1956 | load_krl(const char *path, struct ssh_krl **krlp) |
1928 | { | 1957 | { |
@@ -2145,60 +2174,40 @@ do_check_krl(struct passwd *pw, int argc, char **argv) | |||
2145 | ssh_krl_free(krl); | 2174 | ssh_krl_free(krl); |
2146 | exit(ret); | 2175 | exit(ret); |
2147 | } | 2176 | } |
2177 | #endif | ||
2148 | 2178 | ||
2149 | static void | 2179 | static void |
2150 | usage(void) | 2180 | usage(void) |
2151 | { | 2181 | { |
2152 | fprintf(stderr, "usage: %s [options]\n", __progname); | 2182 | fprintf(stderr, |
2153 | fprintf(stderr, "Options:\n"); | 2183 | "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]\n" |
2154 | fprintf(stderr, " -A Generate non-existent host keys for all key types.\n"); | 2184 | " [-N new_passphrase] [-C comment] [-f output_keyfile]\n" |
2155 | fprintf(stderr, " -a number Number of KDF rounds for new key format or moduli primality tests.\n"); | 2185 | " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n" |
2156 | fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); | 2186 | " ssh-keygen -i [-m key_format] [-f input_keyfile]\n" |
2157 | fprintf(stderr, " -b bits Number of bits in the key to create.\n"); | 2187 | " ssh-keygen -e [-m key_format] [-f input_keyfile]\n" |
2158 | fprintf(stderr, " -C comment Provide new comment.\n"); | 2188 | " ssh-keygen -y [-f input_keyfile]\n" |
2159 | fprintf(stderr, " -c Change comment in private and public key files.\n"); | 2189 | " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n" |
2190 | " ssh-keygen -l [-f input_keyfile]\n" | ||
2191 | " ssh-keygen -B [-f input_keyfile]\n"); | ||
2160 | #ifdef ENABLE_PKCS11 | 2192 | #ifdef ENABLE_PKCS11 |
2161 | fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n"); | 2193 | fprintf(stderr, |
2194 | " ssh-keygen -D pkcs11\n"); | ||
2162 | #endif | 2195 | #endif |
2163 | fprintf(stderr, " -e Export OpenSSH to foreign format key file.\n"); | 2196 | fprintf(stderr, |
2164 | fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); | 2197 | " ssh-keygen -F hostname [-f known_hosts_file] [-l]\n" |
2165 | fprintf(stderr, " -f filename Filename of the key file.\n"); | 2198 | " ssh-keygen -H [-f known_hosts_file]\n" |
2166 | fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); | 2199 | " ssh-keygen -R hostname [-f known_hosts_file]\n" |
2167 | fprintf(stderr, " -g Use generic DNS resource record format.\n"); | 2200 | " ssh-keygen -r hostname [-f input_keyfile] [-g]\n" |
2168 | fprintf(stderr, " -H Hash names in known_hosts file.\n"); | 2201 | " ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n" |
2169 | fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); | 2202 | " ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n" |
2170 | fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); | 2203 | " [-j start_line] [-K checkpt] [-W generator]\n" |
2171 | fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); | 2204 | " ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]\n" |
2172 | fprintf(stderr, " -J number Screen this number of moduli lines.\n"); | 2205 | " [-O option] [-V validity_interval] [-z serial_number] file ...\n" |
2173 | fprintf(stderr, " -j number Start screening moduli at specified line.\n"); | 2206 | " ssh-keygen -L [-f input_keyfile]\n" |
2174 | fprintf(stderr, " -K checkpt Write checkpoints to this file.\n"); | 2207 | " ssh-keygen -A\n" |
2175 | fprintf(stderr, " -k Generate a KRL file.\n"); | 2208 | " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" |
2176 | fprintf(stderr, " -L Print the contents of a certificate.\n"); | 2209 | " file ...\n" |
2177 | fprintf(stderr, " -l Show fingerprint of key file.\n"); | 2210 | " ssh-keygen -Q -f krl_file file ...\n"); |
2178 | fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); | ||
2179 | fprintf(stderr, " -m key_fmt Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n"); | ||
2180 | fprintf(stderr, " -N phrase Provide new passphrase.\n"); | ||
2181 | fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); | ||
2182 | fprintf(stderr, " -O option Specify a certificate option.\n"); | ||
2183 | fprintf(stderr, " -o Enforce new private key format.\n"); | ||
2184 | fprintf(stderr, " -P phrase Provide old passphrase.\n"); | ||
2185 | fprintf(stderr, " -p Change passphrase of private key file.\n"); | ||
2186 | fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n"); | ||
2187 | fprintf(stderr, " -q Quiet.\n"); | ||
2188 | fprintf(stderr, " -R hostname Remove host from known_hosts file.\n"); | ||
2189 | fprintf(stderr, " -r hostname Print DNS resource record.\n"); | ||
2190 | fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n"); | ||
2191 | fprintf(stderr, " -s ca_key Certify keys with CA key.\n"); | ||
2192 | fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n"); | ||
2193 | fprintf(stderr, " -t type Specify type of key to create.\n"); | ||
2194 | fprintf(stderr, " -u Update KRL rather than creating a new one.\n"); | ||
2195 | fprintf(stderr, " -V from:to Specify certificate validity interval.\n"); | ||
2196 | fprintf(stderr, " -v Verbose.\n"); | ||
2197 | fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n"); | ||
2198 | fprintf(stderr, " -y Read private key file and print public key.\n"); | ||
2199 | fprintf(stderr, " -Z cipher Specify a cipher for new private key format.\n"); | ||
2200 | fprintf(stderr, " -z serial Specify a serial number.\n"); | ||
2201 | |||
2202 | exit(1); | 2211 | exit(1); |
2203 | } | 2212 | } |
2204 | 2213 | ||
@@ -2469,6 +2478,7 @@ main(int argc, char **argv) | |||
2469 | printf("Cannot use -l with -H or -R.\n"); | 2478 | printf("Cannot use -l with -H or -R.\n"); |
2470 | usage(); | 2479 | usage(); |
2471 | } | 2480 | } |
2481 | #ifdef WITH_OPENSSL | ||
2472 | if (gen_krl) { | 2482 | if (gen_krl) { |
2473 | do_gen_krl(pw, update_krl, argc, argv); | 2483 | do_gen_krl(pw, update_krl, argc, argv); |
2474 | return (0); | 2484 | return (0); |
@@ -2477,6 +2487,7 @@ main(int argc, char **argv) | |||
2477 | do_check_krl(pw, argc, argv); | 2487 | do_check_krl(pw, argc, argv); |
2478 | return (0); | 2488 | return (0); |
2479 | } | 2489 | } |
2490 | #endif | ||
2480 | if (ca_key_path != NULL) { | 2491 | if (ca_key_path != NULL) { |
2481 | if (cert_key_id == NULL) | 2492 | if (cert_key_id == NULL) |
2482 | fatal("Must specify key id (-I) when certifying"); | 2493 | fatal("Must specify key id (-I) when certifying"); |
@@ -2494,10 +2505,12 @@ main(int argc, char **argv) | |||
2494 | do_change_passphrase(pw); | 2505 | do_change_passphrase(pw); |
2495 | if (change_comment) | 2506 | if (change_comment) |
2496 | do_change_comment(pw); | 2507 | do_change_comment(pw); |
2508 | #ifdef WITH_OPENSSL | ||
2497 | if (convert_to) | 2509 | if (convert_to) |
2498 | do_convert_to(pw); | 2510 | do_convert_to(pw); |
2499 | if (convert_from) | 2511 | if (convert_from) |
2500 | do_convert_from(pw); | 2512 | do_convert_from(pw); |
2513 | #endif | ||
2501 | if (print_public) | 2514 | if (print_public) |
2502 | do_print_public(pw); | 2515 | do_print_public(pw); |
2503 | if (rr_hostname != NULL) { | 2516 | if (rr_hostname != NULL) { |
@@ -2519,7 +2532,8 @@ main(int argc, char **argv) | |||
2519 | _PATH_HOST_DSA_KEY_FILE, rr_hostname); | 2532 | _PATH_HOST_DSA_KEY_FILE, rr_hostname); |
2520 | n += do_print_resource_record(pw, | 2533 | n += do_print_resource_record(pw, |
2521 | _PATH_HOST_ECDSA_KEY_FILE, rr_hostname); | 2534 | _PATH_HOST_ECDSA_KEY_FILE, rr_hostname); |
2522 | 2535 | n += do_print_resource_record(pw, | |
2536 | _PATH_HOST_ED25519_KEY_FILE, rr_hostname); | ||
2523 | if (n == 0) | 2537 | if (n == 0) |
2524 | fatal("no keys found."); | 2538 | fatal("no keys found."); |
2525 | exit(0); | 2539 | exit(0); |
diff --git a/ssh-keyscan.0 b/ssh-keyscan.0 index 638c19b48..853bd5152 100644 --- a/ssh-keyscan.0 +++ b/ssh-keyscan.0 | |||
@@ -1,4 +1,4 @@ | |||
1 | SSH-KEYSCAN(1) OpenBSD Reference Manual SSH-KEYSCAN(1) | 1 | SSH-KEYSCAN(1) General Commands Manual SSH-KEYSCAN(1) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh-keyscan - gather ssh public keys | 4 | ssh-keyscan - gather ssh public keys |
@@ -51,7 +51,8 @@ DESCRIPTION | |||
51 | The possible values are ``rsa1'' for protocol version 1 and | 51 | The possible values are ``rsa1'' for protocol version 1 and |
52 | ``dsa'', ``ecdsa'', ``ed25519'', or ``rsa'' for protocol version | 52 | ``dsa'', ``ecdsa'', ``ed25519'', or ``rsa'' for protocol version |
53 | 2. Multiple values may be specified by separating them with | 53 | 2. Multiple values may be specified by separating them with |
54 | commas. The default is to fetch ``rsa'' and ``ecdsa'' keys. | 54 | commas. The default is to fetch ``rsa'', ``ecdsa'', and |
55 | ``ed25519'' keys. | ||
55 | 56 | ||
56 | -v Verbose mode. Causes ssh-keyscan to print debugging messages | 57 | -v Verbose mode. Causes ssh-keyscan to print debugging messages |
57 | about its progress. | 58 | about its progress. |
@@ -69,11 +70,11 @@ FILES | |||
69 | 70 | ||
70 | 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 | 71 | 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 |
71 | 72 | ||
72 | Output format for rsa1 keys: | 73 | Output format for RSA1 keys: |
73 | 74 | ||
74 | host-or-namelist bits exponent modulus | 75 | host-or-namelist bits exponent modulus |
75 | 76 | ||
76 | Output format for rsa, dsa and ecdsa keys: | 77 | Output format for RSA, DSA, ECDSA, and ED25519 keys: |
77 | 78 | ||
78 | host-or-namelist keytype base64-encoded-key | 79 | host-or-namelist keytype base64-encoded-key |
79 | 80 | ||
@@ -90,7 +91,7 @@ EXAMPLES | |||
90 | Find all hosts from the file ssh_hosts which have new or different keys | 91 | Find all hosts from the file ssh_hosts which have new or different keys |
91 | from those in the sorted file ssh_known_hosts: | 92 | from those in the sorted file ssh_known_hosts: |
92 | 93 | ||
93 | $ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \ | 94 | $ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \ |
94 | sort -u - ssh_known_hosts | diff ssh_known_hosts - | 95 | sort -u - ssh_known_hosts | diff ssh_known_hosts - |
95 | 96 | ||
96 | SEE ALSO | 97 | SEE ALSO |
@@ -107,4 +108,4 @@ BUGS | |||
107 | This is because it opens a connection to the ssh port, reads the public | 108 | This is because it opens a connection to the ssh port, reads the public |
108 | key, and drops the connection as soon as it gets the key. | 109 | key, and drops the connection as soon as it gets the key. |
109 | 110 | ||
110 | OpenBSD 5.5 January 28, 2014 OpenBSD 5.5 | 111 | OpenBSD 5.6 March 12, 2014 OpenBSD 5.6 |
diff --git a/ssh-keyscan.1 b/ssh-keyscan.1 index dae4fd9fb..5c32ea9c7 100644 --- a/ssh-keyscan.1 +++ b/ssh-keyscan.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keyscan.1,v 1.34 2014/01/28 14:13:39 jmc Exp $ | 1 | .\" $OpenBSD: ssh-keyscan.1,v 1.35 2014/03/12 13:06:59 naddy Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. | 3 | .\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. |
4 | .\" | 4 | .\" |
@@ -6,7 +6,7 @@ | |||
6 | .\" permitted provided that due credit is given to the author and the | 6 | .\" permitted provided that due credit is given to the author and the |
7 | .\" OpenBSD project by leaving this copyright notice intact. | 7 | .\" OpenBSD project by leaving this copyright notice intact. |
8 | .\" | 8 | .\" |
9 | .Dd $Mdocdate: January 28 2014 $ | 9 | .Dd $Mdocdate: March 12 2014 $ |
10 | .Dt SSH-KEYSCAN 1 | 10 | .Dt SSH-KEYSCAN 1 |
11 | .Os | 11 | .Os |
12 | .Sh NAME | 12 | .Sh NAME |
@@ -98,9 +98,10 @@ or | |||
98 | for protocol version 2. | 98 | for protocol version 2. |
99 | Multiple values may be specified by separating them with commas. | 99 | Multiple values may be specified by separating them with commas. |
100 | The default is to fetch | 100 | The default is to fetch |
101 | .Dq rsa | 101 | .Dq rsa , |
102 | .Dq ecdsa , | ||
102 | and | 103 | and |
103 | .Dq ecdsa | 104 | .Dq ed25519 |
104 | keys. | 105 | keys. |
105 | .It Fl v | 106 | .It Fl v |
106 | Verbose mode. | 107 | Verbose mode. |
@@ -124,12 +125,12 @@ Input format: | |||
124 | 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 | 125 | 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 |
125 | .Ed | 126 | .Ed |
126 | .Pp | 127 | .Pp |
127 | Output format for rsa1 keys: | 128 | Output format for RSA1 keys: |
128 | .Bd -literal | 129 | .Bd -literal |
129 | host-or-namelist bits exponent modulus | 130 | host-or-namelist bits exponent modulus |
130 | .Ed | 131 | .Ed |
131 | .Pp | 132 | .Pp |
132 | Output format for rsa, dsa and ecdsa keys: | 133 | Output format for RSA, DSA, ECDSA, and ED25519 keys: |
133 | .Bd -literal | 134 | .Bd -literal |
134 | host-or-namelist keytype base64-encoded-key | 135 | host-or-namelist keytype base64-encoded-key |
135 | .Ed | 136 | .Ed |
@@ -158,7 +159,7 @@ Find all hosts from the file | |||
158 | which have new or different keys from those in the sorted file | 159 | which have new or different keys from those in the sorted file |
159 | .Pa ssh_known_hosts : | 160 | .Pa ssh_known_hosts : |
160 | .Bd -literal | 161 | .Bd -literal |
161 | $ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \e | 162 | $ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \e |
162 | sort -u - ssh_known_hosts | diff ssh_known_hosts - | 163 | sort -u - ssh_known_hosts | diff ssh_known_hosts - |
163 | .Ed | 164 | .Ed |
164 | .Sh SEE ALSO | 165 | .Sh SEE ALSO |
diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 8d0a6b8d8..3fabfba14 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keyscan.c,v 1.89 2013/12/06 13:39:49 markus Exp $ */ | 1 | /* $OpenBSD: ssh-keyscan.c,v 1.92 2014/04/29 18:01:49 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. | 3 | * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. |
4 | * | 4 | * |
@@ -58,7 +58,7 @@ int ssh_port = SSH_DEFAULT_PORT; | |||
58 | #define KT_ECDSA 8 | 58 | #define KT_ECDSA 8 |
59 | #define KT_ED25519 16 | 59 | #define KT_ED25519 16 |
60 | 60 | ||
61 | int get_keytypes = KT_RSA|KT_ECDSA;/* Get RSA and ECDSA keys by default */ | 61 | int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519; |
62 | 62 | ||
63 | int hash_hosts = 0; /* Hash hostname on output */ | 63 | int hash_hosts = 0; /* Hash hostname on output */ |
64 | 64 | ||
@@ -182,6 +182,7 @@ strnnsep(char **stringp, char *delim) | |||
182 | return (tok); | 182 | return (tok); |
183 | } | 183 | } |
184 | 184 | ||
185 | #ifdef WITH_SSH1 | ||
185 | static Key * | 186 | static Key * |
186 | keygrab_ssh1(con *c) | 187 | keygrab_ssh1(con *c) |
187 | { | 188 | { |
@@ -215,6 +216,7 @@ keygrab_ssh1(con *c) | |||
215 | 216 | ||
216 | return (rsa); | 217 | return (rsa); |
217 | } | 218 | } |
219 | #endif | ||
218 | 220 | ||
219 | static int | 221 | static int |
220 | hostjump(Key *hostkey) | 222 | hostjump(Key *hostkey) |
@@ -242,6 +244,7 @@ ssh2_capable(int remote_major, int remote_minor) | |||
242 | static Key * | 244 | static Key * |
243 | keygrab_ssh2(con *c) | 245 | keygrab_ssh2(con *c) |
244 | { | 246 | { |
247 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; | ||
245 | int j; | 248 | int j; |
246 | 249 | ||
247 | packet_set_connection(c->c_fd, c->c_fd); | 250 | packet_set_connection(c->c_fd, c->c_fd); |
@@ -252,11 +255,13 @@ keygrab_ssh2(con *c) | |||
252 | (c->c_keytype == KT_ED25519 ? "ssh-ed25519" : | 255 | (c->c_keytype == KT_ED25519 ? "ssh-ed25519" : |
253 | "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521")); | 256 | "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521")); |
254 | c->c_kex = kex_setup(myproposal); | 257 | c->c_kex = kex_setup(myproposal); |
258 | #ifdef WITH_OPENSSL | ||
255 | c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; | 259 | c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; |
256 | c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; | 260 | c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; |
257 | c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; | 261 | c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; |
258 | c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; | 262 | c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; |
259 | c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client; | 263 | c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client; |
264 | #endif | ||
260 | c->c_kex->kex[KEX_C25519_SHA256] = kexc25519_client; | 265 | c->c_kex->kex[KEX_C25519_SHA256] = kexc25519_client; |
261 | c->c_kex->verify_host_key = hostjump; | 266 | c->c_kex->verify_host_key = hostjump; |
262 | 267 | ||
@@ -506,10 +511,12 @@ conread(int s) | |||
506 | c->c_data = xmalloc(c->c_len); | 511 | c->c_data = xmalloc(c->c_len); |
507 | c->c_status = CS_KEYS; | 512 | c->c_status = CS_KEYS; |
508 | break; | 513 | break; |
514 | #ifdef WITH_SSH1 | ||
509 | case CS_KEYS: | 515 | case CS_KEYS: |
510 | keyprint(c, keygrab_ssh1(c)); | 516 | keyprint(c, keygrab_ssh1(c)); |
511 | confree(s); | 517 | confree(s); |
512 | return; | 518 | return; |
519 | #endif | ||
513 | default: | 520 | default: |
514 | fatal("conread: invalid status %d", c->c_status); | 521 | fatal("conread: invalid status %d", c->c_status); |
515 | break; | 522 | break; |
diff --git a/ssh-keysign.0 b/ssh-keysign.0 index 5f18b54e3..c34125b72 100644 --- a/ssh-keysign.0 +++ b/ssh-keysign.0 | |||
@@ -1,4 +1,4 @@ | |||
1 | SSH-KEYSIGN(8) OpenBSD System Manager's Manual SSH-KEYSIGN(8) | 1 | SSH-KEYSIGN(8) System Manager's Manual SSH-KEYSIGN(8) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh-keysign - ssh helper program for host-based authentication | 4 | ssh-keysign - ssh helper program for host-based authentication |
@@ -50,4 +50,4 @@ HISTORY | |||
50 | AUTHORS | 50 | AUTHORS |
51 | Markus Friedl <markus@openbsd.org> | 51 | Markus Friedl <markus@openbsd.org> |
52 | 52 | ||
53 | OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 | 53 | OpenBSD 5.6 December 7, 2013 OpenBSD 5.6 |
diff --git a/ssh-keysign.c b/ssh-keysign.c index 6bde8ad17..d95bb7d9d 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keysign.c,v 1.39 2013/12/06 13:39:49 markus Exp $ */ | 1 | /* $OpenBSD: ssh-keysign.c,v 1.42 2014/04/29 18:01:49 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -155,7 +155,7 @@ main(int argc, char **argv) | |||
155 | struct passwd *pw; | 155 | struct passwd *pw; |
156 | int key_fd[NUM_KEYTYPES], i, found, version = 2, fd; | 156 | int key_fd[NUM_KEYTYPES], i, found, version = 2, fd; |
157 | u_char *signature, *data; | 157 | u_char *signature, *data; |
158 | char *host; | 158 | char *host, *fp; |
159 | u_int slen, dlen; | 159 | u_int slen, dlen; |
160 | u_int32_t rnd[256]; | 160 | u_int32_t rnd[256]; |
161 | 161 | ||
@@ -201,8 +201,7 @@ main(int argc, char **argv) | |||
201 | fatal("could not open any host key"); | 201 | fatal("could not open any host key"); |
202 | 202 | ||
203 | OpenSSL_add_all_algorithms(); | 203 | OpenSSL_add_all_algorithms(); |
204 | for (i = 0; i < 256; i++) | 204 | arc4random_buf(rnd, sizeof(rnd)); |
205 | rnd[i] = arc4random(); | ||
206 | RAND_seed(rnd, sizeof(rnd)); | 205 | RAND_seed(rnd, sizeof(rnd)); |
207 | 206 | ||
208 | found = 0; | 207 | found = 0; |
@@ -210,8 +209,11 @@ main(int argc, char **argv) | |||
210 | keys[i] = NULL; | 209 | keys[i] = NULL; |
211 | if (key_fd[i] == -1) | 210 | if (key_fd[i] == -1) |
212 | continue; | 211 | continue; |
212 | #ifdef WITH_OPENSSL | ||
213 | /* XXX wrong api */ | ||
213 | keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, | 214 | keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, |
214 | NULL, NULL); | 215 | NULL, NULL); |
216 | #endif | ||
215 | close(key_fd[i]); | 217 | close(key_fd[i]); |
216 | if (keys[i] != NULL) | 218 | if (keys[i] != NULL) |
217 | found = 1; | 219 | found = 1; |
@@ -243,8 +245,11 @@ main(int argc, char **argv) | |||
243 | break; | 245 | break; |
244 | } | 246 | } |
245 | } | 247 | } |
246 | if (!found) | 248 | if (!found) { |
247 | fatal("no matching hostkey found"); | 249 | fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); |
250 | fatal("no matching hostkey found for key %s %s", | ||
251 | key_type(key), fp); | ||
252 | } | ||
248 | 253 | ||
249 | if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) | 254 | if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) |
250 | fatal("key_sign failed"); | 255 | fatal("key_sign failed"); |
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index 6c9f9d2c1..8c74864aa 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-pkcs11-client.c,v 1.4 2013/05/17 00:13:14 djm Exp $ */ | 1 | /* $OpenBSD: ssh-pkcs11-client.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -30,6 +30,8 @@ | |||
30 | #include <unistd.h> | 30 | #include <unistd.h> |
31 | #include <errno.h> | 31 | #include <errno.h> |
32 | 32 | ||
33 | #include <openssl/rsa.h> | ||
34 | |||
33 | #include "pathnames.h" | 35 | #include "pathnames.h" |
34 | #include "xmalloc.h" | 36 | #include "xmalloc.h" |
35 | #include "buffer.h" | 37 | #include "buffer.h" |
diff --git a/ssh-pkcs11-helper.0 b/ssh-pkcs11-helper.0 index 20d62f7a9..279ec5486 100644 --- a/ssh-pkcs11-helper.0 +++ b/ssh-pkcs11-helper.0 | |||
@@ -1,4 +1,4 @@ | |||
1 | SSH-PKCS11-HELPER(8) OpenBSD System Manager's Manual SSH-PKCS11-HELPER(8) | 1 | SSH-PKCS11-HELPER(8) System Manager's Manual SSH-PKCS11-HELPER(8) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh-pkcs11-helper - ssh-agent helper program for PKCS#11 support | 4 | ssh-pkcs11-helper - ssh-agent helper program for PKCS#11 support |
@@ -22,4 +22,4 @@ HISTORY | |||
22 | AUTHORS | 22 | AUTHORS |
23 | Markus Friedl <markus@openbsd.org> | 23 | Markus Friedl <markus@openbsd.org> |
24 | 24 | ||
25 | OpenBSD 5.5 July 16, 2013 OpenBSD 5.5 | 25 | OpenBSD 5.6 July 16, 2013 OpenBSD 5.6 |
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index b7c52beb8..0b1d8e4cc 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-pkcs11-helper.c,v 1.7 2013/12/02 02:56:17 djm Exp $ */ | 1 | /* $OpenBSD: ssh-pkcs11-helper.c,v 1.8 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -169,7 +169,7 @@ process_sign(void) | |||
169 | { | 169 | { |
170 | u_char *blob, *data, *signature = NULL; | 170 | u_char *blob, *data, *signature = NULL; |
171 | u_int blen, dlen, slen = 0; | 171 | u_int blen, dlen, slen = 0; |
172 | int ok = -1, ret; | 172 | int ok = -1; |
173 | Key *key, *found; | 173 | Key *key, *found; |
174 | Buffer msg; | 174 | Buffer msg; |
175 | 175 | ||
@@ -179,6 +179,9 @@ process_sign(void) | |||
179 | 179 | ||
180 | if ((key = key_from_blob(blob, blen)) != NULL) { | 180 | if ((key = key_from_blob(blob, blen)) != NULL) { |
181 | if ((found = lookup_key(key)) != NULL) { | 181 | if ((found = lookup_key(key)) != NULL) { |
182 | #ifdef WITH_OPENSSL | ||
183 | int ret; | ||
184 | |||
182 | slen = RSA_size(key->rsa); | 185 | slen = RSA_size(key->rsa); |
183 | signature = xmalloc(slen); | 186 | signature = xmalloc(slen); |
184 | if ((ret = RSA_private_encrypt(dlen, data, signature, | 187 | if ((ret = RSA_private_encrypt(dlen, data, signature, |
@@ -186,6 +189,7 @@ process_sign(void) | |||
186 | slen = ret; | 189 | slen = ret; |
187 | ok = 0; | 190 | ok = 0; |
188 | } | 191 | } |
192 | #endif /* WITH_OPENSSL */ | ||
189 | } | 193 | } |
190 | key_free(key); | 194 | key_free(key); |
191 | } | 195 | } |
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index c49cbf42b..c96be3bd2 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-pkcs11.c,v 1.11 2013/11/13 13:48:20 markus Exp $ */ | 1 | /* $OpenBSD: ssh-pkcs11.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -520,7 +520,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, | |||
520 | key = key_new(KEY_UNSPEC); | 520 | key = key_new(KEY_UNSPEC); |
521 | key->rsa = rsa; | 521 | key->rsa = rsa; |
522 | key->type = KEY_RSA; | 522 | key->type = KEY_RSA; |
523 | key->flags |= KEY_FLAG_EXT; | 523 | key->flags |= SSHKEY_FLAG_EXT; |
524 | if (pkcs11_key_included(keysp, nkeys, key)) { | 524 | if (pkcs11_key_included(keysp, nkeys, key)) { |
525 | key_free(key); | 525 | key_free(key); |
526 | } else { | 526 | } else { |
diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h index 59f456adf..4d2efda13 100644 --- a/ssh-pkcs11.h +++ b/ssh-pkcs11.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-pkcs11.h,v 1.2 2010/02/24 06:12:53 djm Exp $ */ | 1 | /* $OpenBSD: ssh-pkcs11.h,v 1.3 2014/04/29 18:01:49 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -18,3 +18,7 @@ int pkcs11_init(int); | |||
18 | void pkcs11_terminate(void); | 18 | void pkcs11_terminate(void); |
19 | int pkcs11_add_provider(char *, char *, Key ***); | 19 | int pkcs11_add_provider(char *, char *, Key ***); |
20 | int pkcs11_del_provider(char *); | 20 | int pkcs11_del_provider(char *); |
21 | |||
22 | #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) | ||
23 | #undef ENABLE_PKCS11 | ||
24 | #endif | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-rsa.c,v 1.51 2014/02/02 03:44:31 djm Exp $ */ | 1 | /* $OpenBSD: ssh-rsa.c,v 1.52 2014/06/24 01:13:21 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> | 3 | * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> |
4 | * | 4 | * |
@@ -25,163 +25,167 @@ | |||
25 | #include <stdarg.h> | 25 | #include <stdarg.h> |
26 | #include <string.h> | 26 | #include <string.h> |
27 | 27 | ||
28 | #include "xmalloc.h" | 28 | #include "sshbuf.h" |
29 | #include "log.h" | ||
30 | #include "buffer.h" | ||
31 | #include "key.h" | ||
32 | #include "compat.h" | 29 | #include "compat.h" |
33 | #include "misc.h" | 30 | #include "ssherr.h" |
34 | #include "ssh.h" | 31 | #define SSHKEY_INTERNAL |
32 | #include "sshkey.h" | ||
35 | #include "digest.h" | 33 | #include "digest.h" |
36 | 34 | ||
37 | static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); | 35 | static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); |
38 | 36 | ||
39 | /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ | 37 | /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ |
40 | int | 38 | int |
41 | ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, | 39 | ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |
42 | const u_char *data, u_int datalen) | 40 | const u_char *data, size_t datalen, u_int compat) |
43 | { | 41 | { |
44 | int hash_alg; | 42 | int hash_alg; |
45 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sig; | 43 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; |
46 | u_int slen, dlen, len; | 44 | size_t slen; |
47 | int ok, nid; | 45 | u_int dlen, len; |
48 | Buffer b; | 46 | int nid, ret = SSH_ERR_INTERNAL_ERROR; |
47 | struct sshbuf *b = NULL; | ||
49 | 48 | ||
50 | if (key == NULL || key_type_plain(key->type) != KEY_RSA || | 49 | if (lenp != NULL) |
51 | key->rsa == NULL) { | 50 | *lenp = 0; |
52 | error("%s: no RSA key", __func__); | 51 | if (sigp != NULL) |
53 | return -1; | 52 | *sigp = NULL; |
54 | } | 53 | |
54 | if (key == NULL || key->rsa == NULL || | ||
55 | sshkey_type_plain(key->type) != KEY_RSA) | ||
56 | return SSH_ERR_INVALID_ARGUMENT; | ||
57 | slen = RSA_size(key->rsa); | ||
58 | if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) | ||
59 | return SSH_ERR_INVALID_ARGUMENT; | ||
55 | 60 | ||
56 | /* hash the data */ | 61 | /* hash the data */ |
57 | hash_alg = SSH_DIGEST_SHA1; | 62 | hash_alg = SSH_DIGEST_SHA1; |
58 | nid = NID_sha1; | 63 | nid = NID_sha1; |
59 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { | 64 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) |
60 | error("%s: bad hash algorithm %d", __func__, hash_alg); | 65 | return SSH_ERR_INTERNAL_ERROR; |
61 | return -1; | 66 | if ((ret = ssh_digest_memory(hash_alg, data, datalen, |
62 | } | 67 | digest, sizeof(digest))) != 0) |
63 | if (ssh_digest_memory(hash_alg, data, datalen, | 68 | goto out; |
64 | digest, sizeof(digest)) != 0) { | ||
65 | error("%s: ssh_digest_memory failed", __func__); | ||
66 | return -1; | ||
67 | } | ||
68 | |||
69 | slen = RSA_size(key->rsa); | ||
70 | sig = xmalloc(slen); | ||
71 | |||
72 | ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); | ||
73 | explicit_bzero(digest, sizeof(digest)); | ||
74 | 69 | ||
75 | if (ok != 1) { | 70 | if ((sig = malloc(slen)) == NULL) { |
76 | int ecode = ERR_get_error(); | 71 | ret = SSH_ERR_ALLOC_FAIL; |
72 | goto out; | ||
73 | } | ||
77 | 74 | ||
78 | error("%s: RSA_sign failed: %s", __func__, | 75 | if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { |
79 | ERR_error_string(ecode, NULL)); | 76 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
80 | free(sig); | 77 | goto out; |
81 | return -1; | ||
82 | } | 78 | } |
83 | if (len < slen) { | 79 | if (len < slen) { |
84 | u_int diff = slen - len; | 80 | size_t diff = slen - len; |
85 | debug("slen %u > len %u", slen, len); | ||
86 | memmove(sig + diff, sig, len); | 81 | memmove(sig + diff, sig, len); |
87 | explicit_bzero(sig, diff); | 82 | explicit_bzero(sig, diff); |
88 | } else if (len > slen) { | 83 | } else if (len > slen) { |
89 | error("%s: slen %u slen2 %u", __func__, slen, len); | 84 | ret = SSH_ERR_INTERNAL_ERROR; |
90 | free(sig); | 85 | goto out; |
91 | return -1; | ||
92 | } | 86 | } |
93 | /* encode signature */ | 87 | /* encode signature */ |
94 | buffer_init(&b); | 88 | if ((b = sshbuf_new()) == NULL) { |
95 | buffer_put_cstring(&b, "ssh-rsa"); | 89 | ret = SSH_ERR_ALLOC_FAIL; |
96 | buffer_put_string(&b, sig, slen); | 90 | goto out; |
97 | len = buffer_len(&b); | 91 | } |
92 | if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 || | ||
93 | (ret = sshbuf_put_string(b, sig, slen)) != 0) | ||
94 | goto out; | ||
95 | len = sshbuf_len(b); | ||
96 | if (sigp != NULL) { | ||
97 | if ((*sigp = malloc(len)) == NULL) { | ||
98 | ret = SSH_ERR_ALLOC_FAIL; | ||
99 | goto out; | ||
100 | } | ||
101 | memcpy(*sigp, sshbuf_ptr(b), len); | ||
102 | } | ||
98 | if (lenp != NULL) | 103 | if (lenp != NULL) |
99 | *lenp = len; | 104 | *lenp = len; |
100 | if (sigp != NULL) { | 105 | ret = 0; |
101 | *sigp = xmalloc(len); | 106 | out: |
102 | memcpy(*sigp, buffer_ptr(&b), len); | 107 | explicit_bzero(digest, sizeof(digest)); |
108 | if (sig != NULL) { | ||
109 | explicit_bzero(sig, slen); | ||
110 | free(sig); | ||
103 | } | 111 | } |
104 | buffer_free(&b); | 112 | if (b != NULL) |
105 | explicit_bzero(sig, slen); | 113 | sshbuf_free(b); |
106 | free(sig); | ||
107 | |||
108 | return 0; | 114 | return 0; |
109 | } | 115 | } |
110 | 116 | ||
111 | int | 117 | int |
112 | ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, | 118 | ssh_rsa_verify(const struct sshkey *key, |
113 | const u_char *data, u_int datalen) | 119 | const u_char *signature, size_t signaturelen, |
120 | const u_char *data, size_t datalen, u_int compat) | ||
114 | { | 121 | { |
115 | Buffer b; | 122 | char *ktype = NULL; |
116 | int hash_alg; | 123 | int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; |
117 | char *ktype; | 124 | size_t len, diff, modlen, dlen; |
118 | u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; | 125 | struct sshbuf *b = NULL; |
119 | u_int len, dlen, modlen; | 126 | u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; |
120 | int rlen, ret; | ||
121 | 127 | ||
122 | if (key == NULL || key_type_plain(key->type) != KEY_RSA || | 128 | if (key == NULL || key->rsa == NULL || |
123 | key->rsa == NULL) { | 129 | sshkey_type_plain(key->type) != KEY_RSA || |
124 | error("%s: no RSA key", __func__); | 130 | BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) |
125 | return -1; | 131 | return SSH_ERR_INVALID_ARGUMENT; |
126 | } | ||
127 | 132 | ||
128 | if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | 133 | if ((b = sshbuf_from(signature, signaturelen)) == NULL) |
129 | error("%s: RSA modulus too small: %d < minimum %d bits", | 134 | return SSH_ERR_ALLOC_FAIL; |
130 | __func__, BN_num_bits(key->rsa->n), | 135 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { |
131 | SSH_RSA_MINIMUM_MODULUS_SIZE); | 136 | ret = SSH_ERR_INVALID_FORMAT; |
132 | return -1; | 137 | goto out; |
133 | } | 138 | } |
134 | buffer_init(&b); | ||
135 | buffer_append(&b, signature, signaturelen); | ||
136 | ktype = buffer_get_cstring(&b, NULL); | ||
137 | if (strcmp("ssh-rsa", ktype) != 0) { | 139 | if (strcmp("ssh-rsa", ktype) != 0) { |
138 | error("%s: cannot handle type %s", __func__, ktype); | 140 | ret = SSH_ERR_KEY_TYPE_MISMATCH; |
139 | buffer_free(&b); | 141 | goto out; |
140 | free(ktype); | ||
141 | return -1; | ||
142 | } | 142 | } |
143 | free(ktype); | 143 | if (sshbuf_get_string(b, &sigblob, &len) != 0) { |
144 | sigblob = buffer_get_string(&b, &len); | 144 | ret = SSH_ERR_INVALID_FORMAT; |
145 | rlen = buffer_len(&b); | 145 | goto out; |
146 | buffer_free(&b); | 146 | } |
147 | if (rlen != 0) { | 147 | if (sshbuf_len(b) != 0) { |
148 | error("%s: remaining bytes in signature %d", __func__, rlen); | 148 | ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; |
149 | free(sigblob); | 149 | goto out; |
150 | return -1; | ||
151 | } | 150 | } |
152 | /* RSA_verify expects a signature of RSA_size */ | 151 | /* RSA_verify expects a signature of RSA_size */ |
153 | modlen = RSA_size(key->rsa); | 152 | modlen = RSA_size(key->rsa); |
154 | if (len > modlen) { | 153 | if (len > modlen) { |
155 | error("%s: len %u > modlen %u", __func__, len, modlen); | 154 | ret = SSH_ERR_KEY_BITS_MISMATCH; |
156 | free(sigblob); | 155 | goto out; |
157 | return -1; | ||
158 | } else if (len < modlen) { | 156 | } else if (len < modlen) { |
159 | u_int diff = modlen - len; | 157 | diff = modlen - len; |
160 | debug("%s: add padding: modlen %u > len %u", __func__, | 158 | osigblob = sigblob; |
161 | modlen, len); | 159 | if ((sigblob = realloc(sigblob, modlen)) == NULL) { |
162 | sigblob = xrealloc(sigblob, 1, modlen); | 160 | sigblob = osigblob; /* put it back for clear/free */ |
161 | ret = SSH_ERR_ALLOC_FAIL; | ||
162 | goto out; | ||
163 | } | ||
163 | memmove(sigblob + diff, sigblob, len); | 164 | memmove(sigblob + diff, sigblob, len); |
164 | explicit_bzero(sigblob, diff); | 165 | explicit_bzero(sigblob, diff); |
165 | len = modlen; | 166 | len = modlen; |
166 | } | 167 | } |
167 | /* hash the data */ | ||
168 | hash_alg = SSH_DIGEST_SHA1; | 168 | hash_alg = SSH_DIGEST_SHA1; |
169 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { | 169 | if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { |
170 | error("%s: bad hash algorithm %d", __func__, hash_alg); | 170 | ret = SSH_ERR_INTERNAL_ERROR; |
171 | return -1; | 171 | goto out; |
172 | } | ||
173 | if (ssh_digest_memory(hash_alg, data, datalen, | ||
174 | digest, sizeof(digest)) != 0) { | ||
175 | error("%s: ssh_digest_memory failed", __func__); | ||
176 | return -1; | ||
177 | } | 172 | } |
173 | if ((ret = ssh_digest_memory(hash_alg, data, datalen, | ||
174 | digest, sizeof(digest))) != 0) | ||
175 | goto out; | ||
178 | 176 | ||
179 | ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, | 177 | ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, |
180 | key->rsa); | 178 | key->rsa); |
179 | out: | ||
180 | if (sigblob != NULL) { | ||
181 | explicit_bzero(sigblob, len); | ||
182 | free(sigblob); | ||
183 | } | ||
184 | if (ktype != NULL) | ||
185 | free(ktype); | ||
186 | if (b != NULL) | ||
187 | sshbuf_free(b); | ||
181 | explicit_bzero(digest, sizeof(digest)); | 188 | explicit_bzero(digest, sizeof(digest)); |
182 | explicit_bzero(sigblob, len); | ||
183 | free(sigblob); | ||
184 | debug("%s: signature %scorrect", __func__, (ret == 0) ? "in" : ""); | ||
185 | return ret; | 189 | return ret; |
186 | } | 190 | } |
187 | 191 | ||
@@ -204,15 +208,15 @@ static const u_char id_sha1[] = { | |||
204 | }; | 208 | }; |
205 | 209 | ||
206 | static int | 210 | static int |
207 | openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen, | 211 | openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, |
208 | u_char *sigbuf, u_int siglen, RSA *rsa) | 212 | u_char *sigbuf, size_t siglen, RSA *rsa) |
209 | { | 213 | { |
210 | u_int ret, rsasize, oidlen = 0, hlen = 0; | 214 | size_t ret, rsasize = 0, oidlen = 0, hlen = 0; |
211 | int len, oidmatch, hashmatch; | 215 | int len, oidmatch, hashmatch; |
212 | const u_char *oid = NULL; | 216 | const u_char *oid = NULL; |
213 | u_char *decrypted = NULL; | 217 | u_char *decrypted = NULL; |
214 | 218 | ||
215 | ret = 0; | 219 | ret = SSH_ERR_INTERNAL_ERROR; |
216 | switch (hash_alg) { | 220 | switch (hash_alg) { |
217 | case SSH_DIGEST_SHA1: | 221 | case SSH_DIGEST_SHA1: |
218 | oid = id_sha1; | 222 | oid = id_sha1; |
@@ -223,37 +227,39 @@ openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen, | |||
223 | goto done; | 227 | goto done; |
224 | } | 228 | } |
225 | if (hashlen != hlen) { | 229 | if (hashlen != hlen) { |
226 | error("bad hashlen"); | 230 | ret = SSH_ERR_INVALID_ARGUMENT; |
227 | goto done; | 231 | goto done; |
228 | } | 232 | } |
229 | rsasize = RSA_size(rsa); | 233 | rsasize = RSA_size(rsa); |
230 | if (siglen == 0 || siglen > rsasize) { | 234 | if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || |
231 | error("bad siglen"); | 235 | siglen == 0 || siglen > rsasize) { |
236 | ret = SSH_ERR_INVALID_ARGUMENT; | ||
237 | goto done; | ||
238 | } | ||
239 | if ((decrypted = malloc(rsasize)) == NULL) { | ||
240 | ret = SSH_ERR_ALLOC_FAIL; | ||
232 | goto done; | 241 | goto done; |
233 | } | 242 | } |
234 | decrypted = xmalloc(rsasize); | ||
235 | if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, | 243 | if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, |
236 | RSA_PKCS1_PADDING)) < 0) { | 244 | RSA_PKCS1_PADDING)) < 0) { |
237 | error("RSA_public_decrypt failed: %s", | 245 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
238 | ERR_error_string(ERR_get_error(), NULL)); | ||
239 | goto done; | 246 | goto done; |
240 | } | 247 | } |
241 | if (len < 0 || (u_int)len != hlen + oidlen) { | 248 | if (len < 0 || (size_t)len != hlen + oidlen) { |
242 | error("bad decrypted len: %d != %d + %d", len, hlen, oidlen); | 249 | ret = SSH_ERR_INVALID_FORMAT; |
243 | goto done; | 250 | goto done; |
244 | } | 251 | } |
245 | oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; | 252 | oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; |
246 | hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; | 253 | hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; |
247 | if (!oidmatch) { | 254 | if (!oidmatch || !hashmatch) { |
248 | error("oid mismatch"); | 255 | ret = SSH_ERR_SIGNATURE_INVALID; |
249 | goto done; | ||
250 | } | ||
251 | if (!hashmatch) { | ||
252 | error("hash mismatch"); | ||
253 | goto done; | 256 | goto done; |
254 | } | 257 | } |
255 | ret = 1; | 258 | ret = 0; |
256 | done: | 259 | done: |
257 | free(decrypted); | 260 | if (decrypted) { |
261 | explicit_bzero(decrypted, rsasize); | ||
262 | free(decrypted); | ||
263 | } | ||
258 | return ret; | 264 | return ret; |
259 | } | 265 | } |
@@ -1,4 +1,4 @@ | |||
1 | SSH(1) OpenBSD Reference Manual SSH(1) | 1 | SSH(1) General Commands Manual SSH(1) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh - OpenSSH SSH client (remote login program) | 4 | ssh - OpenSSH SSH client (remote login program) |
@@ -17,8 +17,9 @@ DESCRIPTION | |||
17 | ssh (SSH client) is a program for logging into a remote machine and for | 17 | ssh (SSH client) is a program for logging into a remote machine and for |
18 | executing commands on a remote machine. It is intended to replace rlogin | 18 | executing commands on a remote machine. It is intended to replace rlogin |
19 | and rsh, and provide secure encrypted communications between two | 19 | and rsh, and provide secure encrypted communications between two |
20 | untrusted hosts over an insecure network. X11 connections and arbitrary | 20 | untrusted hosts over an insecure network. X11 connections, arbitrary TCP |
21 | TCP ports can also be forwarded over the secure channel. | 21 | ports and UNIX-domain sockets can also be forwarded over the secure |
22 | channel. | ||
22 | 23 | ||
23 | ssh connects and logs into the specified hostname (with optional user | 24 | ssh connects and logs into the specified hostname (with optional user |
24 | name). The user must prove his/her identity to the remote machine using | 25 | name). The user must prove his/her identity to the remote machine using |
@@ -58,28 +59,21 @@ DESCRIPTION | |||
58 | address. | 59 | address. |
59 | 60 | ||
60 | -C Requests compression of all data (including stdin, stdout, | 61 | -C Requests compression of all data (including stdin, stdout, |
61 | stderr, and data for forwarded X11 and TCP connections). The | 62 | stderr, and data for forwarded X11, TCP and UNIX-domain |
62 | compression algorithm is the same used by gzip(1), and the | 63 | connections). The compression algorithm is the same used by |
63 | ``level'' can be controlled by the CompressionLevel option for | 64 | gzip(1), and the ``level'' can be controlled by the |
64 | protocol version 1. Compression is desirable on modem lines and | 65 | CompressionLevel option for protocol version 1. Compression is |
65 | other slow connections, but will only slow down things on fast | 66 | desirable on modem lines and other slow connections, but will |
66 | networks. The default value can be set on a host-by-host basis | 67 | only slow down things on fast networks. The default value can be |
67 | in the configuration files; see the Compression option. | 68 | set on a host-by-host basis in the configuration files; see the |
69 | Compression option. | ||
68 | 70 | ||
69 | -c cipher_spec | 71 | -c cipher_spec |
70 | Selects the cipher specification for encrypting the session. | 72 | Selects the cipher specification for encrypting the session. |
71 | 73 | ||
72 | Protocol version 1 allows specification of a single cipher. The | 74 | Protocol version 1 allows specification of a single cipher. The |
73 | supported values are ``3des'', ``blowfish'', and ``des''. 3des | 75 | supported values are ``3des'', ``blowfish'', and ``des''. For |
74 | (triple-des) is an encrypt-decrypt-encrypt triple with three | 76 | protocol version 2, cipher_spec is a comma-separated list of |
75 | different keys. It is believed to be secure. blowfish is a fast | ||
76 | block cipher; it appears very secure and is much faster than | ||
77 | 3des. des is only supported in the ssh client for | ||
78 | interoperability with legacy protocol 1 implementations that do | ||
79 | not support the 3des cipher. Its use is strongly discouraged due | ||
80 | to cryptographic weaknesses. The default is ``3des''. | ||
81 | |||
82 | For protocol version 2, cipher_spec is a comma-separated list of | ||
83 | ciphers listed in order of preference. See the Ciphers keyword | 77 | ciphers listed in order of preference. See the Ciphers keyword |
84 | in ssh_config(5) for more information. | 78 | in ssh_config(5) for more information. |
85 | 79 | ||
@@ -133,7 +127,9 @@ DESCRIPTION | |||
133 | port forwards to be successfully established before placing | 127 | port forwards to be successfully established before placing |
134 | itself in the background. | 128 | itself in the background. |
135 | 129 | ||
136 | -g Allows remote hosts to connect to local forwarded ports. | 130 | -g Allows remote hosts to connect to local forwarded ports. If used |
131 | on a multiplexed connection, then this option must be specified | ||
132 | on the master process. | ||
137 | 133 | ||
138 | -I pkcs11 | 134 | -I pkcs11 |
139 | Specify the PKCS#11 shared library ssh should use to communicate | 135 | Specify the PKCS#11 shared library ssh should use to communicate |
@@ -286,6 +282,8 @@ DESCRIPTION | |||
286 | SendEnv | 282 | SendEnv |
287 | ServerAliveInterval | 283 | ServerAliveInterval |
288 | ServerAliveCountMax | 284 | ServerAliveCountMax |
285 | StreamLocalBindMask | ||
286 | StreamLocalBindUnlink | ||
289 | StrictHostKeyChecking | 287 | StrictHostKeyChecking |
290 | TCPKeepAlive | 288 | TCPKeepAlive |
291 | Tunnel | 289 | Tunnel |
@@ -890,7 +888,7 @@ EXIT STATUS | |||
890 | 888 | ||
891 | SEE ALSO | 889 | SEE ALSO |
892 | scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1), | 890 | scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1), |
893 | tun(4), hosts.equiv(5), ssh_config(5), ssh-keysign(8), sshd(8) | 891 | tun(4), ssh_config(5), ssh-keysign(8), sshd(8) |
894 | 892 | ||
895 | STANDARDS | 893 | STANDARDS |
896 | S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned | 894 | S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned |
@@ -943,4 +941,4 @@ AUTHORS | |||
943 | created OpenSSH. Markus Friedl contributed the support for SSH protocol | 941 | created OpenSSH. Markus Friedl contributed the support for SSH protocol |
944 | versions 1.5 and 2.0. | 942 | versions 1.5 and 2.0. |
945 | 943 | ||
946 | OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 | 944 | OpenBSD 5.6 July 24, 2014 OpenBSD 5.6 |
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 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. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh.1,v 1.343 2013/12/07 11:58:46 naddy Exp $ | 36 | .\" $OpenBSD: ssh.1,v 1.348 2014/07/24 22:57:10 millert Exp $ |
37 | .Dd $Mdocdate: December 7 2013 $ | 37 | .Dd $Mdocdate: July 24 2014 $ |
38 | .Dt SSH 1 | 38 | .Dt SSH 1 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -73,8 +73,9 @@ executing commands on a remote machine. | |||
73 | It is intended to replace rlogin and rsh, | 73 | It is intended to replace rlogin and rsh, |
74 | and provide secure encrypted communications between | 74 | and provide secure encrypted communications between |
75 | two untrusted hosts over an insecure network. | 75 | two untrusted hosts over an insecure network. |
76 | X11 connections and arbitrary TCP ports | 76 | X11 connections, arbitrary TCP ports and |
77 | can also be forwarded over the secure channel. | 77 | .Ux Ns -domain |
78 | sockets can also be forwarded over the secure channel. | ||
78 | .Pp | 79 | .Pp |
79 | .Nm | 80 | .Nm |
80 | connects and logs into the specified | 81 | connects and logs into the specified |
@@ -131,7 +132,9 @@ of the connection. | |||
131 | Only useful on systems with more than one address. | 132 | Only useful on systems with more than one address. |
132 | .It Fl C | 133 | .It Fl C |
133 | Requests compression of all data (including stdin, stdout, stderr, and | 134 | Requests compression of all data (including stdin, stdout, stderr, and |
134 | data for forwarded X11 and TCP connections). | 135 | data for forwarded X11, TCP and |
136 | .Ux Ns -domain | ||
137 | connections). | ||
135 | The compression algorithm is the same used by | 138 | The compression algorithm is the same used by |
136 | .Xr gzip 1 , | 139 | .Xr gzip 1 , |
137 | and the | 140 | and the |
@@ -154,23 +157,6 @@ The supported values are | |||
154 | .Dq blowfish , | 157 | .Dq blowfish , |
155 | and | 158 | and |
156 | .Dq des . | 159 | .Dq des . |
157 | .Ar 3des | ||
158 | (triple-des) is an encrypt-decrypt-encrypt triple with three different keys. | ||
159 | It is believed to be secure. | ||
160 | .Ar blowfish | ||
161 | is a fast block cipher; it appears very secure and is much faster than | ||
162 | .Ar 3des . | ||
163 | .Ar des | ||
164 | is only supported in the | ||
165 | .Nm | ||
166 | client for interoperability with legacy protocol 1 implementations | ||
167 | that do not support the | ||
168 | .Ar 3des | ||
169 | cipher. | ||
170 | Its use is strongly discouraged due to cryptographic weaknesses. | ||
171 | The default is | ||
172 | .Dq 3des . | ||
173 | .Pp | ||
174 | For protocol version 2, | 160 | For protocol version 2, |
175 | .Ar cipher_spec | 161 | .Ar cipher_spec |
176 | is a comma-separated list of ciphers | 162 | is a comma-separated list of ciphers |
@@ -267,6 +253,8 @@ will wait for all remote port forwards to be successfully established | |||
267 | before placing itself in the background. | 253 | before placing itself in the background. |
268 | .It Fl g | 254 | .It Fl g |
269 | Allows remote hosts to connect to local forwarded ports. | 255 | Allows remote hosts to connect to local forwarded ports. |
256 | If used on a multiplexed connection, then this option must be specified | ||
257 | on the master process. | ||
270 | .It Fl I Ar pkcs11 | 258 | .It Fl I Ar pkcs11 |
271 | Specify the PKCS#11 shared library | 259 | Specify the PKCS#11 shared library |
272 | .Nm | 260 | .Nm |
@@ -481,6 +469,8 @@ For full details of the options listed below, and their possible values, see | |||
481 | .It SendEnv | 469 | .It SendEnv |
482 | .It ServerAliveInterval | 470 | .It ServerAliveInterval |
483 | .It ServerAliveCountMax | 471 | .It ServerAliveCountMax |
472 | .It StreamLocalBindMask | ||
473 | .It StreamLocalBindUnlink | ||
484 | .It StrictHostKeyChecking | 474 | .It StrictHostKeyChecking |
485 | .It TCPKeepAlive | 475 | .It TCPKeepAlive |
486 | .It Tunnel | 476 | .It Tunnel |
@@ -1472,7 +1462,6 @@ if an error occurred. | |||
1472 | .Xr ssh-keygen 1 , | 1462 | .Xr ssh-keygen 1 , |
1473 | .Xr ssh-keyscan 1 , | 1463 | .Xr ssh-keyscan 1 , |
1474 | .Xr tun 4 , | 1464 | .Xr tun 4 , |
1475 | .Xr hosts.equiv 5 , | ||
1476 | .Xr ssh_config 5 , | 1465 | .Xr ssh_config 5 , |
1477 | .Xr ssh-keysign 8 , | 1466 | .Xr ssh-keysign 8 , |
1478 | .Xr sshd 8 | 1467 | .Xr sshd 8 |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.401 2014/02/26 20:18:37 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.407 2014/07/17 07:22:19 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -71,8 +71,10 @@ | |||
71 | #include <netinet/in.h> | 71 | #include <netinet/in.h> |
72 | #include <arpa/inet.h> | 72 | #include <arpa/inet.h> |
73 | 73 | ||
74 | #ifdef WITH_OPENSSL | ||
74 | #include <openssl/evp.h> | 75 | #include <openssl/evp.h> |
75 | #include <openssl/err.h> | 76 | #include <openssl/err.h> |
77 | #endif | ||
76 | #include "openbsd-compat/openssl-compat.h" | 78 | #include "openbsd-compat/openssl-compat.h" |
77 | #include "openbsd-compat/sys-queue.h" | 79 | #include "openbsd-compat/sys-queue.h" |
78 | 80 | ||
@@ -83,6 +85,7 @@ | |||
83 | #include "canohost.h" | 85 | #include "canohost.h" |
84 | #include "compat.h" | 86 | #include "compat.h" |
85 | #include "cipher.h" | 87 | #include "cipher.h" |
88 | #include "digest.h" | ||
86 | #include "packet.h" | 89 | #include "packet.h" |
87 | #include "buffer.h" | 90 | #include "buffer.h" |
88 | #include "channels.h" | 91 | #include "channels.h" |
@@ -93,9 +96,9 @@ | |||
93 | #include "dispatch.h" | 96 | #include "dispatch.h" |
94 | #include "clientloop.h" | 97 | #include "clientloop.h" |
95 | #include "log.h" | 98 | #include "log.h" |
99 | #include "misc.h" | ||
96 | #include "readconf.h" | 100 | #include "readconf.h" |
97 | #include "sshconnect.h" | 101 | #include "sshconnect.h" |
98 | #include "misc.h" | ||
99 | #include "kex.h" | 102 | #include "kex.h" |
100 | #include "mac.h" | 103 | #include "mac.h" |
101 | #include "sshpty.h" | 104 | #include "sshpty.h" |
@@ -420,8 +423,11 @@ main(int ac, char **av) | |||
420 | int timeout_ms; | 423 | int timeout_ms; |
421 | extern int optind, optreset; | 424 | extern int optind, optreset; |
422 | extern char *optarg; | 425 | extern char *optarg; |
423 | Forward fwd; | 426 | struct Forward fwd; |
424 | struct addrinfo *addrs = NULL; | 427 | struct addrinfo *addrs = NULL; |
428 | struct ssh_digest_ctx *md; | ||
429 | u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; | ||
430 | char *conn_hash_hex; | ||
425 | 431 | ||
426 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 432 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
427 | sanitise_stdfd(); | 433 | sanitise_stdfd(); |
@@ -539,7 +545,7 @@ main(int ac, char **av) | |||
539 | options.forward_x11_trusted = 1; | 545 | options.forward_x11_trusted = 1; |
540 | break; | 546 | break; |
541 | case 'g': | 547 | case 'g': |
542 | options.gateway_ports = 1; | 548 | options.fwd_opts.gateway_ports = 1; |
543 | break; | 549 | break; |
544 | case 'O': | 550 | case 'O': |
545 | if (stdio_forward_host != NULL) | 551 | if (stdio_forward_host != NULL) |
@@ -631,7 +637,13 @@ main(int ac, char **av) | |||
631 | break; | 637 | break; |
632 | case 'V': | 638 | case 'V': |
633 | fprintf(stderr, "%s, %s\n", | 639 | fprintf(stderr, "%s, %s\n", |
634 | SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); | 640 | SSH_RELEASE, |
641 | #ifdef WITH_OPENSSL | ||
642 | SSLeay_version(SSLEAY_VERSION) | ||
643 | #else | ||
644 | "without OpenSSL" | ||
645 | #endif | ||
646 | ); | ||
635 | if (opt == 'V') | 647 | if (opt == 'V') |
636 | exit(0); | 648 | exit(0); |
637 | break; | 649 | break; |
@@ -828,8 +840,10 @@ main(int ac, char **av) | |||
828 | 840 | ||
829 | host_arg = xstrdup(host); | 841 | host_arg = xstrdup(host); |
830 | 842 | ||
843 | #ifdef WITH_OPENSSL | ||
831 | OpenSSL_add_all_algorithms(); | 844 | OpenSSL_add_all_algorithms(); |
832 | ERR_load_crypto_strings(); | 845 | ERR_load_crypto_strings(); |
846 | #endif | ||
833 | 847 | ||
834 | /* Initialize the command to execute on remote host. */ | 848 | /* Initialize the command to execute on remote host. */ |
835 | buffer_init(&command); | 849 | buffer_init(&command); |
@@ -876,7 +890,13 @@ main(int ac, char **av) | |||
876 | SYSLOG_FACILITY_USER, !use_syslog); | 890 | SYSLOG_FACILITY_USER, !use_syslog); |
877 | 891 | ||
878 | if (debug_flag) | 892 | if (debug_flag) |
879 | logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); | 893 | logit("%s, %s", SSH_RELEASE, |
894 | #ifdef WITH_OPENSSL | ||
895 | SSLeay_version(SSLEAY_VERSION) | ||
896 | #else | ||
897 | "without OpenSSL" | ||
898 | #endif | ||
899 | ); | ||
880 | 900 | ||
881 | /* Parse the configuration files */ | 901 | /* Parse the configuration files */ |
882 | process_config_files(pw); | 902 | process_config_files(pw); |
@@ -914,10 +934,14 @@ main(int ac, char **av) | |||
914 | if (addrs == NULL && options.num_permitted_cnames != 0 && | 934 | if (addrs == NULL && options.num_permitted_cnames != 0 && |
915 | (option_clear_or_none(options.proxy_command) || | 935 | (option_clear_or_none(options.proxy_command) || |
916 | options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { | 936 | options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { |
917 | if ((addrs = resolve_host(host, options.port, 1, | 937 | if ((addrs = resolve_host(host, options.port, |
918 | cname, sizeof(cname))) == NULL) | 938 | option_clear_or_none(options.proxy_command), |
919 | cleanup_exit(255); /* resolve_host logs the error */ | 939 | cname, sizeof(cname))) == NULL) { |
920 | check_follow_cname(&host, cname); | 940 | /* Don't fatal proxied host names not in the DNS */ |
941 | if (option_clear_or_none(options.proxy_command)) | ||
942 | cleanup_exit(255); /* logged in resolve_host */ | ||
943 | } else | ||
944 | check_follow_cname(&host, cname); | ||
921 | } | 945 | } |
922 | 946 | ||
923 | /* | 947 | /* |
@@ -982,12 +1006,29 @@ main(int ac, char **av) | |||
982 | shorthost[strcspn(thishost, ".")] = '\0'; | 1006 | shorthost[strcspn(thishost, ".")] = '\0'; |
983 | snprintf(portstr, sizeof(portstr), "%d", options.port); | 1007 | snprintf(portstr, sizeof(portstr), "%d", options.port); |
984 | 1008 | ||
1009 | if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || | ||
1010 | ssh_digest_update(md, thishost, strlen(thishost)) < 0 || | ||
1011 | ssh_digest_update(md, host, strlen(host)) < 0 || | ||
1012 | ssh_digest_update(md, portstr, strlen(portstr)) < 0 || | ||
1013 | ssh_digest_update(md, options.user, strlen(options.user)) < 0 || | ||
1014 | ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) | ||
1015 | fatal("%s: mux digest failed", __func__); | ||
1016 | ssh_digest_free(md); | ||
1017 | conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); | ||
1018 | |||
985 | if (options.local_command != NULL) { | 1019 | if (options.local_command != NULL) { |
986 | debug3("expanding LocalCommand: %s", options.local_command); | 1020 | debug3("expanding LocalCommand: %s", options.local_command); |
987 | cp = options.local_command; | 1021 | cp = options.local_command; |
988 | options.local_command = percent_expand(cp, "d", pw->pw_dir, | 1022 | options.local_command = percent_expand(cp, |
989 | "h", host, "l", thishost, "n", host_arg, "r", options.user, | 1023 | "C", conn_hash_hex, |
990 | "p", portstr, "u", pw->pw_name, "L", shorthost, | 1024 | "L", shorthost, |
1025 | "d", pw->pw_dir, | ||
1026 | "h", host, | ||
1027 | "l", thishost, | ||
1028 | "n", host_arg, | ||
1029 | "p", portstr, | ||
1030 | "r", options.user, | ||
1031 | "u", pw->pw_name, | ||
991 | (char *)NULL); | 1032 | (char *)NULL); |
992 | debug3("expanded LocalCommand: %s", options.local_command); | 1033 | debug3("expanded LocalCommand: %s", options.local_command); |
993 | free(cp); | 1034 | free(cp); |
@@ -997,12 +1038,20 @@ main(int ac, char **av) | |||
997 | cp = tilde_expand_filename(options.control_path, | 1038 | cp = tilde_expand_filename(options.control_path, |
998 | original_real_uid); | 1039 | original_real_uid); |
999 | free(options.control_path); | 1040 | free(options.control_path); |
1000 | options.control_path = percent_expand(cp, "h", host, | 1041 | options.control_path = percent_expand(cp, |
1001 | "l", thishost, "n", host_arg, "r", options.user, | 1042 | "C", conn_hash_hex, |
1002 | "p", portstr, "u", pw->pw_name, "L", shorthost, | 1043 | "L", shorthost, |
1044 | "h", host, | ||
1045 | "l", thishost, | ||
1046 | "n", host_arg, | ||
1047 | "p", portstr, | ||
1048 | "r", options.user, | ||
1049 | "u", pw->pw_name, | ||
1003 | (char *)NULL); | 1050 | (char *)NULL); |
1004 | free(cp); | 1051 | free(cp); |
1005 | } | 1052 | } |
1053 | free(conn_hash_hex); | ||
1054 | |||
1006 | if (muxclient_command != 0 && options.control_path == NULL) | 1055 | if (muxclient_command != 0 && options.control_path == NULL) |
1007 | fatal("No ControlPath specified for \"-O\" command"); | 1056 | fatal("No ControlPath specified for \"-O\" command"); |
1008 | if (options.control_path != NULL) | 1057 | if (options.control_path != NULL) |
@@ -1256,13 +1305,17 @@ fork_postauth(void) | |||
1256 | static void | 1305 | static void |
1257 | ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | 1306 | ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) |
1258 | { | 1307 | { |
1259 | Forward *rfwd = (Forward *)ctxt; | 1308 | struct Forward *rfwd = (struct Forward *)ctxt; |
1260 | 1309 | ||
1261 | /* XXX verbose() on failure? */ | 1310 | /* XXX verbose() on failure? */ |
1262 | debug("remote forward %s for: listen %d, connect %s:%d", | 1311 | debug("remote forward %s for: listen %s%s%d, connect %s:%d", |
1263 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 1312 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", |
1264 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); | 1313 | rfwd->listen_path ? rfwd->listen_path : |
1265 | if (rfwd->listen_port == 0) { | 1314 | rfwd->listen_host ? rfwd->listen_host : "", |
1315 | (rfwd->listen_path || rfwd->listen_host) ? ":" : "", | ||
1316 | rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : | ||
1317 | rfwd->connect_host, rfwd->connect_port); | ||
1318 | if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { | ||
1266 | if (type == SSH2_MSG_REQUEST_SUCCESS) { | 1319 | if (type == SSH2_MSG_REQUEST_SUCCESS) { |
1267 | rfwd->allocated_port = packet_get_int(); | 1320 | rfwd->allocated_port = packet_get_int(); |
1268 | logit("Allocated port %u for remote forward to %s:%d", | 1321 | logit("Allocated port %u for remote forward to %s:%d", |
@@ -1276,12 +1329,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
1276 | } | 1329 | } |
1277 | 1330 | ||
1278 | if (type == SSH2_MSG_REQUEST_FAILURE) { | 1331 | if (type == SSH2_MSG_REQUEST_FAILURE) { |
1279 | if (options.exit_on_forward_failure) | 1332 | if (options.exit_on_forward_failure) { |
1280 | fatal("Error: remote port forwarding failed for " | 1333 | if (rfwd->listen_path != NULL) |
1281 | "listen port %d", rfwd->listen_port); | 1334 | fatal("Error: remote port forwarding failed " |
1282 | else | 1335 | "for listen path %s", rfwd->listen_path); |
1283 | logit("Warning: remote port forwarding failed for " | 1336 | else |
1284 | "listen port %d", rfwd->listen_port); | 1337 | fatal("Error: remote port forwarding failed " |
1338 | "for listen port %d", rfwd->listen_port); | ||
1339 | } else { | ||
1340 | if (rfwd->listen_path != NULL) | ||
1341 | logit("Warning: remote port forwarding failed " | ||
1342 | "for listen path %s", rfwd->listen_path); | ||
1343 | else | ||
1344 | logit("Warning: remote port forwarding failed " | ||
1345 | "for listen port %d", rfwd->listen_port); | ||
1346 | } | ||
1285 | } | 1347 | } |
1286 | if (++remote_forward_confirms_received == options.num_remote_forwards) { | 1348 | if (++remote_forward_confirms_received == options.num_remote_forwards) { |
1287 | debug("All remote forwarding requests processed"); | 1349 | debug("All remote forwarding requests processed"); |
@@ -1298,6 +1360,13 @@ client_cleanup_stdio_fwd(int id, void *arg) | |||
1298 | } | 1360 | } |
1299 | 1361 | ||
1300 | static void | 1362 | static void |
1363 | ssh_stdio_confirm(int id, int success, void *arg) | ||
1364 | { | ||
1365 | if (!success) | ||
1366 | fatal("stdio forwarding failed"); | ||
1367 | } | ||
1368 | |||
1369 | static void | ||
1301 | ssh_init_stdio_forwarding(void) | 1370 | ssh_init_stdio_forwarding(void) |
1302 | { | 1371 | { |
1303 | Channel *c; | 1372 | Channel *c; |
@@ -1317,6 +1386,7 @@ ssh_init_stdio_forwarding(void) | |||
1317 | stdio_forward_port, in, out)) == NULL) | 1386 | stdio_forward_port, in, out)) == NULL) |
1318 | fatal("%s: channel_connect_stdio_fwd failed", __func__); | 1387 | fatal("%s: channel_connect_stdio_fwd failed", __func__); |
1319 | channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); | 1388 | channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); |
1389 | channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL); | ||
1320 | } | 1390 | } |
1321 | 1391 | ||
1322 | static void | 1392 | static void |
@@ -1329,18 +1399,18 @@ ssh_init_forwarding(void) | |||
1329 | for (i = 0; i < options.num_local_forwards; i++) { | 1399 | for (i = 0; i < options.num_local_forwards; i++) { |
1330 | debug("Local connections to %.200s:%d forwarded to remote " | 1400 | debug("Local connections to %.200s:%d forwarded to remote " |
1331 | "address %.200s:%d", | 1401 | "address %.200s:%d", |
1402 | (options.local_forwards[i].listen_path != NULL) ? | ||
1403 | options.local_forwards[i].listen_path : | ||
1332 | (options.local_forwards[i].listen_host == NULL) ? | 1404 | (options.local_forwards[i].listen_host == NULL) ? |
1333 | (options.gateway_ports ? "*" : "LOCALHOST") : | 1405 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
1334 | options.local_forwards[i].listen_host, | 1406 | options.local_forwards[i].listen_host, |
1335 | options.local_forwards[i].listen_port, | 1407 | options.local_forwards[i].listen_port, |
1408 | (options.local_forwards[i].connect_path != NULL) ? | ||
1409 | options.local_forwards[i].connect_path : | ||
1336 | options.local_forwards[i].connect_host, | 1410 | options.local_forwards[i].connect_host, |
1337 | options.local_forwards[i].connect_port); | 1411 | options.local_forwards[i].connect_port); |
1338 | success += channel_setup_local_fwd_listener( | 1412 | success += channel_setup_local_fwd_listener( |
1339 | options.local_forwards[i].listen_host, | 1413 | &options.local_forwards[i], &options.fwd_opts); |
1340 | options.local_forwards[i].listen_port, | ||
1341 | options.local_forwards[i].connect_host, | ||
1342 | options.local_forwards[i].connect_port, | ||
1343 | options.gateway_ports); | ||
1344 | } | 1414 | } |
1345 | if (i > 0 && success != i && options.exit_on_forward_failure) | 1415 | if (i > 0 && success != i && options.exit_on_forward_failure) |
1346 | fatal("Could not request local forwarding."); | 1416 | fatal("Could not request local forwarding."); |
@@ -1351,17 +1421,18 @@ ssh_init_forwarding(void) | |||
1351 | for (i = 0; i < options.num_remote_forwards; i++) { | 1421 | for (i = 0; i < options.num_remote_forwards; i++) { |
1352 | debug("Remote connections from %.200s:%d forwarded to " | 1422 | debug("Remote connections from %.200s:%d forwarded to " |
1353 | "local address %.200s:%d", | 1423 | "local address %.200s:%d", |
1424 | (options.remote_forwards[i].listen_path != NULL) ? | ||
1425 | options.remote_forwards[i].listen_path : | ||
1354 | (options.remote_forwards[i].listen_host == NULL) ? | 1426 | (options.remote_forwards[i].listen_host == NULL) ? |
1355 | "LOCALHOST" : options.remote_forwards[i].listen_host, | 1427 | "LOCALHOST" : options.remote_forwards[i].listen_host, |
1356 | options.remote_forwards[i].listen_port, | 1428 | options.remote_forwards[i].listen_port, |
1429 | (options.remote_forwards[i].connect_path != NULL) ? | ||
1430 | options.remote_forwards[i].connect_path : | ||
1357 | options.remote_forwards[i].connect_host, | 1431 | options.remote_forwards[i].connect_host, |
1358 | options.remote_forwards[i].connect_port); | 1432 | options.remote_forwards[i].connect_port); |
1359 | options.remote_forwards[i].handle = | 1433 | options.remote_forwards[i].handle = |
1360 | channel_request_remote_forwarding( | 1434 | channel_request_remote_forwarding( |
1361 | options.remote_forwards[i].listen_host, | 1435 | &options.remote_forwards[i]); |
1362 | options.remote_forwards[i].listen_port, | ||
1363 | options.remote_forwards[i].connect_host, | ||
1364 | options.remote_forwards[i].connect_port); | ||
1365 | if (options.remote_forwards[i].handle < 0) { | 1436 | if (options.remote_forwards[i].handle < 0) { |
1366 | if (options.exit_on_forward_failure) | 1437 | if (options.exit_on_forward_failure) |
1367 | fatal("Could not request remote forwarding."); | 1438 | fatal("Could not request remote forwarding."); |
diff --git a/ssh_config.0 b/ssh_config.0 index 6fbd10d61..c40ce5f08 100644 --- a/ssh_config.0 +++ b/ssh_config.0 | |||
@@ -1,4 +1,4 @@ | |||
1 | SSH_CONFIG(5) OpenBSD Programmer's Manual SSH_CONFIG(5) | 1 | SSH_CONFIG(5) File Formats Manual SSH_CONFIG(5) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | ssh_config - OpenSSH SSH client configuration files | 4 | ssh_config - OpenSSH SSH client configuration files |
@@ -176,19 +176,30 @@ DESCRIPTION | |||
176 | preference. Multiple ciphers must be comma-separated. The | 176 | preference. Multiple ciphers must be comma-separated. The |
177 | supported ciphers are: | 177 | supported ciphers are: |
178 | 178 | ||
179 | ``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', ``aes256-cbc'', | 179 | 3des-cbc |
180 | ``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'', | 180 | aes128-cbc |
181 | ``aes128-gcm@openssh.com'', ``aes256-gcm@openssh.com'', | 181 | aes192-cbc |
182 | ``arcfour128'', ``arcfour256'', ``arcfour'', ``blowfish-cbc'', | 182 | aes256-cbc |
183 | ``cast128-cbc'', and ``chacha20-poly1305@openssh.com''. | 183 | aes128-ctr |
184 | aes192-ctr | ||
185 | aes256-ctr | ||
186 | aes128-gcm@openssh.com | ||
187 | aes256-gcm@openssh.com | ||
188 | arcfour | ||
189 | arcfour128 | ||
190 | arcfour256 | ||
191 | blowfish-cbc | ||
192 | cast128-cbc | ||
193 | chacha20-poly1305@openssh.com | ||
184 | 194 | ||
185 | The default is: | 195 | The default is: |
186 | 196 | ||
187 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, | 197 | aes128-ctr,aes192-ctr,aes256-ctr, |
188 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, | 198 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, |
189 | chacha20-poly1305@openssh.com, | 199 | chacha20-poly1305@openssh.com, |
190 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, | 200 | arcfour256,arcfour128, |
191 | aes256-cbc,arcfour | 201 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc, |
202 | aes192-cbc,aes256-cbc,arcfour | ||
192 | 203 | ||
193 | The list of available ciphers may also be obtained using the -Q | 204 | The list of available ciphers may also be obtained using the -Q |
194 | option of ssh(1). | 205 | option of ssh(1). |
@@ -261,10 +272,12 @@ DESCRIPTION | |||
261 | any domain name), `%h' will be substituted by the target host | 272 | any domain name), `%h' will be substituted by the target host |
262 | name, `%n' will be substituted by the original target host name | 273 | name, `%n' will be substituted by the original target host name |
263 | specified on the command line, `%p' the destination port, `%r' by | 274 | specified on the command line, `%p' the destination port, `%r' by |
264 | the remote login username, and `%u' by the username of the user | 275 | the remote login username, `%u' by the username of the user |
265 | running ssh(1). It is recommended that any ControlPath used for | 276 | running ssh(1), and `%C' by a hash of the concatenation: |
266 | opportunistic connection sharing include at least %h, %p, and %r. | 277 | %l%h%p%r. It is recommended that any ControlPath used for |
267 | This ensures that shared connections are uniquely identified. | 278 | opportunistic connection sharing include at least %h, %p, and %r |
279 | (or alternatively %C). This ensures that shared connections are | ||
280 | uniquely identified. | ||
268 | 281 | ||
269 | ControlPersist | 282 | ControlPersist |
270 | When used in conjunction with ControlMaster, specifies that the | 283 | When used in conjunction with ControlMaster, specifies that the |
@@ -437,10 +450,13 @@ DESCRIPTION | |||
437 | specify nicknames or abbreviations for hosts. If the hostname | 450 | specify nicknames or abbreviations for hosts. If the hostname |
438 | contains the character sequence `%h', then this will be replaced | 451 | contains the character sequence `%h', then this will be replaced |
439 | with the host name specified on the command line (this is useful | 452 | with the host name specified on the command line (this is useful |
440 | for manipulating unqualified names). The default is the name | 453 | for manipulating unqualified names). The character sequence `%%' |
441 | given on the command line. Numeric IP addresses are also | 454 | will be replaced by a single `%' character, which may be used |
442 | permitted (both on the command line and in HostName | 455 | when specifying IPv6 link-local addresses. |
443 | specifications). | 456 | |
457 | The default is the name given on the command line. Numeric IP | ||
458 | addresses are also permitted (both on the command line and in | ||
459 | HostName specifications). | ||
444 | 460 | ||
445 | IdentitiesOnly | 461 | IdentitiesOnly |
446 | Specifies that ssh(1) should only use the authentication identity | 462 | Specifies that ssh(1) should only use the authentication identity |
@@ -517,8 +533,8 @@ DESCRIPTION | |||
517 | curve25519-sha256@libssh.org, | 533 | curve25519-sha256@libssh.org, |
518 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, | 534 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, |
519 | diffie-hellman-group-exchange-sha256, | 535 | diffie-hellman-group-exchange-sha256, |
520 | diffie-hellman-group-exchange-sha1, | ||
521 | diffie-hellman-group14-sha1, | 536 | diffie-hellman-group14-sha1, |
537 | diffie-hellman-group-exchange-sha1, | ||
522 | diffie-hellman-group1-sha1 | 538 | diffie-hellman-group1-sha1 |
523 | 539 | ||
524 | LocalCommand | 540 | LocalCommand |
@@ -529,7 +545,8 @@ DESCRIPTION | |||
529 | performed: `%d' (local user's home directory), `%h' (remote host | 545 | performed: `%d' (local user's home directory), `%h' (remote host |
530 | name), `%l' (local host name), `%n' (host name as provided on the | 546 | name), `%l' (local host name), `%n' (host name as provided on the |
531 | command line), `%p' (remote port), `%r' (remote user name) or | 547 | command line), `%p' (remote port), `%r' (remote user name) or |
532 | `%u' (local user name). | 548 | `%u' (local user name) or `%C' by a hash of the concatenation: |
549 | %l%h%p%r. | ||
533 | 550 | ||
534 | The command is run synchronously and does not have access to the | 551 | The command is run synchronously and does not have access to the |
535 | session of the ssh(1) that spawned it. It should not be used for | 552 | session of the ssh(1) that spawned it. It should not be used for |
@@ -568,13 +585,14 @@ DESCRIPTION | |||
568 | calculate the MAC after encryption (encrypt-then-mac). These are | 585 | calculate the MAC after encryption (encrypt-then-mac). These are |
569 | considered safer and their use recommended. The default is: | 586 | considered safer and their use recommended. The default is: |
570 | 587 | ||
571 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, | ||
572 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, | 588 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, |
573 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, | 589 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, |
574 | hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, | 590 | umac-64@openssh.com,umac-128@openssh.com, |
575 | hmac-md5-96-etm@openssh.com, | 591 | hmac-sha2-256,hmac-sha2-512, |
576 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, | 592 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, |
577 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, | 593 | hmac-ripemd160-etm@openssh.com, |
594 | hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com, | ||
595 | hmac-md5,hmac-sha1,hmac-ripemd160, | ||
578 | hmac-sha1-96,hmac-md5-96 | 596 | hmac-sha1-96,hmac-md5-96 |
579 | 597 | ||
580 | NoHostAuthenticationForLocalhost | 598 | NoHostAuthenticationForLocalhost |
@@ -628,17 +646,19 @@ DESCRIPTION | |||
628 | ProxyCommand | 646 | ProxyCommand |
629 | Specifies the command to use to connect to the server. The | 647 | Specifies the command to use to connect to the server. The |
630 | command string extends to the end of the line, and is executed | 648 | command string extends to the end of the line, and is executed |
631 | with the user's shell. In the command string, any occurrence of | 649 | using the user's shell `exec' directive to avoid a lingering |
632 | `%h' will be substituted by the host name to connect, `%p' by the | 650 | shell process. |
633 | port, and `%r' by the remote user name. The command can be | 651 | |
634 | basically anything, and should read from its standard input and | 652 | In the command string, any occurrence of `%h' will be substituted |
635 | write to its standard output. It should eventually connect an | 653 | by the host name to connect, `%p' by the port, and `%r' by the |
636 | sshd(8) server running on some machine, or execute sshd -i | 654 | remote user name. The command can be basically anything, and |
637 | somewhere. Host key management will be done using the HostName | 655 | should read from its standard input and write to its standard |
638 | of the host being connected (defaulting to the name typed by the | 656 | output. It should eventually connect an sshd(8) server running |
639 | user). Setting the command to ``none'' disables this option | 657 | on some machine, or execute sshd -i somewhere. Host key |
640 | entirely. Note that CheckHostIP is not available for connects | 658 | management will be done using the HostName of the host being |
641 | with a proxy command. | 659 | connected (defaulting to the name typed by the user). Setting |
660 | the command to ``none'' disables this option entirely. Note that | ||
661 | CheckHostIP is not available for connects with a proxy command. | ||
642 | 662 | ||
643 | This directive is useful in conjunction with nc(1) and its proxy | 663 | This directive is useful in conjunction with nc(1) and its proxy |
644 | support. For example, the following directive would connect via | 664 | support. For example, the following directive would connect via |
@@ -751,6 +771,27 @@ DESCRIPTION | |||
751 | default is 0, indicating that these messages will not be sent to | 771 | default is 0, indicating that these messages will not be sent to |
752 | the server. This option applies to protocol version 2 only. | 772 | the server. This option applies to protocol version 2 only. |
753 | 773 | ||
774 | StreamLocalBindMask | ||
775 | Sets the octal file creation mode mask (umask) used when creating | ||
776 | a Unix-domain socket file for local or remote port forwarding. | ||
777 | This option is only used for port forwarding to a Unix-domain | ||
778 | socket file. | ||
779 | |||
780 | The default value is 0177, which creates a Unix-domain socket | ||
781 | file that is readable and writable only by the owner. Note that | ||
782 | not all operating systems honor the file mode on Unix-domain | ||
783 | socket files. | ||
784 | |||
785 | StreamLocalBindUnlink | ||
786 | Specifies whether to remove an existing Unix-domain socket file | ||
787 | for local or remote port forwarding before creating a new one. | ||
788 | If the socket file already exists and StreamLocalBindUnlink is | ||
789 | not enabled, ssh will be unable to forward the port to the Unix- | ||
790 | domain socket file. This option is only used for port forwarding | ||
791 | to a Unix-domain socket file. | ||
792 | |||
793 | The argument must be ``yes'' or ``no''. The default is ``no''. | ||
794 | |||
754 | StrictHostKeyChecking | 795 | StrictHostKeyChecking |
755 | If this flag is set to ``yes'', ssh(1) will never automatically | 796 | If this flag is set to ``yes'', ssh(1) will never automatically |
756 | add host keys to the ~/.ssh/known_hosts file, and refuses to | 797 | add host keys to the ~/.ssh/known_hosts file, and refuses to |
@@ -886,4 +927,4 @@ AUTHORS | |||
886 | created OpenSSH. Markus Friedl contributed the support for SSH protocol | 927 | created OpenSSH. Markus Friedl contributed the support for SSH protocol |
887 | versions 1.5 and 2.0. | 928 | versions 1.5 and 2.0. |
888 | 929 | ||
889 | OpenBSD 5.5 February 23, 2014 OpenBSD 5.5 | 930 | OpenBSD 5.6 July 15, 2014 OpenBSD 5.6 |
diff --git a/ssh_config.5 b/ssh_config.5 index 22e637265..da3c1771a 100644 --- a/ssh_config.5 +++ b/ssh_config.5 | |||
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 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. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh_config.5,v 1.185 2014/02/23 20:11:36 djm Exp $ | 36 | .\" $OpenBSD: ssh_config.5,v 1.191 2014/07/15 15:54:14 millert Exp $ |
37 | .Dd $Mdocdate: February 23 2014 $ | 37 | .Dd $Mdocdate: July 15 2014 $ |
38 | .Dt SSH_CONFIG 5 | 38 | .Dt SSH_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -362,30 +362,47 @@ in order of preference. | |||
362 | Multiple ciphers must be comma-separated. | 362 | Multiple ciphers must be comma-separated. |
363 | The supported ciphers are: | 363 | The supported ciphers are: |
364 | .Pp | 364 | .Pp |
365 | .Dq 3des-cbc , | 365 | .Bl -item -compact -offset indent |
366 | .Dq aes128-cbc , | 366 | .It |
367 | .Dq aes192-cbc , | 367 | 3des-cbc |
368 | .Dq aes256-cbc , | 368 | .It |
369 | .Dq aes128-ctr , | 369 | aes128-cbc |
370 | .Dq aes192-ctr , | 370 | .It |
371 | .Dq aes256-ctr , | 371 | aes192-cbc |
372 | .Dq aes128-gcm@openssh.com , | 372 | .It |
373 | .Dq aes256-gcm@openssh.com , | 373 | aes256-cbc |
374 | .Dq arcfour128 , | 374 | .It |
375 | .Dq arcfour256 , | 375 | aes128-ctr |
376 | .Dq arcfour , | 376 | .It |
377 | .Dq blowfish-cbc , | 377 | aes192-ctr |
378 | .Dq cast128-cbc , | 378 | .It |
379 | and | 379 | aes256-ctr |
380 | .Dq chacha20-poly1305@openssh.com . | 380 | .It |
381 | aes128-gcm@openssh.com | ||
382 | .It | ||
383 | aes256-gcm@openssh.com | ||
384 | .It | ||
385 | arcfour | ||
386 | .It | ||
387 | arcfour128 | ||
388 | .It | ||
389 | arcfour256 | ||
390 | .It | ||
391 | blowfish-cbc | ||
392 | .It | ||
393 | cast128-cbc | ||
394 | .It | ||
395 | chacha20-poly1305@openssh.com | ||
396 | .El | ||
381 | .Pp | 397 | .Pp |
382 | The default is: | 398 | The default is: |
383 | .Bd -literal -offset 3n | 399 | .Bd -literal -offset indent |
384 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, | 400 | aes128-ctr,aes192-ctr,aes256-ctr, |
385 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, | 401 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, |
386 | chacha20-poly1305@openssh.com, | 402 | chacha20-poly1305@openssh.com, |
387 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, | 403 | arcfour256,arcfour128, |
388 | aes256-cbc,arcfour | 404 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc, |
405 | aes192-cbc,aes256-cbc,arcfour | ||
389 | .Ed | 406 | .Ed |
390 | .Pp | 407 | .Pp |
391 | The list of available ciphers may also be obtained using the | 408 | The list of available ciphers may also be obtained using the |
@@ -502,14 +519,16 @@ specified on the command line, | |||
502 | .Ql %p | 519 | .Ql %p |
503 | the destination port, | 520 | the destination port, |
504 | .Ql %r | 521 | .Ql %r |
505 | by the remote login username, and | 522 | by the remote login username, |
506 | .Ql %u | 523 | .Ql %u |
507 | by the username of the user running | 524 | by the username of the user running |
508 | .Xr ssh 1 . | 525 | .Xr ssh 1 , and |
526 | .Ql \&%C | ||
527 | by a hash of the concatenation: %l%h%p%r. | ||
509 | It is recommended that any | 528 | It is recommended that any |
510 | .Cm ControlPath | 529 | .Cm ControlPath |
511 | used for opportunistic connection sharing include | 530 | used for opportunistic connection sharing include |
512 | at least %h, %p, and %r. | 531 | at least %h, %p, and %r (or alternatively %C). |
513 | This ensures that shared connections are uniquely identified. | 532 | This ensures that shared connections are uniquely identified. |
514 | .It Cm ControlPersist | 533 | .It Cm ControlPersist |
515 | When used in conjunction with | 534 | When used in conjunction with |
@@ -802,6 +821,12 @@ If the hostname contains the character sequence | |||
802 | .Ql %h , | 821 | .Ql %h , |
803 | then this will be replaced with the host name specified on the command line | 822 | then this will be replaced with the host name specified on the command line |
804 | (this is useful for manipulating unqualified names). | 823 | (this is useful for manipulating unqualified names). |
824 | The character sequence | ||
825 | .Ql %% | ||
826 | will be replaced by a single | ||
827 | .Ql % | ||
828 | character, which may be used when specifying IPv6 link-local addresses. | ||
829 | .Pp | ||
805 | The default is the name given on the command line. | 830 | The default is the name given on the command line. |
806 | Numeric IP addresses are also permitted (both on the command line and in | 831 | Numeric IP addresses are also permitted (both on the command line and in |
807 | .Cm HostName | 832 | .Cm HostName |
@@ -949,8 +974,8 @@ The default is: | |||
949 | curve25519-sha256@libssh.org, | 974 | curve25519-sha256@libssh.org, |
950 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, | 975 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, |
951 | diffie-hellman-group-exchange-sha256, | 976 | diffie-hellman-group-exchange-sha256, |
952 | diffie-hellman-group-exchange-sha1, | ||
953 | diffie-hellman-group14-sha1, | 977 | diffie-hellman-group14-sha1, |
978 | diffie-hellman-group-exchange-sha1, | ||
954 | diffie-hellman-group1-sha1 | 979 | diffie-hellman-group1-sha1 |
955 | .Ed | 980 | .Ed |
956 | .It Cm LocalCommand | 981 | .It Cm LocalCommand |
@@ -972,7 +997,9 @@ The following escape character substitutions will be performed: | |||
972 | .Ql %r | 997 | .Ql %r |
973 | (remote user name) or | 998 | (remote user name) or |
974 | .Ql %u | 999 | .Ql %u |
975 | (local user name). | 1000 | (local user name) or |
1001 | .Ql \&%C | ||
1002 | by a hash of the concatenation: %l%h%p%r. | ||
976 | .Pp | 1003 | .Pp |
977 | The command is run synchronously and does not have access to the | 1004 | The command is run synchronously and does not have access to the |
978 | session of the | 1005 | session of the |
@@ -1030,13 +1057,14 @@ calculate the MAC after encryption (encrypt-then-mac). | |||
1030 | These are considered safer and their use recommended. | 1057 | These are considered safer and their use recommended. |
1031 | The default is: | 1058 | The default is: |
1032 | .Bd -literal -offset indent | 1059 | .Bd -literal -offset indent |
1033 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, | ||
1034 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, | 1060 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, |
1035 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, | 1061 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, |
1036 | hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, | 1062 | umac-64@openssh.com,umac-128@openssh.com, |
1037 | hmac-md5-96-etm@openssh.com, | 1063 | hmac-sha2-256,hmac-sha2-512, |
1038 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, | 1064 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, |
1039 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, | 1065 | hmac-ripemd160-etm@openssh.com, |
1066 | hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com, | ||
1067 | hmac-md5,hmac-sha1,hmac-ripemd160, | ||
1040 | hmac-sha1-96,hmac-md5-96 | 1068 | hmac-sha1-96,hmac-md5-96 |
1041 | .Ed | 1069 | .Ed |
1042 | .It Cm NoHostAuthenticationForLocalhost | 1070 | .It Cm NoHostAuthenticationForLocalhost |
@@ -1114,8 +1142,11 @@ The default is | |||
1114 | .It Cm ProxyCommand | 1142 | .It Cm ProxyCommand |
1115 | Specifies the command to use to connect to the server. | 1143 | Specifies the command to use to connect to the server. |
1116 | The command | 1144 | The command |
1117 | string extends to the end of the line, and is executed with | 1145 | string extends to the end of the line, and is executed |
1118 | the user's shell. | 1146 | using the user's shell |
1147 | .Ql exec | ||
1148 | directive to avoid a lingering shell process. | ||
1149 | .Pp | ||
1119 | In the command string, any occurrence of | 1150 | In the command string, any occurrence of |
1120 | .Ql %h | 1151 | .Ql %h |
1121 | will be substituted by the host name to | 1152 | will be substituted by the host name to |
@@ -1338,6 +1369,33 @@ This option applies to protocol version 2 only. | |||
1338 | and | 1369 | and |
1339 | .Cm SetupTimeOut | 1370 | .Cm SetupTimeOut |
1340 | are Debian-specific compatibility aliases for this option. | 1371 | are Debian-specific compatibility aliases for this option. |
1372 | .It Cm StreamLocalBindMask | ||
1373 | Sets the octal file creation mode mask | ||
1374 | .Pq umask | ||
1375 | used when creating a Unix-domain socket file for local or remote | ||
1376 | port forwarding. | ||
1377 | This option is only used for port forwarding to a Unix-domain socket file. | ||
1378 | .Pp | ||
1379 | The default value is 0177, which creates a Unix-domain socket file that is | ||
1380 | readable and writable only by the owner. | ||
1381 | Note that not all operating systems honor the file mode on Unix-domain | ||
1382 | socket files. | ||
1383 | .It Cm StreamLocalBindUnlink | ||
1384 | Specifies whether to remove an existing Unix-domain socket file for local | ||
1385 | or remote port forwarding before creating a new one. | ||
1386 | If the socket file already exists and | ||
1387 | .Cm StreamLocalBindUnlink | ||
1388 | is not enabled, | ||
1389 | .Nm ssh | ||
1390 | will be unable to forward the port to the Unix-domain socket file. | ||
1391 | This option is only used for port forwarding to a Unix-domain socket file. | ||
1392 | .Pp | ||
1393 | The argument must be | ||
1394 | .Dq yes | ||
1395 | or | ||
1396 | .Dq no . | ||
1397 | The default is | ||
1398 | .Dq no . | ||
1341 | .It Cm StrictHostKeyChecking | 1399 | .It Cm StrictHostKeyChecking |
1342 | If this flag is set to | 1400 | If this flag is set to |
1343 | .Dq yes , | 1401 | .Dq yes , |
diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c new file mode 100644 index 000000000..b7d0758c2 --- /dev/null +++ b/sshbuf-getput-basic.c | |||
@@ -0,0 +1,421 @@ | |||
1 | /* $OpenBSD: sshbuf-getput-basic.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #define SSHBUF_INTERNAL | ||
19 | #include "includes.h" | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <stdio.h> | ||
24 | #include <string.h> | ||
25 | |||
26 | #include "ssherr.h" | ||
27 | #include "sshbuf.h" | ||
28 | |||
29 | int | ||
30 | sshbuf_get(struct sshbuf *buf, void *v, size_t len) | ||
31 | { | ||
32 | const u_char *p = sshbuf_ptr(buf); | ||
33 | int r; | ||
34 | |||
35 | if ((r = sshbuf_consume(buf, len)) < 0) | ||
36 | return r; | ||
37 | if (v != NULL) | ||
38 | memcpy(v, p, len); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | int | ||
43 | sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp) | ||
44 | { | ||
45 | const u_char *p = sshbuf_ptr(buf); | ||
46 | int r; | ||
47 | |||
48 | if ((r = sshbuf_consume(buf, 8)) < 0) | ||
49 | return r; | ||
50 | if (valp != NULL) | ||
51 | *valp = PEEK_U64(p); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | int | ||
56 | sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp) | ||
57 | { | ||
58 | const u_char *p = sshbuf_ptr(buf); | ||
59 | int r; | ||
60 | |||
61 | if ((r = sshbuf_consume(buf, 4)) < 0) | ||
62 | return r; | ||
63 | if (valp != NULL) | ||
64 | *valp = PEEK_U32(p); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | int | ||
69 | sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp) | ||
70 | { | ||
71 | const u_char *p = sshbuf_ptr(buf); | ||
72 | int r; | ||
73 | |||
74 | if ((r = sshbuf_consume(buf, 2)) < 0) | ||
75 | return r; | ||
76 | if (valp != NULL) | ||
77 | *valp = PEEK_U16(p); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | int | ||
82 | sshbuf_get_u8(struct sshbuf *buf, u_char *valp) | ||
83 | { | ||
84 | const u_char *p = sshbuf_ptr(buf); | ||
85 | int r; | ||
86 | |||
87 | if ((r = sshbuf_consume(buf, 1)) < 0) | ||
88 | return r; | ||
89 | if (valp != NULL) | ||
90 | *valp = (u_int8_t)*p; | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | int | ||
95 | sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp) | ||
96 | { | ||
97 | const u_char *val; | ||
98 | size_t len; | ||
99 | int r; | ||
100 | |||
101 | if (valp != NULL) | ||
102 | *valp = NULL; | ||
103 | if (lenp != NULL) | ||
104 | *lenp = 0; | ||
105 | if ((r = sshbuf_get_string_direct(buf, &val, &len)) < 0) | ||
106 | return r; | ||
107 | if (valp != NULL) { | ||
108 | if ((*valp = malloc(len + 1)) == NULL) { | ||
109 | SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); | ||
110 | return SSH_ERR_ALLOC_FAIL; | ||
111 | } | ||
112 | memcpy(*valp, val, len); | ||
113 | (*valp)[len] = '\0'; | ||
114 | } | ||
115 | if (lenp != NULL) | ||
116 | *lenp = len; | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | int | ||
121 | sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp) | ||
122 | { | ||
123 | size_t len; | ||
124 | const u_char *p; | ||
125 | int r; | ||
126 | |||
127 | if (valp != NULL) | ||
128 | *valp = NULL; | ||
129 | if (lenp != NULL) | ||
130 | *lenp = 0; | ||
131 | if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0) | ||
132 | return r; | ||
133 | if (valp != 0) | ||
134 | *valp = p; | ||
135 | if (lenp != NULL) | ||
136 | *lenp = len; | ||
137 | if (sshbuf_consume(buf, len + 4) != 0) { | ||
138 | /* Shouldn't happen */ | ||
139 | SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); | ||
140 | SSHBUF_ABORT(); | ||
141 | return SSH_ERR_INTERNAL_ERROR; | ||
142 | } | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | int | ||
147 | sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, | ||
148 | size_t *lenp) | ||
149 | { | ||
150 | u_int32_t len; | ||
151 | const u_char *p = sshbuf_ptr(buf); | ||
152 | |||
153 | if (valp != NULL) | ||
154 | *valp = NULL; | ||
155 | if (lenp != NULL) | ||
156 | *lenp = 0; | ||
157 | if (sshbuf_len(buf) < 4) { | ||
158 | SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); | ||
159 | return SSH_ERR_MESSAGE_INCOMPLETE; | ||
160 | } | ||
161 | len = PEEK_U32(p); | ||
162 | if (len > SSHBUF_SIZE_MAX - 4) { | ||
163 | SSHBUF_DBG(("SSH_ERR_STRING_TOO_LARGE")); | ||
164 | return SSH_ERR_STRING_TOO_LARGE; | ||
165 | } | ||
166 | if (sshbuf_len(buf) - 4 < len) { | ||
167 | SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); | ||
168 | return SSH_ERR_MESSAGE_INCOMPLETE; | ||
169 | } | ||
170 | if (valp != 0) | ||
171 | *valp = p + 4; | ||
172 | if (lenp != NULL) | ||
173 | *lenp = len; | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | int | ||
178 | sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp) | ||
179 | { | ||
180 | size_t len; | ||
181 | const u_char *p, *z; | ||
182 | int r; | ||
183 | |||
184 | if (valp != NULL) | ||
185 | *valp = NULL; | ||
186 | if (lenp != NULL) | ||
187 | *lenp = 0; | ||
188 | if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) | ||
189 | return r; | ||
190 | /* Allow a \0 only at the end of the string */ | ||
191 | if (len > 0 && | ||
192 | (z = memchr(p , '\0', len)) != NULL && z < p + len - 1) { | ||
193 | SSHBUF_DBG(("SSH_ERR_INVALID_FORMAT")); | ||
194 | return SSH_ERR_INVALID_FORMAT; | ||
195 | } | ||
196 | if ((r = sshbuf_skip_string(buf)) != 0) | ||
197 | return -1; | ||
198 | if (valp != NULL) { | ||
199 | if ((*valp = malloc(len + 1)) == NULL) { | ||
200 | SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); | ||
201 | return SSH_ERR_ALLOC_FAIL; | ||
202 | } | ||
203 | memcpy(*valp, p, len); | ||
204 | (*valp)[len] = '\0'; | ||
205 | } | ||
206 | if (lenp != NULL) | ||
207 | *lenp = (size_t)len; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | int | ||
212 | sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v) | ||
213 | { | ||
214 | u_int32_t len; | ||
215 | u_char *p; | ||
216 | int r; | ||
217 | |||
218 | /* | ||
219 | * Use sshbuf_peek_string_direct() to figure out if there is | ||
220 | * a complete string in 'buf' and copy the string directly | ||
221 | * into 'v'. | ||
222 | */ | ||
223 | if ((r = sshbuf_peek_string_direct(buf, NULL, NULL)) != 0 || | ||
224 | (r = sshbuf_get_u32(buf, &len)) != 0 || | ||
225 | (r = sshbuf_reserve(v, len, &p)) != 0 || | ||
226 | (r = sshbuf_get(buf, p, len)) != 0) | ||
227 | return r; | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | int | ||
232 | sshbuf_put(struct sshbuf *buf, const void *v, size_t len) | ||
233 | { | ||
234 | u_char *p; | ||
235 | int r; | ||
236 | |||
237 | if ((r = sshbuf_reserve(buf, len, &p)) < 0) | ||
238 | return r; | ||
239 | memcpy(p, v, len); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | int | ||
244 | sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v) | ||
245 | { | ||
246 | return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v)); | ||
247 | } | ||
248 | |||
249 | int | ||
250 | sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) | ||
251 | { | ||
252 | va_list ap; | ||
253 | int r; | ||
254 | |||
255 | va_start(ap, fmt); | ||
256 | r = sshbuf_putfv(buf, fmt, ap); | ||
257 | va_end(ap); | ||
258 | return r; | ||
259 | } | ||
260 | |||
261 | int | ||
262 | sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap) | ||
263 | { | ||
264 | va_list ap2; | ||
265 | int r, len; | ||
266 | u_char *p; | ||
267 | |||
268 | va_copy(ap2, ap); | ||
269 | if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) { | ||
270 | r = SSH_ERR_INVALID_ARGUMENT; | ||
271 | goto out; | ||
272 | } | ||
273 | if (len == 0) { | ||
274 | r = 0; | ||
275 | goto out; /* Nothing to do */ | ||
276 | } | ||
277 | va_end(ap2); | ||
278 | va_copy(ap2, ap); | ||
279 | if ((r = sshbuf_reserve(buf, (size_t)len + 1, &p)) < 0) | ||
280 | goto out; | ||
281 | if ((r = vsnprintf((char *)p, len + 1, fmt, ap2)) != len) { | ||
282 | r = SSH_ERR_INTERNAL_ERROR; | ||
283 | goto out; /* Shouldn't happen */ | ||
284 | } | ||
285 | /* Consume terminating \0 */ | ||
286 | if ((r = sshbuf_consume_end(buf, 1)) != 0) | ||
287 | goto out; | ||
288 | r = 0; | ||
289 | out: | ||
290 | va_end(ap2); | ||
291 | return r; | ||
292 | } | ||
293 | |||
294 | int | ||
295 | sshbuf_put_u64(struct sshbuf *buf, u_int64_t val) | ||
296 | { | ||
297 | u_char *p; | ||
298 | int r; | ||
299 | |||
300 | if ((r = sshbuf_reserve(buf, 8, &p)) < 0) | ||
301 | return r; | ||
302 | POKE_U64(p, val); | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | int | ||
307 | sshbuf_put_u32(struct sshbuf *buf, u_int32_t val) | ||
308 | { | ||
309 | u_char *p; | ||
310 | int r; | ||
311 | |||
312 | if ((r = sshbuf_reserve(buf, 4, &p)) < 0) | ||
313 | return r; | ||
314 | POKE_U32(p, val); | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | int | ||
319 | sshbuf_put_u16(struct sshbuf *buf, u_int16_t val) | ||
320 | { | ||
321 | u_char *p; | ||
322 | int r; | ||
323 | |||
324 | if ((r = sshbuf_reserve(buf, 2, &p)) < 0) | ||
325 | return r; | ||
326 | POKE_U16(p, val); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | int | ||
331 | sshbuf_put_u8(struct sshbuf *buf, u_char val) | ||
332 | { | ||
333 | u_char *p; | ||
334 | int r; | ||
335 | |||
336 | if ((r = sshbuf_reserve(buf, 1, &p)) < 0) | ||
337 | return r; | ||
338 | p[0] = val; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | int | ||
343 | sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) | ||
344 | { | ||
345 | u_char *d; | ||
346 | int r; | ||
347 | |||
348 | if (len > SSHBUF_SIZE_MAX - 4) { | ||
349 | SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); | ||
350 | return SSH_ERR_NO_BUFFER_SPACE; | ||
351 | } | ||
352 | if ((r = sshbuf_reserve(buf, len + 4, &d)) < 0) | ||
353 | return r; | ||
354 | POKE_U32(d, len); | ||
355 | memcpy(d + 4, v, len); | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | int | ||
360 | sshbuf_put_cstring(struct sshbuf *buf, const char *v) | ||
361 | { | ||
362 | return sshbuf_put_string(buf, (u_char *)v, strlen(v)); | ||
363 | } | ||
364 | |||
365 | int | ||
366 | sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v) | ||
367 | { | ||
368 | return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v)); | ||
369 | } | ||
370 | |||
371 | int | ||
372 | sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp) | ||
373 | { | ||
374 | const u_char *p; | ||
375 | size_t len; | ||
376 | struct sshbuf *ret; | ||
377 | int r; | ||
378 | |||
379 | if (buf == NULL || bufp == NULL) | ||
380 | return SSH_ERR_INVALID_ARGUMENT; | ||
381 | *bufp = NULL; | ||
382 | if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) | ||
383 | return r; | ||
384 | if ((ret = sshbuf_from(p, len)) == NULL) | ||
385 | return SSH_ERR_ALLOC_FAIL; | ||
386 | if ((r = sshbuf_consume(buf, len + 4)) != 0 || /* Shouldn't happen */ | ||
387 | (r = sshbuf_set_parent(ret, buf)) != 0) { | ||
388 | sshbuf_free(ret); | ||
389 | return r; | ||
390 | } | ||
391 | *bufp = ret; | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | int | ||
396 | sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len) | ||
397 | { | ||
398 | u_char *d; | ||
399 | const u_char *s = (const u_char *)v; | ||
400 | int r, prepend; | ||
401 | |||
402 | if (len > SSHBUF_SIZE_MAX - 5) { | ||
403 | SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); | ||
404 | return SSH_ERR_NO_BUFFER_SPACE; | ||
405 | } | ||
406 | /* Skip leading zero bytes */ | ||
407 | for (; len > 0 && *s == 0; len--, s++) | ||
408 | ; | ||
409 | /* | ||
410 | * If most significant bit is set then prepend a zero byte to | ||
411 | * avoid interpretation as a negative number. | ||
412 | */ | ||
413 | prepend = len > 0 && (s[0] & 0x80) != 0; | ||
414 | if ((r = sshbuf_reserve(buf, len + 4 + prepend, &d)) < 0) | ||
415 | return r; | ||
416 | POKE_U32(d, len + prepend); | ||
417 | if (prepend) | ||
418 | d[4] = 0; | ||
419 | memcpy(d + 4 + prepend, s, len); | ||
420 | return 0; | ||
421 | } | ||
diff --git a/sshbuf-getput-crypto.c b/sshbuf-getput-crypto.c new file mode 100644 index 000000000..74351d3e5 --- /dev/null +++ b/sshbuf-getput-crypto.c | |||
@@ -0,0 +1,237 @@ | |||
1 | /* $OpenBSD: sshbuf-getput-crypto.c,v 1.2 2014/06/18 15:42:09 naddy Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #define SSHBUF_INTERNAL | ||
19 | #include "includes.h" | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <stdio.h> | ||
24 | #include <string.h> | ||
25 | |||
26 | #include <openssl/bn.h> | ||
27 | #ifdef OPENSSL_HAS_ECC | ||
28 | # include <openssl/ec.h> | ||
29 | #endif /* OPENSSL_HAS_ECC */ | ||
30 | |||
31 | #include "ssherr.h" | ||
32 | #include "sshbuf.h" | ||
33 | |||
34 | int | ||
35 | sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v) | ||
36 | { | ||
37 | const u_char *d; | ||
38 | size_t len; | ||
39 | int r; | ||
40 | |||
41 | if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) | ||
42 | return r; | ||
43 | /* Refuse negative (MSB set) bignums */ | ||
44 | if ((len != 0 && (*d & 0x80) != 0)) | ||
45 | return SSH_ERR_BIGNUM_IS_NEGATIVE; | ||
46 | /* Refuse overlong bignums, allow prepended \0 to avoid MSB set */ | ||
47 | if (len > SSHBUF_MAX_BIGNUM + 1 || | ||
48 | (len == SSHBUF_MAX_BIGNUM + 1 && *d != 0)) | ||
49 | return SSH_ERR_BIGNUM_TOO_LARGE; | ||
50 | if (v != NULL && BN_bin2bn(d, len, v) == NULL) | ||
51 | return SSH_ERR_ALLOC_FAIL; | ||
52 | /* Consume the string */ | ||
53 | if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { | ||
54 | /* Shouldn't happen */ | ||
55 | SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); | ||
56 | SSHBUF_ABORT(); | ||
57 | return SSH_ERR_INTERNAL_ERROR; | ||
58 | } | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | int | ||
63 | sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v) | ||
64 | { | ||
65 | const u_char *d = sshbuf_ptr(buf); | ||
66 | u_int16_t len_bits; | ||
67 | size_t len_bytes; | ||
68 | |||
69 | /* Length in bits */ | ||
70 | if (sshbuf_len(buf) < 2) | ||
71 | return SSH_ERR_MESSAGE_INCOMPLETE; | ||
72 | len_bits = PEEK_U16(d); | ||
73 | len_bytes = (len_bits + 7) >> 3; | ||
74 | if (len_bytes > SSHBUF_MAX_BIGNUM) | ||
75 | return SSH_ERR_BIGNUM_TOO_LARGE; | ||
76 | if (sshbuf_len(buf) < 2 + len_bytes) | ||
77 | return SSH_ERR_MESSAGE_INCOMPLETE; | ||
78 | if (v != NULL && BN_bin2bn(d + 2, len_bytes, v) == NULL) | ||
79 | return SSH_ERR_ALLOC_FAIL; | ||
80 | if (sshbuf_consume(buf, 2 + len_bytes) != 0) { | ||
81 | SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); | ||
82 | SSHBUF_ABORT(); | ||
83 | return SSH_ERR_INTERNAL_ERROR; | ||
84 | } | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | #ifdef OPENSSL_HAS_ECC | ||
89 | static int | ||
90 | get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g) | ||
91 | { | ||
92 | /* Refuse overlong bignums */ | ||
93 | if (len == 0 || len > SSHBUF_MAX_ECPOINT) | ||
94 | return SSH_ERR_ECPOINT_TOO_LARGE; | ||
95 | /* Only handle uncompressed points */ | ||
96 | if (*d != POINT_CONVERSION_UNCOMPRESSED) | ||
97 | return SSH_ERR_INVALID_FORMAT; | ||
98 | if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1) | ||
99 | return SSH_ERR_INVALID_FORMAT; /* XXX assumption */ | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int | ||
104 | sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g) | ||
105 | { | ||
106 | const u_char *d; | ||
107 | size_t len; | ||
108 | int r; | ||
109 | |||
110 | if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) | ||
111 | return r; | ||
112 | if ((r = get_ec(d, len, v, g)) != 0) | ||
113 | return r; | ||
114 | /* Skip string */ | ||
115 | if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { | ||
116 | /* Shouldn't happen */ | ||
117 | SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); | ||
118 | SSHBUF_ABORT(); | ||
119 | return SSH_ERR_INTERNAL_ERROR; | ||
120 | } | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | int | ||
125 | sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v) | ||
126 | { | ||
127 | EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v)); | ||
128 | int r; | ||
129 | const u_char *d; | ||
130 | size_t len; | ||
131 | |||
132 | if (pt == NULL) { | ||
133 | SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); | ||
134 | return SSH_ERR_ALLOC_FAIL; | ||
135 | } | ||
136 | if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) { | ||
137 | EC_POINT_free(pt); | ||
138 | return r; | ||
139 | } | ||
140 | if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) { | ||
141 | EC_POINT_free(pt); | ||
142 | return r; | ||
143 | } | ||
144 | if (EC_KEY_set_public_key(v, pt) != 1) { | ||
145 | EC_POINT_free(pt); | ||
146 | return SSH_ERR_ALLOC_FAIL; /* XXX assumption */ | ||
147 | } | ||
148 | EC_POINT_free(pt); | ||
149 | /* Skip string */ | ||
150 | if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { | ||
151 | /* Shouldn't happen */ | ||
152 | SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); | ||
153 | SSHBUF_ABORT(); | ||
154 | return SSH_ERR_INTERNAL_ERROR; | ||
155 | } | ||
156 | return 0; | ||
157 | } | ||
158 | #endif /* OPENSSL_HAS_ECC */ | ||
159 | |||
160 | int | ||
161 | sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v) | ||
162 | { | ||
163 | u_char d[SSHBUF_MAX_BIGNUM + 1]; | ||
164 | int len = BN_num_bytes(v), prepend = 0, r; | ||
165 | |||
166 | if (len < 0 || len > SSHBUF_MAX_BIGNUM) | ||
167 | return SSH_ERR_INVALID_ARGUMENT; | ||
168 | *d = '\0'; | ||
169 | if (BN_bn2bin(v, d + 1) != len) | ||
170 | return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ | ||
171 | /* If MSB is set, prepend a \0 */ | ||
172 | if (len > 0 && (d[1] & 0x80) != 0) | ||
173 | prepend = 1; | ||
174 | if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) { | ||
175 | bzero(d, sizeof(d)); | ||
176 | return r; | ||
177 | } | ||
178 | bzero(d, sizeof(d)); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int | ||
183 | sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v) | ||
184 | { | ||
185 | int r, len_bits = BN_num_bits(v); | ||
186 | size_t len_bytes = (len_bits + 7) / 8; | ||
187 | u_char d[SSHBUF_MAX_BIGNUM], *dp; | ||
188 | |||
189 | if (len_bits < 0 || len_bytes > SSHBUF_MAX_BIGNUM) | ||
190 | return SSH_ERR_INVALID_ARGUMENT; | ||
191 | if (BN_bn2bin(v, d) != (int)len_bytes) | ||
192 | return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ | ||
193 | if ((r = sshbuf_reserve(buf, len_bytes + 2, &dp)) < 0) { | ||
194 | bzero(d, sizeof(d)); | ||
195 | return r; | ||
196 | } | ||
197 | POKE_U16(dp, len_bits); | ||
198 | memcpy(dp + 2, d, len_bytes); | ||
199 | bzero(d, sizeof(d)); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | #ifdef OPENSSL_HAS_ECC | ||
204 | int | ||
205 | sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g) | ||
206 | { | ||
207 | u_char d[SSHBUF_MAX_ECPOINT]; | ||
208 | BN_CTX *bn_ctx; | ||
209 | size_t len; | ||
210 | int ret; | ||
211 | |||
212 | if ((bn_ctx = BN_CTX_new()) == NULL) | ||
213 | return SSH_ERR_ALLOC_FAIL; | ||
214 | if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, | ||
215 | NULL, 0, bn_ctx)) > SSHBUF_MAX_ECPOINT) { | ||
216 | BN_CTX_free(bn_ctx); | ||
217 | return SSH_ERR_INVALID_ARGUMENT; | ||
218 | } | ||
219 | if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, | ||
220 | d, len, bn_ctx) != len) { | ||
221 | BN_CTX_free(bn_ctx); | ||
222 | return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ | ||
223 | } | ||
224 | BN_CTX_free(bn_ctx); | ||
225 | ret = sshbuf_put_string(buf, d, len); | ||
226 | bzero(d, len); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | int | ||
231 | sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v) | ||
232 | { | ||
233 | return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v), | ||
234 | EC_KEY_get0_group(v)); | ||
235 | } | ||
236 | #endif /* OPENSSL_HAS_ECC */ | ||
237 | |||
diff --git a/sshbuf-misc.c b/sshbuf-misc.c new file mode 100644 index 000000000..bfeffe674 --- /dev/null +++ b/sshbuf-misc.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* $OpenBSD: sshbuf-misc.c,v 1.2 2014/06/24 01:13:21 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include "includes.h" | ||
19 | |||
20 | #include <sys/types.h> | ||
21 | #include <sys/socket.h> | ||
22 | #include <netinet/in.h> | ||
23 | #include <errno.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <stdio.h> | ||
26 | #include <limits.h> | ||
27 | #include <string.h> | ||
28 | #include <resolv.h> | ||
29 | #include <ctype.h> | ||
30 | |||
31 | #include "ssherr.h" | ||
32 | #define SSHBUF_INTERNAL | ||
33 | #include "sshbuf.h" | ||
34 | |||
35 | void | ||
36 | sshbuf_dump_data(const void *s, size_t len, FILE *f) | ||
37 | { | ||
38 | size_t i, j; | ||
39 | const u_char *p = (const u_char *)s; | ||
40 | |||
41 | for (i = 0; i < len; i += 16) { | ||
42 | fprintf(f, "%.4zd: ", i); | ||
43 | for (j = i; j < i + 16; j++) { | ||
44 | if (j < len) | ||
45 | fprintf(f, "%02x ", p[j]); | ||
46 | else | ||
47 | fprintf(f, " "); | ||
48 | } | ||
49 | fprintf(f, " "); | ||
50 | for (j = i; j < i + 16; j++) { | ||
51 | if (j < len) { | ||
52 | if (isascii(p[j]) && isprint(p[j])) | ||
53 | fprintf(f, "%c", p[j]); | ||
54 | else | ||
55 | fprintf(f, "."); | ||
56 | } | ||
57 | } | ||
58 | fprintf(f, "\n"); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | void | ||
63 | sshbuf_dump(struct sshbuf *buf, FILE *f) | ||
64 | { | ||
65 | fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf)); | ||
66 | sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f); | ||
67 | } | ||
68 | |||
69 | char * | ||
70 | sshbuf_dtob16(struct sshbuf *buf) | ||
71 | { | ||
72 | size_t i, j, len = sshbuf_len(buf); | ||
73 | const u_char *p = sshbuf_ptr(buf); | ||
74 | char *ret; | ||
75 | const char hex[] = "0123456789abcdef"; | ||
76 | |||
77 | if (len == 0) | ||
78 | return strdup(""); | ||
79 | if (SIZE_MAX / 2 <= len || (ret = malloc(len * 2 + 1)) == NULL) | ||
80 | return NULL; | ||
81 | for (i = j = 0; i < len; i++) { | ||
82 | ret[j++] = hex[(p[i] >> 4) & 0xf]; | ||
83 | ret[j++] = hex[p[i] & 0xf]; | ||
84 | } | ||
85 | ret[j] = '\0'; | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | char * | ||
90 | sshbuf_dtob64(struct sshbuf *buf) | ||
91 | { | ||
92 | size_t len = sshbuf_len(buf), plen; | ||
93 | const u_char *p = sshbuf_ptr(buf); | ||
94 | char *ret; | ||
95 | int r; | ||
96 | |||
97 | if (len == 0) | ||
98 | return strdup(""); | ||
99 | plen = ((len + 2) / 3) * 4 + 1; | ||
100 | if (SIZE_MAX / 2 <= len || (ret = malloc(plen)) == NULL) | ||
101 | return NULL; | ||
102 | if ((r = b64_ntop(p, len, ret, plen)) == -1) { | ||
103 | bzero(ret, plen); | ||
104 | free(ret); | ||
105 | return NULL; | ||
106 | } | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | int | ||
111 | sshbuf_b64tod(struct sshbuf *buf, const char *b64) | ||
112 | { | ||
113 | size_t plen = strlen(b64); | ||
114 | int nlen, r; | ||
115 | u_char *p; | ||
116 | |||
117 | if (plen == 0) | ||
118 | return 0; | ||
119 | if ((p = malloc(plen)) == NULL) | ||
120 | return SSH_ERR_ALLOC_FAIL; | ||
121 | if ((nlen = b64_pton(b64, p, plen)) < 0) { | ||
122 | bzero(p, plen); | ||
123 | free(p); | ||
124 | return SSH_ERR_INVALID_FORMAT; | ||
125 | } | ||
126 | if ((r = sshbuf_put(buf, p, nlen)) < 0) { | ||
127 | bzero(p, plen); | ||
128 | free(p); | ||
129 | return r; | ||
130 | } | ||
131 | bzero(p, plen); | ||
132 | free(p); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
diff --git a/sshbuf.c b/sshbuf.c new file mode 100644 index 000000000..78f5340a1 --- /dev/null +++ b/sshbuf.c | |||
@@ -0,0 +1,406 @@ | |||
1 | /* $OpenBSD: sshbuf.c,v 1.2 2014/06/25 14:16:09 deraadt Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #define SSHBUF_INTERNAL | ||
19 | #include "includes.h" | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | #include <sys/param.h> | ||
23 | #include <signal.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <stdio.h> | ||
26 | #include <string.h> | ||
27 | |||
28 | #include "ssherr.h" | ||
29 | #include "sshbuf.h" | ||
30 | |||
31 | static inline int | ||
32 | sshbuf_check_sanity(const struct sshbuf *buf) | ||
33 | { | ||
34 | SSHBUF_TELL("sanity"); | ||
35 | if (__predict_false(buf == NULL || | ||
36 | (!buf->readonly && buf->d != buf->cd) || | ||
37 | buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX || | ||
38 | buf->cd == NULL || | ||
39 | (buf->dont_free && (buf->readonly || buf->parent != NULL)) || | ||
40 | buf->max_size > SSHBUF_SIZE_MAX || | ||
41 | buf->alloc > buf->max_size || | ||
42 | buf->size > buf->alloc || | ||
43 | buf->off > buf->size)) { | ||
44 | /* Do not try to recover from corrupted buffer internals */ | ||
45 | SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); | ||
46 | signal(SIGSEGV, SIG_DFL); | ||
47 | raise(SIGSEGV); | ||
48 | return SSH_ERR_INTERNAL_ERROR; | ||
49 | } | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static void | ||
54 | sshbuf_maybe_pack(struct sshbuf *buf, int force) | ||
55 | { | ||
56 | SSHBUF_DBG(("force %d", force)); | ||
57 | SSHBUF_TELL("pre-pack"); | ||
58 | if (buf->off == 0 || buf->readonly || buf->refcount > 1) | ||
59 | return; | ||
60 | if (force || | ||
61 | (buf->off >= SSHBUF_PACK_MIN && buf->off >= buf->size / 2)) { | ||
62 | memmove(buf->d, buf->d + buf->off, buf->size - buf->off); | ||
63 | buf->size -= buf->off; | ||
64 | buf->off = 0; | ||
65 | SSHBUF_TELL("packed"); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | struct sshbuf * | ||
70 | sshbuf_new(void) | ||
71 | { | ||
72 | struct sshbuf *ret; | ||
73 | |||
74 | if ((ret = calloc(sizeof(*ret), 1)) == NULL) | ||
75 | return NULL; | ||
76 | ret->alloc = SSHBUF_SIZE_INIT; | ||
77 | ret->max_size = SSHBUF_SIZE_MAX; | ||
78 | ret->readonly = 0; | ||
79 | ret->refcount = 1; | ||
80 | ret->parent = NULL; | ||
81 | if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) { | ||
82 | free(ret); | ||
83 | return NULL; | ||
84 | } | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | struct sshbuf * | ||
89 | sshbuf_from(const void *blob, size_t len) | ||
90 | { | ||
91 | struct sshbuf *ret; | ||
92 | |||
93 | if (blob == NULL || len > SSHBUF_SIZE_MAX || | ||
94 | (ret = calloc(sizeof(*ret), 1)) == NULL) | ||
95 | return NULL; | ||
96 | ret->alloc = ret->size = ret->max_size = len; | ||
97 | ret->readonly = 1; | ||
98 | ret->refcount = 1; | ||
99 | ret->parent = NULL; | ||
100 | ret->cd = blob; | ||
101 | ret->d = NULL; | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | int | ||
106 | sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent) | ||
107 | { | ||
108 | int r; | ||
109 | |||
110 | if ((r = sshbuf_check_sanity(child)) != 0 || | ||
111 | (r = sshbuf_check_sanity(parent)) != 0) | ||
112 | return r; | ||
113 | child->parent = parent; | ||
114 | child->parent->refcount++; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | struct sshbuf * | ||
119 | sshbuf_fromb(struct sshbuf *buf) | ||
120 | { | ||
121 | struct sshbuf *ret; | ||
122 | |||
123 | if (sshbuf_check_sanity(buf) != 0) | ||
124 | return NULL; | ||
125 | if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL) | ||
126 | return NULL; | ||
127 | if (sshbuf_set_parent(ret, buf) != 0) { | ||
128 | sshbuf_free(ret); | ||
129 | return NULL; | ||
130 | } | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | void | ||
135 | sshbuf_init(struct sshbuf *ret) | ||
136 | { | ||
137 | bzero(ret, sizeof(*ret)); | ||
138 | ret->alloc = SSHBUF_SIZE_INIT; | ||
139 | ret->max_size = SSHBUF_SIZE_MAX; | ||
140 | ret->readonly = 0; | ||
141 | ret->dont_free = 1; | ||
142 | ret->refcount = 1; | ||
143 | if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) | ||
144 | ret->alloc = 0; | ||
145 | } | ||
146 | |||
147 | void | ||
148 | sshbuf_free(struct sshbuf *buf) | ||
149 | { | ||
150 | int dont_free = 0; | ||
151 | |||
152 | if (buf == NULL) | ||
153 | return; | ||
154 | /* | ||
155 | * The following will leak on insane buffers, but this is the safest | ||
156 | * course of action - an invalid pointer or already-freed pointer may | ||
157 | * have been passed to us and continuing to scribble over memory would | ||
158 | * be bad. | ||
159 | */ | ||
160 | if (sshbuf_check_sanity(buf) != 0) | ||
161 | return; | ||
162 | /* | ||
163 | * If we are a child, the free our parent to decrement its reference | ||
164 | * count and possibly free it. | ||
165 | */ | ||
166 | if (buf->parent != NULL) { | ||
167 | sshbuf_free(buf->parent); | ||
168 | buf->parent = NULL; | ||
169 | } | ||
170 | /* | ||
171 | * If we are a parent with still-extant children, then don't free just | ||
172 | * yet. The last child's call to sshbuf_free should decrement our | ||
173 | * refcount to 0 and trigger the actual free. | ||
174 | */ | ||
175 | buf->refcount--; | ||
176 | if (buf->refcount > 0) | ||
177 | return; | ||
178 | dont_free = buf->dont_free; | ||
179 | if (!buf->readonly) { | ||
180 | bzero(buf->d, buf->alloc); | ||
181 | free(buf->d); | ||
182 | } | ||
183 | bzero(buf, sizeof(*buf)); | ||
184 | if (!dont_free) | ||
185 | free(buf); | ||
186 | } | ||
187 | |||
188 | void | ||
189 | sshbuf_reset(struct sshbuf *buf) | ||
190 | { | ||
191 | u_char *d; | ||
192 | |||
193 | if (buf->readonly || buf->refcount > 1) { | ||
194 | /* Nonsensical. Just make buffer appear empty */ | ||
195 | buf->off = buf->size; | ||
196 | return; | ||
197 | } | ||
198 | if (sshbuf_check_sanity(buf) == 0) | ||
199 | bzero(buf->d, buf->alloc); | ||
200 | buf->off = buf->size = 0; | ||
201 | if (buf->alloc != SSHBUF_SIZE_INIT) { | ||
202 | if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) { | ||
203 | buf->cd = buf->d = d; | ||
204 | buf->alloc = SSHBUF_SIZE_INIT; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | size_t | ||
210 | sshbuf_max_size(const struct sshbuf *buf) | ||
211 | { | ||
212 | return buf->max_size; | ||
213 | } | ||
214 | |||
215 | size_t | ||
216 | sshbuf_alloc(const struct sshbuf *buf) | ||
217 | { | ||
218 | return buf->alloc; | ||
219 | } | ||
220 | |||
221 | const struct sshbuf * | ||
222 | sshbuf_parent(const struct sshbuf *buf) | ||
223 | { | ||
224 | return buf->parent; | ||
225 | } | ||
226 | |||
227 | u_int | ||
228 | sshbuf_refcount(const struct sshbuf *buf) | ||
229 | { | ||
230 | return buf->refcount; | ||
231 | } | ||
232 | |||
233 | int | ||
234 | sshbuf_set_max_size(struct sshbuf *buf, size_t max_size) | ||
235 | { | ||
236 | size_t rlen; | ||
237 | u_char *dp; | ||
238 | int r; | ||
239 | |||
240 | SSHBUF_DBG(("set max buf = %p len = %zu", buf, max_size)); | ||
241 | if ((r = sshbuf_check_sanity(buf)) != 0) | ||
242 | return r; | ||
243 | if (max_size == buf->max_size) | ||
244 | return 0; | ||
245 | if (buf->readonly || buf->refcount > 1) | ||
246 | return SSH_ERR_BUFFER_READ_ONLY; | ||
247 | if (max_size > SSHBUF_SIZE_MAX) | ||
248 | return SSH_ERR_NO_BUFFER_SPACE; | ||
249 | /* pack and realloc if necessary */ | ||
250 | sshbuf_maybe_pack(buf, max_size < buf->size); | ||
251 | if (max_size < buf->alloc && max_size > buf->size) { | ||
252 | if (buf->size < SSHBUF_SIZE_INIT) | ||
253 | rlen = SSHBUF_SIZE_INIT; | ||
254 | else | ||
255 | rlen = roundup(buf->size, SSHBUF_SIZE_INC); | ||
256 | if (rlen > max_size) | ||
257 | rlen = max_size; | ||
258 | bzero(buf->d + buf->size, buf->alloc - buf->size); | ||
259 | SSHBUF_DBG(("new alloc = %zu", rlen)); | ||
260 | if ((dp = realloc(buf->d, rlen)) == NULL) | ||
261 | return SSH_ERR_ALLOC_FAIL; | ||
262 | buf->cd = buf->d = dp; | ||
263 | buf->alloc = rlen; | ||
264 | } | ||
265 | SSHBUF_TELL("new-max"); | ||
266 | if (max_size < buf->alloc) | ||
267 | return SSH_ERR_NO_BUFFER_SPACE; | ||
268 | buf->max_size = max_size; | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | size_t | ||
273 | sshbuf_len(const struct sshbuf *buf) | ||
274 | { | ||
275 | if (sshbuf_check_sanity(buf) != 0) | ||
276 | return 0; | ||
277 | return buf->size - buf->off; | ||
278 | } | ||
279 | |||
280 | size_t | ||
281 | sshbuf_avail(const struct sshbuf *buf) | ||
282 | { | ||
283 | if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) | ||
284 | return 0; | ||
285 | return buf->max_size - (buf->size - buf->off); | ||
286 | } | ||
287 | |||
288 | const u_char * | ||
289 | sshbuf_ptr(const struct sshbuf *buf) | ||
290 | { | ||
291 | if (sshbuf_check_sanity(buf) != 0) | ||
292 | return NULL; | ||
293 | return buf->cd + buf->off; | ||
294 | } | ||
295 | |||
296 | u_char * | ||
297 | sshbuf_mutable_ptr(const struct sshbuf *buf) | ||
298 | { | ||
299 | if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) | ||
300 | return NULL; | ||
301 | return buf->d + buf->off; | ||
302 | } | ||
303 | |||
304 | int | ||
305 | sshbuf_check_reserve(const struct sshbuf *buf, size_t len) | ||
306 | { | ||
307 | int r; | ||
308 | |||
309 | if ((r = sshbuf_check_sanity(buf)) != 0) | ||
310 | return r; | ||
311 | if (buf->readonly || buf->refcount > 1) | ||
312 | return SSH_ERR_BUFFER_READ_ONLY; | ||
313 | SSHBUF_TELL("check"); | ||
314 | /* Check that len is reasonable and that max_size + available < len */ | ||
315 | if (len > buf->max_size || buf->max_size - len < buf->size - buf->off) | ||
316 | return SSH_ERR_NO_BUFFER_SPACE; | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | int | ||
321 | sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp) | ||
322 | { | ||
323 | size_t rlen, need; | ||
324 | u_char *dp; | ||
325 | int r; | ||
326 | |||
327 | if (dpp != NULL) | ||
328 | *dpp = NULL; | ||
329 | |||
330 | SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len)); | ||
331 | if ((r = sshbuf_check_reserve(buf, len)) != 0) | ||
332 | return r; | ||
333 | /* | ||
334 | * If the requested allocation appended would push us past max_size | ||
335 | * then pack the buffer, zeroing buf->off. | ||
336 | */ | ||
337 | sshbuf_maybe_pack(buf, buf->size + len > buf->max_size); | ||
338 | SSHBUF_TELL("reserve"); | ||
339 | if (len + buf->size > buf->alloc) { | ||
340 | /* | ||
341 | * Prefer to alloc in SSHBUF_SIZE_INC units, but | ||
342 | * allocate less if doing so would overflow max_size. | ||
343 | */ | ||
344 | need = len + buf->size - buf->alloc; | ||
345 | rlen = roundup(buf->alloc + need, SSHBUF_SIZE_INC); | ||
346 | SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen)); | ||
347 | if (rlen > buf->max_size) | ||
348 | rlen = buf->alloc + need; | ||
349 | SSHBUF_DBG(("adjusted rlen %zu", rlen)); | ||
350 | if ((dp = realloc(buf->d, rlen)) == NULL) { | ||
351 | SSHBUF_DBG(("realloc fail")); | ||
352 | if (dpp != NULL) | ||
353 | *dpp = NULL; | ||
354 | return SSH_ERR_ALLOC_FAIL; | ||
355 | } | ||
356 | buf->alloc = rlen; | ||
357 | buf->cd = buf->d = dp; | ||
358 | if ((r = sshbuf_check_reserve(buf, len)) < 0) { | ||
359 | /* shouldn't fail */ | ||
360 | if (dpp != NULL) | ||
361 | *dpp = NULL; | ||
362 | return r; | ||
363 | } | ||
364 | } | ||
365 | dp = buf->d + buf->size; | ||
366 | buf->size += len; | ||
367 | SSHBUF_TELL("done"); | ||
368 | if (dpp != NULL) | ||
369 | *dpp = dp; | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | int | ||
374 | sshbuf_consume(struct sshbuf *buf, size_t len) | ||
375 | { | ||
376 | int r; | ||
377 | |||
378 | SSHBUF_DBG(("len = %zu", len)); | ||
379 | if ((r = sshbuf_check_sanity(buf)) != 0) | ||
380 | return r; | ||
381 | if (len == 0) | ||
382 | return 0; | ||
383 | if (len > sshbuf_len(buf)) | ||
384 | return SSH_ERR_MESSAGE_INCOMPLETE; | ||
385 | buf->off += len; | ||
386 | SSHBUF_TELL("done"); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | int | ||
391 | sshbuf_consume_end(struct sshbuf *buf, size_t len) | ||
392 | { | ||
393 | int r; | ||
394 | |||
395 | SSHBUF_DBG(("len = %zu", len)); | ||
396 | if ((r = sshbuf_check_sanity(buf)) != 0) | ||
397 | return r; | ||
398 | if (len == 0) | ||
399 | return 0; | ||
400 | if (len > sshbuf_len(buf)) | ||
401 | return SSH_ERR_MESSAGE_INCOMPLETE; | ||
402 | buf->size -= len; | ||
403 | SSHBUF_TELL("done"); | ||
404 | return 0; | ||
405 | } | ||
406 | |||
diff --git a/sshbuf.h b/sshbuf.h new file mode 100644 index 000000000..3602bc53f --- /dev/null +++ b/sshbuf.h | |||
@@ -0,0 +1,336 @@ | |||
1 | /* $OpenBSD: sshbuf.h,v 1.3 2014/06/24 01:13:21 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef _SSHBUF_H | ||
19 | #define _SSHBUF_H | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | #include <stdarg.h> | ||
23 | #include <stdio.h> | ||
24 | #ifdef WITH_OPENSSL | ||
25 | # include <openssl/bn.h> | ||
26 | # ifdef OPENSSL_HAS_ECC | ||
27 | # include <openssl/ec.h> | ||
28 | # endif /* OPENSSL_HAS_ECC */ | ||
29 | #endif /* WITH_OPENSSL */ | ||
30 | |||
31 | #define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */ | ||
32 | #define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */ | ||
33 | #define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */ | ||
34 | #define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */ | ||
35 | |||
36 | /* | ||
37 | * NB. do not depend on the internals of this. It will be made opaque | ||
38 | * one day. | ||
39 | */ | ||
40 | struct sshbuf { | ||
41 | u_char *d; /* Data */ | ||
42 | const u_char *cd; /* Const data */ | ||
43 | size_t off; /* First available byte is buf->d + buf->off */ | ||
44 | size_t size; /* Last byte is buf->d + buf->size - 1 */ | ||
45 | size_t max_size; /* Maximum size of buffer */ | ||
46 | size_t alloc; /* Total bytes allocated to buf->d */ | ||
47 | int readonly; /* Refers to external, const data */ | ||
48 | int dont_free; /* Kludge to support sshbuf_init */ | ||
49 | u_int refcount; /* Tracks self and number of child buffers */ | ||
50 | struct sshbuf *parent; /* If child, pointer to parent */ | ||
51 | }; | ||
52 | |||
53 | #ifndef SSHBUF_NO_DEPREACTED | ||
54 | /* | ||
55 | * NB. Please do not use sshbuf_init() in new code. Please use sshbuf_new() | ||
56 | * instead. sshbuf_init() is deprectated and will go away soon (it is | ||
57 | * only included to allow compat with buffer_* in OpenSSH) | ||
58 | */ | ||
59 | void sshbuf_init(struct sshbuf *buf); | ||
60 | #endif | ||
61 | |||
62 | /* | ||
63 | * Create a new sshbuf buffer. | ||
64 | * Returns pointer to buffer on success, or NULL on allocation failure. | ||
65 | */ | ||
66 | struct sshbuf *sshbuf_new(void); | ||
67 | |||
68 | /* | ||
69 | * Create a new, read-only sshbuf buffer from existing data. | ||
70 | * Returns pointer to buffer on success, or NULL on allocation failure. | ||
71 | */ | ||
72 | struct sshbuf *sshbuf_from(const void *blob, size_t len); | ||
73 | |||
74 | /* | ||
75 | * Create a new, read-only sshbuf buffer from the contents of an existing | ||
76 | * buffer. The contents of "buf" must not change in the lifetime of the | ||
77 | * resultant buffer. | ||
78 | * Returns pointer to buffer on success, or NULL on allocation failure. | ||
79 | */ | ||
80 | struct sshbuf *sshbuf_fromb(struct sshbuf *buf); | ||
81 | |||
82 | /* | ||
83 | * Create a new, read-only sshbuf buffer from the contents of a string in | ||
84 | * an existing buffer (the string is consumed in the process). | ||
85 | * The contents of "buf" must not change in the lifetime of the resultant | ||
86 | * buffer. | ||
87 | * Returns pointer to buffer on success, or NULL on allocation failure. | ||
88 | */ | ||
89 | int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp); | ||
90 | |||
91 | /* | ||
92 | * Clear and free buf | ||
93 | */ | ||
94 | void sshbuf_free(struct sshbuf *buf); | ||
95 | |||
96 | /* | ||
97 | * Reset buf, clearing its contents. NB. max_size is preserved. | ||
98 | */ | ||
99 | void sshbuf_reset(struct sshbuf *buf); | ||
100 | |||
101 | /* | ||
102 | * Return the maximum size of buf | ||
103 | */ | ||
104 | size_t sshbuf_max_size(const struct sshbuf *buf); | ||
105 | |||
106 | /* | ||
107 | * Set the maximum size of buf | ||
108 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. | ||
109 | */ | ||
110 | int sshbuf_set_max_size(struct sshbuf *buf, size_t max_size); | ||
111 | |||
112 | /* | ||
113 | * Returns the length of data in buf | ||
114 | */ | ||
115 | size_t sshbuf_len(const struct sshbuf *buf); | ||
116 | |||
117 | /* | ||
118 | * Returns number of bytes left in buffer before hitting max_size. | ||
119 | */ | ||
120 | size_t sshbuf_avail(const struct sshbuf *buf); | ||
121 | |||
122 | /* | ||
123 | * Returns a read-only pointer to the start of the the data in buf | ||
124 | */ | ||
125 | const u_char *sshbuf_ptr(const struct sshbuf *buf); | ||
126 | |||
127 | /* | ||
128 | * Returns a mutable pointer to the start of the the data in buf, or | ||
129 | * NULL if the buffer is read-only. | ||
130 | */ | ||
131 | u_char *sshbuf_mutable_ptr(const struct sshbuf *buf); | ||
132 | |||
133 | /* | ||
134 | * Check whether a reservation of size len will succeed in buf | ||
135 | * Safer to use than direct comparisons again sshbuf_avail as it copes | ||
136 | * with unsigned overflows correctly. | ||
137 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. | ||
138 | */ | ||
139 | int sshbuf_check_reserve(const struct sshbuf *buf, size_t len); | ||
140 | |||
141 | /* | ||
142 | * Reserve len bytes in buf. | ||
143 | * Returns 0 on success and a pointer to the first reserved byte via the | ||
144 | * optional dpp parameter or a negative * SSH_ERR_* error code on failure. | ||
145 | */ | ||
146 | int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp); | ||
147 | |||
148 | /* | ||
149 | * Consume len bytes from the start of buf | ||
150 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. | ||
151 | */ | ||
152 | int sshbuf_consume(struct sshbuf *buf, size_t len); | ||
153 | |||
154 | /* | ||
155 | * Consume len bytes from the end of buf | ||
156 | * Returns 0 on success, or a negative SSH_ERR_* error code on failure. | ||
157 | */ | ||
158 | int sshbuf_consume_end(struct sshbuf *buf, size_t len); | ||
159 | |||
160 | /* Extract or deposit some bytes */ | ||
161 | int sshbuf_get(struct sshbuf *buf, void *v, size_t len); | ||
162 | int sshbuf_put(struct sshbuf *buf, const void *v, size_t len); | ||
163 | int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v); | ||
164 | |||
165 | /* Append using a printf(3) format */ | ||
166 | int sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) | ||
167 | __attribute__((format(printf, 2, 3))); | ||
168 | int sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap); | ||
169 | |||
170 | /* Functions to extract or store big-endian words of various sizes */ | ||
171 | int sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp); | ||
172 | int sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp); | ||
173 | int sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp); | ||
174 | int sshbuf_get_u8(struct sshbuf *buf, u_char *valp); | ||
175 | int sshbuf_put_u64(struct sshbuf *buf, u_int64_t val); | ||
176 | int sshbuf_put_u32(struct sshbuf *buf, u_int32_t val); | ||
177 | int sshbuf_put_u16(struct sshbuf *buf, u_int16_t val); | ||
178 | int sshbuf_put_u8(struct sshbuf *buf, u_char val); | ||
179 | |||
180 | /* | ||
181 | * Functions to extract or store SSH wire encoded strings (u32 len || data) | ||
182 | * The "cstring" variants admit no \0 characters in the string contents. | ||
183 | * Caller must free *valp. | ||
184 | */ | ||
185 | int sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp); | ||
186 | int sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp); | ||
187 | int sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v); | ||
188 | int sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len); | ||
189 | int sshbuf_put_cstring(struct sshbuf *buf, const char *v); | ||
190 | int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v); | ||
191 | |||
192 | /* | ||
193 | * "Direct" variant of sshbuf_get_string, returns pointer into the sshbuf to | ||
194 | * avoid an malloc+memcpy. The pointer is guaranteed to be valid until the | ||
195 | * next sshbuf-modifying function call. Caller does not free. | ||
196 | */ | ||
197 | int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, | ||
198 | size_t *lenp); | ||
199 | |||
200 | /* Skip past a string */ | ||
201 | #define sshbuf_skip_string(buf) sshbuf_get_string_direct(buf, NULL, NULL) | ||
202 | |||
203 | /* Another variant: "peeks" into the buffer without modifying it */ | ||
204 | int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, | ||
205 | size_t *lenp); | ||
206 | |||
207 | /* | ||
208 | * Functions to extract or store SSH wire encoded bignums and elliptic | ||
209 | * curve points. | ||
210 | */ | ||
211 | int sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len); | ||
212 | #ifdef WITH_OPENSSL | ||
213 | int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v); | ||
214 | int sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v); | ||
215 | int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v); | ||
216 | int sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v); | ||
217 | # ifdef OPENSSL_HAS_ECC | ||
218 | int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g); | ||
219 | int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v); | ||
220 | int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g); | ||
221 | int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v); | ||
222 | # endif /* OPENSSL_HAS_ECC */ | ||
223 | #endif /* WITH_OPENSSL */ | ||
224 | |||
225 | /* Dump the contents of the buffer in a human-readable format */ | ||
226 | void sshbuf_dump(struct sshbuf *buf, FILE *f); | ||
227 | |||
228 | /* Dump specified memory in a human-readable format */ | ||
229 | void sshbuf_dump_data(const void *s, size_t len, FILE *f); | ||
230 | |||
231 | /* Return the hexadecimal representation of the contents of the buffer */ | ||
232 | char *sshbuf_dtob16(struct sshbuf *buf); | ||
233 | |||
234 | /* Encode the contents of the buffer as base64 */ | ||
235 | char *sshbuf_dtob64(struct sshbuf *buf); | ||
236 | |||
237 | /* Decode base64 data and append it to the buffer */ | ||
238 | int sshbuf_b64tod(struct sshbuf *buf, const char *b64); | ||
239 | |||
240 | /* Macros for decoding/encoding integers */ | ||
241 | #define PEEK_U64(p) \ | ||
242 | (((u_int64_t)(((u_char *)(p))[0]) << 56) | \ | ||
243 | ((u_int64_t)(((u_char *)(p))[1]) << 48) | \ | ||
244 | ((u_int64_t)(((u_char *)(p))[2]) << 40) | \ | ||
245 | ((u_int64_t)(((u_char *)(p))[3]) << 32) | \ | ||
246 | ((u_int64_t)(((u_char *)(p))[4]) << 24) | \ | ||
247 | ((u_int64_t)(((u_char *)(p))[5]) << 16) | \ | ||
248 | ((u_int64_t)(((u_char *)(p))[6]) << 8) | \ | ||
249 | (u_int64_t)(((u_char *)(p))[7])) | ||
250 | #define PEEK_U32(p) \ | ||
251 | (((u_int32_t)(((u_char *)(p))[0]) << 24) | \ | ||
252 | ((u_int32_t)(((u_char *)(p))[1]) << 16) | \ | ||
253 | ((u_int32_t)(((u_char *)(p))[2]) << 8) | \ | ||
254 | (u_int32_t)(((u_char *)(p))[3])) | ||
255 | #define PEEK_U16(p) \ | ||
256 | (((u_int16_t)(((u_char *)(p))[0]) << 8) | \ | ||
257 | (u_int16_t)(((u_char *)(p))[1])) | ||
258 | |||
259 | #define POKE_U64(p, v) \ | ||
260 | do { \ | ||
261 | ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 56) & 0xff; \ | ||
262 | ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 48) & 0xff; \ | ||
263 | ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 40) & 0xff; \ | ||
264 | ((u_char *)(p))[3] = (((u_int64_t)(v)) >> 32) & 0xff; \ | ||
265 | ((u_char *)(p))[4] = (((u_int64_t)(v)) >> 24) & 0xff; \ | ||
266 | ((u_char *)(p))[5] = (((u_int64_t)(v)) >> 16) & 0xff; \ | ||
267 | ((u_char *)(p))[6] = (((u_int64_t)(v)) >> 8) & 0xff; \ | ||
268 | ((u_char *)(p))[7] = ((u_int64_t)(v)) & 0xff; \ | ||
269 | } while (0) | ||
270 | #define POKE_U32(p, v) \ | ||
271 | do { \ | ||
272 | ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 24) & 0xff; \ | ||
273 | ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 16) & 0xff; \ | ||
274 | ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 8) & 0xff; \ | ||
275 | ((u_char *)(p))[3] = ((u_int64_t)(v)) & 0xff; \ | ||
276 | } while (0) | ||
277 | #define POKE_U16(p, v) \ | ||
278 | do { \ | ||
279 | ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 8) & 0xff; \ | ||
280 | ((u_char *)(p))[1] = ((u_int64_t)(v)) & 0xff; \ | ||
281 | } while (0) | ||
282 | |||
283 | /* Internal definitions follow. Exposed for regress tests */ | ||
284 | #ifdef SSHBUF_INTERNAL | ||
285 | |||
286 | /* | ||
287 | * Return the allocation size of buf | ||
288 | */ | ||
289 | size_t sshbuf_alloc(const struct sshbuf *buf); | ||
290 | |||
291 | /* | ||
292 | * Increment the reference count of buf. | ||
293 | */ | ||
294 | int sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent); | ||
295 | |||
296 | /* | ||
297 | * Return the parent buffer of buf, or NULL if it has no parent. | ||
298 | */ | ||
299 | const struct sshbuf *sshbuf_parent(const struct sshbuf *buf); | ||
300 | |||
301 | /* | ||
302 | * Return the reference count of buf | ||
303 | */ | ||
304 | u_int sshbuf_refcount(const struct sshbuf *buf); | ||
305 | |||
306 | # define SSHBUF_SIZE_INIT 256 /* Initial allocation */ | ||
307 | # define SSHBUF_SIZE_INC 256 /* Preferred increment length */ | ||
308 | # define SSHBUF_PACK_MIN 8192 /* Minimim packable offset */ | ||
309 | |||
310 | /* # define SSHBUF_ABORT abort */ | ||
311 | /* # define SSHBUF_DEBUG */ | ||
312 | |||
313 | # ifndef SSHBUF_ABORT | ||
314 | # define SSHBUF_ABORT() | ||
315 | # endif | ||
316 | |||
317 | # ifdef SSHBUF_DEBUG | ||
318 | # define SSHBUF_TELL(what) do { \ | ||
319 | printf("%s:%d %s: %s size %zu alloc %zu off %zu max %zu\n", \ | ||
320 | __FILE__, __LINE__, __func__, what, \ | ||
321 | buf->size, buf->alloc, buf->off, buf->max_size); \ | ||
322 | fflush(stdout); \ | ||
323 | } while (0) | ||
324 | # define SSHBUF_DBG(x) do { \ | ||
325 | printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ | ||
326 | printf x; \ | ||
327 | printf("\n"); \ | ||
328 | fflush(stdout); \ | ||
329 | } while (0) | ||
330 | # else | ||
331 | # define SSHBUF_TELL(what) | ||
332 | # define SSHBUF_DBG(x) | ||
333 | # endif | ||
334 | #endif /* SSHBUF_INTERNAL */ | ||
335 | |||
336 | #endif /* _SSHBUF_H */ | ||
diff --git a/sshconnect.c b/sshconnect.c index 324f5e0a3..563405ecb 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.c,v 1.246 2014/02/06 22:21:01 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -54,9 +54,9 @@ | |||
54 | #include "sshconnect.h" | 54 | #include "sshconnect.h" |
55 | #include "hostfile.h" | 55 | #include "hostfile.h" |
56 | #include "log.h" | 56 | #include "log.h" |
57 | #include "misc.h" | ||
57 | #include "readconf.h" | 58 | #include "readconf.h" |
58 | #include "atomicio.h" | 59 | #include "atomicio.h" |
59 | #include "misc.h" | ||
60 | #include "dns.h" | 60 | #include "dns.h" |
61 | #include "roaming.h" | 61 | #include "roaming.h" |
62 | #include "monitor_fdpass.h" | 62 | #include "monitor_fdpass.h" |
@@ -65,6 +65,7 @@ | |||
65 | 65 | ||
66 | char *client_version_string = NULL; | 66 | char *client_version_string = NULL; |
67 | char *server_version_string = NULL; | 67 | char *server_version_string = NULL; |
68 | Key *previous_host_key = NULL; | ||
68 | 69 | ||
69 | static int matching_host_key_dns = 0; | 70 | static int matching_host_key_dns = 0; |
70 | 71 | ||
@@ -709,7 +710,7 @@ check_host_cert(const char *host, const Key *host_key) | |||
709 | error("%s", reason); | 710 | error("%s", reason); |
710 | return 0; | 711 | return 0; |
711 | } | 712 | } |
712 | if (buffer_len(&host_key->cert->critical) != 0) { | 713 | if (buffer_len(host_key->cert->critical) != 0) { |
713 | error("Certificate for %s contains unsupported " | 714 | error("Certificate for %s contains unsupported " |
714 | "critical options(s)", host); | 715 | "critical options(s)", host); |
715 | return 0; | 716 | return 0; |
@@ -1222,7 +1223,7 @@ fail: | |||
1222 | int | 1223 | int |
1223 | verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | 1224 | verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) |
1224 | { | 1225 | { |
1225 | int flags = 0; | 1226 | int r = -1, flags = 0; |
1226 | char *fp; | 1227 | char *fp; |
1227 | Key *plain = NULL; | 1228 | Key *plain = NULL; |
1228 | 1229 | ||
@@ -1230,6 +1231,11 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | |||
1230 | debug("Server host key: %s %s", key_type(host_key), fp); | 1231 | debug("Server host key: %s %s", key_type(host_key), fp); |
1231 | free(fp); | 1232 | free(fp); |
1232 | 1233 | ||
1234 | if (key_equal(previous_host_key, host_key)) { | ||
1235 | debug("%s: server host key matches cached key", __func__); | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1233 | if (options.verify_host_key_dns) { | 1239 | if (options.verify_host_key_dns) { |
1234 | /* | 1240 | /* |
1235 | * XXX certs are not yet supported for DNS, so downgrade | 1241 | * XXX certs are not yet supported for DNS, so downgrade |
@@ -1244,7 +1250,8 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | |||
1244 | flags & DNS_VERIFY_MATCH && | 1250 | flags & DNS_VERIFY_MATCH && |
1245 | flags & DNS_VERIFY_SECURE) { | 1251 | flags & DNS_VERIFY_SECURE) { |
1246 | key_free(plain); | 1252 | key_free(plain); |
1247 | return 0; | 1253 | r = 0; |
1254 | goto done; | ||
1248 | } | 1255 | } |
1249 | if (flags & DNS_VERIFY_MATCH) { | 1256 | if (flags & DNS_VERIFY_MATCH) { |
1250 | matching_host_key_dns = 1; | 1257 | matching_host_key_dns = 1; |
@@ -1259,9 +1266,17 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | |||
1259 | key_free(plain); | 1266 | key_free(plain); |
1260 | } | 1267 | } |
1261 | 1268 | ||
1262 | return check_host_key(host, hostaddr, options.port, host_key, RDRW, | 1269 | r = check_host_key(host, hostaddr, options.port, host_key, RDRW, |
1263 | options.user_hostfiles, options.num_user_hostfiles, | 1270 | options.user_hostfiles, options.num_user_hostfiles, |
1264 | options.system_hostfiles, options.num_system_hostfiles); | 1271 | options.system_hostfiles, options.num_system_hostfiles); |
1272 | |||
1273 | done: | ||
1274 | if (r == 0 && host_key != NULL) { | ||
1275 | key_free(previous_host_key); | ||
1276 | previous_host_key = key_from_private(host_key); | ||
1277 | } | ||
1278 | |||
1279 | return r; | ||
1265 | } | 1280 | } |
1266 | 1281 | ||
1267 | /* | 1282 | /* |
@@ -1297,8 +1312,12 @@ ssh_login(Sensitive *sensitive, const char *orighost, | |||
1297 | ssh_kex2(host, hostaddr, port); | 1312 | ssh_kex2(host, hostaddr, port); |
1298 | ssh_userauth2(local_user, server_user, host, sensitive); | 1313 | ssh_userauth2(local_user, server_user, host, sensitive); |
1299 | } else { | 1314 | } else { |
1315 | #ifdef WITH_SSH1 | ||
1300 | ssh_kex(host, hostaddr); | 1316 | ssh_kex(host, hostaddr); |
1301 | ssh_userauth1(local_user, server_user, host, sensitive); | 1317 | ssh_userauth1(local_user, server_user, host, sensitive); |
1318 | #else | ||
1319 | fatal("ssh1 is not unsupported"); | ||
1320 | #endif | ||
1302 | } | 1321 | } |
1303 | free(local_user); | 1322 | free(local_user); |
1304 | } | 1323 | } |
diff --git a/sshconnect1.c b/sshconnect1.c index 921408ec1..dd12a3af2 100644 --- a/sshconnect1.c +++ b/sshconnect1.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect1.c,v 1.74 2014/02/02 03:44:32 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect1.c,v 1.76 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -38,11 +38,11 @@ | |||
38 | #include "kex.h" | 38 | #include "kex.h" |
39 | #include "uidswap.h" | 39 | #include "uidswap.h" |
40 | #include "log.h" | 40 | #include "log.h" |
41 | #include "misc.h" | ||
41 | #include "readconf.h" | 42 | #include "readconf.h" |
42 | #include "authfd.h" | 43 | #include "authfd.h" |
43 | #include "sshconnect.h" | 44 | #include "sshconnect.h" |
44 | #include "authfile.h" | 45 | #include "authfile.h" |
45 | #include "misc.h" | ||
46 | #include "canohost.h" | 46 | #include "canohost.h" |
47 | #include "hostfile.h" | 47 | #include "hostfile.h" |
48 | #include "auth.h" | 48 | #include "auth.h" |
@@ -166,7 +166,7 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) | |||
166 | 166 | ||
167 | /* Decrypt the challenge using the private key. */ | 167 | /* Decrypt the challenge using the private key. */ |
168 | /* XXX think about Bleichenbacher, too */ | 168 | /* XXX think about Bleichenbacher, too */ |
169 | if (rsa_private_decrypt(challenge, challenge, prv) <= 0) | 169 | if (rsa_private_decrypt(challenge, challenge, prv) != 0) |
170 | packet_disconnect( | 170 | packet_disconnect( |
171 | "respond_to_rsa_challenge: rsa_private_decrypt failed"); | 171 | "respond_to_rsa_challenge: rsa_private_decrypt failed"); |
172 | 172 | ||
@@ -253,7 +253,7 @@ try_rsa_authentication(int idx) | |||
253 | * load the private key. Try first with empty passphrase; if it | 253 | * load the private key. Try first with empty passphrase; if it |
254 | * fails, ask for a passphrase. | 254 | * fails, ask for a passphrase. |
255 | */ | 255 | */ |
256 | if (public->flags & KEY_FLAG_EXT) | 256 | if (public->flags & SSHKEY_FLAG_EXT) |
257 | private = public; | 257 | private = public; |
258 | else | 258 | else |
259 | private = key_load_private_type(KEY_RSA1, authfile, "", NULL, | 259 | private = key_load_private_type(KEY_RSA1, authfile, "", NULL, |
@@ -302,7 +302,7 @@ try_rsa_authentication(int idx) | |||
302 | respond_to_rsa_challenge(challenge, private->rsa); | 302 | respond_to_rsa_challenge(challenge, private->rsa); |
303 | 303 | ||
304 | /* Destroy the private key unless it in external hardware. */ | 304 | /* Destroy the private key unless it in external hardware. */ |
305 | if (!(private->flags & KEY_FLAG_EXT)) | 305 | if (!(private->flags & SSHKEY_FLAG_EXT)) |
306 | key_free(private); | 306 | key_free(private); |
307 | 307 | ||
308 | /* We no longer need the challenge. */ | 308 | /* We no longer need the challenge. */ |
@@ -592,8 +592,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr) | |||
592 | BN_num_bits(server_key->rsa->n), | 592 | BN_num_bits(server_key->rsa->n), |
593 | SSH_KEY_BITS_RESERVED); | 593 | SSH_KEY_BITS_RESERVED); |
594 | } | 594 | } |
595 | rsa_public_encrypt(key, key, server_key->rsa); | 595 | if (rsa_public_encrypt(key, key, server_key->rsa) != 0 || |
596 | rsa_public_encrypt(key, key, host_key->rsa); | 596 | rsa_public_encrypt(key, key, host_key->rsa) != 0) |
597 | fatal("%s: rsa_public_encrypt failed", __func__); | ||
597 | } else { | 598 | } else { |
598 | /* Host key has smaller modulus (or they are equal). */ | 599 | /* Host key has smaller modulus (or they are equal). */ |
599 | if (BN_num_bits(server_key->rsa->n) < | 600 | if (BN_num_bits(server_key->rsa->n) < |
@@ -604,8 +605,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr) | |||
604 | BN_num_bits(host_key->rsa->n), | 605 | BN_num_bits(host_key->rsa->n), |
605 | SSH_KEY_BITS_RESERVED); | 606 | SSH_KEY_BITS_RESERVED); |
606 | } | 607 | } |
607 | rsa_public_encrypt(key, key, host_key->rsa); | 608 | if (rsa_public_encrypt(key, key, host_key->rsa) != 0 || |
608 | rsa_public_encrypt(key, key, server_key->rsa); | 609 | rsa_public_encrypt(key, key, server_key->rsa) != 0) |
610 | fatal("%s: rsa_public_encrypt failed", __func__); | ||
609 | } | 611 | } |
610 | 612 | ||
611 | /* Destroy the public keys since we no longer need them. */ | 613 | /* Destroy the public keys since we no longer need them. */ |
diff --git a/sshconnect2.c b/sshconnect2.c index 1a4e55179..7b478f16d 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.204 2014/02/02 03:44:32 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.210 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -61,8 +61,8 @@ | |||
61 | #include "dh.h" | 61 | #include "dh.h" |
62 | #include "authfd.h" | 62 | #include "authfd.h" |
63 | #include "log.h" | 63 | #include "log.h" |
64 | #include "readconf.h" | ||
65 | #include "misc.h" | 64 | #include "misc.h" |
65 | #include "readconf.h" | ||
66 | #include "match.h" | 66 | #include "match.h" |
67 | #include "dispatch.h" | 67 | #include "dispatch.h" |
68 | #include "canohost.h" | 68 | #include "canohost.h" |
@@ -156,6 +156,7 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) | |||
156 | void | 156 | void |
157 | ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | 157 | ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) |
158 | { | 158 | { |
159 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; | ||
159 | Kex *kex; | 160 | Kex *kex; |
160 | 161 | ||
161 | #ifdef GSSAPI | 162 | #ifdef GSSAPI |
@@ -240,11 +241,13 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | |||
240 | 241 | ||
241 | /* start key exchange */ | 242 | /* start key exchange */ |
242 | kex = kex_setup(myproposal); | 243 | kex = kex_setup(myproposal); |
244 | #ifdef WITH_OPENSSL | ||
243 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; | 245 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; |
244 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; | 246 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; |
245 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; | 247 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; |
246 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; | 248 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; |
247 | kex->kex[KEX_ECDH_SHA2] = kexecdh_client; | 249 | kex->kex[KEX_ECDH_SHA2] = kexecdh_client; |
250 | #endif | ||
248 | kex->kex[KEX_C25519_SHA256] = kexc25519_client; | 251 | kex->kex[KEX_C25519_SHA256] = kexc25519_client; |
249 | #ifdef GSSAPI | 252 | #ifdef GSSAPI |
250 | if (options.gss_keyex) { | 253 | if (options.gss_keyex) { |
@@ -1083,7 +1086,7 @@ identity_sign(Identity *id, u_char **sigp, u_int *lenp, | |||
1083 | * we have already loaded the private key or | 1086 | * we have already loaded the private key or |
1084 | * the private key is stored in external hardware | 1087 | * the private key is stored in external hardware |
1085 | */ | 1088 | */ |
1086 | if (id->isprivate || (id->key->flags & KEY_FLAG_EXT)) | 1089 | if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)) |
1087 | return (key_sign(id->key, sigp, lenp, data, datalen)); | 1090 | return (key_sign(id->key, sigp, lenp, data, datalen)); |
1088 | /* load the private key from the file */ | 1091 | /* load the private key from the file */ |
1089 | if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) | 1092 | if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) |
@@ -1291,12 +1294,12 @@ pubkey_prepare(Authctxt *authctxt) | |||
1291 | } | 1294 | } |
1292 | /* Prefer PKCS11 keys that are explicitly listed */ | 1295 | /* Prefer PKCS11 keys that are explicitly listed */ |
1293 | TAILQ_FOREACH_SAFE(id, &files, next, tmp) { | 1296 | TAILQ_FOREACH_SAFE(id, &files, next, tmp) { |
1294 | if (id->key == NULL || (id->key->flags & KEY_FLAG_EXT) == 0) | 1297 | if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0) |
1295 | continue; | 1298 | continue; |
1296 | found = 0; | 1299 | found = 0; |
1297 | TAILQ_FOREACH(id2, &files, next) { | 1300 | TAILQ_FOREACH(id2, &files, next) { |
1298 | if (id2->key == NULL || | 1301 | if (id2->key == NULL || |
1299 | (id2->key->flags & KEY_FLAG_EXT) != 0) | 1302 | (id2->key->flags & SSHKEY_FLAG_EXT) == 0) |
1300 | continue; | 1303 | continue; |
1301 | if (key_equal(id->key, id2->key)) { | 1304 | if (key_equal(id->key, id2->key)) { |
1302 | TAILQ_REMOVE(&files, id, next); | 1305 | TAILQ_REMOVE(&files, id, next); |
@@ -1,4 +1,4 @@ | |||
1 | SSHD(8) OpenBSD System Manager's Manual SSHD(8) | 1 | SSHD(8) System Manager's Manual SSHD(8) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | sshd - OpenSSH SSH daemon | 4 | sshd - OpenSSH SSH daemon |
@@ -11,7 +11,7 @@ SYNOPSIS | |||
11 | 11 | ||
12 | DESCRIPTION | 12 | DESCRIPTION |
13 | sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these | 13 | sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these |
14 | programs replace rlogin(1) and rsh(1), and provide secure encrypted | 14 | programs replace rlogin and rsh, and provide secure encrypted |
15 | communications between two untrusted hosts over an insecure network. | 15 | communications between two untrusted hosts over an insecure network. |
16 | 16 | ||
17 | sshd listens for connections from clients. It is normally started at | 17 | sshd listens for connections from clients. It is normally started at |
@@ -228,9 +228,10 @@ LOGIN PROCESS | |||
228 | 228 | ||
229 | 7. Changes to user's home directory. | 229 | 7. Changes to user's home directory. |
230 | 230 | ||
231 | 8. If ~/.ssh/rc exists, runs it; else if /etc/ssh/sshrc exists, | 231 | 8. If ~/.ssh/rc exists and the sshd_config(5) PermitUserRC option |
232 | runs it; otherwise runs xauth. The ``rc'' files are given the | 232 | is set, runs it; else if /etc/ssh/sshrc exists, runs it; |
233 | X11 authentication protocol and cookie in standard input. See | 233 | otherwise runs xauth. The ``rc'' files are given the X11 |
234 | authentication protocol and cookie in standard input. See | ||
234 | SSHRC, below. | 235 | SSHRC, below. |
235 | 236 | ||
236 | 9. Runs user's shell or command. | 237 | 9. Runs user's shell or command. |
@@ -545,11 +546,6 @@ FILES | |||
545 | directory becomes accessible. This file should be writable only | 546 | directory becomes accessible. This file should be writable only |
546 | by the user, and need not be readable by anyone else. | 547 | by the user, and need not be readable by anyone else. |
547 | 548 | ||
548 | /etc/hosts.allow | ||
549 | /etc/hosts.deny | ||
550 | Access controls that should be enforced by tcp-wrappers are | ||
551 | defined here. Further details are described in hosts_access(5). | ||
552 | |||
553 | /etc/hosts.equiv | 549 | /etc/hosts.equiv |
554 | This file is for host-based authentication (see ssh(1)). It | 550 | This file is for host-based authentication (see ssh(1)). It |
555 | should only be writable by root. | 551 | should only be writable by root. |
@@ -625,8 +621,8 @@ FILES | |||
625 | 621 | ||
626 | SEE ALSO | 622 | SEE ALSO |
627 | scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), | 623 | scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), |
628 | ssh-keyscan(1), chroot(2), hosts_access(5), login.conf(5), moduli(5), | 624 | ssh-keyscan(1), chroot(2), login.conf(5), moduli(5), sshd_config(5), |
629 | sshd_config(5), inetd(8), sftp-server(8) | 625 | inetd(8), sftp-server(8) |
630 | 626 | ||
631 | AUTHORS | 627 | AUTHORS |
632 | OpenSSH is a derivative of the original and free ssh 1.2.12 release by | 628 | OpenSSH is a derivative of the original and free ssh 1.2.12 release by |
@@ -636,8 +632,4 @@ AUTHORS | |||
636 | versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support | 632 | versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support |
637 | for privilege separation. | 633 | for privilege separation. |
638 | 634 | ||
639 | CAVEATS | 635 | OpenBSD 5.6 July 3, 2014 OpenBSD 5.6 |
640 | System security is not improved unless rshd, rlogind, and rexecd are | ||
641 | disabled (thus completely disabling rlogin and rsh into the machine). | ||
642 | |||
643 | OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 | ||
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 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. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: sshd.8,v 1.273 2013/12/07 11:58:46 naddy Exp $ | 36 | .\" $OpenBSD: sshd.8,v 1.276 2014/07/03 22:40:43 djm Exp $ |
37 | .Dd $Mdocdate: December 7 2013 $ | 37 | .Dd $Mdocdate: July 3 2014 $ |
38 | .Dt SSHD 8 | 38 | .Dt SSHD 8 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -60,10 +60,7 @@ | |||
60 | .Nm | 60 | .Nm |
61 | (OpenSSH Daemon) is the daemon program for | 61 | (OpenSSH Daemon) is the daemon program for |
62 | .Xr ssh 1 . | 62 | .Xr ssh 1 . |
63 | Together these programs replace | 63 | Together these programs replace rlogin and rsh, |
64 | .Xr rlogin 1 | ||
65 | and | ||
66 | .Xr rsh 1 , | ||
67 | and provide secure encrypted communications between two untrusted hosts | 64 | and provide secure encrypted communications between two untrusted hosts |
68 | over an insecure network. | 65 | over an insecure network. |
69 | .Pp | 66 | .Pp |
@@ -414,7 +411,10 @@ Changes to user's home directory. | |||
414 | .It | 411 | .It |
415 | If | 412 | If |
416 | .Pa ~/.ssh/rc | 413 | .Pa ~/.ssh/rc |
417 | exists, runs it; else if | 414 | exists and the |
415 | .Xr sshd_config 5 | ||
416 | .Cm PermitUserRC | ||
417 | option is set, runs it; else if | ||
418 | .Pa /etc/ssh/sshrc | 418 | .Pa /etc/ssh/sshrc |
419 | exists, runs | 419 | exists, runs |
420 | it; otherwise runs xauth. | 420 | it; otherwise runs xauth. |
@@ -979,14 +979,3 @@ Markus Friedl contributed the support for SSH | |||
979 | protocol versions 1.5 and 2.0. | 979 | protocol versions 1.5 and 2.0. |
980 | Niels Provos and Markus Friedl contributed support | 980 | Niels Provos and Markus Friedl contributed support |
981 | for privilege separation. | 981 | for privilege separation. |
982 | .Sh CAVEATS | ||
983 | System security is not improved unless | ||
984 | .Nm rshd , | ||
985 | .Nm rlogind , | ||
986 | and | ||
987 | .Nm rexecd | ||
988 | are disabled (thus completely disabling | ||
989 | .Xr rlogin | ||
990 | and | ||
991 | .Xr rsh | ||
992 | into the machine). | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.420 2014/02/26 21:53:37 markus Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.428 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -72,10 +72,12 @@ | |||
72 | #include <string.h> | 72 | #include <string.h> |
73 | #include <unistd.h> | 73 | #include <unistd.h> |
74 | 74 | ||
75 | #ifdef WITH_OPENSSL | ||
75 | #include <openssl/dh.h> | 76 | #include <openssl/dh.h> |
76 | #include <openssl/bn.h> | 77 | #include <openssl/bn.h> |
77 | #include <openssl/rand.h> | 78 | #include <openssl/rand.h> |
78 | #include "openbsd-compat/openssl-compat.h" | 79 | #include "openbsd-compat/openssl-compat.h" |
80 | #endif | ||
79 | 81 | ||
80 | #ifdef HAVE_SECUREWARE | 82 | #ifdef HAVE_SECUREWARE |
81 | #include <sys/security.h> | 83 | #include <sys/security.h> |
@@ -91,6 +93,7 @@ | |||
91 | #include "packet.h" | 93 | #include "packet.h" |
92 | #include "log.h" | 94 | #include "log.h" |
93 | #include "buffer.h" | 95 | #include "buffer.h" |
96 | #include "misc.h" | ||
94 | #include "servconf.h" | 97 | #include "servconf.h" |
95 | #include "uidswap.h" | 98 | #include "uidswap.h" |
96 | #include "compat.h" | 99 | #include "compat.h" |
@@ -98,7 +101,6 @@ | |||
98 | #include "digest.h" | 101 | #include "digest.h" |
99 | #include "key.h" | 102 | #include "key.h" |
100 | #include "kex.h" | 103 | #include "kex.h" |
101 | #include "dh.h" | ||
102 | #include "myproposal.h" | 104 | #include "myproposal.h" |
103 | #include "authfile.h" | 105 | #include "authfile.h" |
104 | #include "pathnames.h" | 106 | #include "pathnames.h" |
@@ -107,7 +109,6 @@ | |||
107 | #include "hostfile.h" | 109 | #include "hostfile.h" |
108 | #include "auth.h" | 110 | #include "auth.h" |
109 | #include "authfd.h" | 111 | #include "authfd.h" |
110 | #include "misc.h" | ||
111 | #include "msg.h" | 112 | #include "msg.h" |
112 | #include "dispatch.h" | 113 | #include "dispatch.h" |
113 | #include "channels.h" | 114 | #include "channels.h" |
@@ -267,7 +268,9 @@ struct passwd *privsep_pw = NULL; | |||
267 | void destroy_sensitive_data(void); | 268 | void destroy_sensitive_data(void); |
268 | void demote_sensitive_data(void); | 269 | void demote_sensitive_data(void); |
269 | 270 | ||
271 | #ifdef WITH_SSH1 | ||
270 | static void do_ssh1_kex(void); | 272 | static void do_ssh1_kex(void); |
273 | #endif | ||
271 | static void do_ssh2_kex(void); | 274 | static void do_ssh2_kex(void); |
272 | 275 | ||
273 | /* | 276 | /* |
@@ -943,7 +946,13 @@ static void | |||
943 | usage(void) | 946 | usage(void) |
944 | { | 947 | { |
945 | fprintf(stderr, "%s, %s\n", | 948 | fprintf(stderr, "%s, %s\n", |
946 | SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); | 949 | SSH_RELEASE, |
950 | #ifdef WITH_OPENSSL | ||
951 | SSLeay_version(SSLEAY_VERSION) | ||
952 | #else | ||
953 | "without OpenSSL" | ||
954 | #endif | ||
955 | ); | ||
947 | fprintf(stderr, | 956 | fprintf(stderr, |
948 | "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" | 957 | "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" |
949 | " [-E log_file] [-f config_file] [-g login_grace_time]\n" | 958 | " [-E log_file] [-f config_file] [-g login_grace_time]\n" |
@@ -976,6 +985,7 @@ send_rexec_state(int fd, Buffer *conf) | |||
976 | buffer_init(&m); | 985 | buffer_init(&m); |
977 | buffer_put_cstring(&m, buffer_ptr(conf)); | 986 | buffer_put_cstring(&m, buffer_ptr(conf)); |
978 | 987 | ||
988 | #ifdef WITH_SSH1 | ||
979 | if (sensitive_data.server_key != NULL && | 989 | if (sensitive_data.server_key != NULL && |
980 | sensitive_data.server_key->type == KEY_RSA1) { | 990 | sensitive_data.server_key->type == KEY_RSA1) { |
981 | buffer_put_int(&m, 1); | 991 | buffer_put_int(&m, 1); |
@@ -986,6 +996,7 @@ send_rexec_state(int fd, Buffer *conf) | |||
986 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); | 996 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); |
987 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); | 997 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); |
988 | } else | 998 | } else |
999 | #endif | ||
989 | buffer_put_int(&m, 0); | 1000 | buffer_put_int(&m, 0); |
990 | 1001 | ||
991 | #ifndef OPENSSL_PRNG_ONLY | 1002 | #ifndef OPENSSL_PRNG_ONLY |
@@ -1022,6 +1033,7 @@ recv_rexec_state(int fd, Buffer *conf) | |||
1022 | free(cp); | 1033 | free(cp); |
1023 | 1034 | ||
1024 | if (buffer_get_int(&m)) { | 1035 | if (buffer_get_int(&m)) { |
1036 | #ifdef WITH_SSH1 | ||
1025 | if (sensitive_data.server_key != NULL) | 1037 | if (sensitive_data.server_key != NULL) |
1026 | key_free(sensitive_data.server_key); | 1038 | key_free(sensitive_data.server_key); |
1027 | sensitive_data.server_key = key_new_private(KEY_RSA1); | 1039 | sensitive_data.server_key = key_new_private(KEY_RSA1); |
@@ -1031,8 +1043,13 @@ recv_rexec_state(int fd, Buffer *conf) | |||
1031 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); | 1043 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); |
1032 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); | 1044 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); |
1033 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); | 1045 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); |
1034 | rsa_generate_additional_parameters( | 1046 | if (rsa_generate_additional_parameters( |
1035 | sensitive_data.server_key->rsa); | 1047 | sensitive_data.server_key->rsa) != 0) |
1048 | fatal("%s: rsa_generate_additional_parameters " | ||
1049 | "error", __func__); | ||
1050 | #else | ||
1051 | fatal("ssh1 not supported"); | ||
1052 | #endif | ||
1036 | } | 1053 | } |
1037 | 1054 | ||
1038 | #ifndef OPENSSL_PRNG_ONLY | 1055 | #ifndef OPENSSL_PRNG_ONLY |
@@ -1555,7 +1572,9 @@ main(int ac, char **av) | |||
1555 | else | 1572 | else |
1556 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); | 1573 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); |
1557 | 1574 | ||
1575 | #ifdef WITH_OPENSSL | ||
1558 | OpenSSL_add_all_algorithms(); | 1576 | OpenSSL_add_all_algorithms(); |
1577 | #endif | ||
1559 | 1578 | ||
1560 | /* If requested, redirect the logs to the specified logfile. */ | 1579 | /* If requested, redirect the logs to the specified logfile. */ |
1561 | if (logfile != NULL) { | 1580 | if (logfile != NULL) { |
@@ -1660,7 +1679,12 @@ main(int ac, char **av) | |||
1660 | } | 1679 | } |
1661 | 1680 | ||
1662 | debug("sshd version %s, %s", SSH_VERSION, | 1681 | debug("sshd version %s, %s", SSH_VERSION, |
1663 | SSLeay_version(SSLEAY_VERSION)); | 1682 | #ifdef WITH_OPENSSL |
1683 | SSLeay_version(SSLEAY_VERSION) | ||
1684 | #else | ||
1685 | "without OpenSSL" | ||
1686 | #endif | ||
1687 | ); | ||
1664 | 1688 | ||
1665 | /* Store privilege separation user for later use if required. */ | 1689 | /* Store privilege separation user for later use if required. */ |
1666 | if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { | 1690 | if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { |
@@ -1785,6 +1809,8 @@ main(int ac, char **av) | |||
1785 | debug("host certificate: #%d type %d %s", j, key->type, | 1809 | debug("host certificate: #%d type %d %s", j, key->type, |
1786 | key_type(key)); | 1810 | key_type(key)); |
1787 | } | 1811 | } |
1812 | |||
1813 | #ifdef WITH_SSH1 | ||
1788 | /* Check certain values for sanity. */ | 1814 | /* Check certain values for sanity. */ |
1789 | if (options.protocol & SSH_PROTO_1) { | 1815 | if (options.protocol & SSH_PROTO_1) { |
1790 | if (options.server_key_bits < 512 || | 1816 | if (options.server_key_bits < 512 || |
@@ -1809,6 +1835,7 @@ main(int ac, char **av) | |||
1809 | options.server_key_bits); | 1835 | options.server_key_bits); |
1810 | } | 1836 | } |
1811 | } | 1837 | } |
1838 | #endif | ||
1812 | 1839 | ||
1813 | if (use_privsep) { | 1840 | if (use_privsep) { |
1814 | struct stat st; | 1841 | struct stat st; |
@@ -2174,8 +2201,12 @@ main(int ac, char **av) | |||
2174 | do_ssh2_kex(); | 2201 | do_ssh2_kex(); |
2175 | do_authentication2(authctxt); | 2202 | do_authentication2(authctxt); |
2176 | } else { | 2203 | } else { |
2204 | #ifdef WITH_SSH1 | ||
2177 | do_ssh1_kex(); | 2205 | do_ssh1_kex(); |
2178 | do_authentication(authctxt); | 2206 | do_authentication(authctxt); |
2207 | #else | ||
2208 | fatal("ssh1 not supported"); | ||
2209 | #endif | ||
2179 | } | 2210 | } |
2180 | /* | 2211 | /* |
2181 | * If we use privilege separation, the unprivileged child transfers | 2212 | * If we use privilege separation, the unprivileged child transfers |
@@ -2259,6 +2290,7 @@ main(int ac, char **av) | |||
2259 | exit(0); | 2290 | exit(0); |
2260 | } | 2291 | } |
2261 | 2292 | ||
2293 | #ifdef WITH_SSH1 | ||
2262 | /* | 2294 | /* |
2263 | * Decrypt session_key_int using our private server key and private host key | 2295 | * Decrypt session_key_int using our private server key and private host key |
2264 | * (key with larger modulus first). | 2296 | * (key with larger modulus first). |
@@ -2282,10 +2314,10 @@ ssh1_session_key(BIGNUM *session_key_int) | |||
2282 | SSH_KEY_BITS_RESERVED); | 2314 | SSH_KEY_BITS_RESERVED); |
2283 | } | 2315 | } |
2284 | if (rsa_private_decrypt(session_key_int, session_key_int, | 2316 | if (rsa_private_decrypt(session_key_int, session_key_int, |
2285 | sensitive_data.server_key->rsa) <= 0) | 2317 | sensitive_data.server_key->rsa) != 0) |
2286 | rsafail++; | 2318 | rsafail++; |
2287 | if (rsa_private_decrypt(session_key_int, session_key_int, | 2319 | if (rsa_private_decrypt(session_key_int, session_key_int, |
2288 | sensitive_data.ssh1_host_key->rsa) <= 0) | 2320 | sensitive_data.ssh1_host_key->rsa) != 0) |
2289 | rsafail++; | 2321 | rsafail++; |
2290 | } else { | 2322 | } else { |
2291 | /* Host key has bigger modulus (or they are equal). */ | 2323 | /* Host key has bigger modulus (or they are equal). */ |
@@ -2300,14 +2332,15 @@ ssh1_session_key(BIGNUM *session_key_int) | |||
2300 | SSH_KEY_BITS_RESERVED); | 2332 | SSH_KEY_BITS_RESERVED); |
2301 | } | 2333 | } |
2302 | if (rsa_private_decrypt(session_key_int, session_key_int, | 2334 | if (rsa_private_decrypt(session_key_int, session_key_int, |
2303 | sensitive_data.ssh1_host_key->rsa) < 0) | 2335 | sensitive_data.ssh1_host_key->rsa) != 0) |
2304 | rsafail++; | 2336 | rsafail++; |
2305 | if (rsa_private_decrypt(session_key_int, session_key_int, | 2337 | if (rsa_private_decrypt(session_key_int, session_key_int, |
2306 | sensitive_data.server_key->rsa) < 0) | 2338 | sensitive_data.server_key->rsa) != 0) |
2307 | rsafail++; | 2339 | rsafail++; |
2308 | } | 2340 | } |
2309 | return (rsafail); | 2341 | return (rsafail); |
2310 | } | 2342 | } |
2343 | |||
2311 | /* | 2344 | /* |
2312 | * SSH1 key exchange | 2345 | * SSH1 key exchange |
2313 | */ | 2346 | */ |
@@ -2485,6 +2518,7 @@ do_ssh1_kex(void) | |||
2485 | packet_send(); | 2518 | packet_send(); |
2486 | packet_write_wait(); | 2519 | packet_write_wait(); |
2487 | } | 2520 | } |
2521 | #endif | ||
2488 | 2522 | ||
2489 | void | 2523 | void |
2490 | sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, | 2524 | sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, |
@@ -2509,6 +2543,7 @@ sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, | |||
2509 | static void | 2543 | static void |
2510 | do_ssh2_kex(void) | 2544 | do_ssh2_kex(void) |
2511 | { | 2545 | { |
2546 | char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; | ||
2512 | Kex *kex; | 2547 | Kex *kex; |
2513 | 2548 | ||
2514 | if (options.ciphers != NULL) { | 2549 | if (options.ciphers != NULL) { |
@@ -2588,11 +2623,13 @@ do_ssh2_kex(void) | |||
2588 | 2623 | ||
2589 | /* start key exchange */ | 2624 | /* start key exchange */ |
2590 | kex = kex_setup(myproposal); | 2625 | kex = kex_setup(myproposal); |
2626 | #ifdef WITH_OPENSSL | ||
2591 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 2627 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
2592 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 2628 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
2593 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 2629 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
2594 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 2630 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
2595 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 2631 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; |
2632 | #endif | ||
2596 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 2633 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
2597 | #ifdef GSSAPI | 2634 | #ifdef GSSAPI |
2598 | if (options.gss_keyex) { | 2635 | if (options.gss_keyex) { |
@@ -2632,7 +2669,8 @@ cleanup_exit(int i) | |||
2632 | { | 2669 | { |
2633 | if (the_authctxt) { | 2670 | if (the_authctxt) { |
2634 | do_cleanup(the_authctxt); | 2671 | do_cleanup(the_authctxt); |
2635 | if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) { | 2672 | if (use_privsep && privsep_is_preauth && |
2673 | pmonitor != NULL && pmonitor->m_pid > 1) { | ||
2636 | debug("Killing privsep child %d", pmonitor->m_pid); | 2674 | debug("Killing privsep child %d", pmonitor->m_pid); |
2637 | if (kill(pmonitor->m_pid, SIGKILL) != 0 && | 2675 | if (kill(pmonitor->m_pid, SIGKILL) != 0 && |
2638 | errno != ESRCH) | 2676 | errno != ESRCH) |
diff --git a/sshd_config.0 b/sshd_config.0 index 413c26008..1c82d449f 100644 --- a/sshd_config.0 +++ b/sshd_config.0 | |||
@@ -1,4 +1,4 @@ | |||
1 | SSHD_CONFIG(5) OpenBSD Programmer's Manual SSHD_CONFIG(5) | 1 | SSHD_CONFIG(5) File Formats Manual SSHD_CONFIG(5) |
2 | 2 | ||
3 | NAME | 3 | NAME |
4 | sshd_config - OpenSSH SSH daemon configuration file | 4 | sshd_config - OpenSSH SSH daemon configuration file |
@@ -62,6 +62,16 @@ DESCRIPTION | |||
62 | are also denied shell access, as they can always install their | 62 | are also denied shell access, as they can always install their |
63 | own forwarders. | 63 | own forwarders. |
64 | 64 | ||
65 | AllowStreamLocalForwarding | ||
66 | Specifies whether StreamLocal (Unix-domain socket) forwarding is | ||
67 | permitted. The available options are ``yes'' or ``all'' to allow | ||
68 | StreamLocal forwarding, ``no'' to prevent all StreamLocal | ||
69 | forwarding, ``local'' to allow local (from the perspective of | ||
70 | ssh(1)) forwarding only or ``remote'' to allow remote forwarding | ||
71 | only. The default is ``yes''. Note that disabling StreamLocal | ||
72 | forwarding does not improve security unless users are also denied | ||
73 | shell access, as they can always install their own forwarders. | ||
74 | |||
65 | AllowUsers | 75 | AllowUsers |
66 | This keyword can be followed by a list of user name patterns, | 76 | This keyword can be followed by a list of user name patterns, |
67 | separated by spaces. If specified, login is allowed only for | 77 | separated by spaces. If specified, login is allowed only for |
@@ -168,7 +178,7 @@ DESCRIPTION | |||
168 | 178 | ||
169 | ChallengeResponseAuthentication | 179 | ChallengeResponseAuthentication |
170 | Specifies whether challenge-response authentication is allowed | 180 | Specifies whether challenge-response authentication is allowed |
171 | (e.g. via PAM or though authentication styles supported in | 181 | (e.g. via PAM or through authentication styles supported in |
172 | login.conf(5)) The default is ``yes''. | 182 | login.conf(5)) The default is ``yes''. |
173 | 183 | ||
174 | ChrootDirectory | 184 | ChrootDirectory |
@@ -191,8 +201,9 @@ DESCRIPTION | |||
191 | stderr(4), arandom(4) and tty(4) devices. For file transfer | 201 | stderr(4), arandom(4) and tty(4) devices. For file transfer |
192 | sessions using ``sftp'', no additional configuration of the | 202 | sessions using ``sftp'', no additional configuration of the |
193 | environment is necessary if the in-process sftp server is used, | 203 | environment is necessary if the in-process sftp server is used, |
194 | though sessions which use logging do require /dev/log inside the | 204 | though sessions which use logging may require /dev/log inside the |
195 | chroot directory (see sftp-server(8) for details). | 205 | chroot directory on some operating systems (see sftp-server(8) |
206 | for details). | ||
196 | 207 | ||
197 | The default is not to chroot(2). | 208 | The default is not to chroot(2). |
198 | 209 | ||
@@ -200,19 +211,27 @@ DESCRIPTION | |||
200 | Specifies the ciphers allowed for protocol version 2. Multiple | 211 | Specifies the ciphers allowed for protocol version 2. Multiple |
201 | ciphers must be comma-separated. The supported ciphers are: | 212 | ciphers must be comma-separated. The supported ciphers are: |
202 | 213 | ||
203 | ``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', ``aes256-cbc'', | 214 | 3des-cbc |
204 | ``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'', | 215 | aes128-cbc |
205 | ``aes128-gcm@openssh.com'', ``aes256-gcm@openssh.com'', | 216 | aes192-cbc |
206 | ``arcfour128'', ``arcfour256'', ``arcfour'', ``blowfish-cbc'', | 217 | aes256-cbc |
207 | ``cast128-cbc'', and ``chacha20-poly1305@openssh.com''. | 218 | aes128-ctr |
219 | aes192-ctr | ||
220 | aes256-ctr | ||
221 | aes128-gcm@openssh.com | ||
222 | aes256-gcm@openssh.com | ||
223 | arcfour | ||
224 | arcfour128 | ||
225 | arcfour256 | ||
226 | blowfish-cbc | ||
227 | cast128-cbc | ||
228 | chacha20-poly1305@openssh.com | ||
208 | 229 | ||
209 | The default is: | 230 | The default is: |
210 | 231 | ||
211 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, | 232 | aes128-ctr,aes192-ctr,aes256-ctr, |
212 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, | 233 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, |
213 | chacha20-poly1305@openssh.com, | 234 | chacha20-poly1305@openssh.com |
214 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, | ||
215 | aes256-cbc,arcfour | ||
216 | 235 | ||
217 | The list of available ciphers may also be obtained using the -Q | 236 | The list of available ciphers may also be obtained using the -Q |
218 | option of ssh(1). | 237 | option of ssh(1). |
@@ -403,14 +422,24 @@ DESCRIPTION | |||
403 | 422 | ||
404 | KexAlgorithms | 423 | KexAlgorithms |
405 | Specifies the available KEX (Key Exchange) algorithms. Multiple | 424 | Specifies the available KEX (Key Exchange) algorithms. Multiple |
406 | algorithms must be comma-separated. The default is | 425 | algorithms must be comma-separated. The supported algorithms |
426 | are: | ||
427 | |||
428 | curve25519-sha256@libssh.org | ||
429 | diffie-hellman-group1-sha1 | ||
430 | diffie-hellman-group14-sha1 | ||
431 | diffie-hellman-group-exchange-sha1 | ||
432 | diffie-hellman-group-exchange-sha256 | ||
433 | ecdh-sha2-nistp256 | ||
434 | ecdh-sha2-nistp384 | ||
435 | ecdh-sha2-nistp521 | ||
436 | |||
437 | The default is: | ||
407 | 438 | ||
408 | curve25519-sha256@libssh.org, | 439 | curve25519-sha256@libssh.org, |
409 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, | 440 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, |
410 | diffie-hellman-group-exchange-sha256, | 441 | diffie-hellman-group-exchange-sha256, |
411 | diffie-hellman-group-exchange-sha1, | 442 | diffie-hellman-group14-sha1 |
412 | diffie-hellman-group14-sha1, | ||
413 | diffie-hellman-group1-sha1 | ||
414 | 443 | ||
415 | KeyRegenerationInterval | 444 | KeyRegenerationInterval |
416 | In protocol version 1, the ephemeral server key is automatically | 445 | In protocol version 1, the ephemeral server key is automatically |
@@ -452,16 +481,33 @@ DESCRIPTION | |||
452 | data integrity protection. Multiple algorithms must be comma- | 481 | data integrity protection. Multiple algorithms must be comma- |
453 | separated. The algorithms that contain ``-etm'' calculate the | 482 | separated. The algorithms that contain ``-etm'' calculate the |
454 | MAC after encryption (encrypt-then-mac). These are considered | 483 | MAC after encryption (encrypt-then-mac). These are considered |
455 | safer and their use recommended. The default is: | 484 | safer and their use recommended. The supported MACs are: |
485 | |||
486 | hmac-md5 | ||
487 | hmac-md5-96 | ||
488 | hmac-ripemd160 | ||
489 | hmac-sha1 | ||
490 | hmac-sha1-96 | ||
491 | hmac-sha2-256 | ||
492 | hmac-sha2-512 | ||
493 | umac-64@openssh.com | ||
494 | umac-128@openssh.com | ||
495 | hmac-md5-etm@openssh.com | ||
496 | hmac-md5-96-etm@openssh.com | ||
497 | hmac-ripemd160-etm@openssh.com | ||
498 | hmac-sha1-etm@openssh.com | ||
499 | hmac-sha1-96-etm@openssh.com | ||
500 | hmac-sha2-256-etm@openssh.com | ||
501 | hmac-sha2-512-etm@openssh.com | ||
502 | umac-64-etm@openssh.com | ||
503 | umac-128-etm@openssh.com | ||
504 | |||
505 | The default is: | ||
456 | 506 | ||
457 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, | ||
458 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, | 507 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, |
459 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, | 508 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, |
460 | hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, | 509 | umac-64@openssh.com,umac-128@openssh.com, |
461 | hmac-md5-96-etm@openssh.com, | 510 | hmac-sha2-256,hmac-sha2-512 |
462 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, | ||
463 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, | ||
464 | hmac-sha1-96,hmac-md5-96 | ||
465 | 511 | ||
466 | Match Introduces a conditional block. If all of the criteria on the | 512 | Match Introduces a conditional block. If all of the criteria on the |
467 | Match line are satisfied, the keywords on the following lines | 513 | Match line are satisfied, the keywords on the following lines |
@@ -496,7 +542,7 @@ DESCRIPTION | |||
496 | KbdInteractiveAuthentication, KerberosAuthentication, | 542 | KbdInteractiveAuthentication, KerberosAuthentication, |
497 | MaxAuthTries, MaxSessions, PasswordAuthentication, | 543 | MaxAuthTries, MaxSessions, PasswordAuthentication, |
498 | PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTTY, | 544 | PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTTY, |
499 | PermitTunnel, PubkeyAuthentication, RekeyLimit, | 545 | PermitTunnel, PermitUserRC, PubkeyAuthentication, RekeyLimit, |
500 | RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset, | 546 | RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset, |
501 | X11Forwarding and X11UseLocalHost. | 547 | X11Forwarding and X11UseLocalHost. |
502 | 548 | ||
@@ -580,6 +626,10 @@ DESCRIPTION | |||
580 | bypass access restrictions in some configurations using | 626 | bypass access restrictions in some configurations using |
581 | mechanisms such as LD_PRELOAD. | 627 | mechanisms such as LD_PRELOAD. |
582 | 628 | ||
629 | PermitUserRC | ||
630 | Specifies whether any ~/.ssh/rc file is executed. The default is | ||
631 | ``yes''. | ||
632 | |||
583 | PidFile | 633 | PidFile |
584 | Specifies the file that contains the process ID of the SSH | 634 | Specifies the file that contains the process ID of the SSH |
585 | daemon. The default is /var/run/sshd.pid. | 635 | daemon. The default is /var/run/sshd.pid. |
@@ -650,6 +700,27 @@ DESCRIPTION | |||
650 | Defines the number of bits in the ephemeral protocol version 1 | 700 | Defines the number of bits in the ephemeral protocol version 1 |
651 | server key. The minimum value is 512, and the default is 1024. | 701 | server key. The minimum value is 512, and the default is 1024. |
652 | 702 | ||
703 | StreamLocalBindMask | ||
704 | Sets the octal file creation mode mask (umask) used when creating | ||
705 | a Unix-domain socket file for local or remote port forwarding. | ||
706 | This option is only used for port forwarding to a Unix-domain | ||
707 | socket file. | ||
708 | |||
709 | The default value is 0177, which creates a Unix-domain socket | ||
710 | file that is readable and writable only by the owner. Note that | ||
711 | not all operating systems honor the file mode on Unix-domain | ||
712 | socket files. | ||
713 | |||
714 | StreamLocalBindUnlink | ||
715 | Specifies whether to remove an existing Unix-domain socket file | ||
716 | for local or remote port forwarding before creating a new one. | ||
717 | If the socket file already exists and StreamLocalBindUnlink is | ||
718 | not enabled, sshd will be unable to forward the port to the Unix- | ||
719 | domain socket file. This option is only used for port forwarding | ||
720 | to a Unix-domain socket file. | ||
721 | |||
722 | The argument must be ``yes'' or ``no''. The default is ``no''. | ||
723 | |||
653 | StrictModes | 724 | StrictModes |
654 | Specifies whether sshd(8) should check file modes and ownership | 725 | Specifies whether sshd(8) should check file modes and ownership |
655 | of the user's files and home directory before accepting login. | 726 | of the user's files and home directory before accepting login. |
@@ -832,4 +903,4 @@ AUTHORS | |||
832 | versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support | 903 | versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support |
833 | for privilege separation. | 904 | for privilege separation. |
834 | 905 | ||
835 | OpenBSD 5.5 February 27, 2014 OpenBSD 5.5 | 906 | OpenBSD 5.6 July 28, 2014 OpenBSD 5.6 |
diff --git a/sshd_config.5 b/sshd_config.5 index 90fd3f4a8..7aa7b4733 100644 --- a/sshd_config.5 +++ b/sshd_config.5 | |||
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 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. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: sshd_config.5,v 1.172 2014/02/27 22:47:07 djm Exp $ | 36 | .\" $OpenBSD: sshd_config.5,v 1.176 2014/07/28 15:40:08 schwarze Exp $ |
37 | .Dd $Mdocdate: February 27 2014 $ | 37 | .Dd $Mdocdate: July 28 2014 $ |
38 | .Dt SSHD_CONFIG 5 | 38 | .Dt SSHD_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -165,6 +165,26 @@ The default is | |||
165 | Note that disabling TCP forwarding does not improve security unless | 165 | Note that disabling TCP forwarding does not improve security unless |
166 | users are also denied shell access, as they can always install their | 166 | users are also denied shell access, as they can always install their |
167 | own forwarders. | 167 | own forwarders. |
168 | .It Cm AllowStreamLocalForwarding | ||
169 | Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted. | ||
170 | The available options are | ||
171 | .Dq yes | ||
172 | or | ||
173 | .Dq all | ||
174 | to allow StreamLocal forwarding, | ||
175 | .Dq no | ||
176 | to prevent all StreamLocal forwarding, | ||
177 | .Dq local | ||
178 | to allow local (from the perspective of | ||
179 | .Xr ssh 1 ) | ||
180 | forwarding only or | ||
181 | .Dq remote | ||
182 | to allow remote forwarding only. | ||
183 | The default is | ||
184 | .Dq yes . | ||
185 | Note that disabling StreamLocal forwarding does not improve security unless | ||
186 | users are also denied shell access, as they can always install their | ||
187 | own forwarders. | ||
168 | .It Cm AllowUsers | 188 | .It Cm AllowUsers |
169 | This keyword can be followed by a list of user name patterns, separated | 189 | This keyword can be followed by a list of user name patterns, separated |
170 | by spaces. | 190 | by spaces. |
@@ -348,9 +368,9 @@ For file transfer sessions using | |||
348 | .Dq sftp , | 368 | .Dq sftp , |
349 | no additional configuration of the environment is necessary if the | 369 | no additional configuration of the environment is necessary if the |
350 | in-process sftp server is used, | 370 | in-process sftp server is used, |
351 | though sessions which use logging do require | 371 | though sessions which use logging may require |
352 | .Pa /dev/log | 372 | .Pa /dev/log |
353 | inside the chroot directory (see | 373 | inside the chroot directory on some operating systems (see |
354 | .Xr sftp-server 8 | 374 | .Xr sftp-server 8 |
355 | for details). | 375 | for details). |
356 | .Pp | 376 | .Pp |
@@ -361,30 +381,44 @@ Specifies the ciphers allowed for protocol version 2. | |||
361 | Multiple ciphers must be comma-separated. | 381 | Multiple ciphers must be comma-separated. |
362 | The supported ciphers are: | 382 | The supported ciphers are: |
363 | .Pp | 383 | .Pp |
364 | .Dq 3des-cbc , | 384 | .Bl -item -compact -offset indent |
365 | .Dq aes128-cbc , | 385 | .It |
366 | .Dq aes192-cbc , | 386 | 3des-cbc |
367 | .Dq aes256-cbc , | 387 | .It |
368 | .Dq aes128-ctr , | 388 | aes128-cbc |
369 | .Dq aes192-ctr , | 389 | .It |
370 | .Dq aes256-ctr , | 390 | aes192-cbc |
371 | .Dq aes128-gcm@openssh.com , | 391 | .It |
372 | .Dq aes256-gcm@openssh.com , | 392 | aes256-cbc |
373 | .Dq arcfour128 , | 393 | .It |
374 | .Dq arcfour256 , | 394 | aes128-ctr |
375 | .Dq arcfour , | 395 | .It |
376 | .Dq blowfish-cbc , | 396 | aes192-ctr |
377 | .Dq cast128-cbc , | 397 | .It |
378 | and | 398 | aes256-ctr |
379 | .Dq chacha20-poly1305@openssh.com . | 399 | .It |
400 | aes128-gcm@openssh.com | ||
401 | .It | ||
402 | aes256-gcm@openssh.com | ||
403 | .It | ||
404 | arcfour | ||
405 | .It | ||
406 | arcfour128 | ||
407 | .It | ||
408 | arcfour256 | ||
409 | .It | ||
410 | blowfish-cbc | ||
411 | .It | ||
412 | cast128-cbc | ||
413 | .It | ||
414 | chacha20-poly1305@openssh.com | ||
415 | .El | ||
380 | .Pp | 416 | .Pp |
381 | The default is: | 417 | The default is: |
382 | .Bd -literal -offset 3n | 418 | .Bd -literal -offset indent |
383 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, | 419 | aes128-ctr,aes192-ctr,aes256-ctr, |
384 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, | 420 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, |
385 | chacha20-poly1305@openssh.com, | 421 | chacha20-poly1305@openssh.com |
386 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, | ||
387 | aes256-cbc,arcfour | ||
388 | .Ed | 422 | .Ed |
389 | .Pp | 423 | .Pp |
390 | The list of available ciphers may also be obtained using the | 424 | The list of available ciphers may also be obtained using the |
@@ -729,14 +763,33 @@ The default is | |||
729 | .It Cm KexAlgorithms | 763 | .It Cm KexAlgorithms |
730 | Specifies the available KEX (Key Exchange) algorithms. | 764 | Specifies the available KEX (Key Exchange) algorithms. |
731 | Multiple algorithms must be comma-separated. | 765 | Multiple algorithms must be comma-separated. |
732 | The default is | 766 | The supported algorithms are: |
767 | .Pp | ||
768 | .Bl -item -compact -offset indent | ||
769 | .It | ||
770 | curve25519-sha256@libssh.org | ||
771 | .It | ||
772 | diffie-hellman-group1-sha1 | ||
773 | .It | ||
774 | diffie-hellman-group14-sha1 | ||
775 | .It | ||
776 | diffie-hellman-group-exchange-sha1 | ||
777 | .It | ||
778 | diffie-hellman-group-exchange-sha256 | ||
779 | .It | ||
780 | ecdh-sha2-nistp256 | ||
781 | .It | ||
782 | ecdh-sha2-nistp384 | ||
783 | .It | ||
784 | ecdh-sha2-nistp521 | ||
785 | .El | ||
786 | .Pp | ||
787 | The default is: | ||
733 | .Bd -literal -offset indent | 788 | .Bd -literal -offset indent |
734 | curve25519-sha256@libssh.org, | 789 | curve25519-sha256@libssh.org, |
735 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, | 790 | ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, |
736 | diffie-hellman-group-exchange-sha256, | 791 | diffie-hellman-group-exchange-sha256, |
737 | diffie-hellman-group-exchange-sha1, | 792 | diffie-hellman-group14-sha1 |
738 | diffie-hellman-group14-sha1, | ||
739 | diffie-hellman-group1-sha1 | ||
740 | .Ed | 793 | .Ed |
741 | .It Cm KeyRegenerationInterval | 794 | .It Cm KeyRegenerationInterval |
742 | In protocol version 1, the ephemeral server key is automatically regenerated | 795 | In protocol version 1, the ephemeral server key is automatically regenerated |
@@ -808,16 +861,53 @@ The algorithms that contain | |||
808 | .Dq -etm | 861 | .Dq -etm |
809 | calculate the MAC after encryption (encrypt-then-mac). | 862 | calculate the MAC after encryption (encrypt-then-mac). |
810 | These are considered safer and their use recommended. | 863 | These are considered safer and their use recommended. |
864 | The supported MACs are: | ||
865 | .Pp | ||
866 | .Bl -item -compact -offset indent | ||
867 | .It | ||
868 | hmac-md5 | ||
869 | .It | ||
870 | hmac-md5-96 | ||
871 | .It | ||
872 | hmac-ripemd160 | ||
873 | .It | ||
874 | hmac-sha1 | ||
875 | .It | ||
876 | hmac-sha1-96 | ||
877 | .It | ||
878 | hmac-sha2-256 | ||
879 | .It | ||
880 | hmac-sha2-512 | ||
881 | .It | ||
882 | umac-64@openssh.com | ||
883 | .It | ||
884 | umac-128@openssh.com | ||
885 | .It | ||
886 | hmac-md5-etm@openssh.com | ||
887 | .It | ||
888 | hmac-md5-96-etm@openssh.com | ||
889 | .It | ||
890 | hmac-ripemd160-etm@openssh.com | ||
891 | .It | ||
892 | hmac-sha1-etm@openssh.com | ||
893 | .It | ||
894 | hmac-sha1-96-etm@openssh.com | ||
895 | .It | ||
896 | hmac-sha2-256-etm@openssh.com | ||
897 | .It | ||
898 | hmac-sha2-512-etm@openssh.com | ||
899 | .It | ||
900 | umac-64-etm@openssh.com | ||
901 | .It | ||
902 | umac-128-etm@openssh.com | ||
903 | .El | ||
904 | .Pp | ||
811 | The default is: | 905 | The default is: |
812 | .Bd -literal -offset indent | 906 | .Bd -literal -offset indent |
813 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, | ||
814 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, | 907 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, |
815 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, | 908 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, |
816 | hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, | 909 | umac-64@openssh.com,umac-128@openssh.com, |
817 | hmac-md5-96-etm@openssh.com, | 910 | hmac-sha2-256,hmac-sha2-512 |
818 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, | ||
819 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, | ||
820 | hmac-sha1-96,hmac-md5-96 | ||
821 | .Ed | 911 | .Ed |
822 | .It Cm Match | 912 | .It Cm Match |
823 | Introduces a conditional block. | 913 | Introduces a conditional block. |
@@ -899,6 +989,7 @@ Available keywords are | |||
899 | .Cm PermitRootLogin , | 989 | .Cm PermitRootLogin , |
900 | .Cm PermitTTY , | 990 | .Cm PermitTTY , |
901 | .Cm PermitTunnel , | 991 | .Cm PermitTunnel , |
992 | .Cm PermitUserRC , | ||
902 | .Cm PubkeyAuthentication , | 993 | .Cm PubkeyAuthentication , |
903 | .Cm RekeyLimit , | 994 | .Cm RekeyLimit , |
904 | .Cm RhostsRSAAuthentication , | 995 | .Cm RhostsRSAAuthentication , |
@@ -1047,6 +1138,12 @@ The default is | |||
1047 | Enabling environment processing may enable users to bypass access | 1138 | Enabling environment processing may enable users to bypass access |
1048 | restrictions in some configurations using mechanisms such as | 1139 | restrictions in some configurations using mechanisms such as |
1049 | .Ev LD_PRELOAD . | 1140 | .Ev LD_PRELOAD . |
1141 | .It Cm PermitUserRC | ||
1142 | Specifies whether any | ||
1143 | .Pa ~/.ssh/rc | ||
1144 | file is executed. | ||
1145 | The default is | ||
1146 | .Dq yes . | ||
1050 | .It Cm PidFile | 1147 | .It Cm PidFile |
1051 | Specifies the file that contains the process ID of the | 1148 | Specifies the file that contains the process ID of the |
1052 | SSH daemon. | 1149 | SSH daemon. |
@@ -1151,6 +1248,33 @@ This option applies to protocol version 1 only. | |||
1151 | .It Cm ServerKeyBits | 1248 | .It Cm ServerKeyBits |
1152 | Defines the number of bits in the ephemeral protocol version 1 server key. | 1249 | Defines the number of bits in the ephemeral protocol version 1 server key. |
1153 | The minimum value is 512, and the default is 1024. | 1250 | The minimum value is 512, and the default is 1024. |
1251 | .It Cm StreamLocalBindMask | ||
1252 | Sets the octal file creation mode mask | ||
1253 | .Pq umask | ||
1254 | used when creating a Unix-domain socket file for local or remote | ||
1255 | port forwarding. | ||
1256 | This option is only used for port forwarding to a Unix-domain socket file. | ||
1257 | .Pp | ||
1258 | The default value is 0177, which creates a Unix-domain socket file that is | ||
1259 | readable and writable only by the owner. | ||
1260 | Note that not all operating systems honor the file mode on Unix-domain | ||
1261 | socket files. | ||
1262 | .It Cm StreamLocalBindUnlink | ||
1263 | Specifies whether to remove an existing Unix-domain socket file for local | ||
1264 | or remote port forwarding before creating a new one. | ||
1265 | If the socket file already exists and | ||
1266 | .Cm StreamLocalBindUnlink | ||
1267 | is not enabled, | ||
1268 | .Nm sshd | ||
1269 | will be unable to forward the port to the Unix-domain socket file. | ||
1270 | This option is only used for port forwarding to a Unix-domain socket file. | ||
1271 | .Pp | ||
1272 | The argument must be | ||
1273 | .Dq yes | ||
1274 | or | ||
1275 | .Dq no . | ||
1276 | The default is | ||
1277 | .Dq no . | ||
1154 | .It Cm StrictModes | 1278 | .It Cm StrictModes |
1155 | Specifies whether | 1279 | Specifies whether |
1156 | .Xr sshd 8 | 1280 | .Xr sshd 8 |
diff --git a/ssherr.c b/ssherr.c new file mode 100644 index 000000000..49fbb71de --- /dev/null +++ b/ssherr.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* $OpenBSD: ssherr.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <errno.h> | ||
19 | #include <string.h> | ||
20 | #include "ssherr.h" | ||
21 | |||
22 | const char * | ||
23 | ssh_err(int n) | ||
24 | { | ||
25 | switch (n) { | ||
26 | case SSH_ERR_SUCCESS: | ||
27 | return "success"; | ||
28 | case SSH_ERR_INTERNAL_ERROR: | ||
29 | return "unexpected internal error"; | ||
30 | case SSH_ERR_ALLOC_FAIL: | ||
31 | return "memory allocation failed"; | ||
32 | case SSH_ERR_MESSAGE_INCOMPLETE: | ||
33 | return "incomplete message"; | ||
34 | case SSH_ERR_INVALID_FORMAT: | ||
35 | return "invalid format"; | ||
36 | case SSH_ERR_BIGNUM_IS_NEGATIVE: | ||
37 | return "bignum is negative"; | ||
38 | case SSH_ERR_STRING_TOO_LARGE: | ||
39 | return "string is too large"; | ||
40 | case SSH_ERR_BIGNUM_TOO_LARGE: | ||
41 | return "bignum is too large"; | ||
42 | case SSH_ERR_ECPOINT_TOO_LARGE: | ||
43 | return "elliptic curve point is too large"; | ||
44 | case SSH_ERR_NO_BUFFER_SPACE: | ||
45 | return "insufficient buffer space"; | ||
46 | case SSH_ERR_INVALID_ARGUMENT: | ||
47 | return "invalid argument"; | ||
48 | case SSH_ERR_KEY_BITS_MISMATCH: | ||
49 | return "key bits do not match"; | ||
50 | case SSH_ERR_EC_CURVE_INVALID: | ||
51 | return "invalid elliptic curve"; | ||
52 | case SSH_ERR_KEY_TYPE_MISMATCH: | ||
53 | return "key type does not match"; | ||
54 | case SSH_ERR_KEY_TYPE_UNKNOWN: | ||
55 | return "unknown or unsupported key type"; | ||
56 | case SSH_ERR_EC_CURVE_MISMATCH: | ||
57 | return "elliptic curve does not match"; | ||
58 | case SSH_ERR_EXPECTED_CERT: | ||
59 | return "plain key provided where certificate required"; | ||
60 | case SSH_ERR_KEY_LACKS_CERTBLOB: | ||
61 | return "key lacks certificate data"; | ||
62 | case SSH_ERR_KEY_CERT_UNKNOWN_TYPE: | ||
63 | return "unknown/unsupported certificate type"; | ||
64 | case SSH_ERR_KEY_CERT_INVALID_SIGN_KEY: | ||
65 | return "invalid certificate signing key"; | ||
66 | case SSH_ERR_KEY_INVALID_EC_VALUE: | ||
67 | return "invalid elliptic curve value"; | ||
68 | case SSH_ERR_SIGNATURE_INVALID: | ||
69 | return "incorrect signature"; | ||
70 | case SSH_ERR_LIBCRYPTO_ERROR: | ||
71 | return "error in libcrypto"; /* XXX fetch and return */ | ||
72 | case SSH_ERR_UNEXPECTED_TRAILING_DATA: | ||
73 | return "unexpected bytes remain after decoding"; | ||
74 | case SSH_ERR_SYSTEM_ERROR: | ||
75 | return strerror(errno); | ||
76 | case SSH_ERR_KEY_CERT_INVALID: | ||
77 | return "invalid certificate"; | ||
78 | case SSH_ERR_AGENT_COMMUNICATION: | ||
79 | return "communication with agent failed"; | ||
80 | case SSH_ERR_AGENT_FAILURE: | ||
81 | return "agent refused operation"; | ||
82 | case SSH_ERR_DH_GEX_OUT_OF_RANGE: | ||
83 | return "DH GEX group out of range"; | ||
84 | case SSH_ERR_DISCONNECTED: | ||
85 | return "disconnected"; | ||
86 | case SSH_ERR_MAC_INVALID: | ||
87 | return "message authentication code incorrect"; | ||
88 | case SSH_ERR_NO_CIPHER_ALG_MATCH: | ||
89 | return "no matching cipher found"; | ||
90 | case SSH_ERR_NO_MAC_ALG_MATCH: | ||
91 | return "no matching MAC found"; | ||
92 | case SSH_ERR_NO_COMPRESS_ALG_MATCH: | ||
93 | return "no matching compression method found"; | ||
94 | case SSH_ERR_NO_KEX_ALG_MATCH: | ||
95 | return "no matching key exchange method found"; | ||
96 | case SSH_ERR_NO_HOSTKEY_ALG_MATCH: | ||
97 | return "no matching host key type found"; | ||
98 | case SSH_ERR_PROTOCOL_MISMATCH: | ||
99 | return "protocol version mismatch"; | ||
100 | case SSH_ERR_NO_PROTOCOL_VERSION: | ||
101 | return "could not read protocol version"; | ||
102 | case SSH_ERR_NO_HOSTKEY_LOADED: | ||
103 | return "could not load host key"; | ||
104 | case SSH_ERR_NEED_REKEY: | ||
105 | return "rekeying not supported by peer"; | ||
106 | case SSH_ERR_PASSPHRASE_TOO_SHORT: | ||
107 | return "passphrase is too short (minimum four characters)"; | ||
108 | case SSH_ERR_FILE_CHANGED: | ||
109 | return "file changed while reading"; | ||
110 | case SSH_ERR_KEY_UNKNOWN_CIPHER: | ||
111 | return "key encrypted using unsupported cipher"; | ||
112 | case SSH_ERR_KEY_WRONG_PASSPHRASE: | ||
113 | return "incorrect passphrase supplied to decrypt private key"; | ||
114 | case SSH_ERR_KEY_BAD_PERMISSIONS: | ||
115 | return "bad permissions"; | ||
116 | case SSH_ERR_KEY_CERT_MISMATCH: | ||
117 | return "certificate does not match key"; | ||
118 | case SSH_ERR_KEY_NOT_FOUND: | ||
119 | return "key not found"; | ||
120 | case SSH_ERR_AGENT_NOT_PRESENT: | ||
121 | return "agent not present"; | ||
122 | case SSH_ERR_AGENT_NO_IDENTITIES: | ||
123 | return "agent contains no identities"; | ||
124 | case SSH_ERR_KRL_BAD_MAGIC: | ||
125 | return "KRL file has invalid magic number"; | ||
126 | case SSH_ERR_KEY_REVOKED: | ||
127 | return "Key is revoked"; | ||
128 | default: | ||
129 | return "unknown error"; | ||
130 | } | ||
131 | } | ||
diff --git a/ssherr.h b/ssherr.h new file mode 100644 index 000000000..106f786ea --- /dev/null +++ b/ssherr.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* $OpenBSD: ssherr.h,v 1.1 2014/04/30 05:29:56 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef _SSHERR_H | ||
19 | #define _SSHERR_H | ||
20 | |||
21 | /* XXX are these too granular? not granular enough? I can't decide - djm */ | ||
22 | |||
23 | /* Error codes */ | ||
24 | #define SSH_ERR_SUCCESS 0 | ||
25 | #define SSH_ERR_INTERNAL_ERROR -1 | ||
26 | #define SSH_ERR_ALLOC_FAIL -2 | ||
27 | #define SSH_ERR_MESSAGE_INCOMPLETE -3 | ||
28 | #define SSH_ERR_INVALID_FORMAT -4 | ||
29 | #define SSH_ERR_BIGNUM_IS_NEGATIVE -5 | ||
30 | #define SSH_ERR_STRING_TOO_LARGE -6 | ||
31 | #define SSH_ERR_BIGNUM_TOO_LARGE -7 | ||
32 | #define SSH_ERR_ECPOINT_TOO_LARGE -8 | ||
33 | #define SSH_ERR_NO_BUFFER_SPACE -9 | ||
34 | #define SSH_ERR_INVALID_ARGUMENT -10 | ||
35 | #define SSH_ERR_KEY_BITS_MISMATCH -11 | ||
36 | #define SSH_ERR_EC_CURVE_INVALID -12 | ||
37 | #define SSH_ERR_KEY_TYPE_MISMATCH -13 | ||
38 | #define SSH_ERR_KEY_TYPE_UNKNOWN -14 /* XXX UNSUPPORTED? */ | ||
39 | #define SSH_ERR_EC_CURVE_MISMATCH -15 | ||
40 | #define SSH_ERR_EXPECTED_CERT -16 | ||
41 | #define SSH_ERR_KEY_LACKS_CERTBLOB -17 | ||
42 | #define SSH_ERR_KEY_CERT_UNKNOWN_TYPE -18 | ||
43 | #define SSH_ERR_KEY_CERT_INVALID_SIGN_KEY -19 | ||
44 | #define SSH_ERR_KEY_INVALID_EC_VALUE -20 | ||
45 | #define SSH_ERR_SIGNATURE_INVALID -21 | ||
46 | #define SSH_ERR_LIBCRYPTO_ERROR -22 | ||
47 | #define SSH_ERR_UNEXPECTED_TRAILING_DATA -23 | ||
48 | #define SSH_ERR_SYSTEM_ERROR -24 | ||
49 | #define SSH_ERR_KEY_CERT_INVALID -25 | ||
50 | #define SSH_ERR_AGENT_COMMUNICATION -26 | ||
51 | #define SSH_ERR_AGENT_FAILURE -27 | ||
52 | #define SSH_ERR_DH_GEX_OUT_OF_RANGE -28 | ||
53 | #define SSH_ERR_DISCONNECTED -29 | ||
54 | #define SSH_ERR_MAC_INVALID -30 | ||
55 | #define SSH_ERR_NO_CIPHER_ALG_MATCH -31 | ||
56 | #define SSH_ERR_NO_MAC_ALG_MATCH -32 | ||
57 | #define SSH_ERR_NO_COMPRESS_ALG_MATCH -33 | ||
58 | #define SSH_ERR_NO_KEX_ALG_MATCH -34 | ||
59 | #define SSH_ERR_NO_HOSTKEY_ALG_MATCH -35 | ||
60 | #define SSH_ERR_NO_HOSTKEY_LOADED -36 | ||
61 | #define SSH_ERR_PROTOCOL_MISMATCH -37 | ||
62 | #define SSH_ERR_NO_PROTOCOL_VERSION -38 | ||
63 | #define SSH_ERR_NEED_REKEY -39 | ||
64 | #define SSH_ERR_PASSPHRASE_TOO_SHORT -40 | ||
65 | #define SSH_ERR_FILE_CHANGED -41 | ||
66 | #define SSH_ERR_KEY_UNKNOWN_CIPHER -42 | ||
67 | #define SSH_ERR_KEY_WRONG_PASSPHRASE -43 | ||
68 | #define SSH_ERR_KEY_BAD_PERMISSIONS -44 | ||
69 | #define SSH_ERR_KEY_CERT_MISMATCH -45 | ||
70 | #define SSH_ERR_KEY_NOT_FOUND -46 | ||
71 | #define SSH_ERR_AGENT_NOT_PRESENT -47 | ||
72 | #define SSH_ERR_AGENT_NO_IDENTITIES -48 | ||
73 | #define SSH_ERR_BUFFER_READ_ONLY -49 | ||
74 | #define SSH_ERR_KRL_BAD_MAGIC -50 | ||
75 | #define SSH_ERR_KEY_REVOKED -51 | ||
76 | |||
77 | /* Translate a numeric error code to a human-readable error string */ | ||
78 | const char *ssh_err(int n); | ||
79 | |||
80 | #endif /* _SSHERR_H */ | ||
diff --git a/sshkey.c b/sshkey.c new file mode 100644 index 000000000..1a96eae19 --- /dev/null +++ b/sshkey.c | |||
@@ -0,0 +1,3857 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.3 2014/07/03 01:45:38 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | ||
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | ||
5 | * Copyright (c) 2010,2011 Damien Miller. All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #include "includes.h" | ||
29 | |||
30 | #include <sys/param.h> | ||
31 | #include <sys/types.h> | ||
32 | |||
33 | #include <openssl/evp.h> | ||
34 | #include <openssl/err.h> | ||
35 | #include <openssl/pem.h> | ||
36 | |||
37 | #include "crypto_api.h" | ||
38 | |||
39 | #include <errno.h> | ||
40 | #include <stdio.h> | ||
41 | #include <string.h> | ||
42 | #ifdef HAVE_UTIL_H | ||
43 | #include <util.h> | ||
44 | #endif /* HAVE_UTIL_H */ | ||
45 | |||
46 | #include "ssh2.h" | ||
47 | #include "ssherr.h" | ||
48 | #include "misc.h" | ||
49 | #include "sshbuf.h" | ||
50 | #include "rsa.h" | ||
51 | #include "cipher.h" | ||
52 | #include "digest.h" | ||
53 | #define SSHKEY_INTERNAL | ||
54 | #include "sshkey.h" | ||
55 | |||
56 | /* openssh private key file format */ | ||
57 | #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" | ||
58 | #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" | ||
59 | #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1) | ||
60 | #define MARK_END_LEN (sizeof(MARK_END) - 1) | ||
61 | #define KDFNAME "bcrypt" | ||
62 | #define AUTH_MAGIC "openssh-key-v1" | ||
63 | #define SALT_LEN 16 | ||
64 | #define DEFAULT_CIPHERNAME "aes256-cbc" | ||
65 | #define DEFAULT_ROUNDS 16 | ||
66 | |||
67 | /* Version identification string for SSH v1 identity files. */ | ||
68 | #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" | ||
69 | |||
70 | static int sshkey_from_blob_internal(const u_char *blob, size_t blen, | ||
71 | struct sshkey **keyp, int allow_cert); | ||
72 | |||
73 | /* Supported key types */ | ||
74 | struct keytype { | ||
75 | const char *name; | ||
76 | const char *shortname; | ||
77 | int type; | ||
78 | int nid; | ||
79 | int cert; | ||
80 | }; | ||
81 | static const struct keytype keytypes[] = { | ||
82 | { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 }, | ||
83 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", | ||
84 | KEY_ED25519_CERT, 0, 1 }, | ||
85 | #ifdef WITH_OPENSSL | ||
86 | { NULL, "RSA1", KEY_RSA1, 0, 0 }, | ||
87 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, | ||
88 | { "ssh-dss", "DSA", KEY_DSA, 0, 0 }, | ||
89 | # ifdef OPENSSL_HAS_ECC | ||
90 | { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, | ||
91 | { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, | ||
92 | # ifdef OPENSSL_HAS_NISTP521 | ||
93 | { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, | ||
94 | # endif /* OPENSSL_HAS_NISTP521 */ | ||
95 | # endif /* OPENSSL_HAS_ECC */ | ||
96 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 }, | ||
97 | { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 }, | ||
98 | # ifdef OPENSSL_HAS_ECC | ||
99 | { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", | ||
100 | KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 }, | ||
101 | { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", | ||
102 | KEY_ECDSA_CERT, NID_secp384r1, 1 }, | ||
103 | # ifdef OPENSSL_HAS_NISTP521 | ||
104 | { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", | ||
105 | KEY_ECDSA_CERT, NID_secp521r1, 1 }, | ||
106 | # endif /* OPENSSL_HAS_NISTP521 */ | ||
107 | # endif /* OPENSSL_HAS_ECC */ | ||
108 | { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00", | ||
109 | KEY_RSA_CERT_V00, 0, 1 }, | ||
110 | { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", | ||
111 | KEY_DSA_CERT_V00, 0, 1 }, | ||
112 | #endif /* WITH_OPENSSL */ | ||
113 | { "null", "null", KEY_NULL, 0, 0 }, | ||
114 | { NULL, NULL, -1, -1, 0 } | ||
115 | }; | ||
116 | |||
117 | const char * | ||
118 | sshkey_type(const struct sshkey *k) | ||
119 | { | ||
120 | const struct keytype *kt; | ||
121 | |||
122 | for (kt = keytypes; kt->type != -1; kt++) { | ||
123 | if (kt->type == k->type) | ||
124 | return kt->shortname; | ||
125 | } | ||
126 | return "unknown"; | ||
127 | } | ||
128 | |||
129 | static const char * | ||
130 | sshkey_ssh_name_from_type_nid(int type, int nid) | ||
131 | { | ||
132 | const struct keytype *kt; | ||
133 | |||
134 | for (kt = keytypes; kt->type != -1; kt++) { | ||
135 | if (kt->type == type && (kt->nid == 0 || kt->nid == nid)) | ||
136 | return kt->name; | ||
137 | } | ||
138 | return "ssh-unknown"; | ||
139 | } | ||
140 | |||
141 | int | ||
142 | sshkey_type_is_cert(int type) | ||
143 | { | ||
144 | const struct keytype *kt; | ||
145 | |||
146 | for (kt = keytypes; kt->type != -1; kt++) { | ||
147 | if (kt->type == type) | ||
148 | return kt->cert; | ||
149 | } | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | const char * | ||
154 | sshkey_ssh_name(const struct sshkey *k) | ||
155 | { | ||
156 | return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid); | ||
157 | } | ||
158 | |||
159 | const char * | ||
160 | sshkey_ssh_name_plain(const struct sshkey *k) | ||
161 | { | ||
162 | return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type), | ||
163 | k->ecdsa_nid); | ||
164 | } | ||
165 | |||
166 | int | ||
167 | sshkey_type_from_name(const char *name) | ||
168 | { | ||
169 | const struct keytype *kt; | ||
170 | |||
171 | for (kt = keytypes; kt->type != -1; kt++) { | ||
172 | /* Only allow shortname matches for plain key types */ | ||
173 | if ((kt->name != NULL && strcmp(name, kt->name) == 0) || | ||
174 | (!kt->cert && strcasecmp(kt->shortname, name) == 0)) | ||
175 | return kt->type; | ||
176 | } | ||
177 | return KEY_UNSPEC; | ||
178 | } | ||
179 | |||
180 | int | ||
181 | sshkey_ecdsa_nid_from_name(const char *name) | ||
182 | { | ||
183 | const struct keytype *kt; | ||
184 | |||
185 | for (kt = keytypes; kt->type != -1; kt++) { | ||
186 | if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) | ||
187 | continue; | ||
188 | if (kt->name != NULL && strcmp(name, kt->name) == 0) | ||
189 | return kt->nid; | ||
190 | } | ||
191 | return -1; | ||
192 | } | ||
193 | |||
194 | char * | ||
195 | key_alg_list(int certs_only, int plain_only) | ||
196 | { | ||
197 | char *tmp, *ret = NULL; | ||
198 | size_t nlen, rlen = 0; | ||
199 | const struct keytype *kt; | ||
200 | |||
201 | for (kt = keytypes; kt->type != -1; kt++) { | ||
202 | if (kt->name == NULL || kt->type == KEY_NULL) | ||
203 | continue; | ||
204 | if ((certs_only && !kt->cert) || (plain_only && kt->cert)) | ||
205 | continue; | ||
206 | if (ret != NULL) | ||
207 | ret[rlen++] = '\n'; | ||
208 | nlen = strlen(kt->name); | ||
209 | if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { | ||
210 | free(ret); | ||
211 | return NULL; | ||
212 | } | ||
213 | ret = tmp; | ||
214 | memcpy(ret + rlen, kt->name, nlen + 1); | ||
215 | rlen += nlen; | ||
216 | } | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | int | ||
221 | sshkey_names_valid2(const char *names) | ||
222 | { | ||
223 | char *s, *cp, *p; | ||
224 | |||
225 | if (names == NULL || strcmp(names, "") == 0) | ||
226 | return 0; | ||
227 | if ((s = cp = strdup(names)) == NULL) | ||
228 | return 0; | ||
229 | for ((p = strsep(&cp, ",")); p && *p != '\0'; | ||
230 | (p = strsep(&cp, ","))) { | ||
231 | switch (sshkey_type_from_name(p)) { | ||
232 | case KEY_RSA1: | ||
233 | case KEY_UNSPEC: | ||
234 | free(s); | ||
235 | return 0; | ||
236 | } | ||
237 | } | ||
238 | free(s); | ||
239 | return 1; | ||
240 | } | ||
241 | |||
242 | u_int | ||
243 | sshkey_size(const struct sshkey *k) | ||
244 | { | ||
245 | switch (k->type) { | ||
246 | #ifdef WITH_OPENSSL | ||
247 | case KEY_RSA1: | ||
248 | case KEY_RSA: | ||
249 | case KEY_RSA_CERT_V00: | ||
250 | case KEY_RSA_CERT: | ||
251 | return BN_num_bits(k->rsa->n); | ||
252 | case KEY_DSA: | ||
253 | case KEY_DSA_CERT_V00: | ||
254 | case KEY_DSA_CERT: | ||
255 | return BN_num_bits(k->dsa->p); | ||
256 | case KEY_ECDSA: | ||
257 | case KEY_ECDSA_CERT: | ||
258 | return sshkey_curve_nid_to_bits(k->ecdsa_nid); | ||
259 | #endif /* WITH_OPENSSL */ | ||
260 | case KEY_ED25519: | ||
261 | case KEY_ED25519_CERT: | ||
262 | return 256; /* XXX */ | ||
263 | } | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | int | ||
268 | sshkey_cert_is_legacy(const struct sshkey *k) | ||
269 | { | ||
270 | switch (k->type) { | ||
271 | case KEY_DSA_CERT_V00: | ||
272 | case KEY_RSA_CERT_V00: | ||
273 | return 1; | ||
274 | default: | ||
275 | return 0; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | static int | ||
280 | sshkey_type_is_valid_ca(int type) | ||
281 | { | ||
282 | switch (type) { | ||
283 | case KEY_RSA: | ||
284 | case KEY_DSA: | ||
285 | case KEY_ECDSA: | ||
286 | case KEY_ED25519: | ||
287 | return 1; | ||
288 | default: | ||
289 | return 0; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | int | ||
294 | sshkey_is_cert(const struct sshkey *k) | ||
295 | { | ||
296 | if (k == NULL) | ||
297 | return 0; | ||
298 | return sshkey_type_is_cert(k->type); | ||
299 | } | ||
300 | |||
301 | /* Return the cert-less equivalent to a certified key type */ | ||
302 | int | ||
303 | sshkey_type_plain(int type) | ||
304 | { | ||
305 | switch (type) { | ||
306 | case KEY_RSA_CERT_V00: | ||
307 | case KEY_RSA_CERT: | ||
308 | return KEY_RSA; | ||
309 | case KEY_DSA_CERT_V00: | ||
310 | case KEY_DSA_CERT: | ||
311 | return KEY_DSA; | ||
312 | case KEY_ECDSA_CERT: | ||
313 | return KEY_ECDSA; | ||
314 | case KEY_ED25519_CERT: | ||
315 | return KEY_ED25519; | ||
316 | default: | ||
317 | return type; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | #ifdef WITH_OPENSSL | ||
322 | /* XXX: these are really begging for a table-driven approach */ | ||
323 | int | ||
324 | sshkey_curve_name_to_nid(const char *name) | ||
325 | { | ||
326 | if (strcmp(name, "nistp256") == 0) | ||
327 | return NID_X9_62_prime256v1; | ||
328 | else if (strcmp(name, "nistp384") == 0) | ||
329 | return NID_secp384r1; | ||
330 | # ifdef OPENSSL_HAS_NISTP521 | ||
331 | else if (strcmp(name, "nistp521") == 0) | ||
332 | return NID_secp521r1; | ||
333 | # endif /* OPENSSL_HAS_NISTP521 */ | ||
334 | else | ||
335 | return -1; | ||
336 | } | ||
337 | |||
338 | u_int | ||
339 | sshkey_curve_nid_to_bits(int nid) | ||
340 | { | ||
341 | switch (nid) { | ||
342 | case NID_X9_62_prime256v1: | ||
343 | return 256; | ||
344 | case NID_secp384r1: | ||
345 | return 384; | ||
346 | # ifdef OPENSSL_HAS_NISTP521 | ||
347 | case NID_secp521r1: | ||
348 | return 521; | ||
349 | # endif /* OPENSSL_HAS_NISTP521 */ | ||
350 | default: | ||
351 | return 0; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | int | ||
356 | sshkey_ecdsa_bits_to_nid(int bits) | ||
357 | { | ||
358 | switch (bits) { | ||
359 | case 256: | ||
360 | return NID_X9_62_prime256v1; | ||
361 | case 384: | ||
362 | return NID_secp384r1; | ||
363 | # ifdef OPENSSL_HAS_NISTP521 | ||
364 | case 521: | ||
365 | return NID_secp521r1; | ||
366 | # endif /* OPENSSL_HAS_NISTP521 */ | ||
367 | default: | ||
368 | return -1; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | const char * | ||
373 | sshkey_curve_nid_to_name(int nid) | ||
374 | { | ||
375 | switch (nid) { | ||
376 | case NID_X9_62_prime256v1: | ||
377 | return "nistp256"; | ||
378 | case NID_secp384r1: | ||
379 | return "nistp384"; | ||
380 | # ifdef OPENSSL_HAS_NISTP521 | ||
381 | case NID_secp521r1: | ||
382 | return "nistp521"; | ||
383 | # endif /* OPENSSL_HAS_NISTP521 */ | ||
384 | default: | ||
385 | return NULL; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | int | ||
390 | sshkey_ec_nid_to_hash_alg(int nid) | ||
391 | { | ||
392 | int kbits = sshkey_curve_nid_to_bits(nid); | ||
393 | |||
394 | if (kbits <= 0) | ||
395 | return -1; | ||
396 | |||
397 | /* RFC5656 section 6.2.1 */ | ||
398 | if (kbits <= 256) | ||
399 | return SSH_DIGEST_SHA256; | ||
400 | else if (kbits <= 384) | ||
401 | return SSH_DIGEST_SHA384; | ||
402 | else | ||
403 | return SSH_DIGEST_SHA512; | ||
404 | } | ||
405 | #endif /* WITH_OPENSSL */ | ||
406 | |||
407 | static void | ||
408 | cert_free(struct sshkey_cert *cert) | ||
409 | { | ||
410 | u_int i; | ||
411 | |||
412 | if (cert == NULL) | ||
413 | return; | ||
414 | if (cert->certblob != NULL) | ||
415 | sshbuf_free(cert->certblob); | ||
416 | if (cert->critical != NULL) | ||
417 | sshbuf_free(cert->critical); | ||
418 | if (cert->extensions != NULL) | ||
419 | sshbuf_free(cert->extensions); | ||
420 | if (cert->key_id != NULL) | ||
421 | free(cert->key_id); | ||
422 | for (i = 0; i < cert->nprincipals; i++) | ||
423 | free(cert->principals[i]); | ||
424 | if (cert->principals != NULL) | ||
425 | free(cert->principals); | ||
426 | if (cert->signature_key != NULL) | ||
427 | sshkey_free(cert->signature_key); | ||
428 | explicit_bzero(cert, sizeof(*cert)); | ||
429 | free(cert); | ||
430 | } | ||
431 | |||
432 | static struct sshkey_cert * | ||
433 | cert_new(void) | ||
434 | { | ||
435 | struct sshkey_cert *cert; | ||
436 | |||
437 | if ((cert = calloc(1, sizeof(*cert))) == NULL) | ||
438 | return NULL; | ||
439 | if ((cert->certblob = sshbuf_new()) == NULL || | ||
440 | (cert->critical = sshbuf_new()) == NULL || | ||
441 | (cert->extensions = sshbuf_new()) == NULL) { | ||
442 | cert_free(cert); | ||
443 | return NULL; | ||
444 | } | ||
445 | cert->key_id = NULL; | ||
446 | cert->principals = NULL; | ||
447 | cert->signature_key = NULL; | ||
448 | return cert; | ||
449 | } | ||
450 | |||
451 | struct sshkey * | ||
452 | sshkey_new(int type) | ||
453 | { | ||
454 | struct sshkey *k; | ||
455 | #ifdef WITH_OPENSSL | ||
456 | RSA *rsa; | ||
457 | DSA *dsa; | ||
458 | #endif /* WITH_OPENSSL */ | ||
459 | |||
460 | if ((k = calloc(1, sizeof(*k))) == NULL) | ||
461 | return NULL; | ||
462 | k->type = type; | ||
463 | k->ecdsa = NULL; | ||
464 | k->ecdsa_nid = -1; | ||
465 | k->dsa = NULL; | ||
466 | k->rsa = NULL; | ||
467 | k->cert = NULL; | ||
468 | k->ed25519_sk = NULL; | ||
469 | k->ed25519_pk = NULL; | ||
470 | switch (k->type) { | ||
471 | #ifdef WITH_OPENSSL | ||
472 | case KEY_RSA1: | ||
473 | case KEY_RSA: | ||
474 | case KEY_RSA_CERT_V00: | ||
475 | case KEY_RSA_CERT: | ||
476 | if ((rsa = RSA_new()) == NULL || | ||
477 | (rsa->n = BN_new()) == NULL || | ||
478 | (rsa->e = BN_new()) == NULL) { | ||
479 | if (rsa != NULL) | ||
480 | RSA_free(rsa); | ||
481 | free(k); | ||
482 | return NULL; | ||
483 | } | ||
484 | k->rsa = rsa; | ||
485 | break; | ||
486 | case KEY_DSA: | ||
487 | case KEY_DSA_CERT_V00: | ||
488 | case KEY_DSA_CERT: | ||
489 | if ((dsa = DSA_new()) == NULL || | ||
490 | (dsa->p = BN_new()) == NULL || | ||
491 | (dsa->q = BN_new()) == NULL || | ||
492 | (dsa->g = BN_new()) == NULL || | ||
493 | (dsa->pub_key = BN_new()) == NULL) { | ||
494 | if (dsa != NULL) | ||
495 | DSA_free(dsa); | ||
496 | free(k); | ||
497 | return NULL; | ||
498 | } | ||
499 | k->dsa = dsa; | ||
500 | break; | ||
501 | case KEY_ECDSA: | ||
502 | case KEY_ECDSA_CERT: | ||
503 | /* Cannot do anything until we know the group */ | ||
504 | break; | ||
505 | #endif /* WITH_OPENSSL */ | ||
506 | case KEY_ED25519: | ||
507 | case KEY_ED25519_CERT: | ||
508 | /* no need to prealloc */ | ||
509 | break; | ||
510 | case KEY_UNSPEC: | ||
511 | break; | ||
512 | default: | ||
513 | free(k); | ||
514 | return NULL; | ||
515 | break; | ||
516 | } | ||
517 | |||
518 | if (sshkey_is_cert(k)) { | ||
519 | if ((k->cert = cert_new()) == NULL) { | ||
520 | sshkey_free(k); | ||
521 | return NULL; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | return k; | ||
526 | } | ||
527 | |||
528 | int | ||
529 | sshkey_add_private(struct sshkey *k) | ||
530 | { | ||
531 | switch (k->type) { | ||
532 | #ifdef WITH_OPENSSL | ||
533 | case KEY_RSA1: | ||
534 | case KEY_RSA: | ||
535 | case KEY_RSA_CERT_V00: | ||
536 | case KEY_RSA_CERT: | ||
537 | #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) | ||
538 | if (bn_maybe_alloc_failed(k->rsa->d) || | ||
539 | bn_maybe_alloc_failed(k->rsa->iqmp) || | ||
540 | bn_maybe_alloc_failed(k->rsa->q) || | ||
541 | bn_maybe_alloc_failed(k->rsa->p) || | ||
542 | bn_maybe_alloc_failed(k->rsa->dmq1) || | ||
543 | bn_maybe_alloc_failed(k->rsa->dmp1)) | ||
544 | return SSH_ERR_ALLOC_FAIL; | ||
545 | break; | ||
546 | case KEY_DSA: | ||
547 | case KEY_DSA_CERT_V00: | ||
548 | case KEY_DSA_CERT: | ||
549 | if (bn_maybe_alloc_failed(k->dsa->priv_key)) | ||
550 | return SSH_ERR_ALLOC_FAIL; | ||
551 | break; | ||
552 | #undef bn_maybe_alloc_failed | ||
553 | case KEY_ECDSA: | ||
554 | case KEY_ECDSA_CERT: | ||
555 | /* Cannot do anything until we know the group */ | ||
556 | break; | ||
557 | #endif /* WITH_OPENSSL */ | ||
558 | case KEY_ED25519: | ||
559 | case KEY_ED25519_CERT: | ||
560 | /* no need to prealloc */ | ||
561 | break; | ||
562 | case KEY_UNSPEC: | ||
563 | break; | ||
564 | default: | ||
565 | return SSH_ERR_INVALID_ARGUMENT; | ||
566 | } | ||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | struct sshkey * | ||
571 | sshkey_new_private(int type) | ||
572 | { | ||
573 | struct sshkey *k = sshkey_new(type); | ||
574 | |||
575 | if (k == NULL) | ||
576 | return NULL; | ||
577 | if (sshkey_add_private(k) != 0) { | ||
578 | sshkey_free(k); | ||
579 | return NULL; | ||
580 | } | ||
581 | return k; | ||
582 | } | ||
583 | |||
584 | void | ||
585 | sshkey_free(struct sshkey *k) | ||
586 | { | ||
587 | if (k == NULL) | ||
588 | return; | ||
589 | switch (k->type) { | ||
590 | #ifdef WITH_OPENSSL | ||
591 | case KEY_RSA1: | ||
592 | case KEY_RSA: | ||
593 | case KEY_RSA_CERT_V00: | ||
594 | case KEY_RSA_CERT: | ||
595 | if (k->rsa != NULL) | ||
596 | RSA_free(k->rsa); | ||
597 | k->rsa = NULL; | ||
598 | break; | ||
599 | case KEY_DSA: | ||
600 | case KEY_DSA_CERT_V00: | ||
601 | case KEY_DSA_CERT: | ||
602 | if (k->dsa != NULL) | ||
603 | DSA_free(k->dsa); | ||
604 | k->dsa = NULL; | ||
605 | break; | ||
606 | # ifdef OPENSSL_HAS_ECC | ||
607 | case KEY_ECDSA: | ||
608 | case KEY_ECDSA_CERT: | ||
609 | if (k->ecdsa != NULL) | ||
610 | EC_KEY_free(k->ecdsa); | ||
611 | k->ecdsa = NULL; | ||
612 | break; | ||
613 | # endif /* OPENSSL_HAS_ECC */ | ||
614 | #endif /* WITH_OPENSSL */ | ||
615 | case KEY_ED25519: | ||
616 | case KEY_ED25519_CERT: | ||
617 | if (k->ed25519_pk) { | ||
618 | explicit_bzero(k->ed25519_pk, ED25519_PK_SZ); | ||
619 | free(k->ed25519_pk); | ||
620 | k->ed25519_pk = NULL; | ||
621 | } | ||
622 | if (k->ed25519_sk) { | ||
623 | explicit_bzero(k->ed25519_sk, ED25519_SK_SZ); | ||
624 | free(k->ed25519_sk); | ||
625 | k->ed25519_sk = NULL; | ||
626 | } | ||
627 | break; | ||
628 | case KEY_UNSPEC: | ||
629 | break; | ||
630 | default: | ||
631 | break; | ||
632 | } | ||
633 | if (sshkey_is_cert(k)) | ||
634 | cert_free(k->cert); | ||
635 | explicit_bzero(k, sizeof(*k)); | ||
636 | free(k); | ||
637 | } | ||
638 | |||
639 | static int | ||
640 | cert_compare(struct sshkey_cert *a, struct sshkey_cert *b) | ||
641 | { | ||
642 | if (a == NULL && b == NULL) | ||
643 | return 1; | ||
644 | if (a == NULL || b == NULL) | ||
645 | return 0; | ||
646 | if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob)) | ||
647 | return 0; | ||
648 | if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob), | ||
649 | sshbuf_len(a->certblob)) != 0) | ||
650 | return 0; | ||
651 | return 1; | ||
652 | } | ||
653 | |||
654 | /* | ||
655 | * Compare public portions of key only, allowing comparisons between | ||
656 | * certificates and plain keys too. | ||
657 | */ | ||
658 | int | ||
659 | sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) | ||
660 | { | ||
661 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | ||
662 | BN_CTX *bnctx; | ||
663 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | ||
664 | |||
665 | if (a == NULL || b == NULL || | ||
666 | sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) | ||
667 | return 0; | ||
668 | |||
669 | switch (a->type) { | ||
670 | #ifdef WITH_OPENSSL | ||
671 | case KEY_RSA1: | ||
672 | case KEY_RSA_CERT_V00: | ||
673 | case KEY_RSA_CERT: | ||
674 | case KEY_RSA: | ||
675 | return a->rsa != NULL && b->rsa != NULL && | ||
676 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && | ||
677 | BN_cmp(a->rsa->n, b->rsa->n) == 0; | ||
678 | case KEY_DSA_CERT_V00: | ||
679 | case KEY_DSA_CERT: | ||
680 | case KEY_DSA: | ||
681 | return a->dsa != NULL && b->dsa != NULL && | ||
682 | BN_cmp(a->dsa->p, b->dsa->p) == 0 && | ||
683 | BN_cmp(a->dsa->q, b->dsa->q) == 0 && | ||
684 | BN_cmp(a->dsa->g, b->dsa->g) == 0 && | ||
685 | BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; | ||
686 | # ifdef OPENSSL_HAS_ECC | ||
687 | case KEY_ECDSA_CERT: | ||
688 | case KEY_ECDSA: | ||
689 | if (a->ecdsa == NULL || b->ecdsa == NULL || | ||
690 | EC_KEY_get0_public_key(a->ecdsa) == NULL || | ||
691 | EC_KEY_get0_public_key(b->ecdsa) == NULL) | ||
692 | return 0; | ||
693 | if ((bnctx = BN_CTX_new()) == NULL) | ||
694 | return 0; | ||
695 | if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa), | ||
696 | EC_KEY_get0_group(b->ecdsa), bnctx) != 0 || | ||
697 | EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa), | ||
698 | EC_KEY_get0_public_key(a->ecdsa), | ||
699 | EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) { | ||
700 | BN_CTX_free(bnctx); | ||
701 | return 0; | ||
702 | } | ||
703 | BN_CTX_free(bnctx); | ||
704 | return 1; | ||
705 | # endif /* OPENSSL_HAS_ECC */ | ||
706 | #endif /* WITH_OPENSSL */ | ||
707 | case KEY_ED25519: | ||
708 | case KEY_ED25519_CERT: | ||
709 | return a->ed25519_pk != NULL && b->ed25519_pk != NULL && | ||
710 | memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0; | ||
711 | default: | ||
712 | return 0; | ||
713 | } | ||
714 | /* NOTREACHED */ | ||
715 | } | ||
716 | |||
717 | int | ||
718 | sshkey_equal(const struct sshkey *a, const struct sshkey *b) | ||
719 | { | ||
720 | if (a == NULL || b == NULL || a->type != b->type) | ||
721 | return 0; | ||
722 | if (sshkey_is_cert(a)) { | ||
723 | if (!cert_compare(a->cert, b->cert)) | ||
724 | return 0; | ||
725 | } | ||
726 | return sshkey_equal_public(a, b); | ||
727 | } | ||
728 | |||
729 | static int | ||
730 | to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) | ||
731 | { | ||
732 | int type, ret = SSH_ERR_INTERNAL_ERROR; | ||
733 | const char *typename; | ||
734 | |||
735 | if (key == NULL) | ||
736 | return SSH_ERR_INVALID_ARGUMENT; | ||
737 | |||
738 | type = force_plain ? sshkey_type_plain(key->type) : key->type; | ||
739 | typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); | ||
740 | |||
741 | switch (type) { | ||
742 | #ifdef WITH_OPENSSL | ||
743 | case KEY_DSA_CERT_V00: | ||
744 | case KEY_RSA_CERT_V00: | ||
745 | case KEY_DSA_CERT: | ||
746 | case KEY_ECDSA_CERT: | ||
747 | case KEY_RSA_CERT: | ||
748 | #endif /* WITH_OPENSSL */ | ||
749 | case KEY_ED25519_CERT: | ||
750 | /* Use the existing blob */ | ||
751 | /* XXX modified flag? */ | ||
752 | if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0) | ||
753 | return ret; | ||
754 | break; | ||
755 | #ifdef WITH_OPENSSL | ||
756 | case KEY_DSA: | ||
757 | if (key->dsa == NULL) | ||
758 | return SSH_ERR_INVALID_ARGUMENT; | ||
759 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | ||
760 | (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || | ||
761 | (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || | ||
762 | (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || | ||
763 | (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0) | ||
764 | return ret; | ||
765 | break; | ||
766 | # ifdef OPENSSL_HAS_ECC | ||
767 | case KEY_ECDSA: | ||
768 | if (key->ecdsa == NULL) | ||
769 | return SSH_ERR_INVALID_ARGUMENT; | ||
770 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | ||
771 | (ret = sshbuf_put_cstring(b, | ||
772 | sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || | ||
773 | (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0) | ||
774 | return ret; | ||
775 | break; | ||
776 | # endif | ||
777 | case KEY_RSA: | ||
778 | if (key->rsa == NULL) | ||
779 | return SSH_ERR_INVALID_ARGUMENT; | ||
780 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | ||
781 | (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || | ||
782 | (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0) | ||
783 | return ret; | ||
784 | break; | ||
785 | #endif /* WITH_OPENSSL */ | ||
786 | case KEY_ED25519: | ||
787 | if (key->ed25519_pk == NULL) | ||
788 | return SSH_ERR_INVALID_ARGUMENT; | ||
789 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | ||
790 | (ret = sshbuf_put_string(b, | ||
791 | key->ed25519_pk, ED25519_PK_SZ)) != 0) | ||
792 | return ret; | ||
793 | break; | ||
794 | default: | ||
795 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
796 | } | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | int | ||
801 | sshkey_to_blob_buf(const struct sshkey *key, struct sshbuf *b) | ||
802 | { | ||
803 | return to_blob_buf(key, b, 0); | ||
804 | } | ||
805 | |||
806 | int | ||
807 | sshkey_plain_to_blob_buf(const struct sshkey *key, struct sshbuf *b) | ||
808 | { | ||
809 | return to_blob_buf(key, b, 1); | ||
810 | } | ||
811 | |||
812 | static int | ||
813 | to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain) | ||
814 | { | ||
815 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
816 | size_t len; | ||
817 | struct sshbuf *b = NULL; | ||
818 | |||
819 | if (lenp != NULL) | ||
820 | *lenp = 0; | ||
821 | if (blobp != NULL) | ||
822 | *blobp = NULL; | ||
823 | if ((b = sshbuf_new()) == NULL) | ||
824 | return SSH_ERR_ALLOC_FAIL; | ||
825 | if ((ret = to_blob_buf(key, b, force_plain)) != 0) | ||
826 | goto out; | ||
827 | len = sshbuf_len(b); | ||
828 | if (lenp != NULL) | ||
829 | *lenp = len; | ||
830 | if (blobp != NULL) { | ||
831 | if ((*blobp = malloc(len)) == NULL) { | ||
832 | ret = SSH_ERR_ALLOC_FAIL; | ||
833 | goto out; | ||
834 | } | ||
835 | memcpy(*blobp, sshbuf_ptr(b), len); | ||
836 | } | ||
837 | ret = 0; | ||
838 | out: | ||
839 | sshbuf_free(b); | ||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | int | ||
844 | sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) | ||
845 | { | ||
846 | return to_blob(key, blobp, lenp, 0); | ||
847 | } | ||
848 | |||
849 | int | ||
850 | sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) | ||
851 | { | ||
852 | return to_blob(key, blobp, lenp, 1); | ||
853 | } | ||
854 | |||
855 | int | ||
856 | sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, | ||
857 | u_char **retp, size_t *lenp) | ||
858 | { | ||
859 | u_char *blob = NULL, *ret = NULL; | ||
860 | size_t blob_len = 0; | ||
861 | int hash_alg = -1, r = SSH_ERR_INTERNAL_ERROR; | ||
862 | |||
863 | if (retp != NULL) | ||
864 | *retp = NULL; | ||
865 | if (lenp != NULL) | ||
866 | *lenp = 0; | ||
867 | |||
868 | switch (dgst_type) { | ||
869 | case SSH_FP_MD5: | ||
870 | hash_alg = SSH_DIGEST_MD5; | ||
871 | break; | ||
872 | case SSH_FP_SHA1: | ||
873 | hash_alg = SSH_DIGEST_SHA1; | ||
874 | break; | ||
875 | case SSH_FP_SHA256: | ||
876 | hash_alg = SSH_DIGEST_SHA256; | ||
877 | break; | ||
878 | default: | ||
879 | r = SSH_ERR_INVALID_ARGUMENT; | ||
880 | goto out; | ||
881 | } | ||
882 | |||
883 | if (k->type == KEY_RSA1) { | ||
884 | #ifdef WITH_OPENSSL | ||
885 | int nlen = BN_num_bytes(k->rsa->n); | ||
886 | int elen = BN_num_bytes(k->rsa->e); | ||
887 | |||
888 | blob_len = nlen + elen; | ||
889 | if (nlen >= INT_MAX - elen || | ||
890 | (blob = malloc(blob_len)) == NULL) { | ||
891 | r = SSH_ERR_ALLOC_FAIL; | ||
892 | goto out; | ||
893 | } | ||
894 | BN_bn2bin(k->rsa->n, blob); | ||
895 | BN_bn2bin(k->rsa->e, blob + nlen); | ||
896 | #endif /* WITH_OPENSSL */ | ||
897 | } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) | ||
898 | goto out; | ||
899 | if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { | ||
900 | r = SSH_ERR_ALLOC_FAIL; | ||
901 | goto out; | ||
902 | } | ||
903 | if ((r = ssh_digest_memory(hash_alg, blob, blob_len, | ||
904 | ret, SSH_DIGEST_MAX_LENGTH)) != 0) | ||
905 | goto out; | ||
906 | /* success */ | ||
907 | if (retp != NULL) { | ||
908 | *retp = ret; | ||
909 | ret = NULL; | ||
910 | } | ||
911 | if (lenp != NULL) | ||
912 | *lenp = ssh_digest_bytes(hash_alg); | ||
913 | r = 0; | ||
914 | out: | ||
915 | free(ret); | ||
916 | if (blob != NULL) { | ||
917 | explicit_bzero(blob, blob_len); | ||
918 | free(blob); | ||
919 | } | ||
920 | return r; | ||
921 | } | ||
922 | |||
923 | static char * | ||
924 | fingerprint_hex(u_char *dgst_raw, size_t dgst_raw_len) | ||
925 | { | ||
926 | char *retval; | ||
927 | size_t i; | ||
928 | |||
929 | if ((retval = calloc(1, dgst_raw_len * 3 + 1)) == NULL) | ||
930 | return NULL; | ||
931 | for (i = 0; i < dgst_raw_len; i++) { | ||
932 | char hex[4]; | ||
933 | snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); | ||
934 | strlcat(retval, hex, dgst_raw_len * 3 + 1); | ||
935 | } | ||
936 | |||
937 | /* Remove the trailing ':' character */ | ||
938 | retval[(dgst_raw_len * 3) - 1] = '\0'; | ||
939 | return retval; | ||
940 | } | ||
941 | |||
942 | static char * | ||
943 | fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len) | ||
944 | { | ||
945 | char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; | ||
946 | char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', | ||
947 | 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; | ||
948 | u_int i, j = 0, rounds, seed = 1; | ||
949 | char *retval; | ||
950 | |||
951 | rounds = (dgst_raw_len / 2) + 1; | ||
952 | if ((retval = calloc(rounds, 6)) == NULL) | ||
953 | return NULL; | ||
954 | retval[j++] = 'x'; | ||
955 | for (i = 0; i < rounds; i++) { | ||
956 | u_int idx0, idx1, idx2, idx3, idx4; | ||
957 | if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { | ||
958 | idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + | ||
959 | seed) % 6; | ||
960 | idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; | ||
961 | idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + | ||
962 | (seed / 6)) % 6; | ||
963 | retval[j++] = vowels[idx0]; | ||
964 | retval[j++] = consonants[idx1]; | ||
965 | retval[j++] = vowels[idx2]; | ||
966 | if ((i + 1) < rounds) { | ||
967 | idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; | ||
968 | idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; | ||
969 | retval[j++] = consonants[idx3]; | ||
970 | retval[j++] = '-'; | ||
971 | retval[j++] = consonants[idx4]; | ||
972 | seed = ((seed * 5) + | ||
973 | ((((u_int)(dgst_raw[2 * i])) * 7) + | ||
974 | ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; | ||
975 | } | ||
976 | } else { | ||
977 | idx0 = seed % 6; | ||
978 | idx1 = 16; | ||
979 | idx2 = seed / 6; | ||
980 | retval[j++] = vowels[idx0]; | ||
981 | retval[j++] = consonants[idx1]; | ||
982 | retval[j++] = vowels[idx2]; | ||
983 | } | ||
984 | } | ||
985 | retval[j++] = 'x'; | ||
986 | retval[j++] = '\0'; | ||
987 | return retval; | ||
988 | } | ||
989 | |||
990 | /* | ||
991 | * Draw an ASCII-Art representing the fingerprint so human brain can | ||
992 | * profit from its built-in pattern recognition ability. | ||
993 | * This technique is called "random art" and can be found in some | ||
994 | * scientific publications like this original paper: | ||
995 | * | ||
996 | * "Hash Visualization: a New Technique to improve Real-World Security", | ||
997 | * Perrig A. and Song D., 1999, International Workshop on Cryptographic | ||
998 | * Techniques and E-Commerce (CrypTEC '99) | ||
999 | * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf | ||
1000 | * | ||
1001 | * The subject came up in a talk by Dan Kaminsky, too. | ||
1002 | * | ||
1003 | * If you see the picture is different, the key is different. | ||
1004 | * If the picture looks the same, you still know nothing. | ||
1005 | * | ||
1006 | * The algorithm used here is a worm crawling over a discrete plane, | ||
1007 | * leaving a trace (augmenting the field) everywhere it goes. | ||
1008 | * Movement is taken from dgst_raw 2bit-wise. Bumping into walls | ||
1009 | * makes the respective movement vector be ignored for this turn. | ||
1010 | * Graphs are not unambiguous, because circles in graphs can be | ||
1011 | * walked in either direction. | ||
1012 | */ | ||
1013 | |||
1014 | /* | ||
1015 | * Field sizes for the random art. Have to be odd, so the starting point | ||
1016 | * can be in the exact middle of the picture, and FLDBASE should be >=8 . | ||
1017 | * Else pictures would be too dense, and drawing the frame would | ||
1018 | * fail, too, because the key type would not fit in anymore. | ||
1019 | */ | ||
1020 | #define FLDBASE 8 | ||
1021 | #define FLDSIZE_Y (FLDBASE + 1) | ||
1022 | #define FLDSIZE_X (FLDBASE * 2 + 1) | ||
1023 | static char * | ||
1024 | fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, | ||
1025 | const struct sshkey *k) | ||
1026 | { | ||
1027 | /* | ||
1028 | * Chars to be used after each other every time the worm | ||
1029 | * intersects with itself. Matter of taste. | ||
1030 | */ | ||
1031 | char *augmentation_string = " .o+=*BOX@%&#/^SE"; | ||
1032 | char *retval, *p, title[FLDSIZE_X]; | ||
1033 | u_char field[FLDSIZE_X][FLDSIZE_Y]; | ||
1034 | size_t i, tlen; | ||
1035 | u_int b; | ||
1036 | int x, y, r; | ||
1037 | size_t len = strlen(augmentation_string) - 1; | ||
1038 | |||
1039 | if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL) | ||
1040 | return NULL; | ||
1041 | |||
1042 | /* initialize field */ | ||
1043 | memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); | ||
1044 | x = FLDSIZE_X / 2; | ||
1045 | y = FLDSIZE_Y / 2; | ||
1046 | |||
1047 | /* process raw key */ | ||
1048 | for (i = 0; i < dgst_raw_len; i++) { | ||
1049 | int input; | ||
1050 | /* each byte conveys four 2-bit move commands */ | ||
1051 | input = dgst_raw[i]; | ||
1052 | for (b = 0; b < 4; b++) { | ||
1053 | /* evaluate 2 bit, rest is shifted later */ | ||
1054 | x += (input & 0x1) ? 1 : -1; | ||
1055 | y += (input & 0x2) ? 1 : -1; | ||
1056 | |||
1057 | /* assure we are still in bounds */ | ||
1058 | x = MAX(x, 0); | ||
1059 | y = MAX(y, 0); | ||
1060 | x = MIN(x, FLDSIZE_X - 1); | ||
1061 | y = MIN(y, FLDSIZE_Y - 1); | ||
1062 | |||
1063 | /* augment the field */ | ||
1064 | if (field[x][y] < len - 2) | ||
1065 | field[x][y]++; | ||
1066 | input = input >> 2; | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | /* mark starting point and end point*/ | ||
1071 | field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; | ||
1072 | field[x][y] = len; | ||
1073 | |||
1074 | /* assemble title */ | ||
1075 | r = snprintf(title, sizeof(title), "[%s %u]", | ||
1076 | sshkey_type(k), sshkey_size(k)); | ||
1077 | /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ | ||
1078 | if (r < 0 || r > (int)sizeof(title)) | ||
1079 | snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); | ||
1080 | tlen = strlen(title); | ||
1081 | |||
1082 | /* output upper border */ | ||
1083 | p = retval; | ||
1084 | *p++ = '+'; | ||
1085 | for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++) | ||
1086 | *p++ = '-'; | ||
1087 | memcpy(p, title, tlen); | ||
1088 | p += tlen; | ||
1089 | for (i = p - retval - 1; i < FLDSIZE_X; i++) | ||
1090 | *p++ = '-'; | ||
1091 | *p++ = '+'; | ||
1092 | *p++ = '\n'; | ||
1093 | |||
1094 | /* output content */ | ||
1095 | for (y = 0; y < FLDSIZE_Y; y++) { | ||
1096 | *p++ = '|'; | ||
1097 | for (x = 0; x < FLDSIZE_X; x++) | ||
1098 | *p++ = augmentation_string[MIN(field[x][y], len)]; | ||
1099 | *p++ = '|'; | ||
1100 | *p++ = '\n'; | ||
1101 | } | ||
1102 | |||
1103 | /* output lower border */ | ||
1104 | *p++ = '+'; | ||
1105 | for (i = 0; i < FLDSIZE_X; i++) | ||
1106 | *p++ = '-'; | ||
1107 | *p++ = '+'; | ||
1108 | |||
1109 | return retval; | ||
1110 | } | ||
1111 | |||
1112 | char * | ||
1113 | sshkey_fingerprint(const struct sshkey *k, enum sshkey_fp_type dgst_type, | ||
1114 | enum sshkey_fp_rep dgst_rep) | ||
1115 | { | ||
1116 | char *retval = NULL; | ||
1117 | u_char *dgst_raw; | ||
1118 | size_t dgst_raw_len; | ||
1119 | |||
1120 | if (sshkey_fingerprint_raw(k, dgst_type, &dgst_raw, &dgst_raw_len) != 0) | ||
1121 | return NULL; | ||
1122 | switch (dgst_rep) { | ||
1123 | case SSH_FP_HEX: | ||
1124 | retval = fingerprint_hex(dgst_raw, dgst_raw_len); | ||
1125 | break; | ||
1126 | case SSH_FP_BUBBLEBABBLE: | ||
1127 | retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); | ||
1128 | break; | ||
1129 | case SSH_FP_RANDOMART: | ||
1130 | retval = fingerprint_randomart(dgst_raw, dgst_raw_len, k); | ||
1131 | break; | ||
1132 | default: | ||
1133 | explicit_bzero(dgst_raw, dgst_raw_len); | ||
1134 | free(dgst_raw); | ||
1135 | return NULL; | ||
1136 | } | ||
1137 | explicit_bzero(dgst_raw, dgst_raw_len); | ||
1138 | free(dgst_raw); | ||
1139 | return retval; | ||
1140 | } | ||
1141 | |||
1142 | #ifdef WITH_SSH1 | ||
1143 | /* | ||
1144 | * Reads a multiple-precision integer in decimal from the buffer, and advances | ||
1145 | * the pointer. The integer must already be initialized. This function is | ||
1146 | * permitted to modify the buffer. This leaves *cpp to point just beyond the | ||
1147 | * last processed character. | ||
1148 | */ | ||
1149 | static int | ||
1150 | read_decimal_bignum(char **cpp, BIGNUM *v) | ||
1151 | { | ||
1152 | char *cp; | ||
1153 | size_t e; | ||
1154 | int skip = 1; /* skip white space */ | ||
1155 | |||
1156 | cp = *cpp; | ||
1157 | while (*cp == ' ' || *cp == '\t') | ||
1158 | cp++; | ||
1159 | e = strspn(cp, "0123456789"); | ||
1160 | if (e == 0) | ||
1161 | return SSH_ERR_INVALID_FORMAT; | ||
1162 | if (e > SSHBUF_MAX_BIGNUM * 3) | ||
1163 | return SSH_ERR_BIGNUM_TOO_LARGE; | ||
1164 | if (cp[e] == '\0') | ||
1165 | skip = 0; | ||
1166 | else if (index(" \t\r\n", cp[e]) == NULL) | ||
1167 | return SSH_ERR_INVALID_FORMAT; | ||
1168 | cp[e] = '\0'; | ||
1169 | if (BN_dec2bn(&v, cp) <= 0) | ||
1170 | return SSH_ERR_INVALID_FORMAT; | ||
1171 | *cpp = cp + e + skip; | ||
1172 | return 0; | ||
1173 | } | ||
1174 | #endif /* WITH_SSH1 */ | ||
1175 | |||
1176 | /* returns 0 ok, and < 0 error */ | ||
1177 | int | ||
1178 | sshkey_read(struct sshkey *ret, char **cpp) | ||
1179 | { | ||
1180 | struct sshkey *k; | ||
1181 | int retval = SSH_ERR_INVALID_FORMAT; | ||
1182 | char *cp, *space; | ||
1183 | int r, type, curve_nid = -1; | ||
1184 | struct sshbuf *blob; | ||
1185 | #ifdef WITH_SSH1 | ||
1186 | char *ep; | ||
1187 | u_long bits; | ||
1188 | #endif /* WITH_SSH1 */ | ||
1189 | |||
1190 | cp = *cpp; | ||
1191 | |||
1192 | switch (ret->type) { | ||
1193 | case KEY_RSA1: | ||
1194 | #ifdef WITH_SSH1 | ||
1195 | /* Get number of bits. */ | ||
1196 | bits = strtoul(cp, &ep, 10); | ||
1197 | if (*cp == '\0' || index(" \t\r\n", *ep) == NULL || | ||
1198 | bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8) | ||
1199 | return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */ | ||
1200 | /* Get public exponent, public modulus. */ | ||
1201 | if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0) | ||
1202 | return r; | ||
1203 | if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0) | ||
1204 | return r; | ||
1205 | *cpp = ep; | ||
1206 | /* validate the claimed number of bits */ | ||
1207 | if (BN_num_bits(ret->rsa->n) != (int)bits) | ||
1208 | return SSH_ERR_KEY_BITS_MISMATCH; | ||
1209 | retval = 0; | ||
1210 | #endif /* WITH_SSH1 */ | ||
1211 | break; | ||
1212 | case KEY_UNSPEC: | ||
1213 | case KEY_RSA: | ||
1214 | case KEY_DSA: | ||
1215 | case KEY_ECDSA: | ||
1216 | case KEY_ED25519: | ||
1217 | case KEY_DSA_CERT_V00: | ||
1218 | case KEY_RSA_CERT_V00: | ||
1219 | case KEY_DSA_CERT: | ||
1220 | case KEY_ECDSA_CERT: | ||
1221 | case KEY_RSA_CERT: | ||
1222 | case KEY_ED25519_CERT: | ||
1223 | space = strchr(cp, ' '); | ||
1224 | if (space == NULL) | ||
1225 | return SSH_ERR_INVALID_FORMAT; | ||
1226 | *space = '\0'; | ||
1227 | type = sshkey_type_from_name(cp); | ||
1228 | if (sshkey_type_plain(type) == KEY_ECDSA && | ||
1229 | (curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1) | ||
1230 | return SSH_ERR_EC_CURVE_INVALID; | ||
1231 | *space = ' '; | ||
1232 | if (type == KEY_UNSPEC) | ||
1233 | return SSH_ERR_INVALID_FORMAT; | ||
1234 | cp = space+1; | ||
1235 | if (*cp == '\0') | ||
1236 | return SSH_ERR_INVALID_FORMAT; | ||
1237 | if (ret->type == KEY_UNSPEC) { | ||
1238 | ret->type = type; | ||
1239 | } else if (ret->type != type) | ||
1240 | return SSH_ERR_KEY_TYPE_MISMATCH; | ||
1241 | if ((blob = sshbuf_new()) == NULL) | ||
1242 | return SSH_ERR_ALLOC_FAIL; | ||
1243 | /* trim comment */ | ||
1244 | space = strchr(cp, ' '); | ||
1245 | if (space) | ||
1246 | *space = '\0'; | ||
1247 | if ((r = sshbuf_b64tod(blob, cp)) != 0) { | ||
1248 | sshbuf_free(blob); | ||
1249 | return r; | ||
1250 | } | ||
1251 | if ((r = sshkey_from_blob(sshbuf_ptr(blob), | ||
1252 | sshbuf_len(blob), &k)) != 0) { | ||
1253 | sshbuf_free(blob); | ||
1254 | return r; | ||
1255 | } | ||
1256 | sshbuf_free(blob); | ||
1257 | if (k->type != type) { | ||
1258 | sshkey_free(k); | ||
1259 | return SSH_ERR_KEY_TYPE_MISMATCH; | ||
1260 | } | ||
1261 | if (sshkey_type_plain(type) == KEY_ECDSA && | ||
1262 | curve_nid != k->ecdsa_nid) { | ||
1263 | sshkey_free(k); | ||
1264 | return SSH_ERR_EC_CURVE_MISMATCH; | ||
1265 | } | ||
1266 | /*XXXX*/ | ||
1267 | if (sshkey_is_cert(ret)) { | ||
1268 | if (!sshkey_is_cert(k)) { | ||
1269 | sshkey_free(k); | ||
1270 | return SSH_ERR_EXPECTED_CERT; | ||
1271 | } | ||
1272 | if (ret->cert != NULL) | ||
1273 | cert_free(ret->cert); | ||
1274 | ret->cert = k->cert; | ||
1275 | k->cert = NULL; | ||
1276 | } | ||
1277 | #ifdef WITH_OPENSSL | ||
1278 | if (sshkey_type_plain(ret->type) == KEY_RSA) { | ||
1279 | if (ret->rsa != NULL) | ||
1280 | RSA_free(ret->rsa); | ||
1281 | ret->rsa = k->rsa; | ||
1282 | k->rsa = NULL; | ||
1283 | #ifdef DEBUG_PK | ||
1284 | RSA_print_fp(stderr, ret->rsa, 8); | ||
1285 | #endif | ||
1286 | } | ||
1287 | if (sshkey_type_plain(ret->type) == KEY_DSA) { | ||
1288 | if (ret->dsa != NULL) | ||
1289 | DSA_free(ret->dsa); | ||
1290 | ret->dsa = k->dsa; | ||
1291 | k->dsa = NULL; | ||
1292 | #ifdef DEBUG_PK | ||
1293 | DSA_print_fp(stderr, ret->dsa, 8); | ||
1294 | #endif | ||
1295 | } | ||
1296 | # ifdef OPENSSL_HAS_ECC | ||
1297 | if (sshkey_type_plain(ret->type) == KEY_ECDSA) { | ||
1298 | if (ret->ecdsa != NULL) | ||
1299 | EC_KEY_free(ret->ecdsa); | ||
1300 | ret->ecdsa = k->ecdsa; | ||
1301 | ret->ecdsa_nid = k->ecdsa_nid; | ||
1302 | k->ecdsa = NULL; | ||
1303 | k->ecdsa_nid = -1; | ||
1304 | #ifdef DEBUG_PK | ||
1305 | sshkey_dump_ec_key(ret->ecdsa); | ||
1306 | #endif | ||
1307 | } | ||
1308 | # endif /* OPENSSL_HAS_ECC */ | ||
1309 | #endif /* WITH_OPENSSL */ | ||
1310 | if (sshkey_type_plain(ret->type) == KEY_ED25519) { | ||
1311 | free(ret->ed25519_pk); | ||
1312 | ret->ed25519_pk = k->ed25519_pk; | ||
1313 | k->ed25519_pk = NULL; | ||
1314 | #ifdef DEBUG_PK | ||
1315 | /* XXX */ | ||
1316 | #endif | ||
1317 | } | ||
1318 | retval = 0; | ||
1319 | /*XXXX*/ | ||
1320 | sshkey_free(k); | ||
1321 | if (retval != 0) | ||
1322 | break; | ||
1323 | /* advance cp: skip whitespace and data */ | ||
1324 | while (*cp == ' ' || *cp == '\t') | ||
1325 | cp++; | ||
1326 | while (*cp != '\0' && *cp != ' ' && *cp != '\t') | ||
1327 | cp++; | ||
1328 | *cpp = cp; | ||
1329 | break; | ||
1330 | default: | ||
1331 | return SSH_ERR_INVALID_ARGUMENT; | ||
1332 | } | ||
1333 | return retval; | ||
1334 | } | ||
1335 | |||
1336 | int | ||
1337 | sshkey_write(const struct sshkey *key, FILE *f) | ||
1338 | { | ||
1339 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1340 | struct sshbuf *b = NULL, *bb = NULL; | ||
1341 | char *uu = NULL; | ||
1342 | #ifdef WITH_SSH1 | ||
1343 | u_int bits = 0; | ||
1344 | char *dec_e = NULL, *dec_n = NULL; | ||
1345 | #endif /* WITH_SSH1 */ | ||
1346 | |||
1347 | if (sshkey_is_cert(key)) { | ||
1348 | if (key->cert == NULL) | ||
1349 | return SSH_ERR_EXPECTED_CERT; | ||
1350 | if (sshbuf_len(key->cert->certblob) == 0) | ||
1351 | return SSH_ERR_KEY_LACKS_CERTBLOB; | ||
1352 | } | ||
1353 | if ((b = sshbuf_new()) == NULL) | ||
1354 | return SSH_ERR_ALLOC_FAIL; | ||
1355 | switch (key->type) { | ||
1356 | #ifdef WITH_SSH1 | ||
1357 | case KEY_RSA1: | ||
1358 | if (key->rsa == NULL || key->rsa->e == NULL || | ||
1359 | key->rsa->n == NULL) { | ||
1360 | ret = SSH_ERR_INVALID_ARGUMENT; | ||
1361 | goto out; | ||
1362 | } | ||
1363 | if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || | ||
1364 | (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { | ||
1365 | ret = SSH_ERR_ALLOC_FAIL; | ||
1366 | goto out; | ||
1367 | } | ||
1368 | /* size of modulus 'n' */ | ||
1369 | if ((bits = BN_num_bits(key->rsa->n)) <= 0) { | ||
1370 | ret = SSH_ERR_INVALID_ARGUMENT; | ||
1371 | goto out; | ||
1372 | } | ||
1373 | if ((ret = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) | ||
1374 | goto out; | ||
1375 | #endif /* WITH_SSH1 */ | ||
1376 | break; | ||
1377 | #ifdef WITH_OPENSSL | ||
1378 | case KEY_DSA: | ||
1379 | case KEY_DSA_CERT_V00: | ||
1380 | case KEY_DSA_CERT: | ||
1381 | case KEY_ECDSA: | ||
1382 | case KEY_ECDSA_CERT: | ||
1383 | case KEY_RSA: | ||
1384 | case KEY_RSA_CERT_V00: | ||
1385 | case KEY_RSA_CERT: | ||
1386 | #endif /* WITH_OPENSSL */ | ||
1387 | case KEY_ED25519: | ||
1388 | case KEY_ED25519_CERT: | ||
1389 | if ((bb = sshbuf_new()) == NULL) { | ||
1390 | ret = SSH_ERR_ALLOC_FAIL; | ||
1391 | goto out; | ||
1392 | } | ||
1393 | if ((ret = sshkey_to_blob_buf(key, bb)) != 0) | ||
1394 | goto out; | ||
1395 | if ((uu = sshbuf_dtob64(bb)) == NULL) { | ||
1396 | ret = SSH_ERR_ALLOC_FAIL; | ||
1397 | goto out; | ||
1398 | } | ||
1399 | if ((ret = sshbuf_putf(b, "%s ", sshkey_ssh_name(key))) != 0) | ||
1400 | goto out; | ||
1401 | if ((ret = sshbuf_put(b, uu, strlen(uu))) != 0) | ||
1402 | goto out; | ||
1403 | break; | ||
1404 | default: | ||
1405 | ret = SSH_ERR_KEY_TYPE_UNKNOWN; | ||
1406 | goto out; | ||
1407 | } | ||
1408 | if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) { | ||
1409 | if (feof(f)) | ||
1410 | errno = EPIPE; | ||
1411 | ret = SSH_ERR_SYSTEM_ERROR; | ||
1412 | goto out; | ||
1413 | } | ||
1414 | ret = 0; | ||
1415 | out: | ||
1416 | if (b != NULL) | ||
1417 | sshbuf_free(b); | ||
1418 | if (bb != NULL) | ||
1419 | sshbuf_free(bb); | ||
1420 | if (uu != NULL) | ||
1421 | free(uu); | ||
1422 | #ifdef WITH_SSH1 | ||
1423 | if (dec_e != NULL) | ||
1424 | OPENSSL_free(dec_e); | ||
1425 | if (dec_n != NULL) | ||
1426 | OPENSSL_free(dec_n); | ||
1427 | #endif /* WITH_SSH1 */ | ||
1428 | return ret; | ||
1429 | } | ||
1430 | |||
1431 | const char * | ||
1432 | sshkey_cert_type(const struct sshkey *k) | ||
1433 | { | ||
1434 | switch (k->cert->type) { | ||
1435 | case SSH2_CERT_TYPE_USER: | ||
1436 | return "user"; | ||
1437 | case SSH2_CERT_TYPE_HOST: | ||
1438 | return "host"; | ||
1439 | default: | ||
1440 | return "unknown"; | ||
1441 | } | ||
1442 | } | ||
1443 | |||
1444 | #ifdef WITH_OPENSSL | ||
1445 | static int | ||
1446 | rsa_generate_private_key(u_int bits, RSA **rsap) | ||
1447 | { | ||
1448 | RSA *private = NULL; | ||
1449 | BIGNUM *f4 = NULL; | ||
1450 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1451 | |||
1452 | if (rsap == NULL || | ||
1453 | bits < SSH_RSA_MINIMUM_MODULUS_SIZE || | ||
1454 | bits > SSHBUF_MAX_BIGNUM * 8) | ||
1455 | return SSH_ERR_INVALID_ARGUMENT; | ||
1456 | *rsap = NULL; | ||
1457 | if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { | ||
1458 | ret = SSH_ERR_ALLOC_FAIL; | ||
1459 | goto out; | ||
1460 | } | ||
1461 | if (!BN_set_word(f4, RSA_F4) || | ||
1462 | !RSA_generate_key_ex(private, bits, f4, NULL)) { | ||
1463 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
1464 | goto out; | ||
1465 | } | ||
1466 | *rsap = private; | ||
1467 | private = NULL; | ||
1468 | ret = 0; | ||
1469 | out: | ||
1470 | if (private != NULL) | ||
1471 | RSA_free(private); | ||
1472 | if (f4 != NULL) | ||
1473 | BN_free(f4); | ||
1474 | return ret; | ||
1475 | } | ||
1476 | |||
1477 | static int | ||
1478 | dsa_generate_private_key(u_int bits, DSA **dsap) | ||
1479 | { | ||
1480 | DSA *private; | ||
1481 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1482 | |||
1483 | if (dsap == NULL || bits != 1024) | ||
1484 | return SSH_ERR_INVALID_ARGUMENT; | ||
1485 | if ((private = DSA_new()) == NULL) { | ||
1486 | ret = SSH_ERR_ALLOC_FAIL; | ||
1487 | goto out; | ||
1488 | } | ||
1489 | *dsap = NULL; | ||
1490 | if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, | ||
1491 | NULL, NULL) || !DSA_generate_key(private)) { | ||
1492 | DSA_free(private); | ||
1493 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
1494 | goto out; | ||
1495 | } | ||
1496 | *dsap = private; | ||
1497 | private = NULL; | ||
1498 | ret = 0; | ||
1499 | out: | ||
1500 | if (private != NULL) | ||
1501 | DSA_free(private); | ||
1502 | return ret; | ||
1503 | } | ||
1504 | |||
1505 | # ifdef OPENSSL_HAS_ECC | ||
1506 | int | ||
1507 | sshkey_ecdsa_key_to_nid(EC_KEY *k) | ||
1508 | { | ||
1509 | EC_GROUP *eg; | ||
1510 | int nids[] = { | ||
1511 | NID_X9_62_prime256v1, | ||
1512 | NID_secp384r1, | ||
1513 | # ifdef OPENSSL_HAS_NISTP521 | ||
1514 | NID_secp521r1, | ||
1515 | # endif /* OPENSSL_HAS_NISTP521 */ | ||
1516 | -1 | ||
1517 | }; | ||
1518 | int nid; | ||
1519 | u_int i; | ||
1520 | BN_CTX *bnctx; | ||
1521 | const EC_GROUP *g = EC_KEY_get0_group(k); | ||
1522 | |||
1523 | /* | ||
1524 | * The group may be stored in a ASN.1 encoded private key in one of two | ||
1525 | * ways: as a "named group", which is reconstituted by ASN.1 object ID | ||
1526 | * or explicit group parameters encoded into the key blob. Only the | ||
1527 | * "named group" case sets the group NID for us, but we can figure | ||
1528 | * it out for the other case by comparing against all the groups that | ||
1529 | * are supported. | ||
1530 | */ | ||
1531 | if ((nid = EC_GROUP_get_curve_name(g)) > 0) | ||
1532 | return nid; | ||
1533 | if ((bnctx = BN_CTX_new()) == NULL) | ||
1534 | return -1; | ||
1535 | for (i = 0; nids[i] != -1; i++) { | ||
1536 | if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) { | ||
1537 | BN_CTX_free(bnctx); | ||
1538 | return -1; | ||
1539 | } | ||
1540 | if (EC_GROUP_cmp(g, eg, bnctx) == 0) | ||
1541 | break; | ||
1542 | EC_GROUP_free(eg); | ||
1543 | } | ||
1544 | BN_CTX_free(bnctx); | ||
1545 | if (nids[i] != -1) { | ||
1546 | /* Use the group with the NID attached */ | ||
1547 | EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); | ||
1548 | if (EC_KEY_set_group(k, eg) != 1) { | ||
1549 | EC_GROUP_free(eg); | ||
1550 | return -1; | ||
1551 | } | ||
1552 | } | ||
1553 | return nids[i]; | ||
1554 | } | ||
1555 | |||
1556 | static int | ||
1557 | ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) | ||
1558 | { | ||
1559 | EC_KEY *private; | ||
1560 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1561 | |||
1562 | if (nid == NULL || ecdsap == NULL || | ||
1563 | (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) | ||
1564 | return SSH_ERR_INVALID_ARGUMENT; | ||
1565 | *ecdsap = NULL; | ||
1566 | if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { | ||
1567 | ret = SSH_ERR_ALLOC_FAIL; | ||
1568 | goto out; | ||
1569 | } | ||
1570 | if (EC_KEY_generate_key(private) != 1) { | ||
1571 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
1572 | goto out; | ||
1573 | } | ||
1574 | EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); | ||
1575 | *ecdsap = private; | ||
1576 | private = NULL; | ||
1577 | ret = 0; | ||
1578 | out: | ||
1579 | if (private != NULL) | ||
1580 | EC_KEY_free(private); | ||
1581 | return ret; | ||
1582 | } | ||
1583 | # endif /* OPENSSL_HAS_ECC */ | ||
1584 | #endif /* WITH_OPENSSL */ | ||
1585 | |||
1586 | int | ||
1587 | sshkey_generate(int type, u_int bits, struct sshkey **keyp) | ||
1588 | { | ||
1589 | struct sshkey *k; | ||
1590 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1591 | |||
1592 | if (keyp == NULL) | ||
1593 | return SSH_ERR_INVALID_ARGUMENT; | ||
1594 | *keyp = NULL; | ||
1595 | if ((k = sshkey_new(KEY_UNSPEC)) == NULL) | ||
1596 | return SSH_ERR_ALLOC_FAIL; | ||
1597 | switch (type) { | ||
1598 | case KEY_ED25519: | ||
1599 | if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL || | ||
1600 | (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) { | ||
1601 | ret = SSH_ERR_ALLOC_FAIL; | ||
1602 | break; | ||
1603 | } | ||
1604 | crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); | ||
1605 | ret = 0; | ||
1606 | break; | ||
1607 | #ifdef WITH_OPENSSL | ||
1608 | case KEY_DSA: | ||
1609 | ret = dsa_generate_private_key(bits, &k->dsa); | ||
1610 | break; | ||
1611 | # ifdef OPENSSL_HAS_ECC | ||
1612 | case KEY_ECDSA: | ||
1613 | ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, | ||
1614 | &k->ecdsa); | ||
1615 | break; | ||
1616 | # endif /* OPENSSL_HAS_ECC */ | ||
1617 | case KEY_RSA: | ||
1618 | case KEY_RSA1: | ||
1619 | ret = rsa_generate_private_key(bits, &k->rsa); | ||
1620 | break; | ||
1621 | #endif /* WITH_OPENSSL */ | ||
1622 | default: | ||
1623 | ret = SSH_ERR_INVALID_ARGUMENT; | ||
1624 | } | ||
1625 | if (ret == 0) { | ||
1626 | k->type = type; | ||
1627 | *keyp = k; | ||
1628 | } else | ||
1629 | sshkey_free(k); | ||
1630 | return ret; | ||
1631 | } | ||
1632 | |||
1633 | int | ||
1634 | sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) | ||
1635 | { | ||
1636 | u_int i; | ||
1637 | const struct sshkey_cert *from; | ||
1638 | struct sshkey_cert *to; | ||
1639 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1640 | |||
1641 | if (to_key->cert != NULL) { | ||
1642 | cert_free(to_key->cert); | ||
1643 | to_key->cert = NULL; | ||
1644 | } | ||
1645 | |||
1646 | if ((from = from_key->cert) == NULL) | ||
1647 | return SSH_ERR_INVALID_ARGUMENT; | ||
1648 | |||
1649 | if ((to = to_key->cert = cert_new()) == NULL) | ||
1650 | return SSH_ERR_ALLOC_FAIL; | ||
1651 | |||
1652 | if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 || | ||
1653 | (ret = sshbuf_putb(to->critical, from->critical)) != 0 || | ||
1654 | (ret = sshbuf_putb(to->extensions, from->extensions) != 0)) | ||
1655 | return ret; | ||
1656 | |||
1657 | to->serial = from->serial; | ||
1658 | to->type = from->type; | ||
1659 | if (from->key_id == NULL) | ||
1660 | to->key_id = NULL; | ||
1661 | else if ((to->key_id = strdup(from->key_id)) == NULL) | ||
1662 | return SSH_ERR_ALLOC_FAIL; | ||
1663 | to->valid_after = from->valid_after; | ||
1664 | to->valid_before = from->valid_before; | ||
1665 | if (from->signature_key == NULL) | ||
1666 | to->signature_key = NULL; | ||
1667 | else if ((ret = sshkey_from_private(from->signature_key, | ||
1668 | &to->signature_key)) != 0) | ||
1669 | return ret; | ||
1670 | |||
1671 | if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) | ||
1672 | return SSH_ERR_INVALID_ARGUMENT; | ||
1673 | if (from->nprincipals > 0) { | ||
1674 | if ((to->principals = calloc(from->nprincipals, | ||
1675 | sizeof(*to->principals))) == NULL) | ||
1676 | return SSH_ERR_ALLOC_FAIL; | ||
1677 | for (i = 0; i < from->nprincipals; i++) { | ||
1678 | to->principals[i] = strdup(from->principals[i]); | ||
1679 | if (to->principals[i] == NULL) { | ||
1680 | to->nprincipals = i; | ||
1681 | return SSH_ERR_ALLOC_FAIL; | ||
1682 | } | ||
1683 | } | ||
1684 | } | ||
1685 | to->nprincipals = from->nprincipals; | ||
1686 | return 0; | ||
1687 | } | ||
1688 | |||
1689 | int | ||
1690 | sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | ||
1691 | { | ||
1692 | struct sshkey *n = NULL; | ||
1693 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1694 | |||
1695 | if (pkp != NULL) | ||
1696 | *pkp = NULL; | ||
1697 | |||
1698 | switch (k->type) { | ||
1699 | #ifdef WITH_OPENSSL | ||
1700 | case KEY_DSA: | ||
1701 | case KEY_DSA_CERT_V00: | ||
1702 | case KEY_DSA_CERT: | ||
1703 | if ((n = sshkey_new(k->type)) == NULL) | ||
1704 | return SSH_ERR_ALLOC_FAIL; | ||
1705 | if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || | ||
1706 | (BN_copy(n->dsa->q, k->dsa->q) == NULL) || | ||
1707 | (BN_copy(n->dsa->g, k->dsa->g) == NULL) || | ||
1708 | (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) { | ||
1709 | sshkey_free(n); | ||
1710 | return SSH_ERR_ALLOC_FAIL; | ||
1711 | } | ||
1712 | break; | ||
1713 | # ifdef OPENSSL_HAS_ECC | ||
1714 | case KEY_ECDSA: | ||
1715 | case KEY_ECDSA_CERT: | ||
1716 | if ((n = sshkey_new(k->type)) == NULL) | ||
1717 | return SSH_ERR_ALLOC_FAIL; | ||
1718 | n->ecdsa_nid = k->ecdsa_nid; | ||
1719 | n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); | ||
1720 | if (n->ecdsa == NULL) { | ||
1721 | sshkey_free(n); | ||
1722 | return SSH_ERR_ALLOC_FAIL; | ||
1723 | } | ||
1724 | if (EC_KEY_set_public_key(n->ecdsa, | ||
1725 | EC_KEY_get0_public_key(k->ecdsa)) != 1) { | ||
1726 | sshkey_free(n); | ||
1727 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
1728 | } | ||
1729 | break; | ||
1730 | # endif /* OPENSSL_HAS_ECC */ | ||
1731 | case KEY_RSA: | ||
1732 | case KEY_RSA1: | ||
1733 | case KEY_RSA_CERT_V00: | ||
1734 | case KEY_RSA_CERT: | ||
1735 | if ((n = sshkey_new(k->type)) == NULL) | ||
1736 | return SSH_ERR_ALLOC_FAIL; | ||
1737 | if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || | ||
1738 | (BN_copy(n->rsa->e, k->rsa->e) == NULL)) { | ||
1739 | sshkey_free(n); | ||
1740 | return SSH_ERR_ALLOC_FAIL; | ||
1741 | } | ||
1742 | break; | ||
1743 | #endif /* WITH_OPENSSL */ | ||
1744 | case KEY_ED25519: | ||
1745 | case KEY_ED25519_CERT: | ||
1746 | if ((n = sshkey_new(k->type)) == NULL) | ||
1747 | return SSH_ERR_ALLOC_FAIL; | ||
1748 | if (k->ed25519_pk != NULL) { | ||
1749 | if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { | ||
1750 | sshkey_free(n); | ||
1751 | return SSH_ERR_ALLOC_FAIL; | ||
1752 | } | ||
1753 | memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); | ||
1754 | } | ||
1755 | break; | ||
1756 | default: | ||
1757 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
1758 | } | ||
1759 | if (sshkey_is_cert(k)) { | ||
1760 | if ((ret = sshkey_cert_copy(k, n)) != 0) { | ||
1761 | sshkey_free(n); | ||
1762 | return ret; | ||
1763 | } | ||
1764 | } | ||
1765 | *pkp = n; | ||
1766 | return 0; | ||
1767 | } | ||
1768 | |||
1769 | static int | ||
1770 | cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, | ||
1771 | size_t blen) | ||
1772 | { | ||
1773 | u_char *principals = NULL, *critical = NULL, *exts = NULL; | ||
1774 | u_char *sig_key = NULL, *sig = NULL; | ||
1775 | size_t signed_len, plen, clen, sklen, slen, kidlen, elen; | ||
1776 | struct sshbuf *tmp; | ||
1777 | char *principal; | ||
1778 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
1779 | int v00 = sshkey_cert_is_legacy(key); | ||
1780 | char **oprincipals; | ||
1781 | |||
1782 | if ((tmp = sshbuf_new()) == NULL) | ||
1783 | return SSH_ERR_ALLOC_FAIL; | ||
1784 | |||
1785 | /* Copy the entire key blob for verification and later serialisation */ | ||
1786 | if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0) | ||
1787 | return ret; | ||
1788 | |||
1789 | elen = 0; /* Not touched for v00 certs */ | ||
1790 | principals = exts = critical = sig_key = sig = NULL; | ||
1791 | if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) || | ||
1792 | (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || | ||
1793 | (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || | ||
1794 | (ret = sshbuf_get_string(b, &principals, &plen)) != 0 || | ||
1795 | (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || | ||
1796 | (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || | ||
1797 | (ret = sshbuf_get_string(b, &critical, &clen)) != 0 || | ||
1798 | (!v00 && (ret = sshbuf_get_string(b, &exts, &elen)) != 0) || | ||
1799 | (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) || | ||
1800 | (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || | ||
1801 | (ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) { | ||
1802 | /* XXX debug print error for ret */ | ||
1803 | ret = SSH_ERR_INVALID_FORMAT; | ||
1804 | goto out; | ||
1805 | } | ||
1806 | |||
1807 | /* Signature is left in the buffer so we can calculate this length */ | ||
1808 | signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b); | ||
1809 | |||
1810 | if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) { | ||
1811 | ret = SSH_ERR_INVALID_FORMAT; | ||
1812 | goto out; | ||
1813 | } | ||
1814 | |||
1815 | if (key->cert->type != SSH2_CERT_TYPE_USER && | ||
1816 | key->cert->type != SSH2_CERT_TYPE_HOST) { | ||
1817 | ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE; | ||
1818 | goto out; | ||
1819 | } | ||
1820 | |||
1821 | if ((ret = sshbuf_put(tmp, principals, plen)) != 0) | ||
1822 | goto out; | ||
1823 | while (sshbuf_len(tmp) > 0) { | ||
1824 | if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { | ||
1825 | ret = SSH_ERR_INVALID_FORMAT; | ||
1826 | goto out; | ||
1827 | } | ||
1828 | if ((ret = sshbuf_get_cstring(tmp, &principal, &plen)) != 0) { | ||
1829 | ret = SSH_ERR_INVALID_FORMAT; | ||
1830 | goto out; | ||
1831 | } | ||
1832 | oprincipals = key->cert->principals; | ||
1833 | key->cert->principals = realloc(key->cert->principals, | ||
1834 | (key->cert->nprincipals + 1) * | ||
1835 | sizeof(*key->cert->principals)); | ||
1836 | if (key->cert->principals == NULL) { | ||
1837 | free(principal); | ||
1838 | key->cert->principals = oprincipals; | ||
1839 | ret = SSH_ERR_ALLOC_FAIL; | ||
1840 | goto out; | ||
1841 | } | ||
1842 | key->cert->principals[key->cert->nprincipals++] = principal; | ||
1843 | } | ||
1844 | |||
1845 | sshbuf_reset(tmp); | ||
1846 | |||
1847 | if ((ret = sshbuf_put(key->cert->critical, critical, clen)) != 0 || | ||
1848 | (ret = sshbuf_put(tmp, critical, clen)) != 0) | ||
1849 | goto out; | ||
1850 | |||
1851 | /* validate structure */ | ||
1852 | while (sshbuf_len(tmp) != 0) { | ||
1853 | if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 || | ||
1854 | (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) { | ||
1855 | ret = SSH_ERR_INVALID_FORMAT; | ||
1856 | goto out; | ||
1857 | } | ||
1858 | } | ||
1859 | sshbuf_reset(tmp); | ||
1860 | |||
1861 | if ((ret = sshbuf_put(key->cert->extensions, exts, elen)) != 0 || | ||
1862 | (ret = sshbuf_put(tmp, exts, elen)) != 0) | ||
1863 | goto out; | ||
1864 | |||
1865 | /* validate structure */ | ||
1866 | while (sshbuf_len(tmp) != 0) { | ||
1867 | if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 || | ||
1868 | (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) { | ||
1869 | ret = SSH_ERR_INVALID_FORMAT; | ||
1870 | goto out; | ||
1871 | } | ||
1872 | } | ||
1873 | sshbuf_reset(tmp); | ||
1874 | |||
1875 | if (sshkey_from_blob_internal(sig_key, sklen, | ||
1876 | &key->cert->signature_key, 0) != 0) { | ||
1877 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | ||
1878 | goto out; | ||
1879 | } | ||
1880 | if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) { | ||
1881 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | ||
1882 | goto out; | ||
1883 | } | ||
1884 | |||
1885 | if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, | ||
1886 | sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) | ||
1887 | goto out; | ||
1888 | ret = 0; | ||
1889 | |||
1890 | out: | ||
1891 | sshbuf_free(tmp); | ||
1892 | free(principals); | ||
1893 | free(critical); | ||
1894 | free(exts); | ||
1895 | free(sig_key); | ||
1896 | free(sig); | ||
1897 | return ret; | ||
1898 | } | ||
1899 | |||
1900 | static int | ||
1901 | sshkey_from_blob_internal(const u_char *blob, size_t blen, | ||
1902 | struct sshkey **keyp, int allow_cert) | ||
1903 | { | ||
1904 | struct sshbuf *b = NULL; | ||
1905 | int type, nid = -1, ret = SSH_ERR_INTERNAL_ERROR; | ||
1906 | char *ktype = NULL, *curve = NULL; | ||
1907 | struct sshkey *key = NULL; | ||
1908 | size_t len; | ||
1909 | u_char *pk = NULL; | ||
1910 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | ||
1911 | EC_POINT *q = NULL; | ||
1912 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | ||
1913 | |||
1914 | #ifdef DEBUG_PK /* XXX */ | ||
1915 | dump_base64(stderr, blob, blen); | ||
1916 | #endif | ||
1917 | *keyp = NULL; | ||
1918 | if ((b = sshbuf_from(blob, blen)) == NULL) | ||
1919 | return SSH_ERR_ALLOC_FAIL; | ||
1920 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { | ||
1921 | ret = SSH_ERR_INVALID_FORMAT; | ||
1922 | goto out; | ||
1923 | } | ||
1924 | |||
1925 | type = sshkey_type_from_name(ktype); | ||
1926 | if (sshkey_type_plain(type) == KEY_ECDSA) | ||
1927 | nid = sshkey_ecdsa_nid_from_name(ktype); | ||
1928 | if (!allow_cert && sshkey_type_is_cert(type)) { | ||
1929 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | ||
1930 | goto out; | ||
1931 | } | ||
1932 | switch (type) { | ||
1933 | #ifdef WITH_OPENSSL | ||
1934 | case KEY_RSA_CERT: | ||
1935 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | ||
1936 | ret = SSH_ERR_INVALID_FORMAT; | ||
1937 | goto out; | ||
1938 | } | ||
1939 | /* FALLTHROUGH */ | ||
1940 | case KEY_RSA: | ||
1941 | case KEY_RSA_CERT_V00: | ||
1942 | if ((key = sshkey_new(type)) == NULL) { | ||
1943 | ret = SSH_ERR_ALLOC_FAIL; | ||
1944 | goto out; | ||
1945 | } | ||
1946 | if (sshbuf_get_bignum2(b, key->rsa->e) == -1 || | ||
1947 | sshbuf_get_bignum2(b, key->rsa->n) == -1) { | ||
1948 | ret = SSH_ERR_INVALID_FORMAT; | ||
1949 | goto out; | ||
1950 | } | ||
1951 | #ifdef DEBUG_PK | ||
1952 | RSA_print_fp(stderr, key->rsa, 8); | ||
1953 | #endif | ||
1954 | break; | ||
1955 | case KEY_DSA_CERT: | ||
1956 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | ||
1957 | ret = SSH_ERR_INVALID_FORMAT; | ||
1958 | goto out; | ||
1959 | } | ||
1960 | /* FALLTHROUGH */ | ||
1961 | case KEY_DSA: | ||
1962 | case KEY_DSA_CERT_V00: | ||
1963 | if ((key = sshkey_new(type)) == NULL) { | ||
1964 | ret = SSH_ERR_ALLOC_FAIL; | ||
1965 | goto out; | ||
1966 | } | ||
1967 | if (sshbuf_get_bignum2(b, key->dsa->p) == -1 || | ||
1968 | sshbuf_get_bignum2(b, key->dsa->q) == -1 || | ||
1969 | sshbuf_get_bignum2(b, key->dsa->g) == -1 || | ||
1970 | sshbuf_get_bignum2(b, key->dsa->pub_key) == -1) { | ||
1971 | ret = SSH_ERR_INVALID_FORMAT; | ||
1972 | goto out; | ||
1973 | } | ||
1974 | #ifdef DEBUG_PK | ||
1975 | DSA_print_fp(stderr, key->dsa, 8); | ||
1976 | #endif | ||
1977 | break; | ||
1978 | case KEY_ECDSA_CERT: | ||
1979 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | ||
1980 | ret = SSH_ERR_INVALID_FORMAT; | ||
1981 | goto out; | ||
1982 | } | ||
1983 | /* FALLTHROUGH */ | ||
1984 | # ifdef OPENSSL_HAS_ECC | ||
1985 | case KEY_ECDSA: | ||
1986 | if ((key = sshkey_new(type)) == NULL) { | ||
1987 | ret = SSH_ERR_ALLOC_FAIL; | ||
1988 | goto out; | ||
1989 | } | ||
1990 | key->ecdsa_nid = nid; | ||
1991 | if (sshbuf_get_cstring(b, &curve, NULL) != 0) { | ||
1992 | ret = SSH_ERR_INVALID_FORMAT; | ||
1993 | goto out; | ||
1994 | } | ||
1995 | if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) { | ||
1996 | ret = SSH_ERR_EC_CURVE_MISMATCH; | ||
1997 | goto out; | ||
1998 | } | ||
1999 | if (key->ecdsa != NULL) | ||
2000 | EC_KEY_free(key->ecdsa); | ||
2001 | if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) | ||
2002 | == NULL) { | ||
2003 | ret = SSH_ERR_EC_CURVE_INVALID; | ||
2004 | goto out; | ||
2005 | } | ||
2006 | if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) { | ||
2007 | ret = SSH_ERR_ALLOC_FAIL; | ||
2008 | goto out; | ||
2009 | } | ||
2010 | if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) { | ||
2011 | ret = SSH_ERR_INVALID_FORMAT; | ||
2012 | goto out; | ||
2013 | } | ||
2014 | if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), | ||
2015 | q) != 0) { | ||
2016 | ret = SSH_ERR_KEY_INVALID_EC_VALUE; | ||
2017 | goto out; | ||
2018 | } | ||
2019 | if (EC_KEY_set_public_key(key->ecdsa, q) != 1) { | ||
2020 | /* XXX assume it is a allocation error */ | ||
2021 | ret = SSH_ERR_ALLOC_FAIL; | ||
2022 | goto out; | ||
2023 | } | ||
2024 | #ifdef DEBUG_PK | ||
2025 | sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); | ||
2026 | #endif | ||
2027 | break; | ||
2028 | # endif /* OPENSSL_HAS_ECC */ | ||
2029 | #endif /* WITH_OPENSSL */ | ||
2030 | case KEY_ED25519_CERT: | ||
2031 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | ||
2032 | ret = SSH_ERR_INVALID_FORMAT; | ||
2033 | goto out; | ||
2034 | } | ||
2035 | /* FALLTHROUGH */ | ||
2036 | case KEY_ED25519: | ||
2037 | if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) | ||
2038 | goto out; | ||
2039 | if (len != ED25519_PK_SZ) { | ||
2040 | ret = SSH_ERR_INVALID_FORMAT; | ||
2041 | goto out; | ||
2042 | } | ||
2043 | if ((key = sshkey_new(type)) == NULL) { | ||
2044 | ret = SSH_ERR_ALLOC_FAIL; | ||
2045 | goto out; | ||
2046 | } | ||
2047 | key->ed25519_pk = pk; | ||
2048 | pk = NULL; | ||
2049 | break; | ||
2050 | case KEY_UNSPEC: | ||
2051 | if ((key = sshkey_new(type)) == NULL) { | ||
2052 | ret = SSH_ERR_ALLOC_FAIL; | ||
2053 | goto out; | ||
2054 | } | ||
2055 | break; | ||
2056 | default: | ||
2057 | ret = SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2058 | goto out; | ||
2059 | } | ||
2060 | |||
2061 | /* Parse certificate potion */ | ||
2062 | if (sshkey_is_cert(key) && | ||
2063 | (ret = cert_parse(b, key, blob, blen)) != 0) | ||
2064 | goto out; | ||
2065 | |||
2066 | if (key != NULL && sshbuf_len(b) != 0) { | ||
2067 | ret = SSH_ERR_INVALID_FORMAT; | ||
2068 | goto out; | ||
2069 | } | ||
2070 | ret = 0; | ||
2071 | *keyp = key; | ||
2072 | key = NULL; | ||
2073 | out: | ||
2074 | sshbuf_free(b); | ||
2075 | sshkey_free(key); | ||
2076 | free(ktype); | ||
2077 | free(curve); | ||
2078 | free(pk); | ||
2079 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | ||
2080 | if (q != NULL) | ||
2081 | EC_POINT_free(q); | ||
2082 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | ||
2083 | return ret; | ||
2084 | } | ||
2085 | |||
2086 | int | ||
2087 | sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) | ||
2088 | { | ||
2089 | return sshkey_from_blob_internal(blob, blen, keyp, 1); | ||
2090 | } | ||
2091 | |||
2092 | int | ||
2093 | sshkey_sign(const struct sshkey *key, | ||
2094 | u_char **sigp, size_t *lenp, | ||
2095 | const u_char *data, size_t datalen, u_int compat) | ||
2096 | { | ||
2097 | if (sigp != NULL) | ||
2098 | *sigp = NULL; | ||
2099 | if (lenp != NULL) | ||
2100 | *lenp = 0; | ||
2101 | if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) | ||
2102 | return SSH_ERR_INVALID_ARGUMENT; | ||
2103 | switch (key->type) { | ||
2104 | #ifdef WITH_OPENSSL | ||
2105 | case KEY_DSA_CERT_V00: | ||
2106 | case KEY_DSA_CERT: | ||
2107 | case KEY_DSA: | ||
2108 | return ssh_dss_sign(key, sigp, lenp, data, datalen, compat); | ||
2109 | # ifdef OPENSSL_HAS_ECC | ||
2110 | case KEY_ECDSA_CERT: | ||
2111 | case KEY_ECDSA: | ||
2112 | return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); | ||
2113 | # endif /* OPENSSL_HAS_ECC */ | ||
2114 | case KEY_RSA_CERT_V00: | ||
2115 | case KEY_RSA_CERT: | ||
2116 | case KEY_RSA: | ||
2117 | return ssh_rsa_sign(key, sigp, lenp, data, datalen, compat); | ||
2118 | #endif /* WITH_OPENSSL */ | ||
2119 | case KEY_ED25519: | ||
2120 | case KEY_ED25519_CERT: | ||
2121 | return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat); | ||
2122 | default: | ||
2123 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2124 | } | ||
2125 | } | ||
2126 | |||
2127 | /* | ||
2128 | * ssh_key_verify returns 0 for a correct signature and < 0 on error. | ||
2129 | */ | ||
2130 | int | ||
2131 | sshkey_verify(const struct sshkey *key, | ||
2132 | const u_char *sig, size_t siglen, | ||
2133 | const u_char *data, size_t dlen, u_int compat) | ||
2134 | { | ||
2135 | if (siglen == 0) | ||
2136 | return -1; | ||
2137 | |||
2138 | if (dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) | ||
2139 | return SSH_ERR_INVALID_ARGUMENT; | ||
2140 | switch (key->type) { | ||
2141 | #ifdef WITH_OPENSSL | ||
2142 | case KEY_DSA_CERT_V00: | ||
2143 | case KEY_DSA_CERT: | ||
2144 | case KEY_DSA: | ||
2145 | return ssh_dss_verify(key, sig, siglen, data, dlen, compat); | ||
2146 | # ifdef OPENSSL_HAS_ECC | ||
2147 | case KEY_ECDSA_CERT: | ||
2148 | case KEY_ECDSA: | ||
2149 | return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat); | ||
2150 | # endif /* OPENSSL_HAS_ECC */ | ||
2151 | case KEY_RSA_CERT_V00: | ||
2152 | case KEY_RSA_CERT: | ||
2153 | case KEY_RSA: | ||
2154 | return ssh_rsa_verify(key, sig, siglen, data, dlen, compat); | ||
2155 | #endif /* WITH_OPENSSL */ | ||
2156 | case KEY_ED25519: | ||
2157 | case KEY_ED25519_CERT: | ||
2158 | return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat); | ||
2159 | default: | ||
2160 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2164 | /* Converts a private to a public key */ | ||
2165 | int | ||
2166 | sshkey_demote(const struct sshkey *k, struct sshkey **dkp) | ||
2167 | { | ||
2168 | struct sshkey *pk; | ||
2169 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
2170 | |||
2171 | if (dkp != NULL) | ||
2172 | *dkp = NULL; | ||
2173 | |||
2174 | if ((pk = calloc(1, sizeof(*pk))) == NULL) | ||
2175 | return SSH_ERR_ALLOC_FAIL; | ||
2176 | pk->type = k->type; | ||
2177 | pk->flags = k->flags; | ||
2178 | pk->ecdsa_nid = k->ecdsa_nid; | ||
2179 | pk->dsa = NULL; | ||
2180 | pk->ecdsa = NULL; | ||
2181 | pk->rsa = NULL; | ||
2182 | pk->ed25519_pk = NULL; | ||
2183 | pk->ed25519_sk = NULL; | ||
2184 | |||
2185 | switch (k->type) { | ||
2186 | #ifdef WITH_OPENSSL | ||
2187 | case KEY_RSA_CERT_V00: | ||
2188 | case KEY_RSA_CERT: | ||
2189 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2190 | goto fail; | ||
2191 | /* FALLTHROUGH */ | ||
2192 | case KEY_RSA1: | ||
2193 | case KEY_RSA: | ||
2194 | if ((pk->rsa = RSA_new()) == NULL || | ||
2195 | (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || | ||
2196 | (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) { | ||
2197 | ret = SSH_ERR_ALLOC_FAIL; | ||
2198 | goto fail; | ||
2199 | } | ||
2200 | break; | ||
2201 | case KEY_DSA_CERT_V00: | ||
2202 | case KEY_DSA_CERT: | ||
2203 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2204 | goto fail; | ||
2205 | /* FALLTHROUGH */ | ||
2206 | case KEY_DSA: | ||
2207 | if ((pk->dsa = DSA_new()) == NULL || | ||
2208 | (pk->dsa->p = BN_dup(k->dsa->p)) == NULL || | ||
2209 | (pk->dsa->q = BN_dup(k->dsa->q)) == NULL || | ||
2210 | (pk->dsa->g = BN_dup(k->dsa->g)) == NULL || | ||
2211 | (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) { | ||
2212 | ret = SSH_ERR_ALLOC_FAIL; | ||
2213 | goto fail; | ||
2214 | } | ||
2215 | break; | ||
2216 | case KEY_ECDSA_CERT: | ||
2217 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2218 | goto fail; | ||
2219 | /* FALLTHROUGH */ | ||
2220 | # ifdef OPENSSL_HAS_ECC | ||
2221 | case KEY_ECDSA: | ||
2222 | pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid); | ||
2223 | if (pk->ecdsa == NULL) { | ||
2224 | ret = SSH_ERR_ALLOC_FAIL; | ||
2225 | goto fail; | ||
2226 | } | ||
2227 | if (EC_KEY_set_public_key(pk->ecdsa, | ||
2228 | EC_KEY_get0_public_key(k->ecdsa)) != 1) { | ||
2229 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2230 | goto fail; | ||
2231 | } | ||
2232 | break; | ||
2233 | # endif /* OPENSSL_HAS_ECC */ | ||
2234 | #endif /* WITH_OPENSSL */ | ||
2235 | case KEY_ED25519_CERT: | ||
2236 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2237 | goto fail; | ||
2238 | /* FALLTHROUGH */ | ||
2239 | case KEY_ED25519: | ||
2240 | if (k->ed25519_pk != NULL) { | ||
2241 | if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { | ||
2242 | ret = SSH_ERR_ALLOC_FAIL; | ||
2243 | goto fail; | ||
2244 | } | ||
2245 | memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); | ||
2246 | } | ||
2247 | break; | ||
2248 | default: | ||
2249 | ret = SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2250 | fail: | ||
2251 | sshkey_free(pk); | ||
2252 | return ret; | ||
2253 | } | ||
2254 | *dkp = pk; | ||
2255 | return 0; | ||
2256 | } | ||
2257 | |||
2258 | /* Convert a plain key to their _CERT equivalent */ | ||
2259 | int | ||
2260 | sshkey_to_certified(struct sshkey *k, int legacy) | ||
2261 | { | ||
2262 | int newtype; | ||
2263 | |||
2264 | switch (k->type) { | ||
2265 | #ifdef WITH_OPENSSL | ||
2266 | case KEY_RSA: | ||
2267 | newtype = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT; | ||
2268 | break; | ||
2269 | case KEY_DSA: | ||
2270 | newtype = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT; | ||
2271 | break; | ||
2272 | case KEY_ECDSA: | ||
2273 | if (legacy) | ||
2274 | return SSH_ERR_INVALID_ARGUMENT; | ||
2275 | newtype = KEY_ECDSA_CERT; | ||
2276 | break; | ||
2277 | #endif /* WITH_OPENSSL */ | ||
2278 | case KEY_ED25519: | ||
2279 | if (legacy) | ||
2280 | return SSH_ERR_INVALID_ARGUMENT; | ||
2281 | newtype = KEY_ED25519_CERT; | ||
2282 | break; | ||
2283 | default: | ||
2284 | return SSH_ERR_INVALID_ARGUMENT; | ||
2285 | } | ||
2286 | if ((k->cert = cert_new()) == NULL) | ||
2287 | return SSH_ERR_ALLOC_FAIL; | ||
2288 | k->type = newtype; | ||
2289 | return 0; | ||
2290 | } | ||
2291 | |||
2292 | /* Convert a certificate to its raw key equivalent */ | ||
2293 | int | ||
2294 | sshkey_drop_cert(struct sshkey *k) | ||
2295 | { | ||
2296 | if (!sshkey_type_is_cert(k->type)) | ||
2297 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2298 | cert_free(k->cert); | ||
2299 | k->cert = NULL; | ||
2300 | k->type = sshkey_type_plain(k->type); | ||
2301 | return 0; | ||
2302 | } | ||
2303 | |||
2304 | /* Sign a certified key, (re-)generating the signed certblob. */ | ||
2305 | int | ||
2306 | sshkey_certify(struct sshkey *k, struct sshkey *ca) | ||
2307 | { | ||
2308 | struct sshbuf *principals = NULL; | ||
2309 | u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; | ||
2310 | size_t i, ca_len, sig_len; | ||
2311 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
2312 | struct sshbuf *cert; | ||
2313 | |||
2314 | if (k == NULL || k->cert == NULL || | ||
2315 | k->cert->certblob == NULL || ca == NULL) | ||
2316 | return SSH_ERR_INVALID_ARGUMENT; | ||
2317 | if (!sshkey_is_cert(k)) | ||
2318 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2319 | if (!sshkey_type_is_valid_ca(ca->type)) | ||
2320 | return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | ||
2321 | |||
2322 | if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) | ||
2323 | return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | ||
2324 | |||
2325 | cert = k->cert->certblob; /* for readability */ | ||
2326 | sshbuf_reset(cert); | ||
2327 | if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0) | ||
2328 | goto out; | ||
2329 | |||
2330 | /* -v01 certs put nonce first */ | ||
2331 | arc4random_buf(&nonce, sizeof(nonce)); | ||
2332 | if (!sshkey_cert_is_legacy(k)) { | ||
2333 | if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0) | ||
2334 | goto out; | ||
2335 | } | ||
2336 | |||
2337 | /* XXX this substantially duplicates to_blob(); refactor */ | ||
2338 | switch (k->type) { | ||
2339 | #ifdef WITH_OPENSSL | ||
2340 | case KEY_DSA_CERT_V00: | ||
2341 | case KEY_DSA_CERT: | ||
2342 | if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 || | ||
2343 | (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 || | ||
2344 | (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 || | ||
2345 | (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0) | ||
2346 | goto out; | ||
2347 | break; | ||
2348 | # ifdef OPENSSL_HAS_ECC | ||
2349 | case KEY_ECDSA_CERT: | ||
2350 | if ((ret = sshbuf_put_cstring(cert, | ||
2351 | sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 || | ||
2352 | (ret = sshbuf_put_ec(cert, | ||
2353 | EC_KEY_get0_public_key(k->ecdsa), | ||
2354 | EC_KEY_get0_group(k->ecdsa))) != 0) | ||
2355 | goto out; | ||
2356 | break; | ||
2357 | # endif /* OPENSSL_HAS_ECC */ | ||
2358 | case KEY_RSA_CERT_V00: | ||
2359 | case KEY_RSA_CERT: | ||
2360 | if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 || | ||
2361 | (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0) | ||
2362 | goto out; | ||
2363 | break; | ||
2364 | #endif /* WITH_OPENSSL */ | ||
2365 | case KEY_ED25519_CERT: | ||
2366 | if ((ret = sshbuf_put_string(cert, | ||
2367 | k->ed25519_pk, ED25519_PK_SZ)) != 0) | ||
2368 | goto out; | ||
2369 | break; | ||
2370 | default: | ||
2371 | ret = SSH_ERR_INVALID_ARGUMENT; | ||
2372 | } | ||
2373 | |||
2374 | /* -v01 certs have a serial number next */ | ||
2375 | if (!sshkey_cert_is_legacy(k)) { | ||
2376 | if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0) | ||
2377 | goto out; | ||
2378 | } | ||
2379 | |||
2380 | if ((ret = sshbuf_put_u32(cert, k->cert->type)) != 0 || | ||
2381 | (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0) | ||
2382 | goto out; | ||
2383 | |||
2384 | if ((principals = sshbuf_new()) == NULL) { | ||
2385 | ret = SSH_ERR_ALLOC_FAIL; | ||
2386 | goto out; | ||
2387 | } | ||
2388 | for (i = 0; i < k->cert->nprincipals; i++) { | ||
2389 | if ((ret = sshbuf_put_cstring(principals, | ||
2390 | k->cert->principals[i])) != 0) | ||
2391 | goto out; | ||
2392 | } | ||
2393 | if ((ret = sshbuf_put_stringb(cert, principals)) != 0 || | ||
2394 | (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 || | ||
2395 | (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 || | ||
2396 | (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0) | ||
2397 | goto out; | ||
2398 | |||
2399 | /* -v01 certs have non-critical options here */ | ||
2400 | if (!sshkey_cert_is_legacy(k)) { | ||
2401 | if ((ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0) | ||
2402 | goto out; | ||
2403 | } | ||
2404 | |||
2405 | /* -v00 certs put the nonce at the end */ | ||
2406 | if (sshkey_cert_is_legacy(k)) { | ||
2407 | if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0) | ||
2408 | goto out; | ||
2409 | } | ||
2410 | |||
2411 | if ((ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */ | ||
2412 | (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0) | ||
2413 | goto out; | ||
2414 | |||
2415 | /* Sign the whole mess */ | ||
2416 | if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), | ||
2417 | sshbuf_len(cert), 0)) != 0) | ||
2418 | goto out; | ||
2419 | |||
2420 | /* Append signature and we are done */ | ||
2421 | if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) | ||
2422 | goto out; | ||
2423 | ret = 0; | ||
2424 | out: | ||
2425 | if (ret != 0) | ||
2426 | sshbuf_reset(cert); | ||
2427 | if (sig_blob != NULL) | ||
2428 | free(sig_blob); | ||
2429 | if (ca_blob != NULL) | ||
2430 | free(ca_blob); | ||
2431 | if (principals != NULL) | ||
2432 | sshbuf_free(principals); | ||
2433 | return ret; | ||
2434 | } | ||
2435 | |||
2436 | int | ||
2437 | sshkey_cert_check_authority(const struct sshkey *k, | ||
2438 | int want_host, int require_principal, | ||
2439 | const char *name, const char **reason) | ||
2440 | { | ||
2441 | u_int i, principal_matches; | ||
2442 | time_t now = time(NULL); | ||
2443 | |||
2444 | if (reason != NULL) | ||
2445 | *reason = NULL; | ||
2446 | |||
2447 | if (want_host) { | ||
2448 | if (k->cert->type != SSH2_CERT_TYPE_HOST) { | ||
2449 | *reason = "Certificate invalid: not a host certificate"; | ||
2450 | return SSH_ERR_KEY_CERT_INVALID; | ||
2451 | } | ||
2452 | } else { | ||
2453 | if (k->cert->type != SSH2_CERT_TYPE_USER) { | ||
2454 | *reason = "Certificate invalid: not a user certificate"; | ||
2455 | return SSH_ERR_KEY_CERT_INVALID; | ||
2456 | } | ||
2457 | } | ||
2458 | if (now < 0) { | ||
2459 | /* yikes - system clock before epoch! */ | ||
2460 | *reason = "Certificate invalid: not yet valid"; | ||
2461 | return SSH_ERR_KEY_CERT_INVALID; | ||
2462 | } | ||
2463 | if ((u_int64_t)now < k->cert->valid_after) { | ||
2464 | *reason = "Certificate invalid: not yet valid"; | ||
2465 | return SSH_ERR_KEY_CERT_INVALID; | ||
2466 | } | ||
2467 | if ((u_int64_t)now >= k->cert->valid_before) { | ||
2468 | *reason = "Certificate invalid: expired"; | ||
2469 | return SSH_ERR_KEY_CERT_INVALID; | ||
2470 | } | ||
2471 | if (k->cert->nprincipals == 0) { | ||
2472 | if (require_principal) { | ||
2473 | *reason = "Certificate lacks principal list"; | ||
2474 | return SSH_ERR_KEY_CERT_INVALID; | ||
2475 | } | ||
2476 | } else if (name != NULL) { | ||
2477 | principal_matches = 0; | ||
2478 | for (i = 0; i < k->cert->nprincipals; i++) { | ||
2479 | if (strcmp(name, k->cert->principals[i]) == 0) { | ||
2480 | principal_matches = 1; | ||
2481 | break; | ||
2482 | } | ||
2483 | } | ||
2484 | if (!principal_matches) { | ||
2485 | *reason = "Certificate invalid: name is not a listed " | ||
2486 | "principal"; | ||
2487 | return SSH_ERR_KEY_CERT_INVALID; | ||
2488 | } | ||
2489 | } | ||
2490 | return 0; | ||
2491 | } | ||
2492 | |||
2493 | int | ||
2494 | sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) | ||
2495 | { | ||
2496 | int r = SSH_ERR_INTERNAL_ERROR; | ||
2497 | |||
2498 | if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) | ||
2499 | goto out; | ||
2500 | switch (key->type) { | ||
2501 | #ifdef WITH_OPENSSL | ||
2502 | case KEY_RSA: | ||
2503 | if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 || | ||
2504 | (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || | ||
2505 | (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || | ||
2506 | (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || | ||
2507 | (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || | ||
2508 | (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) | ||
2509 | goto out; | ||
2510 | break; | ||
2511 | case KEY_RSA_CERT_V00: | ||
2512 | case KEY_RSA_CERT: | ||
2513 | if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { | ||
2514 | r = SSH_ERR_INVALID_ARGUMENT; | ||
2515 | goto out; | ||
2516 | } | ||
2517 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | ||
2518 | (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || | ||
2519 | (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || | ||
2520 | (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || | ||
2521 | (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) | ||
2522 | goto out; | ||
2523 | break; | ||
2524 | case KEY_DSA: | ||
2525 | if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || | ||
2526 | (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || | ||
2527 | (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || | ||
2528 | (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 || | ||
2529 | (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) | ||
2530 | goto out; | ||
2531 | break; | ||
2532 | case KEY_DSA_CERT_V00: | ||
2533 | case KEY_DSA_CERT: | ||
2534 | if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { | ||
2535 | r = SSH_ERR_INVALID_ARGUMENT; | ||
2536 | goto out; | ||
2537 | } | ||
2538 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | ||
2539 | (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) | ||
2540 | goto out; | ||
2541 | break; | ||
2542 | # ifdef OPENSSL_HAS_ECC | ||
2543 | case KEY_ECDSA: | ||
2544 | if ((r = sshbuf_put_cstring(b, | ||
2545 | sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || | ||
2546 | (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 || | ||
2547 | (r = sshbuf_put_bignum2(b, | ||
2548 | EC_KEY_get0_private_key(key->ecdsa))) != 0) | ||
2549 | goto out; | ||
2550 | break; | ||
2551 | case KEY_ECDSA_CERT: | ||
2552 | if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { | ||
2553 | r = SSH_ERR_INVALID_ARGUMENT; | ||
2554 | goto out; | ||
2555 | } | ||
2556 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | ||
2557 | (r = sshbuf_put_bignum2(b, | ||
2558 | EC_KEY_get0_private_key(key->ecdsa))) != 0) | ||
2559 | goto out; | ||
2560 | break; | ||
2561 | # endif /* OPENSSL_HAS_ECC */ | ||
2562 | #endif /* WITH_OPENSSL */ | ||
2563 | case KEY_ED25519: | ||
2564 | if ((r = sshbuf_put_string(b, key->ed25519_pk, | ||
2565 | ED25519_PK_SZ)) != 0 || | ||
2566 | (r = sshbuf_put_string(b, key->ed25519_sk, | ||
2567 | ED25519_SK_SZ)) != 0) | ||
2568 | goto out; | ||
2569 | break; | ||
2570 | case KEY_ED25519_CERT: | ||
2571 | if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { | ||
2572 | r = SSH_ERR_INVALID_ARGUMENT; | ||
2573 | goto out; | ||
2574 | } | ||
2575 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | ||
2576 | (r = sshbuf_put_string(b, key->ed25519_pk, | ||
2577 | ED25519_PK_SZ)) != 0 || | ||
2578 | (r = sshbuf_put_string(b, key->ed25519_sk, | ||
2579 | ED25519_SK_SZ)) != 0) | ||
2580 | goto out; | ||
2581 | break; | ||
2582 | default: | ||
2583 | r = SSH_ERR_INVALID_ARGUMENT; | ||
2584 | goto out; | ||
2585 | } | ||
2586 | /* success */ | ||
2587 | r = 0; | ||
2588 | out: | ||
2589 | return r; | ||
2590 | } | ||
2591 | |||
2592 | int | ||
2593 | sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | ||
2594 | { | ||
2595 | char *tname = NULL, *curve = NULL; | ||
2596 | struct sshkey *k = NULL; | ||
2597 | const u_char *cert; | ||
2598 | size_t len, pklen = 0, sklen = 0; | ||
2599 | int type, r = SSH_ERR_INTERNAL_ERROR; | ||
2600 | u_char *ed25519_pk = NULL, *ed25519_sk = NULL; | ||
2601 | #ifdef WITH_OPENSSL | ||
2602 | BIGNUM *exponent = NULL; | ||
2603 | #endif /* WITH_OPENSSL */ | ||
2604 | |||
2605 | if (kp != NULL) | ||
2606 | *kp = NULL; | ||
2607 | if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0) | ||
2608 | goto out; | ||
2609 | type = sshkey_type_from_name(tname); | ||
2610 | switch (type) { | ||
2611 | #ifdef WITH_OPENSSL | ||
2612 | case KEY_DSA: | ||
2613 | if ((k = sshkey_new_private(type)) == NULL) { | ||
2614 | r = SSH_ERR_ALLOC_FAIL; | ||
2615 | goto out; | ||
2616 | } | ||
2617 | if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 || | ||
2618 | (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 || | ||
2619 | (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 || | ||
2620 | (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 || | ||
2621 | (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) | ||
2622 | goto out; | ||
2623 | break; | ||
2624 | case KEY_DSA_CERT_V00: | ||
2625 | case KEY_DSA_CERT: | ||
2626 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | ||
2627 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2628 | (r = sshkey_add_private(k)) != 0 || | ||
2629 | (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) | ||
2630 | goto out; | ||
2631 | break; | ||
2632 | # ifdef OPENSSL_HAS_ECC | ||
2633 | case KEY_ECDSA: | ||
2634 | if ((k = sshkey_new_private(type)) == NULL) { | ||
2635 | r = SSH_ERR_ALLOC_FAIL; | ||
2636 | goto out; | ||
2637 | } | ||
2638 | if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { | ||
2639 | r = SSH_ERR_INVALID_ARGUMENT; | ||
2640 | goto out; | ||
2641 | } | ||
2642 | if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0) | ||
2643 | goto out; | ||
2644 | if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) { | ||
2645 | r = SSH_ERR_EC_CURVE_MISMATCH; | ||
2646 | goto out; | ||
2647 | } | ||
2648 | k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); | ||
2649 | if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) { | ||
2650 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2651 | goto out; | ||
2652 | } | ||
2653 | if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || | ||
2654 | (r = sshbuf_get_bignum2(buf, exponent))) | ||
2655 | goto out; | ||
2656 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { | ||
2657 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2658 | goto out; | ||
2659 | } | ||
2660 | if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
2661 | EC_KEY_get0_public_key(k->ecdsa)) != 0) || | ||
2662 | (r = sshkey_ec_validate_private(k->ecdsa)) != 0) | ||
2663 | goto out; | ||
2664 | break; | ||
2665 | case KEY_ECDSA_CERT: | ||
2666 | if ((exponent = BN_new()) == NULL) { | ||
2667 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2668 | goto out; | ||
2669 | } | ||
2670 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | ||
2671 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2672 | (r = sshkey_add_private(k)) != 0 || | ||
2673 | (r = sshbuf_get_bignum2(buf, exponent)) != 0) | ||
2674 | goto out; | ||
2675 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { | ||
2676 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2677 | goto out; | ||
2678 | } | ||
2679 | if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
2680 | EC_KEY_get0_public_key(k->ecdsa)) != 0) || | ||
2681 | (r = sshkey_ec_validate_private(k->ecdsa)) != 0) | ||
2682 | goto out; | ||
2683 | break; | ||
2684 | # endif /* OPENSSL_HAS_ECC */ | ||
2685 | case KEY_RSA: | ||
2686 | if ((k = sshkey_new_private(type)) == NULL) { | ||
2687 | r = SSH_ERR_ALLOC_FAIL; | ||
2688 | goto out; | ||
2689 | } | ||
2690 | if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 || | ||
2691 | (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 || | ||
2692 | (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || | ||
2693 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || | ||
2694 | (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || | ||
2695 | (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || | ||
2696 | (r = rsa_generate_additional_parameters(k->rsa)) != 0) | ||
2697 | goto out; | ||
2698 | break; | ||
2699 | case KEY_RSA_CERT_V00: | ||
2700 | case KEY_RSA_CERT: | ||
2701 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | ||
2702 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2703 | (r = sshkey_add_private(k)) != 0 || | ||
2704 | (r = sshbuf_get_bignum2(buf, k->rsa->d) != 0) || | ||
2705 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp) != 0) || | ||
2706 | (r = sshbuf_get_bignum2(buf, k->rsa->p) != 0) || | ||
2707 | (r = sshbuf_get_bignum2(buf, k->rsa->q) != 0) || | ||
2708 | (r = rsa_generate_additional_parameters(k->rsa)) != 0) | ||
2709 | goto out; | ||
2710 | break; | ||
2711 | #endif /* WITH_OPENSSL */ | ||
2712 | case KEY_ED25519: | ||
2713 | if ((k = sshkey_new_private(type)) == NULL) { | ||
2714 | r = SSH_ERR_ALLOC_FAIL; | ||
2715 | goto out; | ||
2716 | } | ||
2717 | if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || | ||
2718 | (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) | ||
2719 | goto out; | ||
2720 | if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { | ||
2721 | r = SSH_ERR_INVALID_FORMAT; | ||
2722 | goto out; | ||
2723 | } | ||
2724 | k->ed25519_pk = ed25519_pk; | ||
2725 | k->ed25519_sk = ed25519_sk; | ||
2726 | ed25519_pk = ed25519_sk = NULL; | ||
2727 | break; | ||
2728 | case KEY_ED25519_CERT: | ||
2729 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | ||
2730 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2731 | (r = sshkey_add_private(k)) != 0 || | ||
2732 | (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || | ||
2733 | (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) | ||
2734 | goto out; | ||
2735 | if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { | ||
2736 | r = SSH_ERR_INVALID_FORMAT; | ||
2737 | goto out; | ||
2738 | } | ||
2739 | k->ed25519_pk = ed25519_pk; | ||
2740 | k->ed25519_sk = ed25519_sk; | ||
2741 | ed25519_pk = ed25519_sk = NULL; | ||
2742 | break; | ||
2743 | default: | ||
2744 | r = SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2745 | goto out; | ||
2746 | } | ||
2747 | #ifdef WITH_OPENSSL | ||
2748 | /* enable blinding */ | ||
2749 | switch (k->type) { | ||
2750 | case KEY_RSA: | ||
2751 | case KEY_RSA_CERT_V00: | ||
2752 | case KEY_RSA_CERT: | ||
2753 | case KEY_RSA1: | ||
2754 | if (RSA_blinding_on(k->rsa, NULL) != 1) { | ||
2755 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2756 | goto out; | ||
2757 | } | ||
2758 | break; | ||
2759 | } | ||
2760 | #endif /* WITH_OPENSSL */ | ||
2761 | /* success */ | ||
2762 | r = 0; | ||
2763 | if (kp != NULL) { | ||
2764 | *kp = k; | ||
2765 | k = NULL; | ||
2766 | } | ||
2767 | out: | ||
2768 | free(tname); | ||
2769 | free(curve); | ||
2770 | #ifdef WITH_OPENSSL | ||
2771 | if (exponent != NULL) | ||
2772 | BN_clear_free(exponent); | ||
2773 | #endif /* WITH_OPENSSL */ | ||
2774 | sshkey_free(k); | ||
2775 | if (ed25519_pk != NULL) { | ||
2776 | explicit_bzero(ed25519_pk, pklen); | ||
2777 | free(ed25519_pk); | ||
2778 | } | ||
2779 | if (ed25519_sk != NULL) { | ||
2780 | explicit_bzero(ed25519_sk, sklen); | ||
2781 | free(ed25519_sk); | ||
2782 | } | ||
2783 | return r; | ||
2784 | } | ||
2785 | |||
2786 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | ||
2787 | int | ||
2788 | sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) | ||
2789 | { | ||
2790 | BN_CTX *bnctx; | ||
2791 | EC_POINT *nq = NULL; | ||
2792 | BIGNUM *order, *x, *y, *tmp; | ||
2793 | int ret = SSH_ERR_KEY_INVALID_EC_VALUE; | ||
2794 | |||
2795 | if ((bnctx = BN_CTX_new()) == NULL) | ||
2796 | return SSH_ERR_ALLOC_FAIL; | ||
2797 | BN_CTX_start(bnctx); | ||
2798 | |||
2799 | /* | ||
2800 | * We shouldn't ever hit this case because bignum_get_ecpoint() | ||
2801 | * refuses to load GF2m points. | ||
2802 | */ | ||
2803 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != | ||
2804 | NID_X9_62_prime_field) | ||
2805 | goto out; | ||
2806 | |||
2807 | /* Q != infinity */ | ||
2808 | if (EC_POINT_is_at_infinity(group, public)) | ||
2809 | goto out; | ||
2810 | |||
2811 | if ((x = BN_CTX_get(bnctx)) == NULL || | ||
2812 | (y = BN_CTX_get(bnctx)) == NULL || | ||
2813 | (order = BN_CTX_get(bnctx)) == NULL || | ||
2814 | (tmp = BN_CTX_get(bnctx)) == NULL) { | ||
2815 | ret = SSH_ERR_ALLOC_FAIL; | ||
2816 | goto out; | ||
2817 | } | ||
2818 | |||
2819 | /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ | ||
2820 | if (EC_GROUP_get_order(group, order, bnctx) != 1 || | ||
2821 | EC_POINT_get_affine_coordinates_GFp(group, public, | ||
2822 | x, y, bnctx) != 1) { | ||
2823 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2824 | goto out; | ||
2825 | } | ||
2826 | if (BN_num_bits(x) <= BN_num_bits(order) / 2 || | ||
2827 | BN_num_bits(y) <= BN_num_bits(order) / 2) | ||
2828 | goto out; | ||
2829 | |||
2830 | /* nQ == infinity (n == order of subgroup) */ | ||
2831 | if ((nq = EC_POINT_new(group)) == NULL) { | ||
2832 | ret = SSH_ERR_ALLOC_FAIL; | ||
2833 | goto out; | ||
2834 | } | ||
2835 | if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) { | ||
2836 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2837 | goto out; | ||
2838 | } | ||
2839 | if (EC_POINT_is_at_infinity(group, nq) != 1) | ||
2840 | goto out; | ||
2841 | |||
2842 | /* x < order - 1, y < order - 1 */ | ||
2843 | if (!BN_sub(tmp, order, BN_value_one())) { | ||
2844 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2845 | goto out; | ||
2846 | } | ||
2847 | if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0) | ||
2848 | goto out; | ||
2849 | ret = 0; | ||
2850 | out: | ||
2851 | BN_CTX_free(bnctx); | ||
2852 | if (nq != NULL) | ||
2853 | EC_POINT_free(nq); | ||
2854 | return ret; | ||
2855 | } | ||
2856 | |||
2857 | int | ||
2858 | sshkey_ec_validate_private(const EC_KEY *key) | ||
2859 | { | ||
2860 | BN_CTX *bnctx; | ||
2861 | BIGNUM *order, *tmp; | ||
2862 | int ret = SSH_ERR_KEY_INVALID_EC_VALUE; | ||
2863 | |||
2864 | if ((bnctx = BN_CTX_new()) == NULL) | ||
2865 | return SSH_ERR_ALLOC_FAIL; | ||
2866 | BN_CTX_start(bnctx); | ||
2867 | |||
2868 | if ((order = BN_CTX_get(bnctx)) == NULL || | ||
2869 | (tmp = BN_CTX_get(bnctx)) == NULL) { | ||
2870 | ret = SSH_ERR_ALLOC_FAIL; | ||
2871 | goto out; | ||
2872 | } | ||
2873 | |||
2874 | /* log2(private) > log2(order)/2 */ | ||
2875 | if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) { | ||
2876 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2877 | goto out; | ||
2878 | } | ||
2879 | if (BN_num_bits(EC_KEY_get0_private_key(key)) <= | ||
2880 | BN_num_bits(order) / 2) | ||
2881 | goto out; | ||
2882 | |||
2883 | /* private < order - 1 */ | ||
2884 | if (!BN_sub(tmp, order, BN_value_one())) { | ||
2885 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2886 | goto out; | ||
2887 | } | ||
2888 | if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) | ||
2889 | goto out; | ||
2890 | ret = 0; | ||
2891 | out: | ||
2892 | BN_CTX_free(bnctx); | ||
2893 | return ret; | ||
2894 | } | ||
2895 | |||
2896 | void | ||
2897 | sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) | ||
2898 | { | ||
2899 | BIGNUM *x, *y; | ||
2900 | BN_CTX *bnctx; | ||
2901 | |||
2902 | if (point == NULL) { | ||
2903 | fputs("point=(NULL)\n", stderr); | ||
2904 | return; | ||
2905 | } | ||
2906 | if ((bnctx = BN_CTX_new()) == NULL) { | ||
2907 | fprintf(stderr, "%s: BN_CTX_new failed\n", __func__); | ||
2908 | return; | ||
2909 | } | ||
2910 | BN_CTX_start(bnctx); | ||
2911 | if ((x = BN_CTX_get(bnctx)) == NULL || | ||
2912 | (y = BN_CTX_get(bnctx)) == NULL) { | ||
2913 | fprintf(stderr, "%s: BN_CTX_get failed\n", __func__); | ||
2914 | return; | ||
2915 | } | ||
2916 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != | ||
2917 | NID_X9_62_prime_field) { | ||
2918 | fprintf(stderr, "%s: group is not a prime field\n", __func__); | ||
2919 | return; | ||
2920 | } | ||
2921 | if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, | ||
2922 | bnctx) != 1) { | ||
2923 | fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n", | ||
2924 | __func__); | ||
2925 | return; | ||
2926 | } | ||
2927 | fputs("x=", stderr); | ||
2928 | BN_print_fp(stderr, x); | ||
2929 | fputs("\ny=", stderr); | ||
2930 | BN_print_fp(stderr, y); | ||
2931 | fputs("\n", stderr); | ||
2932 | BN_CTX_free(bnctx); | ||
2933 | } | ||
2934 | |||
2935 | void | ||
2936 | sshkey_dump_ec_key(const EC_KEY *key) | ||
2937 | { | ||
2938 | const BIGNUM *exponent; | ||
2939 | |||
2940 | sshkey_dump_ec_point(EC_KEY_get0_group(key), | ||
2941 | EC_KEY_get0_public_key(key)); | ||
2942 | fputs("exponent=", stderr); | ||
2943 | if ((exponent = EC_KEY_get0_private_key(key)) == NULL) | ||
2944 | fputs("(NULL)", stderr); | ||
2945 | else | ||
2946 | BN_print_fp(stderr, EC_KEY_get0_private_key(key)); | ||
2947 | fputs("\n", stderr); | ||
2948 | } | ||
2949 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | ||
2950 | |||
2951 | static int | ||
2952 | sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, | ||
2953 | const char *passphrase, const char *comment, const char *ciphername, | ||
2954 | int rounds) | ||
2955 | { | ||
2956 | u_char *cp, *b64 = NULL, *key = NULL, *pubkeyblob = NULL; | ||
2957 | u_char salt[SALT_LEN]; | ||
2958 | size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; | ||
2959 | u_int check; | ||
2960 | int r = SSH_ERR_INTERNAL_ERROR; | ||
2961 | struct sshcipher_ctx ciphercontext; | ||
2962 | const struct sshcipher *cipher; | ||
2963 | const char *kdfname = KDFNAME; | ||
2964 | struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL; | ||
2965 | |||
2966 | memset(&ciphercontext, 0, sizeof(ciphercontext)); | ||
2967 | |||
2968 | if (rounds <= 0) | ||
2969 | rounds = DEFAULT_ROUNDS; | ||
2970 | if (passphrase == NULL || !strlen(passphrase)) { | ||
2971 | ciphername = "none"; | ||
2972 | kdfname = "none"; | ||
2973 | } else if (ciphername == NULL) | ||
2974 | ciphername = DEFAULT_CIPHERNAME; | ||
2975 | else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) { | ||
2976 | r = SSH_ERR_INVALID_ARGUMENT; | ||
2977 | goto out; | ||
2978 | } | ||
2979 | if ((cipher = cipher_by_name(ciphername)) == NULL) { | ||
2980 | r = SSH_ERR_INTERNAL_ERROR; | ||
2981 | goto out; | ||
2982 | } | ||
2983 | |||
2984 | if ((kdf = sshbuf_new()) == NULL || | ||
2985 | (encoded = sshbuf_new()) == NULL || | ||
2986 | (encrypted = sshbuf_new()) == NULL) { | ||
2987 | r = SSH_ERR_ALLOC_FAIL; | ||
2988 | goto out; | ||
2989 | } | ||
2990 | blocksize = cipher_blocksize(cipher); | ||
2991 | keylen = cipher_keylen(cipher); | ||
2992 | ivlen = cipher_ivlen(cipher); | ||
2993 | authlen = cipher_authlen(cipher); | ||
2994 | if ((key = calloc(1, keylen + ivlen)) == NULL) { | ||
2995 | r = SSH_ERR_ALLOC_FAIL; | ||
2996 | goto out; | ||
2997 | } | ||
2998 | if (strcmp(kdfname, "bcrypt") == 0) { | ||
2999 | arc4random_buf(salt, SALT_LEN); | ||
3000 | if (bcrypt_pbkdf(passphrase, strlen(passphrase), | ||
3001 | salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) { | ||
3002 | r = SSH_ERR_INVALID_ARGUMENT; | ||
3003 | goto out; | ||
3004 | } | ||
3005 | if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 || | ||
3006 | (r = sshbuf_put_u32(kdf, rounds)) != 0) | ||
3007 | goto out; | ||
3008 | } else if (strcmp(kdfname, "none") != 0) { | ||
3009 | /* Unsupported KDF type */ | ||
3010 | r = SSH_ERR_KEY_UNKNOWN_CIPHER; | ||
3011 | goto out; | ||
3012 | } | ||
3013 | if ((r = cipher_init(&ciphercontext, cipher, key, keylen, | ||
3014 | key + keylen, ivlen, 1)) != 0) | ||
3015 | goto out; | ||
3016 | |||
3017 | if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 || | ||
3018 | (r = sshbuf_put_cstring(encoded, ciphername)) != 0 || | ||
3019 | (r = sshbuf_put_cstring(encoded, kdfname)) != 0 || | ||
3020 | (r = sshbuf_put_stringb(encoded, kdf)) != 0 || | ||
3021 | (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */ | ||
3022 | (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 || | ||
3023 | (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0) | ||
3024 | goto out; | ||
3025 | |||
3026 | /* set up the buffer that will be encrypted */ | ||
3027 | |||
3028 | /* Random check bytes */ | ||
3029 | check = arc4random(); | ||
3030 | if ((r = sshbuf_put_u32(encrypted, check)) != 0 || | ||
3031 | (r = sshbuf_put_u32(encrypted, check)) != 0) | ||
3032 | goto out; | ||
3033 | |||
3034 | /* append private key and comment*/ | ||
3035 | if ((r = sshkey_private_serialize(prv, encrypted)) != 0 || | ||
3036 | (r = sshbuf_put_cstring(encrypted, comment)) != 0) | ||
3037 | goto out; | ||
3038 | |||
3039 | /* padding */ | ||
3040 | i = 0; | ||
3041 | while (sshbuf_len(encrypted) % blocksize) { | ||
3042 | if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0) | ||
3043 | goto out; | ||
3044 | } | ||
3045 | |||
3046 | /* length in destination buffer */ | ||
3047 | if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0) | ||
3048 | goto out; | ||
3049 | |||
3050 | /* encrypt */ | ||
3051 | if ((r = sshbuf_reserve(encoded, | ||
3052 | sshbuf_len(encrypted) + authlen, &cp)) != 0) | ||
3053 | goto out; | ||
3054 | if ((r = cipher_crypt(&ciphercontext, 0, cp, | ||
3055 | sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0) | ||
3056 | goto out; | ||
3057 | |||
3058 | /* uuencode */ | ||
3059 | if ((b64 = sshbuf_dtob64(encoded)) == NULL) { | ||
3060 | r = SSH_ERR_ALLOC_FAIL; | ||
3061 | goto out; | ||
3062 | } | ||
3063 | |||
3064 | sshbuf_reset(blob); | ||
3065 | if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0) | ||
3066 | goto out; | ||
3067 | for (i = 0; i < strlen(b64); i++) { | ||
3068 | if ((r = sshbuf_put_u8(blob, b64[i])) != 0) | ||
3069 | goto out; | ||
3070 | /* insert line breaks */ | ||
3071 | if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0) | ||
3072 | goto out; | ||
3073 | } | ||
3074 | if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0) | ||
3075 | goto out; | ||
3076 | if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0) | ||
3077 | goto out; | ||
3078 | |||
3079 | /* success */ | ||
3080 | r = 0; | ||
3081 | |||
3082 | out: | ||
3083 | sshbuf_free(kdf); | ||
3084 | sshbuf_free(encoded); | ||
3085 | sshbuf_free(encrypted); | ||
3086 | cipher_cleanup(&ciphercontext); | ||
3087 | explicit_bzero(salt, sizeof(salt)); | ||
3088 | if (key != NULL) { | ||
3089 | explicit_bzero(key, keylen + ivlen); | ||
3090 | free(key); | ||
3091 | } | ||
3092 | if (pubkeyblob != NULL) { | ||
3093 | explicit_bzero(pubkeyblob, pubkeylen); | ||
3094 | free(pubkeyblob); | ||
3095 | } | ||
3096 | if (b64 != NULL) { | ||
3097 | explicit_bzero(b64, strlen(b64)); | ||
3098 | free(b64); | ||
3099 | } | ||
3100 | return r; | ||
3101 | } | ||
3102 | |||
3103 | static int | ||
3104 | sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | ||
3105 | struct sshkey **keyp, char **commentp) | ||
3106 | { | ||
3107 | char *comment = NULL, *ciphername = NULL, *kdfname = NULL; | ||
3108 | const struct sshcipher *cipher = NULL; | ||
3109 | const u_char *cp; | ||
3110 | int r = SSH_ERR_INTERNAL_ERROR; | ||
3111 | size_t encoded_len; | ||
3112 | size_t i, keylen = 0, ivlen = 0, slen = 0; | ||
3113 | struct sshbuf *encoded = NULL, *decoded = NULL; | ||
3114 | struct sshbuf *kdf = NULL, *decrypted = NULL; | ||
3115 | struct sshcipher_ctx ciphercontext; | ||
3116 | struct sshkey *k = NULL; | ||
3117 | u_char *key = NULL, *salt = NULL, *dp, pad, last; | ||
3118 | u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; | ||
3119 | |||
3120 | memset(&ciphercontext, 0, sizeof(ciphercontext)); | ||
3121 | if (keyp != NULL) | ||
3122 | *keyp = NULL; | ||
3123 | if (commentp != NULL) | ||
3124 | *commentp = NULL; | ||
3125 | |||
3126 | if ((encoded = sshbuf_new()) == NULL || | ||
3127 | (decoded = sshbuf_new()) == NULL || | ||
3128 | (decrypted = sshbuf_new()) == NULL) { | ||
3129 | r = SSH_ERR_ALLOC_FAIL; | ||
3130 | goto out; | ||
3131 | } | ||
3132 | |||
3133 | /* check preamble */ | ||
3134 | cp = sshbuf_ptr(blob); | ||
3135 | encoded_len = sshbuf_len(blob); | ||
3136 | if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) || | ||
3137 | memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) { | ||
3138 | r = SSH_ERR_INVALID_FORMAT; | ||
3139 | goto out; | ||
3140 | } | ||
3141 | cp += MARK_BEGIN_LEN; | ||
3142 | encoded_len -= MARK_BEGIN_LEN; | ||
3143 | |||
3144 | /* Look for end marker, removing whitespace as we go */ | ||
3145 | while (encoded_len > 0) { | ||
3146 | if (*cp != '\n' && *cp != '\r') { | ||
3147 | if ((r = sshbuf_put_u8(encoded, *cp)) != 0) | ||
3148 | goto out; | ||
3149 | } | ||
3150 | last = *cp; | ||
3151 | encoded_len--; | ||
3152 | cp++; | ||
3153 | if (last == '\n') { | ||
3154 | if (encoded_len >= MARK_END_LEN && | ||
3155 | memcmp(cp, MARK_END, MARK_END_LEN) == 0) { | ||
3156 | /* \0 terminate */ | ||
3157 | if ((r = sshbuf_put_u8(encoded, 0)) != 0) | ||
3158 | goto out; | ||
3159 | break; | ||
3160 | } | ||
3161 | } | ||
3162 | } | ||
3163 | if (encoded_len == 0) { | ||
3164 | r = SSH_ERR_INVALID_FORMAT; | ||
3165 | goto out; | ||
3166 | } | ||
3167 | |||
3168 | /* decode base64 */ | ||
3169 | if ((r = sshbuf_b64tod(decoded, sshbuf_ptr(encoded))) != 0) | ||
3170 | goto out; | ||
3171 | |||
3172 | /* check magic */ | ||
3173 | if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) || | ||
3174 | memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { | ||
3175 | r = SSH_ERR_INVALID_FORMAT; | ||
3176 | goto out; | ||
3177 | } | ||
3178 | /* parse public portion of key */ | ||
3179 | if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 || | ||
3180 | (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 || | ||
3181 | (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 || | ||
3182 | (r = sshbuf_froms(decoded, &kdf)) != 0 || | ||
3183 | (r = sshbuf_get_u32(decoded, &nkeys)) != 0 || | ||
3184 | (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */ | ||
3185 | (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) | ||
3186 | goto out; | ||
3187 | |||
3188 | if ((cipher = cipher_by_name(ciphername)) == NULL) { | ||
3189 | r = SSH_ERR_KEY_UNKNOWN_CIPHER; | ||
3190 | goto out; | ||
3191 | } | ||
3192 | if ((passphrase == NULL || strlen(passphrase) == 0) && | ||
3193 | strcmp(ciphername, "none") != 0) { | ||
3194 | /* passphrase required */ | ||
3195 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3196 | goto out; | ||
3197 | } | ||
3198 | if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) { | ||
3199 | r = SSH_ERR_KEY_UNKNOWN_CIPHER; | ||
3200 | goto out; | ||
3201 | } | ||
3202 | if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) { | ||
3203 | r = SSH_ERR_INVALID_FORMAT; | ||
3204 | goto out; | ||
3205 | } | ||
3206 | if (nkeys != 1) { | ||
3207 | /* XXX only one key supported */ | ||
3208 | r = SSH_ERR_INVALID_FORMAT; | ||
3209 | goto out; | ||
3210 | } | ||
3211 | |||
3212 | /* check size of encrypted key blob */ | ||
3213 | blocksize = cipher_blocksize(cipher); | ||
3214 | if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) { | ||
3215 | r = SSH_ERR_INVALID_FORMAT; | ||
3216 | goto out; | ||
3217 | } | ||
3218 | |||
3219 | /* setup key */ | ||
3220 | keylen = cipher_keylen(cipher); | ||
3221 | ivlen = cipher_ivlen(cipher); | ||
3222 | if ((key = calloc(1, keylen + ivlen)) == NULL) { | ||
3223 | r = SSH_ERR_ALLOC_FAIL; | ||
3224 | goto out; | ||
3225 | } | ||
3226 | if (strcmp(kdfname, "bcrypt") == 0) { | ||
3227 | if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 || | ||
3228 | (r = sshbuf_get_u32(kdf, &rounds)) != 0) | ||
3229 | goto out; | ||
3230 | if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, | ||
3231 | key, keylen + ivlen, rounds) < 0) { | ||
3232 | r = SSH_ERR_INVALID_FORMAT; | ||
3233 | goto out; | ||
3234 | } | ||
3235 | } | ||
3236 | |||
3237 | /* decrypt private portion of key */ | ||
3238 | if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 || | ||
3239 | (r = cipher_init(&ciphercontext, cipher, key, keylen, | ||
3240 | key + keylen, ivlen, 0)) != 0) | ||
3241 | goto out; | ||
3242 | if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded), | ||
3243 | sshbuf_len(decoded), 0, cipher_authlen(cipher))) != 0) { | ||
3244 | /* an integrity error here indicates an incorrect passphrase */ | ||
3245 | if (r == SSH_ERR_MAC_INVALID) | ||
3246 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3247 | goto out; | ||
3248 | } | ||
3249 | if ((r = sshbuf_consume(decoded, encrypted_len)) != 0) | ||
3250 | goto out; | ||
3251 | /* there should be no trailing data */ | ||
3252 | if (sshbuf_len(decoded) != 0) { | ||
3253 | r = SSH_ERR_INVALID_FORMAT; | ||
3254 | goto out; | ||
3255 | } | ||
3256 | |||
3257 | /* check check bytes */ | ||
3258 | if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 || | ||
3259 | (r = sshbuf_get_u32(decrypted, &check2)) != 0) | ||
3260 | goto out; | ||
3261 | if (check1 != check2) { | ||
3262 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3263 | goto out; | ||
3264 | } | ||
3265 | |||
3266 | /* Load the private key and comment */ | ||
3267 | if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 || | ||
3268 | (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0) | ||
3269 | goto out; | ||
3270 | |||
3271 | /* Check deterministic padding */ | ||
3272 | i = 0; | ||
3273 | while (sshbuf_len(decrypted)) { | ||
3274 | if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) | ||
3275 | goto out; | ||
3276 | if (pad != (++i & 0xff)) { | ||
3277 | r = SSH_ERR_INVALID_FORMAT; | ||
3278 | goto out; | ||
3279 | } | ||
3280 | } | ||
3281 | |||
3282 | /* XXX decode pubkey and check against private */ | ||
3283 | |||
3284 | /* success */ | ||
3285 | r = 0; | ||
3286 | if (keyp != NULL) { | ||
3287 | *keyp = k; | ||
3288 | k = NULL; | ||
3289 | } | ||
3290 | if (commentp != NULL) { | ||
3291 | *commentp = comment; | ||
3292 | comment = NULL; | ||
3293 | } | ||
3294 | out: | ||
3295 | pad = 0; | ||
3296 | cipher_cleanup(&ciphercontext); | ||
3297 | free(ciphername); | ||
3298 | free(kdfname); | ||
3299 | free(comment); | ||
3300 | if (salt != NULL) { | ||
3301 | explicit_bzero(salt, slen); | ||
3302 | free(salt); | ||
3303 | } | ||
3304 | if (key != NULL) { | ||
3305 | explicit_bzero(key, keylen + ivlen); | ||
3306 | free(key); | ||
3307 | } | ||
3308 | sshbuf_free(encoded); | ||
3309 | sshbuf_free(decoded); | ||
3310 | sshbuf_free(kdf); | ||
3311 | sshbuf_free(decrypted); | ||
3312 | sshkey_free(k); | ||
3313 | return r; | ||
3314 | } | ||
3315 | |||
3316 | #if WITH_SSH1 | ||
3317 | /* | ||
3318 | * Serialises the authentication (private) key to a blob, encrypting it with | ||
3319 | * passphrase. The identification of the blob (lowest 64 bits of n) will | ||
3320 | * precede the key to provide identification of the key without needing a | ||
3321 | * passphrase. | ||
3322 | */ | ||
3323 | static int | ||
3324 | sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, | ||
3325 | const char *passphrase, const char *comment) | ||
3326 | { | ||
3327 | struct sshbuf *buffer = NULL, *encrypted = NULL; | ||
3328 | u_char buf[8]; | ||
3329 | int r, cipher_num; | ||
3330 | struct sshcipher_ctx ciphercontext; | ||
3331 | const struct sshcipher *cipher; | ||
3332 | u_char *cp; | ||
3333 | |||
3334 | /* | ||
3335 | * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting | ||
3336 | * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. | ||
3337 | */ | ||
3338 | cipher_num = (strcmp(passphrase, "") == 0) ? | ||
3339 | SSH_CIPHER_NONE : SSH_CIPHER_3DES; | ||
3340 | if ((cipher = cipher_by_number(cipher_num)) == NULL) | ||
3341 | return SSH_ERR_INTERNAL_ERROR; | ||
3342 | |||
3343 | /* This buffer is used to build the secret part of the private key. */ | ||
3344 | if ((buffer = sshbuf_new()) == NULL) | ||
3345 | return SSH_ERR_ALLOC_FAIL; | ||
3346 | |||
3347 | /* Put checkbytes for checking passphrase validity. */ | ||
3348 | if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0) | ||
3349 | goto out; | ||
3350 | arc4random_buf(cp, 2); | ||
3351 | memcpy(cp + 2, cp, 2); | ||
3352 | |||
3353 | /* | ||
3354 | * Store the private key (n and e will not be stored because they | ||
3355 | * will be stored in plain text, and storing them also in encrypted | ||
3356 | * format would just give known plaintext). | ||
3357 | * Note: q and p are stored in reverse order to SSL. | ||
3358 | */ | ||
3359 | if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 || | ||
3360 | (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 || | ||
3361 | (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 || | ||
3362 | (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0) | ||
3363 | goto out; | ||
3364 | |||
3365 | /* Pad the part to be encrypted to a size that is a multiple of 8. */ | ||
3366 | explicit_bzero(buf, 8); | ||
3367 | if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0) | ||
3368 | goto out; | ||
3369 | |||
3370 | /* This buffer will be used to contain the data in the file. */ | ||
3371 | if ((encrypted = sshbuf_new()) == NULL) { | ||
3372 | r = SSH_ERR_ALLOC_FAIL; | ||
3373 | goto out; | ||
3374 | } | ||
3375 | |||
3376 | /* First store keyfile id string. */ | ||
3377 | if ((r = sshbuf_put(encrypted, LEGACY_BEGIN, | ||
3378 | sizeof(LEGACY_BEGIN))) != 0) | ||
3379 | goto out; | ||
3380 | |||
3381 | /* Store cipher type and "reserved" field. */ | ||
3382 | if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 || | ||
3383 | (r = sshbuf_put_u32(encrypted, 0)) != 0) | ||
3384 | goto out; | ||
3385 | |||
3386 | /* Store public key. This will be in plain text. */ | ||
3387 | if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 || | ||
3388 | (r = sshbuf_put_bignum1(encrypted, key->rsa->n) != 0) || | ||
3389 | (r = sshbuf_put_bignum1(encrypted, key->rsa->e) != 0) || | ||
3390 | (r = sshbuf_put_cstring(encrypted, comment) != 0)) | ||
3391 | goto out; | ||
3392 | |||
3393 | /* Allocate space for the private part of the key in the buffer. */ | ||
3394 | if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0) | ||
3395 | goto out; | ||
3396 | |||
3397 | if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, | ||
3398 | CIPHER_ENCRYPT)) != 0) | ||
3399 | goto out; | ||
3400 | if ((r = cipher_crypt(&ciphercontext, 0, cp, | ||
3401 | sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0) | ||
3402 | goto out; | ||
3403 | if ((r = cipher_cleanup(&ciphercontext)) != 0) | ||
3404 | goto out; | ||
3405 | |||
3406 | r = sshbuf_putb(blob, encrypted); | ||
3407 | |||
3408 | out: | ||
3409 | explicit_bzero(&ciphercontext, sizeof(ciphercontext)); | ||
3410 | explicit_bzero(buf, sizeof(buf)); | ||
3411 | if (buffer != NULL) | ||
3412 | sshbuf_free(buffer); | ||
3413 | if (encrypted != NULL) | ||
3414 | sshbuf_free(encrypted); | ||
3415 | |||
3416 | return r; | ||
3417 | } | ||
3418 | #endif /* WITH_SSH1 */ | ||
3419 | |||
3420 | #ifdef WITH_OPENSSL | ||
3421 | /* convert SSH v2 key in OpenSSL PEM format */ | ||
3422 | static int | ||
3423 | sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, | ||
3424 | const char *_passphrase, const char *comment) | ||
3425 | { | ||
3426 | int success, r; | ||
3427 | int blen, len = strlen(_passphrase); | ||
3428 | u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; | ||
3429 | #if (OPENSSL_VERSION_NUMBER < 0x00907000L) | ||
3430 | const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; | ||
3431 | #else | ||
3432 | const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; | ||
3433 | #endif | ||
3434 | const u_char *bptr; | ||
3435 | BIO *bio = NULL; | ||
3436 | |||
3437 | if (len > 0 && len <= 4) | ||
3438 | return SSH_ERR_PASSPHRASE_TOO_SHORT; | ||
3439 | if ((bio = BIO_new(BIO_s_mem())) == NULL) | ||
3440 | return SSH_ERR_ALLOC_FAIL; | ||
3441 | |||
3442 | switch (key->type) { | ||
3443 | case KEY_DSA: | ||
3444 | success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, | ||
3445 | cipher, passphrase, len, NULL, NULL); | ||
3446 | break; | ||
3447 | #ifdef OPENSSL_HAS_ECC | ||
3448 | case KEY_ECDSA: | ||
3449 | success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, | ||
3450 | cipher, passphrase, len, NULL, NULL); | ||
3451 | break; | ||
3452 | #endif | ||
3453 | case KEY_RSA: | ||
3454 | success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, | ||
3455 | cipher, passphrase, len, NULL, NULL); | ||
3456 | break; | ||
3457 | default: | ||
3458 | success = 0; | ||
3459 | break; | ||
3460 | } | ||
3461 | if (success == 0) { | ||
3462 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3463 | goto out; | ||
3464 | } | ||
3465 | if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { | ||
3466 | r = SSH_ERR_INTERNAL_ERROR; | ||
3467 | goto out; | ||
3468 | } | ||
3469 | if ((r = sshbuf_put(blob, bptr, blen)) != 0) | ||
3470 | goto out; | ||
3471 | r = 0; | ||
3472 | out: | ||
3473 | BIO_free(bio); | ||
3474 | return r; | ||
3475 | } | ||
3476 | #endif /* WITH_OPENSSL */ | ||
3477 | |||
3478 | /* Serialise "key" to buffer "blob" */ | ||
3479 | int | ||
3480 | sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | ||
3481 | const char *passphrase, const char *comment, | ||
3482 | int force_new_format, const char *new_format_cipher, int new_format_rounds) | ||
3483 | { | ||
3484 | switch (key->type) { | ||
3485 | #ifdef WITH_OPENSSL | ||
3486 | case KEY_RSA1: | ||
3487 | return sshkey_private_rsa1_to_blob(key, blob, | ||
3488 | passphrase, comment); | ||
3489 | case KEY_DSA: | ||
3490 | case KEY_ECDSA: | ||
3491 | case KEY_RSA: | ||
3492 | if (force_new_format) { | ||
3493 | return sshkey_private_to_blob2(key, blob, passphrase, | ||
3494 | comment, new_format_cipher, new_format_rounds); | ||
3495 | } | ||
3496 | return sshkey_private_pem_to_blob(key, blob, | ||
3497 | passphrase, comment); | ||
3498 | #endif /* WITH_OPENSSL */ | ||
3499 | case KEY_ED25519: | ||
3500 | return sshkey_private_to_blob2(key, blob, passphrase, | ||
3501 | comment, new_format_cipher, new_format_rounds); | ||
3502 | default: | ||
3503 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
3504 | } | ||
3505 | } | ||
3506 | |||
3507 | #ifdef WITH_SSH1 | ||
3508 | /* | ||
3509 | * Parse the public, unencrypted portion of a RSA1 key. | ||
3510 | */ | ||
3511 | int | ||
3512 | sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, | ||
3513 | struct sshkey **keyp, char **commentp) | ||
3514 | { | ||
3515 | int r; | ||
3516 | struct sshkey *pub = NULL; | ||
3517 | struct sshbuf *copy = NULL; | ||
3518 | |||
3519 | if (keyp != NULL) | ||
3520 | *keyp = NULL; | ||
3521 | if (commentp != NULL) | ||
3522 | *commentp = NULL; | ||
3523 | |||
3524 | /* Check that it is at least big enough to contain the ID string. */ | ||
3525 | if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) | ||
3526 | return SSH_ERR_INVALID_FORMAT; | ||
3527 | |||
3528 | /* | ||
3529 | * Make sure it begins with the id string. Consume the id string | ||
3530 | * from the buffer. | ||
3531 | */ | ||
3532 | if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) | ||
3533 | return SSH_ERR_INVALID_FORMAT; | ||
3534 | /* Make a working copy of the keyblob and skip past the magic */ | ||
3535 | if ((copy = sshbuf_fromb(blob)) == NULL) | ||
3536 | return SSH_ERR_ALLOC_FAIL; | ||
3537 | if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) | ||
3538 | goto out; | ||
3539 | |||
3540 | /* Skip cipher type, reserved data and key bits. */ | ||
3541 | if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */ | ||
3542 | (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */ | ||
3543 | (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */ | ||
3544 | goto out; | ||
3545 | |||
3546 | /* Read the public key from the buffer. */ | ||
3547 | if ((pub = sshkey_new(KEY_RSA1)) == NULL || | ||
3548 | (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 || | ||
3549 | (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0) | ||
3550 | goto out; | ||
3551 | |||
3552 | /* Finally, the comment */ | ||
3553 | if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0) | ||
3554 | goto out; | ||
3555 | |||
3556 | /* The encrypted private part is not parsed by this function. */ | ||
3557 | |||
3558 | r = 0; | ||
3559 | if (keyp != NULL) | ||
3560 | *keyp = pub; | ||
3561 | else | ||
3562 | sshkey_free(pub); | ||
3563 | pub = NULL; | ||
3564 | |||
3565 | out: | ||
3566 | if (copy != NULL) | ||
3567 | sshbuf_free(copy); | ||
3568 | if (pub != NULL) | ||
3569 | sshkey_free(pub); | ||
3570 | return r; | ||
3571 | } | ||
3572 | |||
3573 | static int | ||
3574 | sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, | ||
3575 | struct sshkey **keyp, char **commentp) | ||
3576 | { | ||
3577 | int r; | ||
3578 | u_int16_t check1, check2; | ||
3579 | u_int8_t cipher_type; | ||
3580 | struct sshbuf *decrypted = NULL, *copy = NULL; | ||
3581 | u_char *cp; | ||
3582 | char *comment = NULL; | ||
3583 | struct sshcipher_ctx ciphercontext; | ||
3584 | const struct sshcipher *cipher; | ||
3585 | struct sshkey *prv = NULL; | ||
3586 | |||
3587 | *keyp = NULL; | ||
3588 | if (commentp != NULL) | ||
3589 | *commentp = NULL; | ||
3590 | |||
3591 | /* Check that it is at least big enough to contain the ID string. */ | ||
3592 | if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) | ||
3593 | return SSH_ERR_INVALID_FORMAT; | ||
3594 | |||
3595 | /* | ||
3596 | * Make sure it begins with the id string. Consume the id string | ||
3597 | * from the buffer. | ||
3598 | */ | ||
3599 | if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) | ||
3600 | return SSH_ERR_INVALID_FORMAT; | ||
3601 | |||
3602 | if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) { | ||
3603 | r = SSH_ERR_ALLOC_FAIL; | ||
3604 | goto out; | ||
3605 | } | ||
3606 | if ((copy = sshbuf_fromb(blob)) == NULL || | ||
3607 | (decrypted = sshbuf_new()) == NULL) { | ||
3608 | r = SSH_ERR_ALLOC_FAIL; | ||
3609 | goto out; | ||
3610 | } | ||
3611 | if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) | ||
3612 | goto out; | ||
3613 | |||
3614 | /* Read cipher type. */ | ||
3615 | if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 || | ||
3616 | (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */ | ||
3617 | goto out; | ||
3618 | |||
3619 | /* Read the public key and comment from the buffer. */ | ||
3620 | if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */ | ||
3621 | (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 || | ||
3622 | (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 || | ||
3623 | (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0) | ||
3624 | goto out; | ||
3625 | |||
3626 | /* Check that it is a supported cipher. */ | ||
3627 | cipher = cipher_by_number(cipher_type); | ||
3628 | if (cipher == NULL) { | ||
3629 | r = SSH_ERR_KEY_UNKNOWN_CIPHER; | ||
3630 | goto out; | ||
3631 | } | ||
3632 | /* Initialize space for decrypted data. */ | ||
3633 | if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0) | ||
3634 | goto out; | ||
3635 | |||
3636 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ | ||
3637 | if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, | ||
3638 | CIPHER_DECRYPT)) != 0) | ||
3639 | goto out; | ||
3640 | if ((r = cipher_crypt(&ciphercontext, 0, cp, | ||
3641 | sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) { | ||
3642 | cipher_cleanup(&ciphercontext); | ||
3643 | goto out; | ||
3644 | } | ||
3645 | if ((r = cipher_cleanup(&ciphercontext)) != 0) | ||
3646 | goto out; | ||
3647 | |||
3648 | if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 || | ||
3649 | (r = sshbuf_get_u16(decrypted, &check2)) != 0) | ||
3650 | goto out; | ||
3651 | if (check1 != check2) { | ||
3652 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3653 | goto out; | ||
3654 | } | ||
3655 | |||
3656 | /* Read the rest of the private key. */ | ||
3657 | if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 || | ||
3658 | (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 || | ||
3659 | (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 || | ||
3660 | (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0) | ||
3661 | goto out; | ||
3662 | |||
3663 | /* calculate p-1 and q-1 */ | ||
3664 | if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0) | ||
3665 | goto out; | ||
3666 | |||
3667 | /* enable blinding */ | ||
3668 | if (RSA_blinding_on(prv->rsa, NULL) != 1) { | ||
3669 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3670 | goto out; | ||
3671 | } | ||
3672 | r = 0; | ||
3673 | *keyp = prv; | ||
3674 | prv = NULL; | ||
3675 | if (commentp != NULL) { | ||
3676 | *commentp = comment; | ||
3677 | comment = NULL; | ||
3678 | } | ||
3679 | out: | ||
3680 | explicit_bzero(&ciphercontext, sizeof(ciphercontext)); | ||
3681 | if (comment != NULL) | ||
3682 | free(comment); | ||
3683 | if (prv != NULL) | ||
3684 | sshkey_free(prv); | ||
3685 | if (copy != NULL) | ||
3686 | sshbuf_free(copy); | ||
3687 | if (decrypted != NULL) | ||
3688 | sshbuf_free(decrypted); | ||
3689 | return r; | ||
3690 | } | ||
3691 | #endif /* WITH_SSH1 */ | ||
3692 | |||
3693 | #ifdef WITH_OPENSSL | ||
3694 | /* XXX make private once ssh-keysign.c fixed */ | ||
3695 | int | ||
3696 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | ||
3697 | const char *passphrase, struct sshkey **keyp, char **commentp) | ||
3698 | { | ||
3699 | EVP_PKEY *pk = NULL; | ||
3700 | struct sshkey *prv = NULL; | ||
3701 | char *name = "<no key>"; | ||
3702 | BIO *bio = NULL; | ||
3703 | int r; | ||
3704 | |||
3705 | *keyp = NULL; | ||
3706 | if (commentp != NULL) | ||
3707 | *commentp = NULL; | ||
3708 | |||
3709 | if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) | ||
3710 | return SSH_ERR_ALLOC_FAIL; | ||
3711 | if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) != | ||
3712 | (int)sshbuf_len(blob)) { | ||
3713 | r = SSH_ERR_ALLOC_FAIL; | ||
3714 | goto out; | ||
3715 | } | ||
3716 | |||
3717 | if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, | ||
3718 | (char *)passphrase)) == NULL) { | ||
3719 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3720 | goto out; | ||
3721 | } | ||
3722 | if (pk->type == EVP_PKEY_RSA && | ||
3723 | (type == KEY_UNSPEC || type == KEY_RSA)) { | ||
3724 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { | ||
3725 | r = SSH_ERR_ALLOC_FAIL; | ||
3726 | goto out; | ||
3727 | } | ||
3728 | prv->rsa = EVP_PKEY_get1_RSA(pk); | ||
3729 | prv->type = KEY_RSA; | ||
3730 | name = "rsa w/o comment"; | ||
3731 | #ifdef DEBUG_PK | ||
3732 | RSA_print_fp(stderr, prv->rsa, 8); | ||
3733 | #endif | ||
3734 | if (RSA_blinding_on(prv->rsa, NULL) != 1) { | ||
3735 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3736 | goto out; | ||
3737 | } | ||
3738 | } else if (pk->type == EVP_PKEY_DSA && | ||
3739 | (type == KEY_UNSPEC || type == KEY_DSA)) { | ||
3740 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { | ||
3741 | r = SSH_ERR_ALLOC_FAIL; | ||
3742 | goto out; | ||
3743 | } | ||
3744 | prv->dsa = EVP_PKEY_get1_DSA(pk); | ||
3745 | prv->type = KEY_DSA; | ||
3746 | name = "dsa w/o comment"; | ||
3747 | #ifdef DEBUG_PK | ||
3748 | DSA_print_fp(stderr, prv->dsa, 8); | ||
3749 | #endif | ||
3750 | #ifdef OPENSSL_HAS_ECC | ||
3751 | } else if (pk->type == EVP_PKEY_EC && | ||
3752 | (type == KEY_UNSPEC || type == KEY_ECDSA)) { | ||
3753 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { | ||
3754 | r = SSH_ERR_ALLOC_FAIL; | ||
3755 | goto out; | ||
3756 | } | ||
3757 | prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); | ||
3758 | prv->type = KEY_ECDSA; | ||
3759 | prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa); | ||
3760 | if (prv->ecdsa_nid == -1 || | ||
3761 | sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || | ||
3762 | sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), | ||
3763 | EC_KEY_get0_public_key(prv->ecdsa)) != 0 || | ||
3764 | sshkey_ec_validate_private(prv->ecdsa) != 0) { | ||
3765 | r = SSH_ERR_INVALID_FORMAT; | ||
3766 | goto out; | ||
3767 | } | ||
3768 | name = "ecdsa w/o comment"; | ||
3769 | # ifdef DEBUG_PK | ||
3770 | if (prv != NULL && prv->ecdsa != NULL) | ||
3771 | sshkey_dump_ec_key(prv->ecdsa); | ||
3772 | # endif | ||
3773 | #endif /* OPENSSL_HAS_ECC */ | ||
3774 | } else { | ||
3775 | r = SSH_ERR_INVALID_FORMAT; | ||
3776 | goto out; | ||
3777 | } | ||
3778 | if (commentp != NULL && | ||
3779 | (*commentp = strdup(name)) == NULL) { | ||
3780 | r = SSH_ERR_ALLOC_FAIL; | ||
3781 | goto out; | ||
3782 | } | ||
3783 | r = 0; | ||
3784 | *keyp = prv; | ||
3785 | prv = NULL; | ||
3786 | out: | ||
3787 | BIO_free(bio); | ||
3788 | if (pk != NULL) | ||
3789 | EVP_PKEY_free(pk); | ||
3790 | if (prv != NULL) | ||
3791 | sshkey_free(prv); | ||
3792 | return r; | ||
3793 | } | ||
3794 | #endif /* WITH_OPENSSL */ | ||
3795 | |||
3796 | int | ||
3797 | sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, | ||
3798 | const char *passphrase, struct sshkey **keyp, char **commentp) | ||
3799 | { | ||
3800 | int r; | ||
3801 | |||
3802 | *keyp = NULL; | ||
3803 | if (commentp != NULL) | ||
3804 | *commentp = NULL; | ||
3805 | |||
3806 | switch (type) { | ||
3807 | #ifdef WITH_OPENSSL | ||
3808 | case KEY_RSA1: | ||
3809 | return sshkey_parse_private_rsa1(blob, passphrase, | ||
3810 | keyp, commentp); | ||
3811 | case KEY_DSA: | ||
3812 | case KEY_ECDSA: | ||
3813 | case KEY_RSA: | ||
3814 | return sshkey_parse_private_pem_fileblob(blob, type, passphrase, | ||
3815 | keyp, commentp); | ||
3816 | #endif /* WITH_OPENSSL */ | ||
3817 | case KEY_ED25519: | ||
3818 | return sshkey_parse_private2(blob, type, passphrase, | ||
3819 | keyp, commentp); | ||
3820 | case KEY_UNSPEC: | ||
3821 | if ((r = sshkey_parse_private2(blob, type, passphrase, keyp, | ||
3822 | commentp)) == 0) | ||
3823 | return 0; | ||
3824 | #ifdef WITH_OPENSSL | ||
3825 | return sshkey_parse_private_pem_fileblob(blob, type, passphrase, | ||
3826 | keyp, commentp); | ||
3827 | #else | ||
3828 | return SSH_ERR_INVALID_FORMAT; | ||
3829 | #endif /* WITH_OPENSSL */ | ||
3830 | default: | ||
3831 | return SSH_ERR_KEY_TYPE_UNKNOWN; | ||
3832 | } | ||
3833 | } | ||
3834 | |||
3835 | int | ||
3836 | sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, | ||
3837 | const char *filename, struct sshkey **keyp, char **commentp) | ||
3838 | { | ||
3839 | int r; | ||
3840 | |||
3841 | if (keyp != NULL) | ||
3842 | *keyp = NULL; | ||
3843 | if (commentp != NULL) | ||
3844 | *commentp = NULL; | ||
3845 | |||
3846 | #ifdef WITH_SSH1 | ||
3847 | /* it's a SSH v1 key if the public key part is readable */ | ||
3848 | if ((r = sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL)) == 0) { | ||
3849 | return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1, | ||
3850 | passphrase, keyp, commentp); | ||
3851 | } | ||
3852 | #endif /* WITH_SSH1 */ | ||
3853 | if ((r = sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, | ||
3854 | passphrase, keyp, commentp)) == 0) | ||
3855 | return 0; | ||
3856 | return r; | ||
3857 | } | ||
diff --git a/sshkey.h b/sshkey.h new file mode 100644 index 000000000..b573e7f33 --- /dev/null +++ b/sshkey.h | |||
@@ -0,0 +1,233 @@ | |||
1 | /* $OpenBSD: sshkey.h,v 1.1 2014/06/24 01:16:58 djm Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * 1. Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | #ifndef SSHKEY_H | ||
27 | #define SSHKEY_H | ||
28 | |||
29 | #include <sys/types.h> | ||
30 | |||
31 | #ifdef WITH_OPENSSL | ||
32 | #include <openssl/rsa.h> | ||
33 | #include <openssl/dsa.h> | ||
34 | # ifdef OPENSSL_HAS_ECC | ||
35 | # include <openssl/ec.h> | ||
36 | # else /* OPENSSL_HAS_ECC */ | ||
37 | # define EC_KEY void | ||
38 | # define EC_GROUP void | ||
39 | # define EC_POINT void | ||
40 | # endif /* OPENSSL_HAS_ECC */ | ||
41 | #else /* WITH_OPENSSL */ | ||
42 | # define RSA void | ||
43 | # define DSA void | ||
44 | # define EC_KEY void | ||
45 | # define EC_GROUP void | ||
46 | # define EC_POINT void | ||
47 | #endif /* WITH_OPENSSL */ | ||
48 | |||
49 | #define SSH_RSA_MINIMUM_MODULUS_SIZE 768 | ||
50 | #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) | ||
51 | |||
52 | struct sshbuf; | ||
53 | |||
54 | /* Key types */ | ||
55 | enum sshkey_types { | ||
56 | KEY_RSA1, | ||
57 | KEY_RSA, | ||
58 | KEY_DSA, | ||
59 | KEY_ECDSA, | ||
60 | KEY_ED25519, | ||
61 | KEY_RSA_CERT, | ||
62 | KEY_DSA_CERT, | ||
63 | KEY_ECDSA_CERT, | ||
64 | KEY_ED25519_CERT, | ||
65 | KEY_RSA_CERT_V00, | ||
66 | KEY_DSA_CERT_V00, | ||
67 | KEY_NULL, | ||
68 | KEY_UNSPEC | ||
69 | }; | ||
70 | |||
71 | /* Fingerprint hash algorithms */ | ||
72 | enum sshkey_fp_type { | ||
73 | SSH_FP_SHA1, | ||
74 | SSH_FP_MD5, | ||
75 | SSH_FP_SHA256 | ||
76 | }; | ||
77 | |||
78 | /* Fingerprint representation formats */ | ||
79 | enum sshkey_fp_rep { | ||
80 | SSH_FP_HEX, | ||
81 | SSH_FP_BUBBLEBABBLE, | ||
82 | SSH_FP_RANDOMART | ||
83 | }; | ||
84 | |||
85 | /* key is stored in external hardware */ | ||
86 | #define SSHKEY_FLAG_EXT 0x0001 | ||
87 | |||
88 | #define SSHKEY_CERT_MAX_PRINCIPALS 256 | ||
89 | /* XXX opaquify? */ | ||
90 | struct sshkey_cert { | ||
91 | struct sshbuf *certblob; /* Kept around for use on wire */ | ||
92 | u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ | ||
93 | u_int64_t serial; | ||
94 | char *key_id; | ||
95 | u_int nprincipals; | ||
96 | char **principals; | ||
97 | u_int64_t valid_after, valid_before; | ||
98 | struct sshbuf *critical; | ||
99 | struct sshbuf *extensions; | ||
100 | struct sshkey *signature_key; | ||
101 | }; | ||
102 | |||
103 | /* XXX opaquify? */ | ||
104 | struct sshkey { | ||
105 | int type; | ||
106 | int flags; | ||
107 | RSA *rsa; | ||
108 | DSA *dsa; | ||
109 | int ecdsa_nid; /* NID of curve */ | ||
110 | EC_KEY *ecdsa; | ||
111 | u_char *ed25519_sk; | ||
112 | u_char *ed25519_pk; | ||
113 | struct sshkey_cert *cert; | ||
114 | }; | ||
115 | |||
116 | #define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES | ||
117 | #define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES | ||
118 | |||
119 | struct sshkey *sshkey_new(int); | ||
120 | int sshkey_add_private(struct sshkey *); | ||
121 | struct sshkey *sshkey_new_private(int); | ||
122 | void sshkey_free(struct sshkey *); | ||
123 | int sshkey_demote(const struct sshkey *, struct sshkey **); | ||
124 | int sshkey_equal_public(const struct sshkey *, | ||
125 | const struct sshkey *); | ||
126 | int sshkey_equal(const struct sshkey *, const struct sshkey *); | ||
127 | char *sshkey_fingerprint(const struct sshkey *, | ||
128 | enum sshkey_fp_type, enum sshkey_fp_rep); | ||
129 | int sshkey_fingerprint_raw(const struct sshkey *k, | ||
130 | enum sshkey_fp_type dgst_type, u_char **retp, size_t *lenp); | ||
131 | const char *sshkey_type(const struct sshkey *); | ||
132 | const char *sshkey_cert_type(const struct sshkey *); | ||
133 | int sshkey_write(const struct sshkey *, FILE *); | ||
134 | int sshkey_read(struct sshkey *, char **); | ||
135 | u_int sshkey_size(const struct sshkey *); | ||
136 | |||
137 | int sshkey_generate(int type, u_int bits, struct sshkey **keyp); | ||
138 | int sshkey_from_private(const struct sshkey *, struct sshkey **); | ||
139 | int sshkey_type_from_name(const char *); | ||
140 | int sshkey_is_cert(const struct sshkey *); | ||
141 | int sshkey_type_is_cert(int); | ||
142 | int sshkey_type_plain(int); | ||
143 | int sshkey_to_certified(struct sshkey *, int); | ||
144 | int sshkey_drop_cert(struct sshkey *); | ||
145 | int sshkey_certify(struct sshkey *, struct sshkey *); | ||
146 | int sshkey_cert_copy(const struct sshkey *, struct sshkey *); | ||
147 | int sshkey_cert_check_authority(const struct sshkey *, int, int, | ||
148 | const char *, const char **); | ||
149 | int sshkey_cert_is_legacy(const struct sshkey *); | ||
150 | |||
151 | int sshkey_ecdsa_nid_from_name(const char *); | ||
152 | int sshkey_curve_name_to_nid(const char *); | ||
153 | const char * sshkey_curve_nid_to_name(int); | ||
154 | u_int sshkey_curve_nid_to_bits(int); | ||
155 | int sshkey_ecdsa_bits_to_nid(int); | ||
156 | int sshkey_ecdsa_key_to_nid(EC_KEY *); | ||
157 | int sshkey_ec_nid_to_hash_alg(int nid); | ||
158 | int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *); | ||
159 | int sshkey_ec_validate_private(const EC_KEY *); | ||
160 | const char *sshkey_ssh_name(const struct sshkey *); | ||
161 | const char *sshkey_ssh_name_plain(const struct sshkey *); | ||
162 | int sshkey_names_valid2(const char *); | ||
163 | char *key_alg_list(int, int); | ||
164 | |||
165 | int sshkey_from_blob(const u_char *, size_t, struct sshkey **); | ||
166 | int sshkey_to_blob_buf(const struct sshkey *, struct sshbuf *); | ||
167 | int sshkey_to_blob(const struct sshkey *, u_char **, size_t *); | ||
168 | int sshkey_plain_to_blob_buf(const struct sshkey *, struct sshbuf *); | ||
169 | int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); | ||
170 | |||
171 | int sshkey_sign(const struct sshkey *, u_char **, size_t *, | ||
172 | const u_char *, size_t, u_int); | ||
173 | int sshkey_verify(const struct sshkey *, const u_char *, size_t, | ||
174 | const u_char *, size_t, u_int); | ||
175 | |||
176 | /* for debug */ | ||
177 | void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *); | ||
178 | void sshkey_dump_ec_key(const EC_KEY *); | ||
179 | |||
180 | /* private key parsing and serialisation */ | ||
181 | int sshkey_private_serialize(const struct sshkey *key, struct sshbuf *buf); | ||
182 | int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp); | ||
183 | |||
184 | /* private key file format parsing and serialisation */ | ||
185 | int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | ||
186 | const char *passphrase, const char *comment, | ||
187 | int force_new_format, const char *new_format_cipher, int new_format_rounds); | ||
188 | int sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, | ||
189 | struct sshkey **keyp, char **commentp); | ||
190 | int sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | ||
191 | const char *passphrase, struct sshkey **keyp, char **commentp); | ||
192 | int sshkey_parse_private_fileblob(struct sshbuf *buffer, | ||
193 | const char *passphrase, const char *filename, struct sshkey **keyp, | ||
194 | char **commentp); | ||
195 | int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, | ||
196 | const char *passphrase, struct sshkey **keyp, char **commentp); | ||
197 | |||
198 | #ifdef SSHKEY_INTERNAL | ||
199 | int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | ||
200 | const u_char *data, size_t datalen, u_int compat); | ||
201 | int ssh_rsa_verify(const struct sshkey *key, | ||
202 | const u_char *signature, size_t signaturelen, | ||
203 | const u_char *data, size_t datalen, u_int compat); | ||
204 | int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | ||
205 | const u_char *data, size_t datalen, u_int compat); | ||
206 | int ssh_dss_verify(const struct sshkey *key, | ||
207 | const u_char *signature, size_t signaturelen, | ||
208 | const u_char *data, size_t datalen, u_int compat); | ||
209 | int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | ||
210 | const u_char *data, size_t datalen, u_int compat); | ||
211 | int ssh_ecdsa_verify(const struct sshkey *key, | ||
212 | const u_char *signature, size_t signaturelen, | ||
213 | const u_char *data, size_t datalen, u_int compat); | ||
214 | int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | ||
215 | const u_char *data, size_t datalen, u_int compat); | ||
216 | int ssh_ed25519_verify(const struct sshkey *key, | ||
217 | const u_char *signature, size_t signaturelen, | ||
218 | const u_char *data, size_t datalen, u_int compat); | ||
219 | #endif | ||
220 | |||
221 | #if !defined(WITH_OPENSSL) | ||
222 | # undef RSA | ||
223 | # undef DSA | ||
224 | # undef EC_KEY | ||
225 | # undef EC_GROUP | ||
226 | # undef EC_POINT | ||
227 | #elif !defined(OPENSSL_HAS_ECC) | ||
228 | # undef EC_KEY | ||
229 | # undef EC_GROUP | ||
230 | # undef EC_POINT | ||
231 | #endif | ||
232 | |||
233 | #endif /* SSHKEY_H */ | ||
diff --git a/sshlogin.c b/sshlogin.c index e79ca9b47..7b951c844 100644 --- a/sshlogin.c +++ b/sshlogin.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshlogin.c,v 1.28 2014/01/31 16:39:19 tedu Exp $ */ | 1 | /* $OpenBSD: sshlogin.c,v 1.29 2014/07/15 15:54:14 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -58,6 +58,7 @@ | |||
58 | #include "loginrec.h" | 58 | #include "loginrec.h" |
59 | #include "log.h" | 59 | #include "log.h" |
60 | #include "buffer.h" | 60 | #include "buffer.h" |
61 | #include "misc.h" | ||
61 | #include "servconf.h" | 62 | #include "servconf.h" |
62 | 63 | ||
63 | extern Buffer loginmsg; | 64 | extern Buffer loginmsg; |
@@ -99,9 +99,6 @@ void | |||
99 | pty_make_controlling_tty(int *ttyfd, const char *tty) | 99 | pty_make_controlling_tty(int *ttyfd, const char *tty) |
100 | { | 100 | { |
101 | int fd; | 101 | int fd; |
102 | #ifdef USE_VHANGUP | ||
103 | void *old; | ||
104 | #endif /* USE_VHANGUP */ | ||
105 | 102 | ||
106 | #ifdef _UNICOS | 103 | #ifdef _UNICOS |
107 | if (setsid() < 0) | 104 | if (setsid() < 0) |
@@ -157,21 +154,11 @@ pty_make_controlling_tty(int *ttyfd, const char *tty) | |||
157 | if (setpgrp(0,0) < 0) | 154 | if (setpgrp(0,0) < 0) |
158 | error("SETPGRP %s",strerror(errno)); | 155 | error("SETPGRP %s",strerror(errno)); |
159 | #endif /* NEED_SETPGRP */ | 156 | #endif /* NEED_SETPGRP */ |
160 | #ifdef USE_VHANGUP | ||
161 | old = signal(SIGHUP, SIG_IGN); | ||
162 | vhangup(); | ||
163 | signal(SIGHUP, old); | ||
164 | #endif /* USE_VHANGUP */ | ||
165 | fd = open(tty, O_RDWR); | 157 | fd = open(tty, O_RDWR); |
166 | if (fd < 0) { | 158 | if (fd < 0) { |
167 | error("%.100s: %.100s", tty, strerror(errno)); | 159 | error("%.100s: %.100s", tty, strerror(errno)); |
168 | } else { | 160 | } else { |
169 | #ifdef USE_VHANGUP | ||
170 | close(*ttyfd); | ||
171 | *ttyfd = fd; | ||
172 | #else /* USE_VHANGUP */ | ||
173 | close(fd); | 161 | close(fd); |
174 | #endif /* USE_VHANGUP */ | ||
175 | } | 162 | } |
176 | /* Verify that we now have a controlling tty. */ | 163 | /* Verify that we now have a controlling tty. */ |
177 | fd = open(_PATH_TTY, O_WRONLY); | 164 | fd = open(_PATH_TTY, O_WRONLY); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: umac.c,v 1.8 2013/11/08 00:39:15 djm Exp $ */ | 1 | /* $OpenBSD: umac.c,v 1.11 2014/07/22 07:13:42 guenther Exp $ */ |
2 | /* ----------------------------------------------------------------------- | 2 | /* ----------------------------------------------------------------------- |
3 | * | 3 | * |
4 | * umac.c -- C Implementation UMAC Message Authentication | 4 | * umac.c -- C Implementation UMAC Message Authentication |
@@ -73,13 +73,15 @@ | |||
73 | 73 | ||
74 | #include "includes.h" | 74 | #include "includes.h" |
75 | #include <sys/types.h> | 75 | #include <sys/types.h> |
76 | |||
77 | #include "xmalloc.h" | ||
78 | #include "umac.h" | ||
79 | #include <string.h> | 76 | #include <string.h> |
77 | #include <stdio.h> | ||
80 | #include <stdlib.h> | 78 | #include <stdlib.h> |
81 | #include <stddef.h> | 79 | #include <stddef.h> |
82 | 80 | ||
81 | #include "xmalloc.h" | ||
82 | #include "umac.h" | ||
83 | #include "misc.h" | ||
84 | |||
83 | /* ---------------------------------------------------------------------- */ | 85 | /* ---------------------------------------------------------------------- */ |
84 | /* --- Primitive Data Types --- */ | 86 | /* --- Primitive Data Types --- */ |
85 | /* ---------------------------------------------------------------------- */ | 87 | /* ---------------------------------------------------------------------- */ |
@@ -131,41 +133,17 @@ typedef unsigned int UWORD; /* Register */ | |||
131 | /* --- Endian Conversion --- Forcing assembly on some platforms */ | 133 | /* --- Endian Conversion --- Forcing assembly on some platforms */ |
132 | /* ---------------------------------------------------------------------- */ | 134 | /* ---------------------------------------------------------------------- */ |
133 | 135 | ||
134 | #if HAVE_SWAP32 | ||
135 | #define LOAD_UINT32_REVERSED(p) (swap32(*(const UINT32 *)(p))) | ||
136 | #define STORE_UINT32_REVERSED(p,v) (*(UINT32 *)(p) = swap32(v)) | ||
137 | #else /* HAVE_SWAP32 */ | ||
138 | |||
139 | static UINT32 LOAD_UINT32_REVERSED(const void *ptr) | ||
140 | { | ||
141 | UINT32 temp = *(const UINT32 *)ptr; | ||
142 | temp = (temp >> 24) | ((temp & 0x00FF0000) >> 8 ) | ||
143 | | ((temp & 0x0000FF00) << 8 ) | (temp << 24); | ||
144 | return (UINT32)temp; | ||
145 | } | ||
146 | |||
147 | # if (__LITTLE_ENDIAN__) | ||
148 | static void STORE_UINT32_REVERSED(void *ptr, UINT32 x) | ||
149 | { | ||
150 | UINT32 i = (UINT32)x; | ||
151 | *(UINT32 *)ptr = (i >> 24) | ((i & 0x00FF0000) >> 8 ) | ||
152 | | ((i & 0x0000FF00) << 8 ) | (i << 24); | ||
153 | } | ||
154 | # endif /* __LITTLE_ENDIAN */ | ||
155 | #endif /* HAVE_SWAP32 */ | ||
156 | |||
157 | /* The following definitions use the above reversal-primitives to do the right | ||
158 | * thing on endian specific load and stores. | ||
159 | */ | ||
160 | |||
161 | #if (__LITTLE_ENDIAN__) | 136 | #if (__LITTLE_ENDIAN__) |
162 | #define LOAD_UINT32_LITTLE(ptr) (*(const UINT32 *)(ptr)) | 137 | #define LOAD_UINT32_REVERSED(p) get_u32(p) |
163 | #define STORE_UINT32_BIG(ptr,x) STORE_UINT32_REVERSED(ptr,x) | 138 | #define STORE_UINT32_REVERSED(p,v) put_u32(p,v) |
164 | #else | 139 | #else |
165 | #define LOAD_UINT32_LITTLE(ptr) LOAD_UINT32_REVERSED(ptr) | 140 | #define LOAD_UINT32_REVERSED(p) get_u32_le(p) |
166 | #define STORE_UINT32_BIG(ptr,x) (*(UINT32 *)(ptr) = (UINT32)(x)) | 141 | #define STORE_UINT32_REVERSED(p,v) put_u32_le(p,v) |
167 | #endif | 142 | #endif |
168 | 143 | ||
144 | #define LOAD_UINT32_LITTLE(p) (get_u32_le(p)) | ||
145 | #define STORE_UINT32_BIG(p,v) put_u32(p, v) | ||
146 | |||
169 | /* ---------------------------------------------------------------------- */ | 147 | /* ---------------------------------------------------------------------- */ |
170 | /* ---------------------------------------------------------------------- */ | 148 | /* ---------------------------------------------------------------------- */ |
171 | /* ----- Begin KDF & PDF Section ---------------------------------------- */ | 149 | /* ----- Begin KDF & PDF Section ---------------------------------------- */ |
@@ -176,6 +154,7 @@ static void STORE_UINT32_REVERSED(void *ptr, UINT32 x) | |||
176 | #define AES_BLOCK_LEN 16 | 154 | #define AES_BLOCK_LEN 16 |
177 | 155 | ||
178 | /* OpenSSL's AES */ | 156 | /* OpenSSL's AES */ |
157 | #ifdef WITH_OPENSSL | ||
179 | #include "openbsd-compat/openssl-compat.h" | 158 | #include "openbsd-compat/openssl-compat.h" |
180 | #ifndef USE_BUILTIN_RIJNDAEL | 159 | #ifndef USE_BUILTIN_RIJNDAEL |
181 | # include <openssl/aes.h> | 160 | # include <openssl/aes.h> |
@@ -185,6 +164,16 @@ typedef AES_KEY aes_int_key[1]; | |||
185 | AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key) | 164 | AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key) |
186 | #define aes_key_setup(key,int_key) \ | 165 | #define aes_key_setup(key,int_key) \ |
187 | AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key) | 166 | AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key) |
167 | #else | ||
168 | #include "rijndael.h" | ||
169 | #define AES_ROUNDS ((UMAC_KEY_LEN / 4) + 6) | ||
170 | typedef UINT8 aes_int_key[AES_ROUNDS+1][4][4]; /* AES internal */ | ||
171 | #define aes_encryption(in,out,int_key) \ | ||
172 | rijndaelEncrypt((u32 *)(int_key), AES_ROUNDS, (u8 *)(in), (u8 *)(out)) | ||
173 | #define aes_key_setup(key,int_key) \ | ||
174 | rijndaelKeySetupEnc((u32 *)(int_key), (const unsigned char *)(key), \ | ||
175 | UMAC_KEY_LEN*8) | ||
176 | #endif | ||
188 | 177 | ||
189 | /* The user-supplied UMAC key is stretched using AES in a counter | 178 | /* The user-supplied UMAC key is stretched using AES in a counter |
190 | * mode to supply all random bits needed by UMAC. The kdf function takes | 179 | * mode to supply all random bits needed by UMAC. The kdf function takes |
@@ -1,6 +1,6 @@ | |||
1 | /* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */ | 1 | /* $OpenBSD: version.h,v 1.71 2014/04/18 23:52:25 djm Exp $ */ |
2 | 2 | ||
3 | #define SSH_VERSION "OpenSSH_6.6.1" | 3 | #define SSH_VERSION "OpenSSH_6.7" |
4 | 4 | ||
5 | #define SSH_PORTABLE "p1" | 5 | #define SSH_PORTABLE "p1" |
6 | #define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE | 6 | #define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE |