diff options
-rw-r--r-- | ChangeLog | 55 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | acconfig.h | 7 | ||||
-rw-r--r-- | auth1.c | 5 | ||||
-rw-r--r-- | auth2.c | 5 | ||||
-rw-r--r-- | authfd.c | 235 | ||||
-rw-r--r-- | authfd.h | 53 | ||||
-rw-r--r-- | channels.c | 22 | ||||
-rw-r--r-- | channels.h | 14 | ||||
-rw-r--r-- | clientloop.c | 340 | ||||
-rw-r--r-- | configure.in | 41 | ||||
-rw-r--r-- | crc32.c | 4 | ||||
-rw-r--r-- | crc32.h | 4 | ||||
-rw-r--r-- | deattack.c | 4 | ||||
-rw-r--r-- | defines.h | 8 | ||||
-rw-r--r-- | fingerprint.c | 69 | ||||
-rw-r--r-- | fingerprint.h | 34 | ||||
-rw-r--r-- | key.c | 14 | ||||
-rw-r--r-- | log-client.c | 5 | ||||
-rw-r--r-- | packet.c | 8 | ||||
-rw-r--r-- | scp.1 | 12 | ||||
-rw-r--r-- | scp.c | 137 | ||||
-rw-r--r-- | session.c | 120 | ||||
-rw-r--r-- | ssh-add.1 | 8 | ||||
-rw-r--r-- | ssh-add.c | 81 | ||||
-rw-r--r-- | ssh-agent.1 | 11 | ||||
-rw-r--r-- | ssh-agent.c | 514 | ||||
-rw-r--r-- | ssh-keygen.c | 19 | ||||
-rw-r--r-- | ssh.c | 28 | ||||
-rw-r--r-- | ssh.h | 10 | ||||
-rw-r--r-- | sshconnect1.c | 40 | ||||
-rw-r--r-- | sshconnect2.c | 78 |
33 files changed, 1178 insertions, 811 deletions
@@ -3,6 +3,61 @@ | |||
3 | Avoids "scp never exits" problem. Reports from Lutz Jaenicke | 3 | Avoids "scp never exits" problem. Reports from Lutz Jaenicke |
4 | <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA | 4 | <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Tamito KAJIYAMA |
5 | <kajiyama@grad.sccs.chukyo-u.ac.jp> | 5 | <kajiyama@grad.sccs.chukyo-u.ac.jp> |
6 | - (djm) Pick up LOGIN_PROGRAM from environment or PATH if not set by headers | ||
7 | - (djm) OpenBSD CVS updates: | ||
8 | - deraadt@cvs.openbsd.org 2000/08/18 20:07:23 | ||
9 | [ssh.c] | ||
10 | accept remsh as a valid name as well; roman@buildpoint.com | ||
11 | - deraadt@cvs.openbsd.org 2000/08/18 20:17:13 | ||
12 | [deattack.c crc32.c packet.c] | ||
13 | rename crc32() to ssh_crc32() to avoid zlib name clash. do not move to | ||
14 | libz crc32 function yet, because it has ugly "long"'s in it; | ||
15 | oneill@cs.sfu.ca | ||
16 | - deraadt@cvs.openbsd.org 2000/08/18 20:26:08 | ||
17 | [scp.1 scp.c] | ||
18 | -S prog support; tv@debian.org | ||
19 | - deraadt@cvs.openbsd.org 2000/08/18 20:50:07 | ||
20 | [scp.c] | ||
21 | knf | ||
22 | - deraadt@cvs.openbsd.org 2000/08/18 20:57:33 | ||
23 | [log-client.c] | ||
24 | shorten | ||
25 | - markus@cvs.openbsd.org 2000/08/19 12:48:11 | ||
26 | [channels.c channels.h clientloop.c ssh.c ssh.h] | ||
27 | support for ~. in ssh2 | ||
28 | - deraadt@cvs.openbsd.org 2000/08/19 15:29:40 | ||
29 | [crc32.h] | ||
30 | proper prototype | ||
31 | - markus@cvs.openbsd.org 2000/08/19 15:34:44 | ||
32 | [authfd.c authfd.h key.c key.h ssh-add.1 ssh-add.c ssh-agent.1] | ||
33 | [ssh-agent.c ssh-keygen.c sshconnect1.c sshconnect2.c Makefile] | ||
34 | [fingerprint.c fingerprint.h] | ||
35 | add SSH2/DSA support to the agent and some other DSA related cleanups. | ||
36 | (note that we cannot talk to ssh.com's ssh2 agents) | ||
37 | - markus@cvs.openbsd.org 2000/08/19 15:55:52 | ||
38 | [channels.c channels.h clientloop.c] | ||
39 | more ~ support for ssh2 | ||
40 | - markus@cvs.openbsd.org 2000/08/19 16:21:19 | ||
41 | [clientloop.c] | ||
42 | oops | ||
43 | - millert@cvs.openbsd.org 2000/08/20 12:25:53 | ||
44 | [session.c] | ||
45 | We have to stash the result of get_remote_name_or_ip() before we | ||
46 | close our socket or getpeername() will get EBADF and the process | ||
47 | will exit. Only a problem for "UseLogin yes". | ||
48 | - millert@cvs.openbsd.org 2000/08/20 12:30:59 | ||
49 | [session.c] | ||
50 | Only check /etc/nologin if "UseLogin no" since login(1) may have its | ||
51 | own policy on determining who is allowed to login when /etc/nologin | ||
52 | is present. Also use the _PATH_NOLOGIN define. | ||
53 | - millert@cvs.openbsd.org 2000/08/20 12:42:43 | ||
54 | [auth1.c auth2.c session.c ssh.c] | ||
55 | Add calls to setusercontext() and login_get*(). We basically call | ||
56 | setusercontext() in most places where previously we did a setlogin(). | ||
57 | Add default login.conf file and put root in the "daemon" login class. | ||
58 | - millert@cvs.openbsd.org 2000/08/21 10:23:31 | ||
59 | [session.c] | ||
60 | Fix incorrect PATH setting; noted by Markus. | ||
6 | 61 | ||
7 | 20000818 | 62 | 20000818 |
8 | - (djm) OpenBSD CVS changes: | 63 | - (djm) OpenBSD CVS changes: |
diff --git a/Makefile.in b/Makefile.in index ff34c4932..4ceef7043 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -34,7 +34,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ | |||
34 | 34 | ||
35 | TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) | 35 | TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) |
36 | 36 | ||
37 | LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o | 37 | LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o |
38 | 38 | ||
39 | LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o | 39 | LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o |
40 | 40 | ||
@@ -14,3 +14,5 @@ | |||
14 | underlying shell. | 14 | underlying shell. |
15 | 15 | ||
16 | - utmp/wtmp logging does not work on NeXT | 16 | - utmp/wtmp logging does not work on NeXT |
17 | |||
18 | - Complete Tru64 SIA support | ||
diff --git a/acconfig.h b/acconfig.h index 601dc16f7..eeee4eaf1 100644 --- a/acconfig.h +++ b/acconfig.h | |||
@@ -6,6 +6,13 @@ | |||
6 | 6 | ||
7 | @TOP@ | 7 | @TOP@ |
8 | 8 | ||
9 | /* If your header files don't define LOGIN_PROGRAM, then use this (detected) */ | ||
10 | /* from environment and PATH */ | ||
11 | #undef LOGIN_PROGRAM_FALLBACK | ||
12 | |||
13 | /* Define if your password has a pw_class field */ | ||
14 | #undef HAVE_PW_CLASS_IN_PASSWD | ||
15 | |||
9 | /* Define if your socketpair() has bugs */ | 16 | /* Define if your socketpair() has bugs */ |
10 | #undef USE_PIPES | 17 | #undef USE_PIPES |
11 | 18 | ||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "includes.h" | 6 | #include "includes.h" |
7 | RCSID("$OpenBSD: auth1.c,v 1.2 2000/04/29 18:11:52 markus Exp $"); | 7 | RCSID("$OpenBSD: auth1.c,v 1.3 2000/08/20 18:42:40 millert Exp $"); |
8 | 8 | ||
9 | #include "xmalloc.h" | 9 | #include "xmalloc.h" |
10 | #include "rsa.h" | 10 | #include "rsa.h" |
@@ -480,6 +480,9 @@ do_authentication() | |||
480 | pwcopy.pw_passwd = xstrdup(pw->pw_passwd); | 480 | pwcopy.pw_passwd = xstrdup(pw->pw_passwd); |
481 | pwcopy.pw_uid = pw->pw_uid; | 481 | pwcopy.pw_uid = pw->pw_uid; |
482 | pwcopy.pw_gid = pw->pw_gid; | 482 | pwcopy.pw_gid = pw->pw_gid; |
483 | #ifdef HAVE_PW_CLASS_IN_PASSWD | ||
484 | pwcopy.pw_class = xstrdup(pw->pw_class); | ||
485 | #endif | ||
483 | pwcopy.pw_dir = xstrdup(pw->pw_dir); | 486 | pwcopy.pw_dir = xstrdup(pw->pw_dir); |
484 | pwcopy.pw_shell = xstrdup(pw->pw_shell); | 487 | pwcopy.pw_shell = xstrdup(pw->pw_shell); |
485 | pw = &pwcopy; | 488 | pw = &pwcopy; |
@@ -27,7 +27,7 @@ | |||
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ | 28 | */ |
29 | #include "includes.h" | 29 | #include "includes.h" |
30 | RCSID("$OpenBSD: auth2.c,v 1.12 2000/07/07 03:55:03 todd Exp $"); | 30 | RCSID("$OpenBSD: auth2.c,v 1.13 2000/08/20 18:42:40 millert Exp $"); |
31 | 31 | ||
32 | #include <openssl/dsa.h> | 32 | #include <openssl/dsa.h> |
33 | #include <openssl/rsa.h> | 33 | #include <openssl/rsa.h> |
@@ -411,6 +411,9 @@ auth_set_user(char *u, char *s) | |||
411 | copy->pw_passwd = xstrdup(pw->pw_passwd); | 411 | copy->pw_passwd = xstrdup(pw->pw_passwd); |
412 | copy->pw_uid = pw->pw_uid; | 412 | copy->pw_uid = pw->pw_uid; |
413 | copy->pw_gid = pw->pw_gid; | 413 | copy->pw_gid = pw->pw_gid; |
414 | #ifdef HAVE_PW_CLASS_IN_PASSWD | ||
415 | copy->pw_class = xstrdup(pw->pw_class); | ||
416 | #endif | ||
414 | copy->pw_dir = xstrdup(pw->pw_dir); | 417 | copy->pw_dir = xstrdup(pw->pw_dir); |
415 | copy->pw_shell = xstrdup(pw->pw_shell); | 418 | copy->pw_shell = xstrdup(pw->pw_shell); |
416 | authctxt->valid = 1; | 419 | authctxt->valid = 1; |
@@ -11,10 +11,13 @@ | |||
11 | * | 11 | * |
12 | * Functions for connecting the local authentication agent. | 12 | * Functions for connecting the local authentication agent. |
13 | * | 13 | * |
14 | * SSH2 implementation, | ||
15 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
16 | * | ||
14 | */ | 17 | */ |
15 | 18 | ||
16 | #include "includes.h" | 19 | #include "includes.h" |
17 | RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $"); | 20 | RCSID("$OpenBSD: authfd.c,v 1.25 2000/08/19 21:34:42 markus Exp $"); |
18 | 21 | ||
19 | #include "ssh.h" | 22 | #include "ssh.h" |
20 | #include "rsa.h" | 23 | #include "rsa.h" |
@@ -29,6 +32,7 @@ RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $"); | |||
29 | #include "key.h" | 32 | #include "key.h" |
30 | #include "authfd.h" | 33 | #include "authfd.h" |
31 | #include "kex.h" | 34 | #include "kex.h" |
35 | #include "dsa.h" | ||
32 | 36 | ||
33 | /* helper */ | 37 | /* helper */ |
34 | int decode_reply(int type); | 38 | int decode_reply(int type); |
@@ -71,8 +75,7 @@ ssh_get_authentication_socket() | |||
71 | } | 75 | } |
72 | 76 | ||
73 | int | 77 | int |
74 | ssh_request_reply(AuthenticationConnection *auth, | 78 | ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) |
75 | Buffer *request, Buffer *reply) | ||
76 | { | 79 | { |
77 | int l, len; | 80 | int l, len; |
78 | char buf[1024]; | 81 | char buf[1024]; |
@@ -162,7 +165,6 @@ ssh_get_authentication_connection() | |||
162 | 165 | ||
163 | auth = xmalloc(sizeof(*auth)); | 166 | auth = xmalloc(sizeof(*auth)); |
164 | auth->fd = sock; | 167 | auth->fd = sock; |
165 | buffer_init(&auth->packet); | ||
166 | buffer_init(&auth->identities); | 168 | buffer_init(&auth->identities); |
167 | auth->howmany = 0; | 169 | auth->howmany = 0; |
168 | 170 | ||
@@ -175,46 +177,57 @@ ssh_get_authentication_connection() | |||
175 | */ | 177 | */ |
176 | 178 | ||
177 | void | 179 | void |
178 | ssh_close_authentication_connection(AuthenticationConnection *ac) | 180 | ssh_close_authentication_connection(AuthenticationConnection *auth) |
179 | { | 181 | { |
180 | buffer_free(&ac->packet); | 182 | buffer_free(&auth->identities); |
181 | buffer_free(&ac->identities); | 183 | close(auth->fd); |
182 | close(ac->fd); | 184 | xfree(auth); |
183 | xfree(ac); | ||
184 | } | 185 | } |
185 | 186 | ||
186 | /* | 187 | /* |
187 | * Returns the first authentication identity held by the agent. | 188 | * Returns the first authentication identity held by the agent. |
188 | * Returns true if an identity is available, 0 otherwise. | ||
189 | * The caller must initialize the integers before the call, and free the | ||
190 | * comment after a successful call (before calling ssh_get_next_identity). | ||
191 | */ | 189 | */ |
192 | 190 | ||
193 | int | 191 | Key * |
194 | ssh_get_first_identity(AuthenticationConnection *auth, | 192 | ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version) |
195 | BIGNUM *e, BIGNUM *n, char **comment) | ||
196 | { | 193 | { |
194 | int type, code1 = 0, code2 = 0; | ||
197 | Buffer request; | 195 | Buffer request; |
198 | int type; | 196 | |
197 | switch(version){ | ||
198 | case 1: | ||
199 | code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; | ||
200 | code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; | ||
201 | break; | ||
202 | case 2: | ||
203 | code1 = SSH2_AGENTC_REQUEST_IDENTITIES; | ||
204 | code2 = SSH2_AGENT_IDENTITIES_ANSWER; | ||
205 | break; | ||
206 | default: | ||
207 | return NULL; | ||
208 | } | ||
199 | 209 | ||
200 | /* | 210 | /* |
201 | * Send a message to the agent requesting for a list of the | 211 | * Send a message to the agent requesting for a list of the |
202 | * identities it can represent. | 212 | * identities it can represent. |
203 | */ | 213 | */ |
204 | buffer_init(&request); | 214 | buffer_init(&request); |
205 | buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES); | 215 | buffer_put_char(&request, code1); |
206 | 216 | ||
207 | buffer_clear(&auth->identities); | 217 | buffer_clear(&auth->identities); |
208 | if (ssh_request_reply(auth, &request, &auth->identities) == 0) { | 218 | if (ssh_request_reply(auth, &request, &auth->identities) == 0) { |
209 | buffer_free(&request); | 219 | buffer_free(&request); |
210 | return 0; | 220 | return NULL; |
211 | } | 221 | } |
212 | buffer_free(&request); | 222 | buffer_free(&request); |
213 | 223 | ||
214 | /* Get message type, and verify that we got a proper answer. */ | 224 | /* Get message type, and verify that we got a proper answer. */ |
215 | type = buffer_get_char(&auth->identities); | 225 | type = buffer_get_char(&auth->identities); |
216 | if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER) | 226 | if (type == SSH_AGENT_FAILURE) { |
227 | return NULL; | ||
228 | } else if (type != code2) { | ||
217 | fatal("Bad authentication reply message type: %d", type); | 229 | fatal("Bad authentication reply message type: %d", type); |
230 | } | ||
218 | 231 | ||
219 | /* Get the number of entries in the response and check it for sanity. */ | 232 | /* Get the number of entries in the response and check it for sanity. */ |
220 | auth->howmany = buffer_get_int(&auth->identities); | 233 | auth->howmany = buffer_get_int(&auth->identities); |
@@ -223,43 +236,49 @@ ssh_get_first_identity(AuthenticationConnection *auth, | |||
223 | auth->howmany); | 236 | auth->howmany); |
224 | 237 | ||
225 | /* Return the first entry (if any). */ | 238 | /* Return the first entry (if any). */ |
226 | return ssh_get_next_identity(auth, e, n, comment); | 239 | return ssh_get_next_identity(auth, comment, version); |
227 | } | 240 | } |
228 | 241 | ||
229 | /* | 242 | Key * |
230 | * Returns the next authentication identity for the agent. Other functions | 243 | ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) |
231 | * can be called between this and ssh_get_first_identity or two calls of this | ||
232 | * function. This returns 0 if there are no more identities. The caller | ||
233 | * must free comment after a successful return. | ||
234 | */ | ||
235 | |||
236 | int | ||
237 | ssh_get_next_identity(AuthenticationConnection *auth, | ||
238 | BIGNUM *e, BIGNUM *n, char **comment) | ||
239 | { | 244 | { |
240 | unsigned int bits; | 245 | unsigned int bits; |
246 | unsigned char *blob; | ||
247 | unsigned int blen; | ||
248 | Key *key = NULL; | ||
241 | 249 | ||
242 | /* Return failure if no more entries. */ | 250 | /* Return failure if no more entries. */ |
243 | if (auth->howmany <= 0) | 251 | if (auth->howmany <= 0) |
244 | return 0; | 252 | return NULL; |
245 | 253 | ||
246 | /* | 254 | /* |
247 | * Get the next entry from the packet. These will abort with a fatal | 255 | * Get the next entry from the packet. These will abort with a fatal |
248 | * error if the packet is too short or contains corrupt data. | 256 | * error if the packet is too short or contains corrupt data. |
249 | */ | 257 | */ |
250 | bits = buffer_get_int(&auth->identities); | 258 | switch(version){ |
251 | buffer_get_bignum(&auth->identities, e); | 259 | case 1: |
252 | buffer_get_bignum(&auth->identities, n); | 260 | key = key_new(KEY_RSA); |
253 | *comment = buffer_get_string(&auth->identities, NULL); | 261 | bits = buffer_get_int(&auth->identities); |
254 | 262 | buffer_get_bignum(&auth->identities, key->rsa->e); | |
255 | if (bits != BN_num_bits(n)) | 263 | buffer_get_bignum(&auth->identities, key->rsa->n); |
256 | log("Warning: identity keysize mismatch: actual %d, announced %u", | 264 | *comment = buffer_get_string(&auth->identities, NULL); |
257 | BN_num_bits(n), bits); | 265 | if (bits != BN_num_bits(key->rsa->n)) |
258 | 266 | log("Warning: identity keysize mismatch: actual %d, announced %u", | |
267 | BN_num_bits(key->rsa->n), bits); | ||
268 | break; | ||
269 | case 2: | ||
270 | blob = buffer_get_string(&auth->identities, &blen); | ||
271 | *comment = buffer_get_string(&auth->identities, NULL); | ||
272 | key = dsa_key_from_blob(blob, blen); | ||
273 | xfree(blob); | ||
274 | break; | ||
275 | default: | ||
276 | return NULL; | ||
277 | break; | ||
278 | } | ||
259 | /* Decrement the number of remaining entries. */ | 279 | /* Decrement the number of remaining entries. */ |
260 | auth->howmany--; | 280 | auth->howmany--; |
261 | 281 | return key; | |
262 | return 1; | ||
263 | } | 282 | } |
264 | 283 | ||
265 | /* | 284 | /* |
@@ -272,7 +291,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, | |||
272 | 291 | ||
273 | int | 292 | int |
274 | ssh_decrypt_challenge(AuthenticationConnection *auth, | 293 | ssh_decrypt_challenge(AuthenticationConnection *auth, |
275 | BIGNUM* e, BIGNUM *n, BIGNUM *challenge, | 294 | Key* key, BIGNUM *challenge, |
276 | unsigned char session_id[16], | 295 | unsigned char session_id[16], |
277 | unsigned int response_type, | 296 | unsigned int response_type, |
278 | unsigned char response[16]) | 297 | unsigned char response[16]) |
@@ -282,15 +301,17 @@ ssh_decrypt_challenge(AuthenticationConnection *auth, | |||
282 | int i; | 301 | int i; |
283 | int type; | 302 | int type; |
284 | 303 | ||
285 | if (response_type == 0) | 304 | if (key->type != KEY_RSA) |
286 | fatal("Compatibility with ssh protocol version " | 305 | return 0; |
287 | "1.0 no longer supported."); | 306 | if (response_type == 0) { |
288 | 307 | log("Compatibility with ssh protocol version 1.0 no longer supported."); | |
308 | return 0; | ||
309 | } | ||
289 | buffer_init(&buffer); | 310 | buffer_init(&buffer); |
290 | buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); | 311 | buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); |
291 | buffer_put_int(&buffer, BN_num_bits(n)); | 312 | buffer_put_int(&buffer, BN_num_bits(key->rsa->n)); |
292 | buffer_put_bignum(&buffer, e); | 313 | buffer_put_bignum(&buffer, key->rsa->e); |
293 | buffer_put_bignum(&buffer, n); | 314 | buffer_put_bignum(&buffer, key->rsa->n); |
294 | buffer_put_bignum(&buffer, challenge); | 315 | buffer_put_bignum(&buffer, challenge); |
295 | buffer_append(&buffer, (char *) session_id, 16); | 316 | buffer_append(&buffer, (char *) session_id, 16); |
296 | buffer_put_int(&buffer, response_type); | 317 | buffer_put_int(&buffer, response_type); |
@@ -318,6 +339,45 @@ ssh_decrypt_challenge(AuthenticationConnection *auth, | |||
318 | return success; | 339 | return success; |
319 | } | 340 | } |
320 | 341 | ||
342 | /* ask agent to sign data, returns -1 on error, 0 on success */ | ||
343 | int | ||
344 | ssh_agent_sign(AuthenticationConnection *auth, | ||
345 | Key *key, | ||
346 | unsigned char **sigp, int *lenp, | ||
347 | unsigned char *data, int datalen) | ||
348 | { | ||
349 | Buffer msg; | ||
350 | unsigned char *blob; | ||
351 | unsigned int blen; | ||
352 | int type; | ||
353 | int ret = -1; | ||
354 | |||
355 | if (dsa_make_key_blob(key, &blob, &blen) == 0) | ||
356 | return -1; | ||
357 | |||
358 | buffer_init(&msg); | ||
359 | buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); | ||
360 | buffer_put_string(&msg, blob, blen); | ||
361 | buffer_put_string(&msg, data, datalen); | ||
362 | xfree(blob); | ||
363 | |||
364 | if (ssh_request_reply(auth, &msg, &msg) == 0) { | ||
365 | buffer_free(&msg); | ||
366 | return -1; | ||
367 | } | ||
368 | type = buffer_get_char(&msg); | ||
369 | if (type == SSH_AGENT_FAILURE) { | ||
370 | log("Agent admitted failure to sign using the key."); | ||
371 | } else if (type != SSH2_AGENT_SIGN_RESPONSE) { | ||
372 | fatal("Bad authentication response: %d", type); | ||
373 | } else { | ||
374 | ret = 0; | ||
375 | *sigp = buffer_get_string(&msg, lenp); | ||
376 | } | ||
377 | buffer_free(&msg); | ||
378 | return ret; | ||
379 | } | ||
380 | |||
321 | /* Encode key for a message to the agent. */ | 381 | /* Encode key for a message to the agent. */ |
322 | 382 | ||
323 | void | 383 | void |
@@ -358,29 +418,29 @@ ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment) | |||
358 | int | 418 | int |
359 | ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) | 419 | ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) |
360 | { | 420 | { |
361 | Buffer buffer; | 421 | Buffer msg; |
362 | int type; | 422 | int type; |
363 | 423 | ||
364 | buffer_init(&buffer); | 424 | buffer_init(&msg); |
365 | 425 | ||
366 | switch (key->type) { | 426 | switch (key->type) { |
367 | case KEY_RSA: | 427 | case KEY_RSA: |
368 | ssh_encode_identity_rsa(&buffer, key->rsa, comment); | 428 | ssh_encode_identity_rsa(&msg, key->rsa, comment); |
369 | break; | 429 | break; |
370 | case KEY_DSA: | 430 | case KEY_DSA: |
371 | ssh_encode_identity_dsa(&buffer, key->dsa, comment); | 431 | ssh_encode_identity_dsa(&msg, key->dsa, comment); |
372 | break; | 432 | break; |
373 | default: | 433 | default: |
374 | buffer_free(&buffer); | 434 | buffer_free(&msg); |
375 | return 0; | 435 | return 0; |
376 | break; | 436 | break; |
377 | } | 437 | } |
378 | if (ssh_request_reply(auth, &buffer, &buffer) == 0) { | 438 | if (ssh_request_reply(auth, &msg, &msg) == 0) { |
379 | buffer_free(&buffer); | 439 | buffer_free(&msg); |
380 | return 0; | 440 | return 0; |
381 | } | 441 | } |
382 | type = buffer_get_char(&buffer); | 442 | type = buffer_get_char(&msg); |
383 | buffer_free(&buffer); | 443 | buffer_free(&msg); |
384 | return decode_reply(type); | 444 | return decode_reply(type); |
385 | } | 445 | } |
386 | 446 | ||
@@ -390,23 +450,35 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) | |||
390 | */ | 450 | */ |
391 | 451 | ||
392 | int | 452 | int |
393 | ssh_remove_identity(AuthenticationConnection *auth, RSA *key) | 453 | ssh_remove_identity(AuthenticationConnection *auth, Key *key) |
394 | { | 454 | { |
395 | Buffer buffer; | 455 | Buffer msg; |
396 | int type; | 456 | int type; |
397 | 457 | unsigned char *blob; | |
398 | buffer_init(&buffer); | 458 | unsigned int blen; |
399 | buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); | 459 | |
400 | buffer_put_int(&buffer, BN_num_bits(key->n)); | 460 | buffer_init(&msg); |
401 | buffer_put_bignum(&buffer, key->e); | 461 | |
402 | buffer_put_bignum(&buffer, key->n); | 462 | if (key->type == KEY_RSA) { |
403 | 463 | buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); | |
404 | if (ssh_request_reply(auth, &buffer, &buffer) == 0) { | 464 | buffer_put_int(&msg, BN_num_bits(key->rsa->n)); |
405 | buffer_free(&buffer); | 465 | buffer_put_bignum(&msg, key->rsa->e); |
466 | buffer_put_bignum(&msg, key->rsa->n); | ||
467 | } else if (key->type == KEY_DSA) { | ||
468 | dsa_make_key_blob(key, &blob, &blen); | ||
469 | buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); | ||
470 | buffer_put_string(&msg, blob, blen); | ||
471 | xfree(blob); | ||
472 | } else { | ||
473 | buffer_free(&msg); | ||
406 | return 0; | 474 | return 0; |
407 | } | 475 | } |
408 | type = buffer_get_char(&buffer); | 476 | if (ssh_request_reply(auth, &msg, &msg) == 0) { |
409 | buffer_free(&buffer); | 477 | buffer_free(&msg); |
478 | return 0; | ||
479 | } | ||
480 | type = buffer_get_char(&msg); | ||
481 | buffer_free(&msg); | ||
410 | return decode_reply(type); | 482 | return decode_reply(type); |
411 | } | 483 | } |
412 | 484 | ||
@@ -416,20 +488,23 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key) | |||
416 | */ | 488 | */ |
417 | 489 | ||
418 | int | 490 | int |
419 | ssh_remove_all_identities(AuthenticationConnection *auth) | 491 | ssh_remove_all_identities(AuthenticationConnection *auth, int version) |
420 | { | 492 | { |
421 | Buffer buffer; | 493 | Buffer msg; |
422 | int type; | 494 | int type; |
495 | int code = (version==1) ? | ||
496 | SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : | ||
497 | SSH2_AGENTC_REMOVE_ALL_IDENTITIES; | ||
423 | 498 | ||
424 | buffer_init(&buffer); | 499 | buffer_init(&msg); |
425 | buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES); | 500 | buffer_put_char(&msg, code); |
426 | 501 | ||
427 | if (ssh_request_reply(auth, &buffer, &buffer) == 0) { | 502 | if (ssh_request_reply(auth, &msg, &msg) == 0) { |
428 | buffer_free(&buffer); | 503 | buffer_free(&msg); |
429 | return 0; | 504 | return 0; |
430 | } | 505 | } |
431 | type = buffer_get_char(&buffer); | 506 | type = buffer_get_char(&msg); |
432 | buffer_free(&buffer); | 507 | buffer_free(&msg); |
433 | return decode_reply(type); | 508 | return decode_reply(type); |
434 | } | 509 | } |
435 | 510 | ||
@@ -13,7 +13,7 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | /* RCSID("$OpenBSD: authfd.h,v 1.9 2000/07/16 08:27:21 markus Exp $"); */ | 16 | /* RCSID("$OpenBSD: authfd.h,v 1.10 2000/08/19 21:34:43 markus Exp $"); */ |
17 | 17 | ||
18 | #ifndef AUTHFD_H | 18 | #ifndef AUTHFD_H |
19 | #define AUTHFD_H | 19 | #define AUTHFD_H |
@@ -35,18 +35,16 @@ | |||
35 | #define SSH2_AGENT_IDENTITIES_ANSWER 12 | 35 | #define SSH2_AGENT_IDENTITIES_ANSWER 12 |
36 | #define SSH2_AGENTC_SIGN_REQUEST 13 | 36 | #define SSH2_AGENTC_SIGN_REQUEST 13 |
37 | #define SSH2_AGENT_SIGN_RESPONSE 14 | 37 | #define SSH2_AGENT_SIGN_RESPONSE 14 |
38 | #define SSH2_AGENT_FAILURE SSH_AGENT_FAILURE | ||
39 | #define SSH2_AGENT_SUCCESS SSH_AGENT_SUCCESS | ||
40 | #define SSH2_AGENTC_ADD_IDENTITY 17 | 38 | #define SSH2_AGENTC_ADD_IDENTITY 17 |
41 | #define SSH2_AGENTC_REMOVE_IDENTITY 18 | 39 | #define SSH2_AGENTC_REMOVE_IDENTITY 18 |
42 | #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 | 40 | #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 |
43 | 41 | ||
44 | typedef struct { | 42 | typedef struct { |
45 | int fd; | 43 | int fd; |
46 | Buffer packet; | ||
47 | Buffer identities; | 44 | Buffer identities; |
48 | int howmany; | 45 | int howmany; |
49 | } AuthenticationConnection; | 46 | } AuthenticationConnection; |
47 | |||
50 | /* Returns the number of the authentication fd, or -1 if there is none. */ | 48 | /* Returns the number of the authentication fd, or -1 if there is none. */ |
51 | int ssh_get_authentication_socket(); | 49 | int ssh_get_authentication_socket(); |
52 | 50 | ||
@@ -69,44 +67,48 @@ AuthenticationConnection *ssh_get_authentication_connection(); | |||
69 | * Closes the connection to the authentication agent and frees any associated | 67 | * Closes the connection to the authentication agent and frees any associated |
70 | * memory. | 68 | * memory. |
71 | */ | 69 | */ |
72 | void ssh_close_authentication_connection(AuthenticationConnection * ac); | 70 | void ssh_close_authentication_connection(AuthenticationConnection *auth); |
73 | 71 | ||
74 | /* | 72 | /* |
75 | * Returns the first authentication identity held by the agent. Returns true | 73 | * Returns the first authentication identity held by the agent or NULL if |
76 | * if an identity is available, 0 otherwise. The caller must initialize the | 74 | * no identies are available. Caller must free comment and key. |
77 | * integers before the call, and free the comment after a successful call | 75 | * Note that you cannot mix calls with different versions. |
78 | * (before calling ssh_get_next_identity). | ||
79 | */ | 76 | */ |
80 | int | 77 | Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version); |
81 | ssh_get_first_identity(AuthenticationConnection * connection, | ||
82 | BIGNUM * e, BIGNUM * n, char **comment); | ||
83 | 78 | ||
84 | /* | 79 | /* |
85 | * Returns the next authentication identity for the agent. Other functions | 80 | * Returns the next authentication identity for the agent. Other functions |
86 | * can be called between this and ssh_get_first_identity or two calls of this | 81 | * can be called between this and ssh_get_first_identity or two calls of this |
87 | * function. This returns 0 if there are no more identities. The caller | 82 | * function. This returns NULL if there are no more identities. The caller |
88 | * must free comment after a successful return. | 83 | * must free key and comment after a successful return. |
89 | */ | 84 | */ |
90 | int | 85 | Key *ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version); |
91 | ssh_get_next_identity(AuthenticationConnection * connection, | ||
92 | BIGNUM * e, BIGNUM * n, char **comment); | ||
93 | 86 | ||
94 | /* Requests the agent to decrypt the given challenge. Returns true if | 87 | /* |
95 | the agent claims it was able to decrypt it. */ | 88 | * Requests the agent to decrypt the given challenge. Returns true if the |
89 | * agent claims it was able to decrypt it. | ||
90 | */ | ||
96 | int | 91 | int |
97 | ssh_decrypt_challenge(AuthenticationConnection * auth, | 92 | ssh_decrypt_challenge(AuthenticationConnection *auth, |
98 | BIGNUM * e, BIGNUM * n, BIGNUM * challenge, | 93 | Key *key, BIGNUM * challenge, |
99 | unsigned char session_id[16], | 94 | unsigned char session_id[16], |
100 | unsigned int response_type, | 95 | unsigned int response_type, |
101 | unsigned char response[16]); | 96 | unsigned char response[16]); |
102 | 97 | ||
98 | /* Requests the agent to sign data using key */ | ||
99 | int | ||
100 | ssh_agent_sign(AuthenticationConnection *auth, | ||
101 | Key *key, | ||
102 | unsigned char **sigp, int *lenp, | ||
103 | unsigned char *data, int datalen); | ||
104 | |||
103 | /* | 105 | /* |
104 | * Adds an identity to the authentication server. This call is not meant to | 106 | * Adds an identity to the authentication server. This call is not meant to |
105 | * be used by normal applications. This returns true if the identity was | 107 | * be used by normal applications. This returns true if the identity was |
106 | * successfully added. | 108 | * successfully added. |
107 | */ | 109 | */ |
108 | int | 110 | int |
109 | ssh_add_identity(AuthenticationConnection * connection, Key *key, | 111 | ssh_add_identity(AuthenticationConnection *auth, Key *key, |
110 | const char *comment); | 112 | const char *comment); |
111 | 113 | ||
112 | /* | 114 | /* |
@@ -114,16 +116,13 @@ ssh_add_identity(AuthenticationConnection * connection, Key *key, | |||
114 | * meant to be used by normal applications. This returns true if the | 116 | * meant to be used by normal applications. This returns true if the |
115 | * identity was successfully added. | 117 | * identity was successfully added. |
116 | */ | 118 | */ |
117 | int ssh_remove_identity(AuthenticationConnection * connection, RSA * key); | 119 | int ssh_remove_identity(AuthenticationConnection *auth, Key *key); |
118 | 120 | ||
119 | /* | 121 | /* |
120 | * Removes all identities from the authentication agent. This call is not | 122 | * Removes all identities from the authentication agent. This call is not |
121 | * meant to be used by normal applications. This returns true if the | 123 | * meant to be used by normal applications. This returns true if the |
122 | * operation was successful. | 124 | * operation was successful. |
123 | */ | 125 | */ |
124 | int ssh_remove_all_identities(AuthenticationConnection * connection); | 126 | int ssh_remove_all_identities(AuthenticationConnection *auth, int version); |
125 | |||
126 | /* Closes the connection to the authentication agent. */ | ||
127 | void ssh_close_authentication(AuthenticationConnection * connection); | ||
128 | 127 | ||
129 | #endif /* AUTHFD_H */ | 128 | #endif /* AUTHFD_H */ |
diff --git a/channels.c b/channels.c index ea395293a..c77f6b96a 100644 --- a/channels.c +++ b/channels.c | |||
@@ -17,7 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | RCSID("$OpenBSD: channels.c,v 1.64 2000/07/16 08:27:21 markus Exp $"); | 20 | RCSID("$OpenBSD: channels.c,v 1.66 2000/08/19 21:55:51 markus Exp $"); |
21 | 21 | ||
22 | #include "ssh.h" | 22 | #include "ssh.h" |
23 | #include "packet.h" | 23 | #include "packet.h" |
@@ -244,6 +244,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, | |||
244 | c->cb_arg = NULL; | 244 | c->cb_arg = NULL; |
245 | c->cb_event = 0; | 245 | c->cb_event = 0; |
246 | c->dettach_user = NULL; | 246 | c->dettach_user = NULL; |
247 | c->input_filter = NULL; | ||
247 | debug("channel %d: new [%s]", found, remote_name); | 248 | debug("channel %d: new [%s]", found, remote_name); |
248 | return found; | 249 | return found; |
249 | } | 250 | } |
@@ -665,7 +666,14 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) | |||
665 | } | 666 | } |
666 | return -1; | 667 | return -1; |
667 | } | 668 | } |
668 | buffer_append(&c->input, buf, len); | 669 | if(c->input_filter != NULL) { |
670 | if (c->input_filter(c, buf, len) == -1) { | ||
671 | debug("filter stops channel %d", c->self); | ||
672 | chan_read_failed(c); | ||
673 | } | ||
674 | } else { | ||
675 | buffer_append(&c->input, buf, len); | ||
676 | } | ||
669 | } | 677 | } |
670 | return 1; | 678 | return 1; |
671 | } | 679 | } |
@@ -2309,6 +2317,16 @@ channel_cancel_cleanup(int id) | |||
2309 | } | 2317 | } |
2310 | c->dettach_user = NULL; | 2318 | c->dettach_user = NULL; |
2311 | } | 2319 | } |
2320 | void | ||
2321 | channel_register_filter(int id, channel_filter_fn *fn) | ||
2322 | { | ||
2323 | Channel *c = channel_lookup(id); | ||
2324 | if (c == NULL) { | ||
2325 | log("channel_register_filter: %d: bad id", id); | ||
2326 | return; | ||
2327 | } | ||
2328 | c->input_filter = fn; | ||
2329 | } | ||
2312 | 2330 | ||
2313 | void | 2331 | void |
2314 | channel_set_fds(int id, int rfd, int wfd, int efd, int extusage) | 2332 | channel_set_fds(int id, int rfd, int wfd, int efd, int extusage) |
diff --git a/channels.h b/channels.h index 9629124b9..9acdf5810 100644 --- a/channels.h +++ b/channels.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* RCSID("$OpenBSD: channels.h,v 1.14 2000/06/20 01:39:40 markus Exp $"); */ | 1 | /* RCSID("$OpenBSD: channels.h,v 1.16 2000/08/19 21:55:51 markus Exp $"); */ |
2 | 2 | ||
3 | #ifndef CHANNELS_H | 3 | #ifndef CHANNELS_H |
4 | #define CHANNELS_H | 4 | #define CHANNELS_H |
@@ -21,9 +21,13 @@ | |||
21 | * Data structure for channel data. This is iniailized in channel_allocate | 21 | * Data structure for channel data. This is iniailized in channel_allocate |
22 | * and cleared in channel_free. | 22 | * and cleared in channel_free. |
23 | */ | 23 | */ |
24 | struct Channel; | ||
25 | typedef struct Channel Channel; | ||
26 | |||
24 | typedef void channel_callback_fn(int id, void *arg); | 27 | typedef void channel_callback_fn(int id, void *arg); |
28 | typedef int channel_filter_fn(struct Channel *c, char *buf, int len); | ||
25 | 29 | ||
26 | typedef struct Channel { | 30 | struct Channel { |
27 | int type; /* channel type/state */ | 31 | int type; /* channel type/state */ |
28 | int self; /* my own channel identifier */ | 32 | int self; /* my own channel identifier */ |
29 | int remote_id; /* channel identifier for remote peer */ | 33 | int remote_id; /* channel identifier for remote peer */ |
@@ -61,7 +65,10 @@ typedef struct Channel { | |||
61 | void *cb_arg; | 65 | void *cb_arg; |
62 | int cb_event; | 66 | int cb_event; |
63 | channel_callback_fn *dettach_user; | 67 | channel_callback_fn *dettach_user; |
64 | } Channel; | 68 | |
69 | /* filter */ | ||
70 | channel_filter_fn *input_filter; | ||
71 | }; | ||
65 | 72 | ||
66 | #define CHAN_EXTENDED_IGNORE 0 | 73 | #define CHAN_EXTENDED_IGNORE 0 |
67 | #define CHAN_EXTENDED_READ 1 | 74 | #define CHAN_EXTENDED_READ 1 |
@@ -73,6 +80,7 @@ void channel_request(int id, char *service, int wantconfirm); | |||
73 | void channel_request_start(int id, char *service, int wantconfirm); | 80 | void channel_request_start(int id, char *service, int wantconfirm); |
74 | void channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg); | 81 | void channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg); |
75 | void channel_register_cleanup(int id, channel_callback_fn *fn); | 82 | void channel_register_cleanup(int id, channel_callback_fn *fn); |
83 | void channel_register_filter(int id, channel_filter_fn *fn); | ||
76 | void channel_cancel_cleanup(int id); | 84 | void channel_cancel_cleanup(int id); |
77 | Channel *channel_lookup(int id); | 85 | Channel *channel_lookup(int id); |
78 | 86 | ||
diff --git a/clientloop.c b/clientloop.c index 67fa36d91..d339e1274 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -16,7 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "includes.h" | 18 | #include "includes.h" |
19 | RCSID("$OpenBSD: clientloop.c,v 1.29 2000/07/16 08:27:21 markus Exp $"); | 19 | RCSID("$OpenBSD: clientloop.c,v 1.32 2000/08/19 22:21:19 markus Exp $"); |
20 | 20 | ||
21 | #include "xmalloc.h" | 21 | #include "xmalloc.h" |
22 | #include "ssh.h" | 22 | #include "ssh.h" |
@@ -29,6 +29,9 @@ RCSID("$OpenBSD: clientloop.c,v 1.29 2000/07/16 08:27:21 markus Exp $"); | |||
29 | #include "channels.h" | 29 | #include "channels.h" |
30 | #include "dispatch.h" | 30 | #include "dispatch.h" |
31 | 31 | ||
32 | #include "buffer.h" | ||
33 | #include "bufaux.h" | ||
34 | |||
32 | /* Flag indicating that stdin should be redirected from /dev/null. */ | 35 | /* Flag indicating that stdin should be redirected from /dev/null. */ |
33 | extern int stdin_null_flag; | 36 | extern int stdin_null_flag; |
34 | 37 | ||
@@ -60,6 +63,8 @@ static int in_raw_mode = 0; | |||
60 | static int in_non_blocking_mode = 0; | 63 | static int in_non_blocking_mode = 0; |
61 | 64 | ||
62 | /* Common data for the client loop code. */ | 65 | /* Common data for the client loop code. */ |
66 | static int quit_pending; /* Set to non-zero to quit the client loop. */ | ||
67 | static int escape_char; /* Escape character. */ | ||
63 | static int escape_pending; /* Last character was the escape character */ | 68 | static int escape_pending; /* Last character was the escape character */ |
64 | static int last_was_cr; /* Last character was a newline. */ | 69 | static int last_was_cr; /* Last character was a newline. */ |
65 | static int exit_status; /* Used to store the exit status of the command. */ | 70 | static int exit_status; /* Used to store the exit status of the command. */ |
@@ -67,13 +72,11 @@ static int stdin_eof; /* EOF has been encountered on standard error. */ | |||
67 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | 72 | static Buffer stdin_buffer; /* Buffer for stdin data. */ |
68 | static Buffer stdout_buffer; /* Buffer for stdout data. */ | 73 | static Buffer stdout_buffer; /* Buffer for stdout data. */ |
69 | static Buffer stderr_buffer; /* Buffer for stderr data. */ | 74 | static Buffer stderr_buffer; /* Buffer for stderr data. */ |
75 | static unsigned long stdin_bytes, stdout_bytes, stderr_bytes; | ||
70 | static unsigned int buffer_high;/* Soft max buffer size. */ | 76 | static unsigned int buffer_high;/* Soft max buffer size. */ |
71 | static int max_fd; /* Maximum file descriptor number in select(). */ | 77 | static int max_fd; /* Maximum file descriptor number in select(). */ |
72 | static int connection_in; /* Connection to server (input). */ | 78 | static int connection_in; /* Connection to server (input). */ |
73 | static int connection_out; /* Connection to server (output). */ | 79 | static int connection_out; /* Connection to server (output). */ |
74 | static unsigned long stdin_bytes, stdout_bytes, stderr_bytes; | ||
75 | static int quit_pending; /* Set to non-zero to quit the client loop. */ | ||
76 | static int escape_char; /* Escape character. */ | ||
77 | 80 | ||
78 | 81 | ||
79 | void client_init_dispatch(void); | 82 | void client_init_dispatch(void); |
@@ -379,17 +382,15 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) | |||
379 | } | 382 | } |
380 | 383 | ||
381 | void | 384 | void |
382 | client_suspend_self() | 385 | client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) |
383 | { | 386 | { |
384 | struct winsize oldws, newws; | 387 | struct winsize oldws, newws; |
385 | 388 | ||
386 | /* Flush stdout and stderr buffers. */ | 389 | /* Flush stdout and stderr buffers. */ |
387 | if (buffer_len(&stdout_buffer) > 0) | 390 | if (buffer_len(bout) > 0) |
388 | atomicio(write, fileno(stdout), buffer_ptr(&stdout_buffer), | 391 | atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); |
389 | buffer_len(&stdout_buffer)); | 392 | if (buffer_len(berr) > 0) |
390 | if (buffer_len(&stderr_buffer) > 0) | 393 | atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr)); |
391 | atomicio(write, fileno(stderr), buffer_ptr(&stderr_buffer), | ||
392 | buffer_len(&stderr_buffer)); | ||
393 | 394 | ||
394 | leave_raw_mode(); | 395 | leave_raw_mode(); |
395 | 396 | ||
@@ -397,9 +398,9 @@ client_suspend_self() | |||
397 | * Free (and clear) the buffer to reduce the amount of data that gets | 398 | * Free (and clear) the buffer to reduce the amount of data that gets |
398 | * written to swap. | 399 | * written to swap. |
399 | */ | 400 | */ |
400 | buffer_free(&stdin_buffer); | 401 | buffer_free(bin); |
401 | buffer_free(&stdout_buffer); | 402 | buffer_free(bout); |
402 | buffer_free(&stderr_buffer); | 403 | buffer_free(berr); |
403 | 404 | ||
404 | /* Save old window size. */ | 405 | /* Save old window size. */ |
405 | ioctl(fileno(stdin), TIOCGWINSZ, &oldws); | 406 | ioctl(fileno(stdin), TIOCGWINSZ, &oldws); |
@@ -416,9 +417,9 @@ client_suspend_self() | |||
416 | received_window_change_signal = 1; | 417 | received_window_change_signal = 1; |
417 | 418 | ||
418 | /* OK, we have been continued by the user. Reinitialize buffers. */ | 419 | /* OK, we have been continued by the user. Reinitialize buffers. */ |
419 | buffer_init(&stdin_buffer); | 420 | buffer_init(bin); |
420 | buffer_init(&stdout_buffer); | 421 | buffer_init(bout); |
421 | buffer_init(&stderr_buffer); | 422 | buffer_init(berr); |
422 | 423 | ||
423 | enter_raw_mode(); | 424 | enter_raw_mode(); |
424 | } | 425 | } |
@@ -466,12 +467,155 @@ client_process_net_input(fd_set * readset) | |||
466 | } | 467 | } |
467 | } | 468 | } |
468 | 469 | ||
470 | /* process the characters one by one */ | ||
471 | int | ||
472 | process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) | ||
473 | { | ||
474 | char string[1024]; | ||
475 | pid_t pid; | ||
476 | int bytes = 0; | ||
477 | unsigned int i; | ||
478 | unsigned char ch; | ||
479 | char *s; | ||
480 | |||
481 | for (i = 0; i < len; i++) { | ||
482 | /* Get one character at a time. */ | ||
483 | ch = buf[i]; | ||
484 | |||
485 | if (escape_pending) { | ||
486 | /* We have previously seen an escape character. */ | ||
487 | /* Clear the flag now. */ | ||
488 | escape_pending = 0; | ||
489 | |||
490 | /* Process the escaped character. */ | ||
491 | switch (ch) { | ||
492 | case '.': | ||
493 | /* Terminate the connection. */ | ||
494 | snprintf(string, sizeof string, "%c.\r\n", escape_char); | ||
495 | buffer_append(berr, string, strlen(string)); | ||
496 | /*stderr_bytes += strlen(string); XXX*/ | ||
497 | |||
498 | quit_pending = 1; | ||
499 | return -1; | ||
500 | |||
501 | case 'Z' - 64: | ||
502 | /* Suspend the program. */ | ||
503 | /* Print a message to that effect to the user. */ | ||
504 | snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char); | ||
505 | buffer_append(berr, string, strlen(string)); | ||
506 | /*stderr_bytes += strlen(string); XXX*/ | ||
507 | |||
508 | /* Restore terminal modes and suspend. */ | ||
509 | client_suspend_self(bin, bout, berr); | ||
510 | |||
511 | /* We have been continued. */ | ||
512 | continue; | ||
513 | |||
514 | case '&': | ||
515 | /* XXX does not work yet with proto 2 */ | ||
516 | if (compat20) | ||
517 | continue; | ||
518 | /* | ||
519 | * Detach the program (continue to serve connections, | ||
520 | * but put in background and no more new connections). | ||
521 | */ | ||
522 | if (!stdin_eof) { | ||
523 | /* | ||
524 | * Sending SSH_CMSG_EOF alone does not always appear | ||
525 | * to be enough. So we try to send an EOF character | ||
526 | * first. | ||
527 | */ | ||
528 | packet_start(SSH_CMSG_STDIN_DATA); | ||
529 | packet_put_string("\004", 1); | ||
530 | packet_send(); | ||
531 | /* Close stdin. */ | ||
532 | stdin_eof = 1; | ||
533 | if (buffer_len(bin) == 0) { | ||
534 | packet_start(SSH_CMSG_EOF); | ||
535 | packet_send(); | ||
536 | } | ||
537 | } | ||
538 | /* Restore tty modes. */ | ||
539 | leave_raw_mode(); | ||
540 | |||
541 | /* Stop listening for new connections. */ | ||
542 | channel_stop_listening(); | ||
543 | |||
544 | printf("%c& [backgrounded]\n", escape_char); | ||
545 | |||
546 | /* Fork into background. */ | ||
547 | pid = fork(); | ||
548 | if (pid < 0) { | ||
549 | error("fork: %.100s", strerror(errno)); | ||
550 | continue; | ||
551 | } | ||
552 | if (pid != 0) { /* This is the parent. */ | ||
553 | /* The parent just exits. */ | ||
554 | exit(0); | ||
555 | } | ||
556 | /* The child continues serving connections. */ | ||
557 | continue; /*XXX ? */ | ||
558 | |||
559 | case '?': | ||
560 | snprintf(string, sizeof string, | ||
561 | "%c?\r\n\ | ||
562 | Supported escape sequences:\r\n\ | ||
563 | ~. - terminate connection\r\n\ | ||
564 | ~^Z - suspend ssh\r\n\ | ||
565 | ~# - list forwarded connections\r\n\ | ||
566 | ~& - background ssh (when waiting for connections to terminate)\r\n\ | ||
567 | ~? - this message\r\n\ | ||
568 | ~~ - send the escape character by typing it twice\r\n\ | ||
569 | (Note that escapes are only recognized immediately after newline.)\r\n", | ||
570 | escape_char); | ||
571 | buffer_append(berr, string, strlen(string)); | ||
572 | continue; | ||
573 | |||
574 | case '#': | ||
575 | snprintf(string, sizeof string, "%c#\r\n", escape_char); | ||
576 | buffer_append(berr, string, strlen(string)); | ||
577 | s = channel_open_message(); | ||
578 | buffer_append(berr, s, strlen(s)); | ||
579 | xfree(s); | ||
580 | continue; | ||
581 | |||
582 | default: | ||
583 | if (ch != escape_char) { | ||
584 | buffer_put_char(bin, escape_char); | ||
585 | bytes++; | ||
586 | } | ||
587 | /* Escaped characters fall through here */ | ||
588 | break; | ||
589 | } | ||
590 | } else { | ||
591 | /* | ||
592 | * The previous character was not an escape char. Check if this | ||
593 | * is an escape. | ||
594 | */ | ||
595 | if (last_was_cr && ch == escape_char) { | ||
596 | /* It is. Set the flag and continue to next character. */ | ||
597 | escape_pending = 1; | ||
598 | continue; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | /* | ||
603 | * Normal character. Record whether it was a newline, | ||
604 | * and append it to the buffer. | ||
605 | */ | ||
606 | last_was_cr = (ch == '\r' || ch == '\n'); | ||
607 | buffer_put_char(bin, ch); | ||
608 | bytes++; | ||
609 | } | ||
610 | return bytes; | ||
611 | } | ||
612 | |||
469 | void | 613 | void |
470 | client_process_input(fd_set * readset) | 614 | client_process_input(fd_set * readset) |
471 | { | 615 | { |
616 | int ret; | ||
472 | int len; | 617 | int len; |
473 | pid_t pid; | 618 | char buf[8192]; |
474 | char buf[8192], *s; | ||
475 | 619 | ||
476 | /* Read input from stdin. */ | 620 | /* Read input from stdin. */ |
477 | if (FD_ISSET(fileno(stdin), readset)) { | 621 | if (FD_ISSET(fileno(stdin), readset)) { |
@@ -513,145 +657,10 @@ client_process_input(fd_set * readset) | |||
513 | * Normal, successful read. But we have an escape character | 657 | * Normal, successful read. But we have an escape character |
514 | * and have to process the characters one by one. | 658 | * and have to process the characters one by one. |
515 | */ | 659 | */ |
516 | unsigned int i; | 660 | ret = process_escapes(&stdin_buffer, &stdout_buffer, &stderr_buffer, buf, len); |
517 | for (i = 0; i < len; i++) { | 661 | if (ret == -1) |
518 | unsigned char ch; | 662 | return; |
519 | /* Get one character at a time. */ | 663 | stdout_bytes += ret; |
520 | ch = buf[i]; | ||
521 | |||
522 | if (escape_pending) { | ||
523 | /* We have previously seen an escape character. */ | ||
524 | /* Clear the flag now. */ | ||
525 | escape_pending = 0; | ||
526 | /* Process the escaped character. */ | ||
527 | switch (ch) { | ||
528 | case '.': | ||
529 | /* Terminate the connection. */ | ||
530 | snprintf(buf, sizeof buf, "%c.\r\n", escape_char); | ||
531 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
532 | stderr_bytes += strlen(buf); | ||
533 | quit_pending = 1; | ||
534 | return; | ||
535 | |||
536 | case 'Z' - 64: | ||
537 | /* Suspend the program. */ | ||
538 | /* Print a message to that effect to the user. */ | ||
539 | snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char); | ||
540 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
541 | stderr_bytes += strlen(buf); | ||
542 | |||
543 | /* Restore terminal modes and suspend. */ | ||
544 | client_suspend_self(); | ||
545 | |||
546 | /* We have been continued. */ | ||
547 | continue; | ||
548 | |||
549 | case '&': | ||
550 | /* | ||
551 | * Detach the program (continue to serve connections, | ||
552 | * but put in background and no more new connections). | ||
553 | */ | ||
554 | if (!stdin_eof) { | ||
555 | /* | ||
556 | * Sending SSH_CMSG_EOF alone does not always appear | ||
557 | * to be enough. So we try to send an EOF character | ||
558 | * first. | ||
559 | */ | ||
560 | packet_start(SSH_CMSG_STDIN_DATA); | ||
561 | packet_put_string("\004", 1); | ||
562 | packet_send(); | ||
563 | /* Close stdin. */ | ||
564 | stdin_eof = 1; | ||
565 | if (buffer_len(&stdin_buffer) == 0) { | ||
566 | packet_start(SSH_CMSG_EOF); | ||
567 | packet_send(); | ||
568 | } | ||
569 | } | ||
570 | /* Restore tty modes. */ | ||
571 | leave_raw_mode(); | ||
572 | |||
573 | /* Stop listening for new connections. */ | ||
574 | channel_stop_listening(); | ||
575 | |||
576 | printf("%c& [backgrounded]\n", escape_char); | ||
577 | |||
578 | /* Fork into background. */ | ||
579 | pid = fork(); | ||
580 | if (pid < 0) { | ||
581 | error("fork: %.100s", strerror(errno)); | ||
582 | continue; | ||
583 | } | ||
584 | if (pid != 0) { /* This is the parent. */ | ||
585 | /* The parent just exits. */ | ||
586 | exit(0); | ||
587 | } | ||
588 | /* The child continues serving connections. */ | ||
589 | continue; | ||
590 | |||
591 | case '?': | ||
592 | snprintf(buf, sizeof buf, | ||
593 | "%c?\r\n\ | ||
594 | Supported escape sequences:\r\n\ | ||
595 | ~. - terminate connection\r\n\ | ||
596 | ~^Z - suspend ssh\r\n\ | ||
597 | ~# - list forwarded connections\r\n\ | ||
598 | ~& - background ssh (when waiting for connections to terminate)\r\n\ | ||
599 | ~? - this message\r\n\ | ||
600 | ~~ - send the escape character by typing it twice\r\n\ | ||
601 | (Note that escapes are only recognized immediately after newline.)\r\n", | ||
602 | escape_char); | ||
603 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
604 | continue; | ||
605 | |||
606 | case '#': | ||
607 | snprintf(buf, sizeof buf, "%c#\r\n", escape_char); | ||
608 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
609 | s = channel_open_message(); | ||
610 | buffer_append(&stderr_buffer, s, strlen(s)); | ||
611 | xfree(s); | ||
612 | continue; | ||
613 | |||
614 | default: | ||
615 | if (ch != escape_char) { | ||
616 | /* | ||
617 | * Escape character followed by non-special character. | ||
618 | * Append both to the input buffer. | ||
619 | */ | ||
620 | buf[0] = escape_char; | ||
621 | buf[1] = ch; | ||
622 | buffer_append(&stdin_buffer, buf, 2); | ||
623 | stdin_bytes += 2; | ||
624 | continue; | ||
625 | } | ||
626 | /* | ||
627 | * Note that escape character typed twice | ||
628 | * falls through here; the latter gets processed | ||
629 | * as a normal character below. | ||
630 | */ | ||
631 | break; | ||
632 | } | ||
633 | } else { | ||
634 | /* | ||
635 | * The previous character was not an escape char. Check if this | ||
636 | * is an escape. | ||
637 | */ | ||
638 | if (last_was_cr && ch == escape_char) { | ||
639 | /* It is. Set the flag and continue to next character. */ | ||
640 | escape_pending = 1; | ||
641 | continue; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | /* | ||
646 | * Normal character. Record whether it was a newline, | ||
647 | * and append it to the buffer. | ||
648 | */ | ||
649 | last_was_cr = (ch == '\r' || ch == '\n'); | ||
650 | buf[0] = ch; | ||
651 | buffer_append(&stdin_buffer, buf, 1); | ||
652 | stdin_bytes += 1; | ||
653 | continue; | ||
654 | } | ||
655 | } | 664 | } |
656 | } | 665 | } |
657 | } | 666 | } |
@@ -722,6 +731,15 @@ client_process_buffered_input_packets() | |||
722 | dispatch_run(DISPATCH_NONBLOCK, &quit_pending); | 731 | dispatch_run(DISPATCH_NONBLOCK, &quit_pending); |
723 | } | 732 | } |
724 | 733 | ||
734 | /* scan buf[] for '~' before sending data to the peer */ | ||
735 | |||
736 | int | ||
737 | simple_escape_filter(Channel *c, char *buf, int len) | ||
738 | { | ||
739 | /* XXX we assume c->extended is writeable */ | ||
740 | return process_escapes(&c->input, &c->output, &c->extended, buf, len); | ||
741 | } | ||
742 | |||
725 | /* | 743 | /* |
726 | * Implements the interactive session with the server. This is called after | 744 | * Implements the interactive session with the server. This is called after |
727 | * the user has been authenticated, and a command has been started on the | 745 | * the user has been authenticated, and a command has been started on the |
@@ -730,7 +748,7 @@ client_process_buffered_input_packets() | |||
730 | */ | 748 | */ |
731 | 749 | ||
732 | int | 750 | int |
733 | client_loop(int have_pty, int escape_char_arg) | 751 | client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) |
734 | { | 752 | { |
735 | extern Options options; | 753 | extern Options options; |
736 | double start_time, total_time; | 754 | double start_time, total_time; |
@@ -780,6 +798,9 @@ client_loop(int have_pty, int escape_char_arg) | |||
780 | if (!compat20) | 798 | if (!compat20) |
781 | client_check_initial_eof_on_stdin(); | 799 | client_check_initial_eof_on_stdin(); |
782 | 800 | ||
801 | if (compat20 && escape_char != -1) | ||
802 | channel_register_filter(ssh2_chan_id, simple_escape_filter); | ||
803 | |||
783 | /* Main loop of the client for the interactive session mode. */ | 804 | /* Main loop of the client for the interactive session mode. */ |
784 | while (!quit_pending) { | 805 | while (!quit_pending) { |
785 | fd_set readset, writeset; | 806 | fd_set readset, writeset; |
@@ -989,6 +1010,7 @@ client_input_channel_open(int type, int plen) | |||
989 | /* XXX move to channels.c */ | 1010 | /* XXX move to channels.c */ |
990 | sock = x11_connect_display(); | 1011 | sock = x11_connect_display(); |
991 | if (sock >= 0) { | 1012 | if (sock >= 0) { |
1013 | /*XXX MAXPACK */ | ||
992 | id = channel_new("x11", SSH_CHANNEL_X11_OPEN, | 1014 | id = channel_new("x11", SSH_CHANNEL_X11_OPEN, |
993 | sock, sock, -1, 4*1024, 32*1024, 0, | 1015 | sock, sock, -1, 4*1024, 32*1024, 0, |
994 | xstrdup("x11")); | 1016 | xstrdup("x11")); |
diff --git a/configure.in b/configure.in index f048b000d..02287b802 100644 --- a/configure.in +++ b/configure.in | |||
@@ -14,6 +14,17 @@ AC_SUBST(PERL) | |||
14 | AC_PATH_PROG(ENT, ent) | 14 | AC_PATH_PROG(ENT, ent) |
15 | AC_SUBST(ENT) | 15 | AC_SUBST(ENT) |
16 | 16 | ||
17 | # Use LOGIN_PROGRAM from environment if possible | ||
18 | if test ! -z "$LOGIN_PROGRAM" ; then | ||
19 | AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM") | ||
20 | else | ||
21 | # Search for login | ||
22 | AC_PATH_PROG(LOGIN_PROGRAM_FALLBACK, login) | ||
23 | if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then | ||
24 | AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM_FALLBACK") | ||
25 | fi | ||
26 | fi | ||
27 | |||
17 | if test -z "$LD" ; then | 28 | if test -z "$LD" ; then |
18 | LD=$CC | 29 | LD=$CC |
19 | fi | 30 | fi |
@@ -225,18 +236,18 @@ if test -z "$no_libnsl" ; then | |||
225 | fi | 236 | fi |
226 | 237 | ||
227 | # Checks for header files. | 238 | # Checks for header files. |
228 | AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h lastlog.h limits.h login.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h) | 239 | AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h lastlog.h limits.h login.h login_cap.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h) |
229 | 240 | ||
230 | # Checks for library functions. | 241 | dnl Checks for library functions. |
231 | AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock freeaddrinfo gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid sigaction sigvec snprintf strerror strlcat strlcpy strsep vsnprintf vhangup _getpty __b64_ntop) | 242 | AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock freeaddrinfo gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid sigaction sigvec snprintf strerror strlcat strlcpy strsep vsnprintf vhangup _getpty __b64_ntop) |
232 | dnl checks for time functions | 243 | dnl Checks for time functions |
233 | AC_CHECK_FUNCS(gettimeofday time) | 244 | AC_CHECK_FUNCS(gettimeofday time) |
234 | dnl checks for libutil functions | 245 | dnl Checks for libutil functions |
235 | AC_CHECK_FUNCS(login logout updwtmp logwtmp) | 246 | AC_CHECK_FUNCS(login logout updwtmp logwtmp) |
236 | dnl checks for utmp functions | 247 | dnl Checks for utmp functions |
237 | AC_CHECK_FUNCS(entutent getutent getutid getutline pututline setutent) | 248 | AC_CHECK_FUNCS(entutent getutent getutid getutline pututline setutent) |
238 | AC_CHECK_FUNCS(utmpname) | 249 | AC_CHECK_FUNCS(utmpname) |
239 | dnl checks for utmpx functions | 250 | dnl Checks for utmpx functions |
240 | AC_CHECK_FUNCS(entutxent getutxent getutxid getutxline pututxline ) | 251 | AC_CHECK_FUNCS(entutxent getutxent getutxid getutxline pututxline ) |
241 | AC_CHECK_FUNCS(setutxent utmpxname) | 252 | AC_CHECK_FUNCS(setutxent utmpxname) |
242 | 253 | ||
@@ -736,6 +747,22 @@ if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then | |||
736 | AC_DEFINE(HAVE___SS_FAMILY_IN_SS) | 747 | AC_DEFINE(HAVE___SS_FAMILY_IN_SS) |
737 | fi | 748 | fi |
738 | 749 | ||
750 | AC_CACHE_CHECK([for pw_class field in struct passwd], | ||
751 | ac_cv_have_pw_class_in_struct_passwd, [ | ||
752 | AC_TRY_COMPILE( | ||
753 | [ | ||
754 | #include <sys/types.h> | ||
755 | #include <pwd.h> | ||
756 | ], | ||
757 | [ struct passwd p s; p.pw_class = NULL; ], | ||
758 | [ ac_cv_have_pw_class_in_struct_passwd="yes" ], | ||
759 | [ ac_cv_have_pw_class_in_struct_passwd="no" ] | ||
760 | ) | ||
761 | ]) | ||
762 | if test "x$ac_cv_have_pw_class_in_struct_passwd" = "xyes" ; then | ||
763 | AC_DEFINE(HAVE_PW_CLASS_IN_PASSWD) | ||
764 | fi | ||
765 | |||
739 | 766 | ||
740 | AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ | 767 | AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ |
741 | AC_TRY_LINK([], | 768 | AC_TRY_LINK([], |
@@ -6,7 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "includes.h" | 8 | #include "includes.h" |
9 | RCSID("$OpenBSD: crc32.c,v 1.5 2000/06/20 01:39:40 markus Exp $"); | 9 | RCSID("$OpenBSD: crc32.c,v 1.6 2000/08/19 02:17:12 deraadt Exp $"); |
10 | 10 | ||
11 | #include "crc32.h" | 11 | #include "crc32.h" |
12 | 12 | ||
@@ -108,7 +108,7 @@ static unsigned int crc32_tab[] = { | |||
108 | /* Return a 32-bit CRC of the contents of the buffer. */ | 108 | /* Return a 32-bit CRC of the contents of the buffer. */ |
109 | 109 | ||
110 | unsigned int | 110 | unsigned int |
111 | crc32(const unsigned char *s, unsigned int len) | 111 | ssh_crc32(const unsigned char *s, unsigned int len) |
112 | { | 112 | { |
113 | unsigned int i; | 113 | unsigned int i; |
114 | unsigned int crc32val; | 114 | unsigned int crc32val; |
@@ -13,7 +13,7 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | /* RCSID("$OpenBSD: crc32.h,v 1.6 2000/06/20 01:39:40 markus Exp $"); */ | 16 | /* RCSID("$OpenBSD: crc32.h,v 1.7 2000/08/19 21:29:40 deraadt Exp $"); */ |
17 | 17 | ||
18 | #ifndef CRC32_H | 18 | #ifndef CRC32_H |
19 | #define CRC32_H | 19 | #define CRC32_H |
@@ -22,6 +22,6 @@ | |||
22 | * This computes a 32 bit CRC of the data in the buffer, and returns the CRC. | 22 | * This computes a 32 bit CRC of the data in the buffer, and returns the CRC. |
23 | * The polynomial used is 0xedb88320. | 23 | * The polynomial used is 0xedb88320. |
24 | */ | 24 | */ |
25 | unsigned int crc32(const unsigned char *buf, unsigned int len); | 25 | unsigned int ssh_crc32(const unsigned char *buf, unsigned int len); |
26 | 26 | ||
27 | #endif /* CRC32_H */ | 27 | #endif /* CRC32_H */ |
diff --git a/deattack.c b/deattack.c index 7f95eca31..72e7f1e06 100644 --- a/deattack.c +++ b/deattack.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $OpenBSD: deattack.c,v 1.7 2000/06/20 01:39:41 markus Exp $ | 2 | * $OpenBSD: deattack.c,v 1.8 2000/08/19 02:17:12 deraadt Exp $ |
3 | * Cryptographic attack detector for ssh - source code | 3 | * Cryptographic attack detector for ssh - source code |
4 | * | 4 | * |
5 | * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. | 5 | * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. |
@@ -50,7 +50,7 @@ void | |||
50 | crc_update(u_int32_t *a, u_int32_t b) | 50 | crc_update(u_int32_t *a, u_int32_t b) |
51 | { | 51 | { |
52 | b ^= *a; | 52 | b ^= *a; |
53 | *a = crc32((unsigned char *) &b, sizeof(b)); | 53 | *a = ssh_crc32((unsigned char *) &b, sizeof(b)); |
54 | } | 54 | } |
55 | 55 | ||
56 | /* detect if a block is used in a particular pattern */ | 56 | /* detect if a block is used in a particular pattern */ |
@@ -246,8 +246,16 @@ typedef int mode_t; | |||
246 | # endif /* RSH_PATH */ | 246 | # endif /* RSH_PATH */ |
247 | #endif /* _PATH_RSH */ | 247 | #endif /* _PATH_RSH */ |
248 | 248 | ||
249 | #ifndef _PATH_NOLOGIN | ||
250 | # define _PATH_NOLOGIN "/etc/nologin" | ||
251 | #endif | ||
252 | |||
249 | /* Macros */ | 253 | /* Macros */ |
250 | 254 | ||
255 | #if defined(HAVE_LOGIN_GETCAPBOOL) && defined(HAVE_LOGIN_CAP_H) | ||
256 | # define HAVE_LOGIN_CAP | ||
257 | #endif | ||
258 | |||
251 | #ifndef MAX | 259 | #ifndef MAX |
252 | # define MAX(a,b) (((a)>(b))?(a):(b)) | 260 | # define MAX(a,b) (((a)>(b))?(a):(b)) |
253 | # define MIN(a,b) (((a)<(b))?(a):(b)) | 261 | # define MIN(a,b) (((a)<(b))?(a):(b)) |
diff --git a/fingerprint.c b/fingerprint.c deleted file mode 100644 index 801f6a6e2..000000000 --- a/fingerprint.c +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 1999 Markus Friedl. All rights reserved. | ||
3 | * | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * 1. Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * 2. Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * 3. All advertising materials mentioning features or use of this software | ||
13 | * must display the following acknowledgement: | ||
14 | * This product includes software developed by Markus Friedl. | ||
15 | * 4. The name of the author may not be used to endorse or promote products | ||
16 | * derived from this software without specific prior written permission. | ||
17 | * | ||
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | #include "includes.h" | ||
31 | RCSID("$OpenBSD: fingerprint.c,v 1.7 2000/06/20 01:39:41 markus Exp $"); | ||
32 | |||
33 | #include "ssh.h" | ||
34 | #include "xmalloc.h" | ||
35 | #include <openssl/md5.h> | ||
36 | |||
37 | #define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" | ||
38 | |||
39 | /* | ||
40 | * Generate key fingerprint in ascii format. | ||
41 | * Based on ideas and code from Bjoern Groenvall <bg@sics.se> | ||
42 | */ | ||
43 | char * | ||
44 | fingerprint(BIGNUM *e, BIGNUM *n) | ||
45 | { | ||
46 | static char retval[80]; | ||
47 | MD5_CTX md; | ||
48 | unsigned char d[16]; | ||
49 | unsigned char *buf; | ||
50 | int nlen, elen; | ||
51 | |||
52 | nlen = BN_num_bytes(n); | ||
53 | elen = BN_num_bytes(e); | ||
54 | |||
55 | buf = xmalloc(nlen + elen); | ||
56 | |||
57 | BN_bn2bin(n, buf); | ||
58 | BN_bn2bin(e, buf + nlen); | ||
59 | |||
60 | MD5_Init(&md); | ||
61 | MD5_Update(&md, buf, nlen + elen); | ||
62 | MD5_Final(d, &md); | ||
63 | snprintf(retval, sizeof(retval), FPRINT, | ||
64 | d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], | ||
65 | d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); | ||
66 | memset(buf, 0, nlen + elen); | ||
67 | xfree(buf); | ||
68 | return retval; | ||
69 | } | ||
diff --git a/fingerprint.h b/fingerprint.h deleted file mode 100644 index 3d7bcb32c..000000000 --- a/fingerprint.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 1999 Markus Friedl. All rights reserved. | ||
3 | * | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * 1. Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * 2. Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * 3. All advertising materials mentioning features or use of this software | ||
13 | * must display the following acknowledgement: | ||
14 | * This product includes software developed by Markus Friedl. | ||
15 | * 4. The name of the author may not be used to endorse or promote products | ||
16 | * derived from this software without specific prior written permission. | ||
17 | * | ||
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
28 | */ | ||
29 | /* RCSID("$OpenBSD: fingerprint.h,v 1.4 2000/06/20 01:39:41 markus Exp $"); */ | ||
30 | |||
31 | #ifndef FINGERPRINT_H | ||
32 | #define FINGERPRINT_H | ||
33 | char *fingerprint(BIGNUM * e, BIGNUM * n); | ||
34 | #endif | ||
@@ -41,7 +41,7 @@ | |||
41 | #include "dsa.h" | 41 | #include "dsa.h" |
42 | #include "uuencode.h" | 42 | #include "uuencode.h" |
43 | 43 | ||
44 | RCSID("$OpenBSD: key.c,v 1.9 2000/06/22 23:55:00 djm Exp $"); | 44 | RCSID("$OpenBSD: key.c,v 1.10 2000/08/19 21:34:43 markus Exp $"); |
45 | 45 | ||
46 | #define SSH_DSS "ssh-dss" | 46 | #define SSH_DSS "ssh-dss" |
47 | 47 | ||
@@ -335,3 +335,15 @@ key_type(Key *k) | |||
335 | } | 335 | } |
336 | return "unknown"; | 336 | return "unknown"; |
337 | } | 337 | } |
338 | unsigned int | ||
339 | key_size(Key *k){ | ||
340 | switch (k->type) { | ||
341 | case KEY_RSA: | ||
342 | return BN_num_bits(k->rsa->n); | ||
343 | break; | ||
344 | case KEY_DSA: | ||
345 | return BN_num_bits(k->dsa->p); | ||
346 | break; | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
diff --git a/log-client.c b/log-client.c index 7e9fd61e7..7615a94f0 100644 --- a/log-client.c +++ b/log-client.c | |||
@@ -15,7 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "includes.h" | 17 | #include "includes.h" |
18 | RCSID("$OpenBSD: log-client.c,v 1.9 2000/06/20 01:39:42 markus Exp $"); | 18 | RCSID("$OpenBSD: log-client.c,v 1.10 2000/08/19 02:57:33 deraadt Exp $"); |
19 | 19 | ||
20 | #include "xmalloc.h" | 20 | #include "xmalloc.h" |
21 | #include "ssh.h" | 21 | #include "ssh.h" |
@@ -57,6 +57,5 @@ do_log(LogLevel level, const char *fmt, va_list args) | |||
57 | if (level == SYSLOG_LEVEL_DEBUG) | 57 | if (level == SYSLOG_LEVEL_DEBUG) |
58 | fprintf(stderr, "debug: "); | 58 | fprintf(stderr, "debug: "); |
59 | vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); | 59 | vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); |
60 | fprintf(stderr, "%s", msgbuf); | 60 | fprintf(stderr, "%s\r\n", msgbuf); |
61 | fprintf(stderr, "\r\n"); | ||
62 | } | 61 | } |
@@ -17,7 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | RCSID("$OpenBSD: packet.c,v 1.33 2000/06/20 01:39:43 markus Exp $"); | 20 | RCSID("$OpenBSD: packet.c,v 1.34 2000/08/19 02:17:12 deraadt Exp $"); |
21 | 21 | ||
22 | #include "xmalloc.h" | 22 | #include "xmalloc.h" |
23 | #include "buffer.h" | 23 | #include "buffer.h" |
@@ -479,8 +479,8 @@ packet_send1() | |||
479 | buffer_consume(&outgoing_packet, 8 - padding); | 479 | buffer_consume(&outgoing_packet, 8 - padding); |
480 | 480 | ||
481 | /* Add check bytes. */ | 481 | /* Add check bytes. */ |
482 | checksum = crc32((unsigned char *) buffer_ptr(&outgoing_packet), | 482 | checksum = ssh_crc32((unsigned char *) buffer_ptr(&outgoing_packet), |
483 | buffer_len(&outgoing_packet)); | 483 | buffer_len(&outgoing_packet)); |
484 | PUT_32BIT(buf, checksum); | 484 | PUT_32BIT(buf, checksum); |
485 | buffer_append(&outgoing_packet, buf, 4); | 485 | buffer_append(&outgoing_packet, buf, 4); |
486 | 486 | ||
@@ -764,7 +764,7 @@ packet_read_poll1(int *payload_len_ptr) | |||
764 | #endif | 764 | #endif |
765 | 765 | ||
766 | /* Compute packet checksum. */ | 766 | /* Compute packet checksum. */ |
767 | checksum = crc32((unsigned char *) buffer_ptr(&incoming_packet), | 767 | checksum = ssh_crc32((unsigned char *) buffer_ptr(&incoming_packet), |
768 | buffer_len(&incoming_packet) - 4); | 768 | buffer_len(&incoming_packet) - 4); |
769 | 769 | ||
770 | /* Skip padding. */ | 770 | /* Skip padding. */ |
@@ -9,7 +9,7 @@ | |||
9 | .\" | 9 | .\" |
10 | .\" Created: Sun May 7 00:14:37 1995 ylo | 10 | .\" Created: Sun May 7 00:14:37 1995 ylo |
11 | .\" | 11 | .\" |
12 | .\" $Id: scp.1,v 1.8 2000/07/11 07:31:38 djm Exp $ | 12 | .\" $Id: scp.1,v 1.9 2000/08/23 00:46:24 djm Exp $ |
13 | .\" | 13 | .\" |
14 | .Dd September 25, 1999 | 14 | .Dd September 25, 1999 |
15 | .Dt SCP 1 | 15 | .Dt SCP 1 |
@@ -68,6 +68,11 @@ This option is directly passed to | |||
68 | .It Fl p | 68 | .It Fl p |
69 | Preserves modification times, access times, and modes from the | 69 | Preserves modification times, access times, and modes from the |
70 | original file. | 70 | original file. |
71 | .It Fl S | ||
72 | Name of program to use for the encrypted connection. | ||
73 | The program must understand | ||
74 | .Xr ssh 1 | ||
75 | options. | ||
71 | .It Fl r | 76 | .It Fl r |
72 | Recursively copy entire directories. | 77 | Recursively copy entire directories. |
73 | .It Fl v | 78 | .It Fl v |
@@ -98,6 +103,11 @@ because | |||
98 | .Fl p | 103 | .Fl p |
99 | is already reserved for preserving the times and modes of the file in | 104 | is already reserved for preserving the times and modes of the file in |
100 | .Xr rcp 1 . | 105 | .Xr rcp 1 . |
106 | .It Fl S | ||
107 | Name of program to use for the encrypted connection. The program must | ||
108 | understand | ||
109 | .Xr ssh 1 | ||
110 | options. | ||
101 | .It Fl 4 | 111 | .It Fl 4 |
102 | Forces | 112 | Forces |
103 | .Nm | 113 | .Nm |
@@ -11,6 +11,8 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * Parts from: | ||
15 | * | ||
14 | * Copyright (c) 1983, 1990, 1992, 1993, 1995 | 16 | * Copyright (c) 1983, 1990, 1992, 1993, 1995 |
15 | * The Regents of the University of California. All rights reserved. | 17 | * The Regents of the University of California. All rights reserved. |
16 | * | 18 | * |
@@ -45,7 +47,7 @@ | |||
45 | */ | 47 | */ |
46 | 48 | ||
47 | #include "includes.h" | 49 | #include "includes.h" |
48 | RCSID("$OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $"); | 50 | RCSID("$OpenBSD: scp.c,v 1.35 2000/08/19 02:50:07 deraadt Exp $"); |
49 | 51 | ||
50 | #include "ssh.h" | 52 | #include "ssh.h" |
51 | #include "xmalloc.h" | 53 | #include "xmalloc.h" |
@@ -69,6 +71,7 @@ void progressmeter(int); | |||
69 | 71 | ||
70 | /* Returns width of the terminal (for progress meter calculations). */ | 72 | /* Returns width of the terminal (for progress meter calculations). */ |
71 | int getttywidth(void); | 73 | int getttywidth(void); |
74 | int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); | ||
72 | 75 | ||
73 | /* Time a transfer started. */ | 76 | /* Time a transfer started. */ |
74 | static struct timeval start; | 77 | static struct timeval start; |
@@ -111,6 +114,9 @@ char *identity = NULL; | |||
111 | /* This is the port to use in contacting the remote site (is non-NULL). */ | 114 | /* This is the port to use in contacting the remote site (is non-NULL). */ |
112 | char *port = NULL; | 115 | char *port = NULL; |
113 | 116 | ||
117 | /* This is the program to execute for the secured connection. ("ssh" or -S) */ | ||
118 | char *ssh_program = SSH_PROGRAM; | ||
119 | |||
114 | /* | 120 | /* |
115 | * This function executes the given command as the specified user on the | 121 | * This function executes the given command as the specified user on the |
116 | * given host. This returns < 0 if execution fails, and >= 0 otherwise. This | 122 | * given host. This returns < 0 if execution fails, and >= 0 otherwise. This |
@@ -118,13 +124,13 @@ char *port = NULL; | |||
118 | */ | 124 | */ |
119 | 125 | ||
120 | int | 126 | int |
121 | do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | 127 | do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) |
122 | { | 128 | { |
123 | int pin[2], pout[2], reserved[2]; | 129 | int pin[2], pout[2], reserved[2]; |
124 | 130 | ||
125 | if (verbose_mode) | 131 | if (verbose_mode) |
126 | fprintf(stderr, "Executing: host %s, user %s, command %s\n", | 132 | fprintf(stderr, "Executing: host %s, user %s, command %s\n", |
127 | host, remuser ? remuser : "(unspecified)", cmd); | 133 | host, remuser ? remuser : "(unspecified)", cmd); |
128 | 134 | ||
129 | /* | 135 | /* |
130 | * Reserve two descriptors so that the real pipes won't get | 136 | * Reserve two descriptors so that the real pipes won't get |
@@ -144,7 +150,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
144 | 150 | ||
145 | /* For a child to execute the command on the remote host using ssh. */ | 151 | /* For a child to execute the command on the remote host using ssh. */ |
146 | if (fork() == 0) { | 152 | if (fork() == 0) { |
147 | char *args[100]; | 153 | char *args[100]; /* XXX careful */ |
148 | unsigned int i; | 154 | unsigned int i; |
149 | 155 | ||
150 | /* Child. */ | 156 | /* Child. */ |
@@ -156,7 +162,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
156 | close(pout[1]); | 162 | close(pout[1]); |
157 | 163 | ||
158 | i = 0; | 164 | i = 0; |
159 | args[i++] = SSH_PROGRAM; | 165 | args[i++] = ssh_program; |
160 | args[i++] = "-x"; | 166 | args[i++] = "-x"; |
161 | args[i++] = "-oFallBackToRsh no"; | 167 | args[i++] = "-oFallBackToRsh no"; |
162 | if (IPv4) | 168 | if (IPv4) |
@@ -189,8 +195,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
189 | args[i++] = cmd; | 195 | args[i++] = cmd; |
190 | args[i++] = NULL; | 196 | args[i++] = NULL; |
191 | 197 | ||
192 | execvp(SSH_PROGRAM, args); | 198 | execvp(ssh_program, args); |
193 | perror(SSH_PROGRAM); | 199 | perror(ssh_program); |
194 | exit(1); | 200 | exit(1); |
195 | } | 201 | } |
196 | /* Parent. Close the other side, and return the local side. */ | 202 | /* Parent. Close the other side, and return the local side. */ |
@@ -214,8 +220,6 @@ fatal(const char *fmt,...) | |||
214 | exit(255); | 220 | exit(255); |
215 | } | 221 | } |
216 | 222 | ||
217 | /* This stuff used to be in BSD rcp extern.h. */ | ||
218 | |||
219 | typedef struct { | 223 | typedef struct { |
220 | int cnt; | 224 | int cnt; |
221 | char *buf; | 225 | char *buf; |
@@ -231,8 +235,6 @@ int okname(char *); | |||
231 | void run_err(const char *,...); | 235 | void run_err(const char *,...); |
232 | void verifydir(char *); | 236 | void verifydir(char *); |
233 | 237 | ||
234 | /* Stuff from BSD rcp.c continues. */ | ||
235 | |||
236 | struct passwd *pwd; | 238 | struct passwd *pwd; |
237 | uid_t userid; | 239 | uid_t userid; |
238 | int errs, remin, remout; | 240 | int errs, remin, remout; |
@@ -260,7 +262,7 @@ main(argc, argv) | |||
260 | extern int optind; | 262 | extern int optind; |
261 | 263 | ||
262 | fflag = tflag = 0; | 264 | fflag = tflag = 0; |
263 | while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46")) != EOF) | 265 | while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S")) != EOF) |
264 | switch (ch) { | 266 | switch (ch) { |
265 | /* User-visible flags. */ | 267 | /* User-visible flags. */ |
266 | case '4': | 268 | case '4': |
@@ -278,6 +280,10 @@ main(argc, argv) | |||
278 | case 'r': | 280 | case 'r': |
279 | iamrecursive = 1; | 281 | iamrecursive = 1; |
280 | break; | 282 | break; |
283 | case 'S': | ||
284 | ssh_program = optarg; | ||
285 | break; | ||
286 | |||
281 | /* Server options. */ | 287 | /* Server options. */ |
282 | case 'd': | 288 | case 'd': |
283 | targetshouldbedirectory = 1; | 289 | targetshouldbedirectory = 1; |
@@ -343,8 +349,8 @@ main(argc, argv) | |||
343 | remin = remout = -1; | 349 | remin = remout = -1; |
344 | /* Command to be executed on remote system using "ssh". */ | 350 | /* Command to be executed on remote system using "ssh". */ |
345 | (void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", | 351 | (void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", |
346 | iamrecursive ? " -r" : "", pflag ? " -p" : "", | 352 | iamrecursive ? " -r" : "", pflag ? " -p" : "", |
347 | targetshouldbedirectory ? " -d" : ""); | 353 | targetshouldbedirectory ? " -d" : ""); |
348 | 354 | ||
349 | (void) signal(SIGPIPE, lostconn); | 355 | (void) signal(SIGPIPE, lostconn); |
350 | 356 | ||
@@ -401,9 +407,9 @@ toremote(targ, argc, argv) | |||
401 | if (*src == 0) | 407 | if (*src == 0) |
402 | src = "."; | 408 | src = "."; |
403 | host = strchr(argv[i], '@'); | 409 | host = strchr(argv[i], '@'); |
404 | len = strlen(SSH_PROGRAM) + strlen(argv[i]) + | 410 | len = strlen(ssh_program) + strlen(argv[i]) + |
405 | strlen(src) + (tuser ? strlen(tuser) : 0) + | 411 | strlen(src) + (tuser ? strlen(tuser) : 0) + |
406 | strlen(thost) + strlen(targ) + CMDNEEDS + 32; | 412 | strlen(thost) + strlen(targ) + CMDNEEDS + 32; |
407 | bp = xmalloc(len); | 413 | bp = xmalloc(len); |
408 | if (host) { | 414 | if (host) { |
409 | *host++ = 0; | 415 | *host++ = 0; |
@@ -414,19 +420,19 @@ toremote(targ, argc, argv) | |||
414 | else if (!okname(suser)) | 420 | else if (!okname(suser)) |
415 | continue; | 421 | continue; |
416 | (void) sprintf(bp, | 422 | (void) sprintf(bp, |
417 | "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'", | 423 | "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'", |
418 | SSH_PROGRAM, verbose_mode ? " -v" : "", | 424 | ssh_program, verbose_mode ? " -v" : "", |
419 | suser, host, cmd, src, | 425 | suser, host, cmd, src, |
420 | tuser ? tuser : "", tuser ? "@" : "", | 426 | tuser ? tuser : "", tuser ? "@" : "", |
421 | thost, targ); | 427 | thost, targ); |
422 | } else { | 428 | } else { |
423 | host = cleanhostname(argv[i]); | 429 | host = cleanhostname(argv[i]); |
424 | (void) sprintf(bp, | 430 | (void) sprintf(bp, |
425 | "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'", | 431 | "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'", |
426 | SSH_PROGRAM, verbose_mode ? " -v" : "", | 432 | ssh_program, verbose_mode ? " -v" : "", |
427 | host, cmd, src, | 433 | host, cmd, src, |
428 | tuser ? tuser : "", tuser ? "@" : "", | 434 | tuser ? tuser : "", tuser ? "@" : "", |
429 | thost, targ); | 435 | thost, targ); |
430 | } | 436 | } |
431 | if (verbose_mode) | 437 | if (verbose_mode) |
432 | fprintf(stderr, "Executing: %s\n", bp); | 438 | fprintf(stderr, "Executing: %s\n", bp); |
@@ -438,8 +444,8 @@ toremote(targ, argc, argv) | |||
438 | bp = xmalloc(len); | 444 | bp = xmalloc(len); |
439 | (void) sprintf(bp, "%s -t %s", cmd, targ); | 445 | (void) sprintf(bp, "%s -t %s", cmd, targ); |
440 | host = cleanhostname(thost); | 446 | host = cleanhostname(thost); |
441 | if (do_cmd(host, tuser, | 447 | if (do_cmd(host, tuser, bp, &remin, |
442 | bp, &remin, &remout) < 0) | 448 | &remout, argc) < 0) |
443 | exit(1); | 449 | exit(1); |
444 | if (response() < 0) | 450 | if (response() < 0) |
445 | exit(1); | 451 | exit(1); |
@@ -461,11 +467,11 @@ tolocal(argc, argv) | |||
461 | for (i = 0; i < argc - 1; i++) { | 467 | for (i = 0; i < argc - 1; i++) { |
462 | if (!(src = colon(argv[i]))) { /* Local to local. */ | 468 | if (!(src = colon(argv[i]))) { /* Local to local. */ |
463 | len = strlen(_PATH_CP) + strlen(argv[i]) + | 469 | len = strlen(_PATH_CP) + strlen(argv[i]) + |
464 | strlen(argv[argc - 1]) + 20; | 470 | strlen(argv[argc - 1]) + 20; |
465 | bp = xmalloc(len); | 471 | bp = xmalloc(len); |
466 | (void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP, | 472 | (void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP, |
467 | iamrecursive ? " -r" : "", pflag ? " -p" : "", | 473 | iamrecursive ? " -r" : "", pflag ? " -p" : "", |
468 | argv[i], argv[argc - 1]); | 474 | argv[i], argv[argc - 1]); |
469 | if (verbose_mode) | 475 | if (verbose_mode) |
470 | fprintf(stderr, "Executing: %s\n", bp); | 476 | fprintf(stderr, "Executing: %s\n", bp); |
471 | if (system(bp)) | 477 | if (system(bp)) |
@@ -491,7 +497,7 @@ tolocal(argc, argv) | |||
491 | len = strlen(src) + CMDNEEDS + 20; | 497 | len = strlen(src) + CMDNEEDS + 20; |
492 | bp = xmalloc(len); | 498 | bp = xmalloc(len); |
493 | (void) sprintf(bp, "%s -f %s", cmd, src); | 499 | (void) sprintf(bp, "%s -f %s", cmd, src); |
494 | if (do_cmd(host, suser, bp, &remin, &remout) < 0) { | 500 | if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) { |
495 | (void) xfree(bp); | 501 | (void) xfree(bp); |
496 | ++errs; | 502 | ++errs; |
497 | continue; | 503 | continue; |
@@ -548,8 +554,8 @@ syserr: run_err("%s: %s", name, strerror(errno)); | |||
548 | * versions expecting microseconds. | 554 | * versions expecting microseconds. |
549 | */ | 555 | */ |
550 | (void) sprintf(buf, "T%lu 0 %lu 0\n", | 556 | (void) sprintf(buf, "T%lu 0 %lu 0\n", |
551 | (unsigned long) stb.st_mtime, | 557 | (unsigned long) stb.st_mtime, |
552 | (unsigned long) stb.st_atime); | 558 | (unsigned long) stb.st_atime); |
553 | (void) atomicio(write, remout, buf, strlen(buf)); | 559 | (void) atomicio(write, remout, buf, strlen(buf)); |
554 | if (response() < 0) | 560 | if (response() < 0) |
555 | goto next; | 561 | goto next; |
@@ -626,8 +632,8 @@ rsource(name, statp) | |||
626 | last++; | 632 | last++; |
627 | if (pflag) { | 633 | if (pflag) { |
628 | (void) sprintf(path, "T%lu 0 %lu 0\n", | 634 | (void) sprintf(path, "T%lu 0 %lu 0\n", |
629 | (unsigned long) statp->st_mtime, | 635 | (unsigned long) statp->st_mtime, |
630 | (unsigned long) statp->st_atime); | 636 | (unsigned long) statp->st_atime); |
631 | (void) atomicio(write, remout, path, strlen(path)); | 637 | (void) atomicio(write, remout, path, strlen(path)); |
632 | if (response() < 0) { | 638 | if (response() < 0) { |
633 | closedir(dirp); | 639 | closedir(dirp); |
@@ -635,8 +641,7 @@ rsource(name, statp) | |||
635 | } | 641 | } |
636 | } | 642 | } |
637 | (void) sprintf(path, "D%04o %d %.1024s\n", | 643 | (void) sprintf(path, "D%04o %d %.1024s\n", |
638 | (unsigned int) (statp->st_mode & FILEMODEMASK), | 644 | (unsigned int) (statp->st_mode & FILEMODEMASK), 0, last); |
639 | 0, last); | ||
640 | if (verbose_mode) | 645 | if (verbose_mode) |
641 | fprintf(stderr, "Entering directory: %s", path); | 646 | fprintf(stderr, "Entering directory: %s", path); |
642 | (void) atomicio(write, remout, path, strlen(path)); | 647 | (void) atomicio(write, remout, path, strlen(path)); |
@@ -783,7 +788,7 @@ sink(argc, argv) | |||
783 | if (need > cursize) | 788 | if (need > cursize) |
784 | namebuf = xmalloc(need); | 789 | namebuf = xmalloc(need); |
785 | (void) sprintf(namebuf, "%s%s%s", targ, | 790 | (void) sprintf(namebuf, "%s%s%s", targ, |
786 | *targ ? "/" : "", cp); | 791 | *targ ? "/" : "", cp); |
787 | np = namebuf; | 792 | np = namebuf; |
788 | } else | 793 | } else |
789 | np = targ; | 794 | np = targ; |
@@ -954,8 +959,9 @@ response() | |||
954 | void | 959 | void |
955 | usage() | 960 | usage() |
956 | { | 961 | { |
957 | (void) fprintf(stderr, | 962 | (void) fprintf(stderr, "usage: scp " |
958 | "usage: scp [-pqrvC46] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n"); | 963 | "[-pqrvC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2; or:\n" |
964 | " scp [options] f1 ... fn directory\n"); | ||
959 | exit(1); | 965 | exit(1); |
960 | } | 966 | } |
961 | 967 | ||
@@ -984,43 +990,6 @@ run_err(const char *fmt,...) | |||
984 | } | 990 | } |
985 | } | 991 | } |
986 | 992 | ||
987 | /* Stuff below is from BSD rcp util.c. */ | ||
988 | |||
989 | /*- | ||
990 | * Copyright (c) 1992, 1993 | ||
991 | * The Regents of the University of California. All rights reserved. | ||
992 | * | ||
993 | * Redistribution and use in source and binary forms, with or without | ||
994 | * modification, are permitted provided that the following conditions | ||
995 | * are met: | ||
996 | * 1. Redistributions of source code must retain the above copyright | ||
997 | * notice, this list of conditions and the following disclaimer. | ||
998 | * 2. Redistributions in binary form must reproduce the above copyright | ||
999 | * notice, this list of conditions and the following disclaimer in the | ||
1000 | * documentation and/or other materials provided with the distribution. | ||
1001 | * 3. All advertising materials mentioning features or use of this software | ||
1002 | * must display the following acknowledgement: | ||
1003 | * This product includes software developed by the University of | ||
1004 | * California, Berkeley and its contributors. | ||
1005 | * 4. Neither the name of the University nor the names of its contributors | ||
1006 | * may be used to endorse or promote products derived from this software | ||
1007 | * without specific prior written permission. | ||
1008 | * | ||
1009 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
1010 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
1011 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
1012 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
1013 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
1014 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
1015 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
1016 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
1017 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
1018 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
1019 | * SUCH DAMAGE. | ||
1020 | * | ||
1021 | * $OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $ | ||
1022 | */ | ||
1023 | |||
1024 | char * | 993 | char * |
1025 | colon(cp) | 994 | colon(cp) |
1026 | char *cp; | 995 | char *cp; |
@@ -1097,7 +1066,7 @@ allocbuf(bp, fd, blksize) | |||
1097 | size = blksize; | 1066 | size = blksize; |
1098 | else | 1067 | else |
1099 | size = blksize + (stb.st_blksize - blksize % stb.st_blksize) % | 1068 | size = blksize + (stb.st_blksize - blksize % stb.st_blksize) % |
1100 | stb.st_blksize; | 1069 | stb.st_blksize; |
1101 | if (bp->cnt >= size) | 1070 | if (bp->cnt >= size) |
1102 | return (bp); | 1071 | return (bp); |
1103 | if (bp->buf == NULL) | 1072 | if (bp->buf == NULL) |
@@ -1228,14 +1197,14 @@ progressmeter(int flag) | |||
1228 | i = remaining / 3600; | 1197 | i = remaining / 3600; |
1229 | if (i) | 1198 | if (i) |
1230 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), | 1199 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
1231 | "%2d:", i); | 1200 | "%2d:", i); |
1232 | else | 1201 | else |
1233 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), | 1202 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
1234 | " "); | 1203 | " "); |
1235 | i = remaining % 3600; | 1204 | i = remaining % 3600; |
1236 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), | 1205 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
1237 | "%02d:%02d%s", i / 60, i % 60, | 1206 | "%02d:%02d%s", i / 60, i % 60, |
1238 | (flag != 1) ? " ETA" : " "); | 1207 | (flag != 1) ? " ETA" : " "); |
1239 | } | 1208 | } |
1240 | atomicio(write, fileno(stdout), buf, strlen(buf)); | 1209 | atomicio(write, fileno(stdout), buf, strlen(buf)); |
1241 | 1210 | ||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "includes.h" | 10 | #include "includes.h" |
11 | RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $"); | 11 | RCSID("$OpenBSD: session.c,v 1.29 2000/08/21 16:23:31 millert Exp $"); |
12 | 12 | ||
13 | #include "xmalloc.h" | 13 | #include "xmalloc.h" |
14 | #include "ssh.h" | 14 | #include "ssh.h" |
@@ -52,6 +52,10 @@ RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $"); | |||
52 | # define S_UNOFILE_HARD S_UNOFILE "_hard" | 52 | # define S_UNOFILE_HARD S_UNOFILE "_hard" |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | #ifdef HAVE_LOGIN_CAP | ||
56 | #include <login_cap.h> | ||
57 | #endif | ||
58 | |||
55 | /* types */ | 59 | /* types */ |
56 | 60 | ||
57 | #define TTYSZ 64 | 61 | #define TTYSZ 64 |
@@ -117,6 +121,10 @@ Session sessions[MAX_SESSIONS]; | |||
117 | char *aixloginmsg; | 121 | char *aixloginmsg; |
118 | #endif /* WITH_AIXAUTHENTICATE */ | 122 | #endif /* WITH_AIXAUTHENTICATE */ |
119 | 123 | ||
124 | #ifdef HAVE_LOGIN_CAP | ||
125 | static login_cap_t *lc; | ||
126 | #endif | ||
127 | |||
120 | /* | 128 | /* |
121 | * Remove local Xauthority file. | 129 | * Remove local Xauthority file. |
122 | */ | 130 | */ |
@@ -200,6 +208,13 @@ do_authenticated(struct passwd * pw) | |||
200 | s = session_new(); | 208 | s = session_new(); |
201 | s->pw = pw; | 209 | s->pw = pw; |
202 | 210 | ||
211 | #ifdef HAVE_LOGIN_CAP | ||
212 | if ((lc = login_getclass(pw->pw_class)) == NULL) { | ||
213 | error("unable to get login class"); | ||
214 | return; | ||
215 | } | ||
216 | #endif | ||
217 | |||
203 | /* | 218 | /* |
204 | * We stay in this loop until the client requests to execute a shell | 219 | * We stay in this loop until the client requests to execute a shell |
205 | * or a command. | 220 | * or a command. |
@@ -650,7 +665,11 @@ do_login(Session *s) | |||
650 | 665 | ||
651 | /* Done if .hushlogin exists. */ | 666 | /* Done if .hushlogin exists. */ |
652 | snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); | 667 | snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); |
668 | #ifdef HAVE_LOGIN_CAP | ||
669 | if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0) | ||
670 | #else | ||
653 | if (stat(buf, &st) >= 0) | 671 | if (stat(buf, &st) >= 0) |
672 | #endif | ||
654 | return; | 673 | return; |
655 | 674 | ||
656 | #ifdef USE_PAM | 675 | #ifdef USE_PAM |
@@ -677,7 +696,12 @@ do_login(Session *s) | |||
677 | printf("Last login: %s from %s\r\n", time_string, buf); | 696 | printf("Last login: %s from %s\r\n", time_string, buf); |
678 | } | 697 | } |
679 | if (options.print_motd) { | 698 | if (options.print_motd) { |
699 | #ifdef HAVE_LOGIN_CAP | ||
700 | f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", | ||
701 | "/etc/motd"), "r"); | ||
702 | #else | ||
680 | f = fopen("/etc/motd", "r"); | 703 | f = fopen("/etc/motd", "r"); |
704 | #endif | ||
681 | if (f) { | 705 | if (f) { |
682 | while (fgets(buf, sizeof(buf), f)) | 706 | while (fgets(buf, sizeof(buf), f)) |
683 | fputs(buf, stdout); | 707 | fputs(buf, stdout); |
@@ -887,10 +911,10 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
887 | const char *display, const char *auth_proto, | 911 | const char *display, const char *auth_proto, |
888 | const char *auth_data, const char *ttyname) | 912 | const char *auth_data, const char *ttyname) |
889 | { | 913 | { |
890 | const char *shell, *cp = NULL; | 914 | const char *shell, *hostname, *cp = NULL; |
891 | char buf[256]; | 915 | char buf[256]; |
892 | char cmd[1024]; | 916 | char cmd[1024]; |
893 | FILE *f; | 917 | FILE *f = NULL; |
894 | unsigned int envsize, i; | 918 | unsigned int envsize, i; |
895 | char **env; | 919 | char **env; |
896 | extern char **environ; | 920 | extern char **environ; |
@@ -905,24 +929,26 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
905 | options.use_login = 0; | 929 | options.use_login = 0; |
906 | 930 | ||
907 | #ifndef USE_PAM /* pam_nologin handles this */ | 931 | #ifndef USE_PAM /* pam_nologin handles this */ |
908 | f = fopen("/etc/nologin", "r"); | 932 | if (!options.use_login) { |
909 | if (f) { | 933 | # ifdef HAVE_LOGIN_CAP |
910 | /* /etc/nologin exists. Print its contents and exit. */ | 934 | if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) |
911 | while (fgets(buf, sizeof(buf), f)) | 935 | f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, |
912 | fputs(buf, stderr); | 936 | _PATH_NOLOGIN), "r"); |
913 | fclose(f); | 937 | # else /* HAVE_LOGIN_CAP */ |
914 | if (pw->pw_uid != 0) | 938 | if (pw->pw_uid) |
939 | f = fopen(_PATH_NOLOGIN, "r"); | ||
940 | # endif /* HAVE_LOGIN_CAP */ | ||
941 | if (f) { | ||
942 | /* /etc/nologin exists. Print its contents and exit. */ | ||
943 | while (fgets(buf, sizeof(buf), f)) | ||
944 | fputs(buf, stderr); | ||
945 | fclose(f); | ||
915 | exit(254); | 946 | exit(254); |
947 | } | ||
916 | } | 948 | } |
917 | #endif /* USE_PAM */ | 949 | #endif /* USE_PAM */ |
918 | 950 | ||
919 | #ifndef HAVE_OSF_SIA | 951 | /* Set login name, uid, gid, and groups. */ |
920 | /* Set login name in the kernel. */ | ||
921 | if (setlogin(pw->pw_name) < 0) | ||
922 | error("setlogin failed: %s", strerror(errno)); | ||
923 | #endif | ||
924 | |||
925 | /* Set uid, gid, and groups. */ | ||
926 | /* Login(1) does this as well, and it needs uid 0 for the "-h" | 952 | /* Login(1) does this as well, and it needs uid 0 for the "-h" |
927 | switch, so we let login(1) to this for us. */ | 953 | switch, so we let login(1) to this for us. */ |
928 | if (!options.use_login) { | 954 | if (!options.use_login) { |
@@ -943,10 +969,18 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
943 | } | 969 | } |
944 | #else /* HAVE_OSF_SIA */ | 970 | #else /* HAVE_OSF_SIA */ |
945 | if (getuid() == 0 || geteuid() == 0) { | 971 | if (getuid() == 0 || geteuid() == 0) { |
946 | #if defined(HAVE_GETUSERATTR) | 972 | # ifdef HAVE_GETUSERATTR |
947 | set_limits_from_userattr(pw->pw_name); | 973 | set_limits_from_userattr(pw->pw_name); |
948 | #endif /* defined(HAVE_GETUSERATTR) */ | 974 | # endif /* HAVE_GETUSERATTR */ |
949 | 975 | # ifdef HAVE_LOGIN_CAP | |
976 | if (setusercontext(lc, pw, pw->pw_uid, | ||
977 | (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { | ||
978 | perror("unable to set user context"); | ||
979 | exit(1); | ||
980 | } | ||
981 | # else /* HAVE_LOGIN_CAP */ | ||
982 | if (setlogin(pw->pw_name) < 0) | ||
983 | error("setlogin failed: %s", strerror(errno)); | ||
950 | if (setgid(pw->pw_gid) < 0) { | 984 | if (setgid(pw->pw_gid) < 0) { |
951 | perror("setgid"); | 985 | perror("setgid"); |
952 | exit(1); | 986 | exit(1); |
@@ -957,38 +991,39 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
957 | exit(1); | 991 | exit(1); |
958 | } | 992 | } |
959 | endgrent(); | 993 | endgrent(); |
960 | 994 | # ifdef WITH_IRIX_ARRAY | |
961 | #ifdef WITH_IRIX_ARRAY | ||
962 | /* initialize array session */ | 995 | /* initialize array session */ |
963 | if (newarraysess() != 0) | 996 | if (newarraysess() != 0) |
964 | fatal("Failed to set up new array session: %.100s", | 997 | fatal("Failed to set up new array session: %.100s", |
965 | strerror(errno)); | 998 | strerror(errno)); |
966 | #endif /* WITH_IRIX_ARRAY */ | 999 | # endif /* WITH_IRIX_ARRAY */ |
967 | 1000 | # ifdef WITH_IRIX_PROJECT | |
968 | #ifdef WITH_IRIX_PROJECT | ||
969 | /* initialize irix project info */ | 1001 | /* initialize irix project info */ |
970 | if ((projid = getdfltprojuser(pw->pw_name)) == -1) { | 1002 | if ((projid = getdfltprojuser(pw->pw_name)) == -1) { |
971 | debug("Failed to get project id, using projid 0"); | 1003 | debug("Failed to get project id, using projid 0"); |
972 | projid = 0; | 1004 | projid = 0; |
973 | } | 1005 | } |
974 | |||
975 | if (setprid(projid)) | 1006 | if (setprid(projid)) |
976 | fatal("Failed to initialize project %d for %s: %.100s", | 1007 | fatal("Failed to initialize project %d for %s: %.100s", |
977 | (int)projid, pw->pw_name, strerror(errno)); | 1008 | (int)projid, pw->pw_name, strerror(errno)); |
978 | #endif /* WITH_IRIX_PROJECT */ | 1009 | # endif /* WITH_IRIX_PROJECT */ |
979 | |||
980 | /* Permanently switch to the desired uid. */ | 1010 | /* Permanently switch to the desired uid. */ |
981 | permanently_set_uid(pw->pw_uid); | 1011 | permanently_set_uid(pw->pw_uid); |
1012 | # endif /* HAVE_LOGIN_CAP */ | ||
982 | } | 1013 | } |
1014 | #endif /* HAVE_OSF_SIA */ | ||
1015 | |||
983 | if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) | 1016 | if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) |
984 | fatal("Failed to set uids to %d.", (int) pw->pw_uid); | 1017 | fatal("Failed to set uids to %d.", (int) pw->pw_uid); |
985 | #endif /* HAVE_OSF_SIA */ | ||
986 | } | 1018 | } |
987 | /* | 1019 | /* |
988 | * Get the shell from the password data. An empty shell field is | 1020 | * Get the shell from the password data. An empty shell field is |
989 | * legal, and means /bin/sh. | 1021 | * legal, and means /bin/sh. |
990 | */ | 1022 | */ |
991 | shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; | 1023 | shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; |
1024 | #ifdef HAVE_LOGIN_CAP | ||
1025 | shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); | ||
1026 | #endif | ||
992 | 1027 | ||
993 | #ifdef AFS | 1028 | #ifdef AFS |
994 | /* Try to get AFS tokens for the local cell. */ | 1029 | /* Try to get AFS tokens for the local cell. */ |
@@ -1012,7 +1047,12 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
1012 | child_set_env(&env, &envsize, "USER", pw->pw_name); | 1047 | child_set_env(&env, &envsize, "USER", pw->pw_name); |
1013 | child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); | 1048 | child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); |
1014 | child_set_env(&env, &envsize, "HOME", pw->pw_dir); | 1049 | child_set_env(&env, &envsize, "HOME", pw->pw_dir); |
1050 | #ifdef HAVE_LOGIN_CAP | ||
1051 | (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH); | ||
1052 | child_set_env(&env, &envsize, "PATH", getenv("PATH")); | ||
1053 | #else | ||
1015 | child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); | 1054 | child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); |
1055 | #endif | ||
1016 | 1056 | ||
1017 | snprintf(buf, sizeof buf, "%.200s/%.50s", | 1057 | snprintf(buf, sizeof buf, "%.200s/%.50s", |
1018 | _PATH_MAILDIR, pw->pw_name); | 1058 | _PATH_MAILDIR, pw->pw_name); |
@@ -1096,6 +1136,9 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
1096 | for (i = 0; env[i]; i++) | 1136 | for (i = 0; env[i]; i++) |
1097 | fprintf(stderr, " %.200s\n", env[i]); | 1137 | fprintf(stderr, " %.200s\n", env[i]); |
1098 | } | 1138 | } |
1139 | /* we have to stash the hostname before we close our socket. */ | ||
1140 | if (options.use_login) | ||
1141 | hostname = get_remote_name_or_ip(); | ||
1099 | /* | 1142 | /* |
1100 | * Close the connection descriptors; note that this is the child, and | 1143 | * Close the connection descriptors; note that this is the child, and |
1101 | * the server will still have the socket open, and it is important | 1144 | * the server will still have the socket open, and it is important |
@@ -1132,9 +1175,14 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
1132 | close(i); | 1175 | close(i); |
1133 | 1176 | ||
1134 | /* Change current directory to the user\'s home directory. */ | 1177 | /* Change current directory to the user\'s home directory. */ |
1135 | if (chdir(pw->pw_dir) < 0) | 1178 | if (chdir(pw->pw_dir) < 0) { |
1136 | fprintf(stderr, "Could not chdir to home directory %s: %s\n", | 1179 | fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
1137 | pw->pw_dir, strerror(errno)); | 1180 | pw->pw_dir, strerror(errno)); |
1181 | #ifdef HAVE_LOGIN_CAP | ||
1182 | if (login_getcapbool(lc, "requirehome", 0)) | ||
1183 | exit(1); | ||
1184 | #endif | ||
1185 | } | ||
1138 | 1186 | ||
1139 | /* | 1187 | /* |
1140 | * Must take new environment into use so that .ssh/rc, /etc/sshrc and | 1188 | * Must take new environment into use so that .ssh/rc, /etc/sshrc and |
@@ -1252,8 +1300,7 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
1252 | } else { | 1300 | } else { |
1253 | /* Launch login(1). */ | 1301 | /* Launch login(1). */ |
1254 | 1302 | ||
1255 | execl(LOGIN_PROGRAM, "login", | 1303 | execl(LOGIN_PROGRAM, "login", "-h", hostname, |
1256 | "-h", get_remote_name_or_ip(), | ||
1257 | "-p", "-f", "--", pw->pw_name, NULL); | 1304 | "-p", "-f", "--", pw->pw_name, NULL); |
1258 | 1305 | ||
1259 | /* Login couldn't be executed, die. */ | 1306 | /* Login couldn't be executed, die. */ |
@@ -1790,6 +1837,8 @@ session_proctitle(Session *s) | |||
1790 | void | 1837 | void |
1791 | do_authenticated2(void) | 1838 | do_authenticated2(void) |
1792 | { | 1839 | { |
1840 | struct passwd *pw; | ||
1841 | |||
1793 | /* | 1842 | /* |
1794 | * Cancel the alarm we set to limit the time taken for | 1843 | * Cancel the alarm we set to limit the time taken for |
1795 | * authentication. | 1844 | * authentication. |
@@ -1799,6 +1848,13 @@ do_authenticated2(void) | |||
1799 | close(startup_pipe); | 1848 | close(startup_pipe); |
1800 | startup_pipe = -1; | 1849 | startup_pipe = -1; |
1801 | } | 1850 | } |
1851 | #ifdef HAVE_LOGIN_CAP | ||
1852 | pw = auth_get_user(); | ||
1853 | if ((lc = login_getclass(pw->pw_class)) == NULL) { | ||
1854 | error("unable to get login class"); | ||
1855 | return; | ||
1856 | } | ||
1857 | #endif | ||
1802 | server_loop2(); | 1858 | server_loop2(); |
1803 | if (xauthfile) | 1859 | if (xauthfile) |
1804 | xauthfile_cleanup_proc(NULL); | 1860 | xauthfile_cleanup_proc(NULL); |
@@ -9,21 +9,21 @@ | |||
9 | .\" | 9 | .\" |
10 | .\" Created: Sat Apr 22 23:55:14 1995 ylo | 10 | .\" Created: Sat Apr 22 23:55:14 1995 ylo |
11 | .\" | 11 | .\" |
12 | .\" $Id: ssh-add.1,v 1.13 2000/05/07 02:03:18 damien Exp $ | 12 | .\" $Id: ssh-add.1,v 1.14 2000/08/23 00:46:24 djm Exp $ |
13 | .\" | 13 | .\" |
14 | .Dd September 25, 1999 | 14 | .Dd September 25, 1999 |
15 | .Dt SSH-ADD 1 | 15 | .Dt SSH-ADD 1 |
16 | .Os | 16 | .Os |
17 | .Sh NAME | 17 | .Sh NAME |
18 | .Nm ssh-add | 18 | .Nm ssh-add |
19 | .Nd adds RSA identities for the authentication agent | 19 | .Nd adds RSA or DSA identities for the authentication agent |
20 | .Sh SYNOPSIS | 20 | .Sh SYNOPSIS |
21 | .Nm ssh-add | 21 | .Nm ssh-add |
22 | .Op Fl lLdD | 22 | .Op Fl lLdD |
23 | .Op Ar | 23 | .Op Ar |
24 | .Sh DESCRIPTION | 24 | .Sh DESCRIPTION |
25 | .Nm | 25 | .Nm |
26 | adds RSA identities to the authentication agent, | 26 | adds RSA or DSA identities to the authentication agent, |
27 | .Xr ssh-agent 1 . | 27 | .Xr ssh-agent 1 . |
28 | When run without arguments, it adds the file | 28 | When run without arguments, it adds the file |
29 | .Pa $HOME/.ssh/identity . | 29 | .Pa $HOME/.ssh/identity . |
@@ -63,6 +63,8 @@ used to encrypt the private part of this file. | |||
63 | This is the default file added by | 63 | This is the default file added by |
64 | .Nm | 64 | .Nm |
65 | when no other files have been specified. | 65 | when no other files have been specified. |
66 | .It Pa $HOME/.ssh/id_dsa | ||
67 | Contains the DSA authentication identity of the user. | ||
66 | .Pp | 68 | .Pp |
67 | .Sh ENVIRONMENT | 69 | .Sh ENVIRONMENT |
68 | .Bl -tag -width Ds | 70 | .Bl -tag -width Ds |
@@ -4,18 +4,21 @@ | |||
4 | * All rights reserved | 4 | * All rights reserved |
5 | * Created: Thu Apr 6 00:52:24 1995 ylo | 5 | * Created: Thu Apr 6 00:52:24 1995 ylo |
6 | * Adds an identity to the authentication server, or removes an identity. | 6 | * Adds an identity to the authentication server, or removes an identity. |
7 | * | ||
8 | * SSH2 implementation, | ||
9 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
7 | */ | 10 | */ |
8 | 11 | ||
9 | #include "includes.h" | 12 | #include "includes.h" |
10 | RCSID("$OpenBSD: ssh-add.c,v 1.18 2000/07/16 08:27:21 markus Exp $"); | 13 | RCSID("$OpenBSD: ssh-add.c,v 1.19 2000/08/19 21:34:43 markus Exp $"); |
11 | 14 | ||
15 | #include <openssl/evp.h> | ||
12 | #include <openssl/rsa.h> | 16 | #include <openssl/rsa.h> |
13 | #include <openssl/dsa.h> | 17 | #include <openssl/dsa.h> |
14 | 18 | ||
15 | #include "rsa.h" | 19 | #include "rsa.h" |
16 | #include "ssh.h" | 20 | #include "ssh.h" |
17 | #include "xmalloc.h" | 21 | #include "xmalloc.h" |
18 | #include "fingerprint.h" | ||
19 | #include "key.h" | 22 | #include "key.h" |
20 | #include "authfd.h" | 23 | #include "authfd.h" |
21 | #include "authfile.h" | 24 | #include "authfile.h" |
@@ -37,7 +40,7 @@ delete_file(AuthenticationConnection *ac, const char *filename) | |||
37 | printf("Bad key file %s: %s\n", filename, strerror(errno)); | 40 | printf("Bad key file %s: %s\n", filename, strerror(errno)); |
38 | return; | 41 | return; |
39 | } | 42 | } |
40 | if (ssh_remove_identity(ac, public->rsa)) | 43 | if (ssh_remove_identity(ac, public)) |
41 | fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); | 44 | fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); |
42 | else | 45 | else |
43 | fprintf(stderr, "Could not remove identity: %s\n", filename); | 46 | fprintf(stderr, "Could not remove identity: %s\n", filename); |
@@ -45,11 +48,18 @@ delete_file(AuthenticationConnection *ac, const char *filename) | |||
45 | xfree(comment); | 48 | xfree(comment); |
46 | } | 49 | } |
47 | 50 | ||
51 | /* Send a request to remove all identities. */ | ||
48 | void | 52 | void |
49 | delete_all(AuthenticationConnection *ac) | 53 | delete_all(AuthenticationConnection *ac) |
50 | { | 54 | { |
51 | /* Send a request to remove all identities. */ | 55 | int success = 1; |
52 | if (ssh_remove_all_identities(ac)) | 56 | |
57 | if (!ssh_remove_all_identities(ac, 1)) | ||
58 | success = 0; | ||
59 | /* ignore error-code for ssh2 */ | ||
60 | ssh_remove_all_identities(ac, 2); | ||
61 | |||
62 | if (success) | ||
53 | fprintf(stderr, "All identities removed.\n"); | 63 | fprintf(stderr, "All identities removed.\n"); |
54 | else | 64 | else |
55 | fprintf(stderr, "Failed to remove all identitities.\n"); | 65 | fprintf(stderr, "Failed to remove all identitities.\n"); |
@@ -96,6 +106,7 @@ ssh_askpass(char *askpass, char *msg) | |||
96 | void | 106 | void |
97 | add_file(AuthenticationConnection *ac, const char *filename) | 107 | add_file(AuthenticationConnection *ac, const char *filename) |
98 | { | 108 | { |
109 | struct stat st; | ||
99 | Key *public; | 110 | Key *public; |
100 | Key *private; | 111 | Key *private; |
101 | char *saved_comment, *comment, *askpass = NULL; | 112 | char *saved_comment, *comment, *askpass = NULL; |
@@ -104,6 +115,10 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
104 | int interactive = isatty(STDIN_FILENO); | 115 | int interactive = isatty(STDIN_FILENO); |
105 | int type = KEY_RSA; | 116 | int type = KEY_RSA; |
106 | 117 | ||
118 | if (stat(filename, &st) < 0) { | ||
119 | perror(filename); | ||
120 | exit(1); | ||
121 | } | ||
107 | /* | 122 | /* |
108 | * try to load the public key. right now this only works for RSA, | 123 | * try to load the public key. right now this only works for RSA, |
109 | * since DSA keys are fully encrypted | 124 | * since DSA keys are fully encrypted |
@@ -154,54 +169,40 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
154 | strlcpy(msg, "Bad passphrase, try again", sizeof msg); | 169 | strlcpy(msg, "Bad passphrase, try again", sizeof msg); |
155 | } | 170 | } |
156 | } | 171 | } |
157 | xfree(saved_comment); | 172 | xfree(comment); |
158 | 173 | if (ssh_add_identity(ac, private, saved_comment)) | |
159 | if (ssh_add_identity(ac, private, comment)) | 174 | fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment); |
160 | fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); | ||
161 | else | 175 | else |
162 | fprintf(stderr, "Could not add identity: %s\n", filename); | 176 | fprintf(stderr, "Could not add identity: %s\n", filename); |
163 | key_free(private); | 177 | key_free(private); |
164 | xfree(comment); | 178 | xfree(saved_comment); |
165 | } | 179 | } |
166 | 180 | ||
167 | void | 181 | void |
168 | list_identities(AuthenticationConnection *ac, int fp) | 182 | list_identities(AuthenticationConnection *ac, int fp) |
169 | { | 183 | { |
170 | BIGNUM *e, *n; | 184 | Key *key; |
171 | int status; | ||
172 | char *comment; | 185 | char *comment; |
173 | int had_identities; | 186 | int had_identities = 0; |
187 | int version; | ||
174 | 188 | ||
175 | e = BN_new(); | 189 | for (version = 1; version <= 2; version++) { |
176 | n = BN_new(); | 190 | for (key = ssh_get_first_identity(ac, &comment, version); |
177 | had_identities = 0; | 191 | key != NULL; |
178 | for (status = ssh_get_first_identity(ac, e, n, &comment); | 192 | key = ssh_get_next_identity(ac, &comment, version)) { |
179 | status; | 193 | had_identities = 1; |
180 | status = ssh_get_next_identity(ac, e, n, &comment)) { | 194 | if (fp) { |
181 | unsigned int bits = BN_num_bits(n); | 195 | printf("%d %s %s\n", |
182 | had_identities = 1; | 196 | key_size(key), key_fingerprint(key), comment); |
183 | if (fp) { | ||
184 | printf("%d %s %s\n", bits, fingerprint(e, n), comment); | ||
185 | } else { | ||
186 | char *ebuf, *nbuf; | ||
187 | ebuf = BN_bn2dec(e); | ||
188 | if (ebuf == NULL) { | ||
189 | error("list_identities: BN_bn2dec(e) failed."); | ||
190 | } else { | 197 | } else { |
191 | nbuf = BN_bn2dec(n); | 198 | if (!key_write(key, stdout)) |
192 | if (nbuf == NULL) { | 199 | fprintf(stderr, "key_write failed"); |
193 | error("list_identities: BN_bn2dec(n) failed."); | 200 | fprintf(stdout, " %s\n", comment); |
194 | } else { | ||
195 | printf("%d %s %s %s\n", bits, ebuf, nbuf, comment); | ||
196 | free(nbuf); | ||
197 | } | ||
198 | free(ebuf); | ||
199 | } | 201 | } |
202 | key_free(key); | ||
203 | xfree(comment); | ||
200 | } | 204 | } |
201 | xfree(comment); | ||
202 | } | 205 | } |
203 | BN_clear_free(e); | ||
204 | BN_clear_free(n); | ||
205 | if (!had_identities) | 206 | if (!had_identities) |
206 | printf("The agent has no identities.\n"); | 207 | printf("The agent has no identities.\n"); |
207 | } | 208 | } |
@@ -225,6 +226,8 @@ main(int argc, char **argv) | |||
225 | __progname); | 226 | __progname); |
226 | exit(1); | 227 | exit(1); |
227 | } | 228 | } |
229 | SSLeay_add_all_algorithms(); | ||
230 | |||
228 | /* At first, get a connection to the authentication agent. */ | 231 | /* At first, get a connection to the authentication agent. */ |
229 | ac = ssh_get_authentication_connection(); | 232 | ac = ssh_get_authentication_connection(); |
230 | if (ac == NULL) { | 233 | if (ac == NULL) { |
diff --git a/ssh-agent.1 b/ssh-agent.1 index 47b1e5cc5..0aa1ecf49 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-agent.1,v 1.13 2000/07/06 04:06:56 aaron Exp $ | 1 | .\" $OpenBSD: ssh-agent.1,v 1.14 2000/08/19 21:34:43 markus Exp $ |
2 | .\" | 2 | .\" |
3 | .\" -*- nroff -*- | 3 | .\" -*- nroff -*- |
4 | .\" | 4 | .\" |
@@ -27,14 +27,15 @@ | |||
27 | .Oc | 27 | .Oc |
28 | .Sh DESCRIPTION | 28 | .Sh DESCRIPTION |
29 | .Nm | 29 | .Nm |
30 | is a program to hold private keys used for RSA authentication. | 30 | is a program to hold private keys used for public key authentication |
31 | (RSA, DSA). | ||
31 | The idea is that | 32 | The idea is that |
32 | .Nm | 33 | .Nm |
33 | is started in the beginning of an X-session or a login session, and | 34 | is started in the beginning of an X-session or a login session, and |
34 | all other windows or programs are started as clients to the ssh-agent | 35 | all other windows or programs are started as clients to the ssh-agent |
35 | program. | 36 | program. |
36 | Through use of environment variables the agent can be located | 37 | Through use of environment variables the agent can be located |
37 | and automatically used for RSA authentication when logging in to other | 38 | and automatically used for authentication when logging in to other |
38 | machines using | 39 | machines using |
39 | .Xr ssh 1 . | 40 | .Xr ssh 1 . |
40 | .Pp | 41 | .Pp |
@@ -128,7 +129,9 @@ This file is not used by | |||
128 | but is normally added to the agent using | 129 | but is normally added to the agent using |
129 | .Xr ssh-add 1 | 130 | .Xr ssh-add 1 |
130 | at login time. | 131 | at login time. |
131 | .It Pa /tmp/ssh-XXXX/agent.<pid> , | 132 | .It Pa $HOME/.ssh/id_dsa |
133 | Contains the DSA authentication identity of the user. | ||
134 | .Pq Pa /tmp/ssh-XXXXXXXX/agent.<pid> , | ||
132 | Unix-domain sockets used to contain the connection to the | 135 | Unix-domain sockets used to contain the connection to the |
133 | authentication agent. | 136 | authentication agent. |
134 | These sockets should only be readable by the owner. | 137 | These sockets should only be readable by the owner. |
diff --git a/ssh-agent.c b/ssh-agent.c index e8383b5df..56b81a78d 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -6,10 +6,13 @@ | |||
6 | * All rights reserved | 6 | * All rights reserved |
7 | * Created: Wed Mar 29 03:46:59 1995 ylo | 7 | * Created: Wed Mar 29 03:46:59 1995 ylo |
8 | * The authentication agent program. | 8 | * The authentication agent program. |
9 | * | ||
10 | * SSH2 implementation, | ||
11 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
9 | */ | 12 | */ |
10 | 13 | ||
11 | #include "includes.h" | 14 | #include "includes.h" |
12 | RCSID("$OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $"); | 15 | RCSID("$OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $"); |
13 | 16 | ||
14 | #include "ssh.h" | 17 | #include "ssh.h" |
15 | #include "rsa.h" | 18 | #include "rsa.h" |
@@ -20,11 +23,14 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.32 2000/07/16 08:27:21 markus Exp $"); | |||
20 | #include "getput.h" | 23 | #include "getput.h" |
21 | #include "mpaux.h" | 24 | #include "mpaux.h" |
22 | 25 | ||
26 | #include <openssl/evp.h> | ||
23 | #include <openssl/md5.h> | 27 | #include <openssl/md5.h> |
24 | #include <openssl/dsa.h> | 28 | #include <openssl/dsa.h> |
25 | #include <openssl/rsa.h> | 29 | #include <openssl/rsa.h> |
26 | #include "key.h" | 30 | #include "key.h" |
27 | #include "authfd.h" | 31 | #include "authfd.h" |
32 | #include "dsa.h" | ||
33 | #include "kex.h" | ||
28 | 34 | ||
29 | typedef struct { | 35 | typedef struct { |
30 | int fd; | 36 | int fd; |
@@ -39,12 +45,17 @@ unsigned int sockets_alloc = 0; | |||
39 | SocketEntry *sockets = NULL; | 45 | SocketEntry *sockets = NULL; |
40 | 46 | ||
41 | typedef struct { | 47 | typedef struct { |
42 | RSA *key; | 48 | Key *key; |
43 | char *comment; | 49 | char *comment; |
44 | } Identity; | 50 | } Identity; |
45 | 51 | ||
46 | unsigned int num_identities = 0; | 52 | typedef struct { |
47 | Identity *identities = NULL; | 53 | int nentries; |
54 | Identity *identities; | ||
55 | } Idtab; | ||
56 | |||
57 | /* private key table, one per protocol version */ | ||
58 | Idtab idtable[3]; | ||
48 | 59 | ||
49 | int max_fd = 0; | 60 | int max_fd = 0; |
50 | 61 | ||
@@ -62,175 +73,243 @@ static const char *__progname = "ssh-agent"; | |||
62 | #endif /* HAVE___PROGNAME */ | 73 | #endif /* HAVE___PROGNAME */ |
63 | 74 | ||
64 | void | 75 | void |
65 | process_request_identity(SocketEntry *e) | 76 | idtab_init(void) |
77 | { | ||
78 | int i; | ||
79 | for (i = 0; i <=2; i++){ | ||
80 | idtable[i].identities = NULL; | ||
81 | idtable[i].nentries = 0; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | /* return private key table for requested protocol version */ | ||
86 | Idtab * | ||
87 | idtab_lookup(int version) | ||
88 | { | ||
89 | if (version < 1 || version > 2) | ||
90 | fatal("internal error, bad protocol version %d", version); | ||
91 | return &idtable[version]; | ||
92 | } | ||
93 | |||
94 | /* return matching private key for given public key */ | ||
95 | Key * | ||
96 | lookup_private_key(Key *key, int *idx, int version) | ||
97 | { | ||
98 | int i; | ||
99 | Idtab *tab = idtab_lookup(version); | ||
100 | for (i = 0; i < tab->nentries; i++) { | ||
101 | if (key_equal(key, tab->identities[i].key)) { | ||
102 | if (idx != NULL) | ||
103 | *idx = i; | ||
104 | return tab->identities[i].key; | ||
105 | } | ||
106 | } | ||
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | /* send list of supported public keys to 'client' */ | ||
111 | void | ||
112 | process_request_identities(SocketEntry *e, int version) | ||
66 | { | 113 | { |
114 | Idtab *tab = idtab_lookup(version); | ||
67 | Buffer msg; | 115 | Buffer msg; |
68 | int i; | 116 | int i; |
69 | 117 | ||
70 | buffer_init(&msg); | 118 | buffer_init(&msg); |
71 | buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER); | 119 | buffer_put_char(&msg, (version == 1) ? |
72 | buffer_put_int(&msg, num_identities); | 120 | SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); |
73 | for (i = 0; i < num_identities; i++) { | 121 | buffer_put_int(&msg, tab->nentries); |
74 | buffer_put_int(&msg, BN_num_bits(identities[i].key->n)); | 122 | for (i = 0; i < tab->nentries; i++) { |
75 | buffer_put_bignum(&msg, identities[i].key->e); | 123 | Identity *id = &tab->identities[i]; |
76 | buffer_put_bignum(&msg, identities[i].key->n); | 124 | if (id->key->type == KEY_RSA) { |
77 | buffer_put_string(&msg, identities[i].comment, | 125 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); |
78 | strlen(identities[i].comment)); | 126 | buffer_put_bignum(&msg, id->key->rsa->e); |
127 | buffer_put_bignum(&msg, id->key->rsa->n); | ||
128 | } else { | ||
129 | unsigned char *blob; | ||
130 | unsigned int blen; | ||
131 | dsa_make_key_blob(id->key, &blob, &blen); | ||
132 | buffer_put_string(&msg, blob, blen); | ||
133 | xfree(blob); | ||
134 | } | ||
135 | buffer_put_cstring(&msg, id->comment); | ||
79 | } | 136 | } |
80 | buffer_put_int(&e->output, buffer_len(&msg)); | 137 | buffer_put_int(&e->output, buffer_len(&msg)); |
81 | buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); | 138 | buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); |
82 | buffer_free(&msg); | 139 | buffer_free(&msg); |
83 | } | 140 | } |
84 | 141 | ||
142 | /* ssh1 only */ | ||
85 | void | 143 | void |
86 | process_authentication_challenge(SocketEntry *e) | 144 | process_authentication_challenge1(SocketEntry *e) |
87 | { | 145 | { |
88 | int i, pub_bits, len; | 146 | Key *key, *private; |
89 | BIGNUM *pub_e, *pub_n, *challenge; | 147 | BIGNUM *challenge; |
148 | int i, len; | ||
90 | Buffer msg; | 149 | Buffer msg; |
91 | MD5_CTX md; | 150 | MD5_CTX md; |
92 | unsigned char buf[32], mdbuf[16], session_id[16]; | 151 | unsigned char buf[32], mdbuf[16], session_id[16]; |
93 | unsigned int response_type; | 152 | unsigned int response_type; |
94 | 153 | ||
95 | buffer_init(&msg); | 154 | buffer_init(&msg); |
96 | pub_e = BN_new(); | 155 | key = key_new(KEY_RSA); |
97 | pub_n = BN_new(); | ||
98 | challenge = BN_new(); | 156 | challenge = BN_new(); |
99 | pub_bits = buffer_get_int(&e->input); | ||
100 | buffer_get_bignum(&e->input, pub_e); | ||
101 | buffer_get_bignum(&e->input, pub_n); | ||
102 | buffer_get_bignum(&e->input, challenge); | ||
103 | if (buffer_len(&e->input) == 0) { | ||
104 | /* Compatibility code for old servers. */ | ||
105 | memset(session_id, 0, 16); | ||
106 | response_type = 0; | ||
107 | } else { | ||
108 | /* New code. */ | ||
109 | buffer_get(&e->input, (char *) session_id, 16); | ||
110 | response_type = buffer_get_int(&e->input); | ||
111 | } | ||
112 | for (i = 0; i < num_identities; i++) | ||
113 | if (pub_bits == BN_num_bits(identities[i].key->n) && | ||
114 | BN_cmp(pub_e, identities[i].key->e) == 0 && | ||
115 | BN_cmp(pub_n, identities[i].key->n) == 0) { | ||
116 | /* Decrypt the challenge using the private key. */ | ||
117 | rsa_private_decrypt(challenge, challenge, identities[i].key); | ||
118 | |||
119 | /* Compute the desired response. */ | ||
120 | switch (response_type) { | ||
121 | case 0:/* As of protocol 1.0 */ | ||
122 | /* This response type is no longer supported. */ | ||
123 | log("Compatibility with ssh protocol 1.0 no longer supported."); | ||
124 | buffer_put_char(&msg, SSH_AGENT_FAILURE); | ||
125 | goto send; | ||
126 | |||
127 | case 1:/* As of protocol 1.1 */ | ||
128 | /* The response is MD5 of decrypted challenge plus session id. */ | ||
129 | len = BN_num_bytes(challenge); | ||
130 | |||
131 | if (len <= 0 || len > 32) { | ||
132 | fatal("process_authentication_challenge: " | ||
133 | "bad challenge length %d", len); | ||
134 | } | ||
135 | memset(buf, 0, 32); | ||
136 | BN_bn2bin(challenge, buf + 32 - len); | ||
137 | MD5_Init(&md); | ||
138 | MD5_Update(&md, buf, 32); | ||
139 | MD5_Update(&md, session_id, 16); | ||
140 | MD5_Final(mdbuf, &md); | ||
141 | break; | ||
142 | |||
143 | default: | ||
144 | fatal("process_authentication_challenge: bad response_type %d", | ||
145 | response_type); | ||
146 | break; | ||
147 | } | ||
148 | 157 | ||
149 | /* Send the response. */ | 158 | buffer_get_int(&e->input); /* ignored */ |
150 | buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); | 159 | buffer_get_bignum(&e->input, key->rsa->e); |
151 | for (i = 0; i < 16; i++) | 160 | buffer_get_bignum(&e->input, key->rsa->n); |
152 | buffer_put_char(&msg, mdbuf[i]); | 161 | buffer_get_bignum(&e->input, challenge); |
153 | 162 | ||
154 | goto send; | 163 | /* Only protocol 1.1 is supported */ |
164 | if (buffer_len(&e->input) == 0) | ||
165 | goto failure; | ||
166 | buffer_get(&e->input, (char *) session_id, 16); | ||
167 | response_type = buffer_get_int(&e->input); | ||
168 | if (response_type != 1) | ||
169 | goto failure; | ||
170 | |||
171 | private = lookup_private_key(key, NULL, 1); | ||
172 | if (private != NULL) { | ||
173 | /* Decrypt the challenge using the private key. */ | ||
174 | rsa_private_decrypt(challenge, challenge, private->rsa); | ||
175 | |||
176 | /* The response is MD5 of decrypted challenge plus session id. */ | ||
177 | len = BN_num_bytes(challenge); | ||
178 | if (len <= 0 || len > 32) { | ||
179 | log("process_authentication_challenge: bad challenge length %d", len); | ||
180 | goto failure; | ||
155 | } | 181 | } |
156 | /* Unknown identity. Send failure. */ | 182 | memset(buf, 0, 32); |
183 | BN_bn2bin(challenge, buf + 32 - len); | ||
184 | MD5_Init(&md); | ||
185 | MD5_Update(&md, buf, 32); | ||
186 | MD5_Update(&md, session_id, 16); | ||
187 | MD5_Final(mdbuf, &md); | ||
188 | |||
189 | /* Send the response. */ | ||
190 | buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); | ||
191 | for (i = 0; i < 16; i++) | ||
192 | buffer_put_char(&msg, mdbuf[i]); | ||
193 | goto send; | ||
194 | } | ||
195 | |||
196 | failure: | ||
197 | /* Unknown identity or protocol error. Send failure. */ | ||
157 | buffer_put_char(&msg, SSH_AGENT_FAILURE); | 198 | buffer_put_char(&msg, SSH_AGENT_FAILURE); |
158 | send: | 199 | send: |
159 | buffer_put_int(&e->output, buffer_len(&msg)); | 200 | buffer_put_int(&e->output, buffer_len(&msg)); |
201 | buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); | ||
202 | key_free(key); | ||
203 | BN_clear_free(challenge); | ||
204 | buffer_free(&msg); | ||
205 | } | ||
206 | |||
207 | /* ssh2 only */ | ||
208 | void | ||
209 | process_sign_request2(SocketEntry *e) | ||
210 | { | ||
211 | extern int datafellows; | ||
212 | Key *key, *private; | ||
213 | unsigned char *blob, *data, *signature = NULL; | ||
214 | unsigned int blen, dlen, slen = 0; | ||
215 | Buffer msg; | ||
216 | int ok = -1; | ||
217 | |||
218 | datafellows = 0; | ||
219 | |||
220 | blob = buffer_get_string(&e->input, &blen); | ||
221 | data = buffer_get_string(&e->input, &dlen); | ||
222 | |||
223 | key = dsa_key_from_blob(blob, blen); | ||
224 | if (key != NULL) { | ||
225 | private = lookup_private_key(key, NULL, 2); | ||
226 | if (private != NULL) | ||
227 | ok = dsa_sign(private, &signature, &slen, data, dlen); | ||
228 | } | ||
229 | key_free(key); | ||
230 | buffer_init(&msg); | ||
231 | if (ok == 0) { | ||
232 | buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); | ||
233 | buffer_put_string(&msg, signature, slen); | ||
234 | } else { | ||
235 | buffer_put_char(&msg, SSH_AGENT_FAILURE); | ||
236 | } | ||
237 | buffer_put_int(&e->output, buffer_len(&msg)); | ||
160 | buffer_append(&e->output, buffer_ptr(&msg), | 238 | buffer_append(&e->output, buffer_ptr(&msg), |
161 | buffer_len(&msg)); | 239 | buffer_len(&msg)); |
162 | buffer_free(&msg); | 240 | buffer_free(&msg); |
163 | BN_clear_free(pub_e); | 241 | xfree(data); |
164 | BN_clear_free(pub_n); | 242 | xfree(blob); |
165 | BN_clear_free(challenge); | 243 | if (signature != NULL) |
244 | xfree(signature); | ||
166 | } | 245 | } |
167 | 246 | ||
247 | /* shared */ | ||
168 | void | 248 | void |
169 | process_remove_identity(SocketEntry *e) | 249 | process_remove_identity(SocketEntry *e, int version) |
170 | { | 250 | { |
251 | Key *key = NULL, *private; | ||
252 | unsigned char *blob; | ||
253 | unsigned int blen; | ||
171 | unsigned int bits; | 254 | unsigned int bits; |
172 | unsigned int i; | 255 | int success = 0; |
173 | BIGNUM *dummy, *n; | 256 | |
174 | 257 | switch(version){ | |
175 | dummy = BN_new(); | 258 | case 1: |
176 | n = BN_new(); | 259 | key = key_new(KEY_RSA); |
177 | 260 | bits = buffer_get_int(&e->input); | |
178 | /* Get the key from the packet. */ | 261 | buffer_get_bignum(&e->input, key->rsa->e); |
179 | bits = buffer_get_int(&e->input); | 262 | buffer_get_bignum(&e->input, key->rsa->n); |
180 | buffer_get_bignum(&e->input, dummy); | 263 | |
181 | buffer_get_bignum(&e->input, n); | 264 | if (bits != key_size(key)) |
182 | 265 | log("Warning: identity keysize mismatch: actual %d, announced %d", | |
183 | if (bits != BN_num_bits(n)) | 266 | key_size(key), bits); |
184 | log("Warning: identity keysize mismatch: actual %d, announced %d", | 267 | break; |
185 | BN_num_bits(n), bits); | 268 | case 2: |
186 | 269 | blob = buffer_get_string(&e->input, &blen); | |
187 | /* Check if we have the key. */ | 270 | key = dsa_key_from_blob(blob, blen); |
188 | for (i = 0; i < num_identities; i++) | 271 | xfree(blob); |
189 | if (BN_cmp(identities[i].key->n, n) == 0) { | 272 | break; |
273 | } | ||
274 | if (key != NULL) { | ||
275 | int idx; | ||
276 | private = lookup_private_key(key, &idx, version); | ||
277 | if (private != NULL) { | ||
190 | /* | 278 | /* |
191 | * We have this key. Free the old key. Since we | 279 | * We have this key. Free the old key. Since we |
192 | * don\'t want to leave empty slots in the middle of | 280 | * don\'t want to leave empty slots in the middle of |
193 | * the array, we actually free the key there and copy | 281 | * the array, we actually free the key there and copy |
194 | * data from the last entry. | 282 | * data from the last entry. |
195 | */ | 283 | */ |
196 | RSA_free(identities[i].key); | 284 | Idtab *tab = idtab_lookup(version); |
197 | xfree(identities[i].comment); | 285 | key_free(tab->identities[idx].key); |
198 | if (i < num_identities - 1) | 286 | xfree(tab->identities[idx].comment); |
199 | identities[i] = identities[num_identities - 1]; | 287 | if (idx != tab->nentries) |
200 | num_identities--; | 288 | tab->identities[idx] = tab->identities[tab->nentries]; |
201 | BN_clear_free(dummy); | 289 | tab->nentries--; |
202 | BN_clear_free(n); | 290 | success = 1; |
203 | |||
204 | /* Send success. */ | ||
205 | buffer_put_int(&e->output, 1); | ||
206 | buffer_put_char(&e->output, SSH_AGENT_SUCCESS); | ||
207 | return; | ||
208 | } | 291 | } |
209 | /* We did not have the key. */ | 292 | key_free(key); |
210 | BN_clear(dummy); | 293 | } |
211 | BN_clear(n); | ||
212 | |||
213 | /* Send failure. */ | ||
214 | buffer_put_int(&e->output, 1); | 294 | buffer_put_int(&e->output, 1); |
215 | buffer_put_char(&e->output, SSH_AGENT_FAILURE); | 295 | buffer_put_char(&e->output, |
296 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
216 | } | 297 | } |
217 | 298 | ||
218 | /* | ||
219 | * Removes all identities from the agent. | ||
220 | */ | ||
221 | void | 299 | void |
222 | process_remove_all_identities(SocketEntry *e) | 300 | process_remove_all_identities(SocketEntry *e, int version) |
223 | { | 301 | { |
224 | unsigned int i; | 302 | unsigned int i; |
303 | Idtab *tab = idtab_lookup(version); | ||
225 | 304 | ||
226 | /* Loop over all identities and clear the keys. */ | 305 | /* Loop over all identities and clear the keys. */ |
227 | for (i = 0; i < num_identities; i++) { | 306 | for (i = 0; i < tab->nentries; i++) { |
228 | RSA_free(identities[i].key); | 307 | key_free(tab->identities[i].key); |
229 | xfree(identities[i].comment); | 308 | xfree(tab->identities[i].comment); |
230 | } | 309 | } |
231 | 310 | ||
232 | /* Mark that there are no identities. */ | 311 | /* Mark that there are no identities. */ |
233 | num_identities = 0; | 312 | tab->nentries = 0; |
234 | 313 | ||
235 | /* Send success. */ | 314 | /* Send success. */ |
236 | buffer_put_int(&e->output, 1); | 315 | buffer_put_int(&e->output, 1); |
@@ -238,79 +317,108 @@ process_remove_all_identities(SocketEntry *e) | |||
238 | return; | 317 | return; |
239 | } | 318 | } |
240 | 319 | ||
241 | /* | ||
242 | * Adds an identity to the agent. | ||
243 | */ | ||
244 | void | 320 | void |
245 | process_add_identity(SocketEntry *e) | 321 | process_add_identity(SocketEntry *e, int version) |
246 | { | 322 | { |
247 | RSA *k; | 323 | Key *k = NULL; |
248 | int i; | 324 | RSA *rsa; |
249 | BIGNUM *aux; | 325 | BIGNUM *aux; |
250 | BN_CTX *ctx; | 326 | BN_CTX *ctx; |
327 | char *type; | ||
328 | char *comment; | ||
329 | int success = 0; | ||
330 | Idtab *tab = idtab_lookup(version); | ||
251 | 331 | ||
252 | if (num_identities == 0) | 332 | switch (version) { |
253 | identities = xmalloc(sizeof(Identity)); | 333 | case 1: |
254 | else | 334 | k = key_new(KEY_RSA); |
255 | identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity)); | 335 | rsa = k->rsa; |
256 | |||
257 | identities[num_identities].key = RSA_new(); | ||
258 | k = identities[num_identities].key; | ||
259 | buffer_get_int(&e->input); /* bits */ | ||
260 | k->n = BN_new(); | ||
261 | buffer_get_bignum(&e->input, k->n); | ||
262 | k->e = BN_new(); | ||
263 | buffer_get_bignum(&e->input, k->e); | ||
264 | k->d = BN_new(); | ||
265 | buffer_get_bignum(&e->input, k->d); | ||
266 | k->iqmp = BN_new(); | ||
267 | buffer_get_bignum(&e->input, k->iqmp); | ||
268 | /* SSH and SSL have p and q swapped */ | ||
269 | k->q = BN_new(); | ||
270 | buffer_get_bignum(&e->input, k->q); /* p */ | ||
271 | k->p = BN_new(); | ||
272 | buffer_get_bignum(&e->input, k->p); /* q */ | ||
273 | |||
274 | /* Generate additional parameters */ | ||
275 | aux = BN_new(); | ||
276 | ctx = BN_CTX_new(); | ||
277 | |||
278 | BN_sub(aux, k->q, BN_value_one()); | ||
279 | k->dmq1 = BN_new(); | ||
280 | BN_mod(k->dmq1, k->d, aux, ctx); | ||
281 | |||
282 | BN_sub(aux, k->p, BN_value_one()); | ||
283 | k->dmp1 = BN_new(); | ||
284 | BN_mod(k->dmp1, k->d, aux, ctx); | ||
285 | |||
286 | BN_clear_free(aux); | ||
287 | BN_CTX_free(ctx); | ||
288 | |||
289 | identities[num_identities].comment = buffer_get_string(&e->input, NULL); | ||
290 | |||
291 | /* Check if we already have the key. */ | ||
292 | for (i = 0; i < num_identities; i++) | ||
293 | if (BN_cmp(identities[i].key->n, k->n) == 0) { | ||
294 | /* | ||
295 | * We already have this key. Clear and free the new | ||
296 | * data and return success. | ||
297 | */ | ||
298 | RSA_free(k); | ||
299 | xfree(identities[num_identities].comment); | ||
300 | 336 | ||
301 | /* Send success. */ | 337 | /* allocate mem for private key */ |
302 | buffer_put_int(&e->output, 1); | 338 | /* XXX rsa->n and rsa->e are already allocated */ |
303 | buffer_put_char(&e->output, SSH_AGENT_SUCCESS); | 339 | rsa->d = BN_new(); |
304 | return; | 340 | rsa->iqmp = BN_new(); |
341 | rsa->q = BN_new(); | ||
342 | rsa->p = BN_new(); | ||
343 | rsa->dmq1 = BN_new(); | ||
344 | rsa->dmp1 = BN_new(); | ||
345 | |||
346 | buffer_get_int(&e->input); /* ignored */ | ||
347 | |||
348 | buffer_get_bignum(&e->input, rsa->n); | ||
349 | buffer_get_bignum(&e->input, rsa->e); | ||
350 | buffer_get_bignum(&e->input, rsa->d); | ||
351 | buffer_get_bignum(&e->input, rsa->iqmp); | ||
352 | |||
353 | /* SSH and SSL have p and q swapped */ | ||
354 | buffer_get_bignum(&e->input, rsa->q); /* p */ | ||
355 | buffer_get_bignum(&e->input, rsa->p); /* q */ | ||
356 | |||
357 | /* Generate additional parameters */ | ||
358 | aux = BN_new(); | ||
359 | ctx = BN_CTX_new(); | ||
360 | |||
361 | BN_sub(aux, rsa->q, BN_value_one()); | ||
362 | BN_mod(rsa->dmq1, rsa->d, aux, ctx); | ||
363 | |||
364 | BN_sub(aux, rsa->p, BN_value_one()); | ||
365 | BN_mod(rsa->dmp1, rsa->d, aux, ctx); | ||
366 | |||
367 | BN_clear_free(aux); | ||
368 | BN_CTX_free(ctx); | ||
369 | |||
370 | break; | ||
371 | case 2: | ||
372 | type = buffer_get_string(&e->input, NULL); | ||
373 | if (strcmp(type, KEX_DSS)) { | ||
374 | buffer_clear(&e->input); | ||
375 | xfree(type); | ||
376 | goto send; | ||
305 | } | 377 | } |
306 | /* Increment the number of identities. */ | 378 | xfree(type); |
307 | num_identities++; | ||
308 | 379 | ||
309 | /* Send a success message. */ | 380 | k = key_new(KEY_DSA); |
381 | |||
382 | /* allocate mem for private key */ | ||
383 | k->dsa->priv_key = BN_new(); | ||
384 | |||
385 | buffer_get_bignum2(&e->input, k->dsa->p); | ||
386 | buffer_get_bignum2(&e->input, k->dsa->q); | ||
387 | buffer_get_bignum2(&e->input, k->dsa->g); | ||
388 | buffer_get_bignum2(&e->input, k->dsa->pub_key); | ||
389 | buffer_get_bignum2(&e->input, k->dsa->priv_key); | ||
390 | |||
391 | break; | ||
392 | } | ||
393 | |||
394 | comment = buffer_get_string(&e->input, NULL); | ||
395 | if (k == NULL) { | ||
396 | xfree(comment); | ||
397 | goto send; | ||
398 | } | ||
399 | success = 1; | ||
400 | if (lookup_private_key(k, NULL, version) == NULL) { | ||
401 | if (tab->nentries == 0) | ||
402 | tab->identities = xmalloc(sizeof(Identity)); | ||
403 | else | ||
404 | tab->identities = xrealloc(tab->identities, | ||
405 | (tab->nentries + 1) * sizeof(Identity)); | ||
406 | tab->identities[tab->nentries].key = k; | ||
407 | tab->identities[tab->nentries].comment = comment; | ||
408 | /* Increment the number of identities. */ | ||
409 | tab->nentries++; | ||
410 | } else { | ||
411 | key_free(k); | ||
412 | xfree(comment); | ||
413 | } | ||
414 | send: | ||
310 | buffer_put_int(&e->output, 1); | 415 | buffer_put_int(&e->output, 1); |
311 | buffer_put_char(&e->output, SSH_AGENT_SUCCESS); | 416 | buffer_put_char(&e->output, |
417 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
312 | } | 418 | } |
313 | 419 | ||
420 | /* dispatch incoming messages */ | ||
421 | |||
314 | void | 422 | void |
315 | process_message(SocketEntry *e) | 423 | process_message(SocketEntry *e) |
316 | { | 424 | { |
@@ -333,20 +441,37 @@ process_message(SocketEntry *e) | |||
333 | type = buffer_get_char(&e->input); | 441 | type = buffer_get_char(&e->input); |
334 | 442 | ||
335 | switch (type) { | 443 | switch (type) { |
336 | case SSH_AGENTC_REQUEST_RSA_IDENTITIES: | 444 | /* ssh1 */ |
337 | process_request_identity(e); | ||
338 | break; | ||
339 | case SSH_AGENTC_RSA_CHALLENGE: | 445 | case SSH_AGENTC_RSA_CHALLENGE: |
340 | process_authentication_challenge(e); | 446 | process_authentication_challenge1(e); |
447 | break; | ||
448 | case SSH_AGENTC_REQUEST_RSA_IDENTITIES: | ||
449 | process_request_identities(e, 1); | ||
341 | break; | 450 | break; |
342 | case SSH_AGENTC_ADD_RSA_IDENTITY: | 451 | case SSH_AGENTC_ADD_RSA_IDENTITY: |
343 | process_add_identity(e); | 452 | process_add_identity(e, 1); |
344 | break; | 453 | break; |
345 | case SSH_AGENTC_REMOVE_RSA_IDENTITY: | 454 | case SSH_AGENTC_REMOVE_RSA_IDENTITY: |
346 | process_remove_identity(e); | 455 | process_remove_identity(e, 1); |
347 | break; | 456 | break; |
348 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: | 457 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: |
349 | process_remove_all_identities(e); | 458 | process_remove_all_identities(e, 1); |
459 | break; | ||
460 | /* ssh2 */ | ||
461 | case SSH2_AGENTC_SIGN_REQUEST: | ||
462 | process_sign_request2(e); | ||
463 | break; | ||
464 | case SSH2_AGENTC_REQUEST_IDENTITIES: | ||
465 | process_request_identities(e, 2); | ||
466 | break; | ||
467 | case SSH2_AGENTC_ADD_IDENTITY: | ||
468 | process_add_identity(e, 2); | ||
469 | break; | ||
470 | case SSH2_AGENTC_REMOVE_IDENTITY: | ||
471 | process_remove_identity(e, 2); | ||
472 | break; | ||
473 | case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: | ||
474 | process_remove_all_identities(e, 2); | ||
350 | break; | 475 | break; |
351 | default: | 476 | default: |
352 | /* Unknown message. Respond with failure. */ | 477 | /* Unknown message. Respond with failure. */ |
@@ -511,9 +636,9 @@ main(int ac, char **av) | |||
511 | pid_t pid; | 636 | pid_t pid; |
512 | char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; | 637 | char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; |
513 | extern int optind; | 638 | extern int optind; |
514 | 639 | ||
515 | init_rng(); | 640 | init_rng(); |
516 | 641 | ||
517 | /* check if RSA support exists */ | 642 | /* check if RSA support exists */ |
518 | if (rsa_alive() == 0) { | 643 | if (rsa_alive() == 0) { |
519 | fprintf(stderr, | 644 | fprintf(stderr, |
@@ -654,6 +779,7 @@ main(int ac, char **av) | |||
654 | signal(SIGALRM, check_parent_exists); | 779 | signal(SIGALRM, check_parent_exists); |
655 | alarm(10); | 780 | alarm(10); |
656 | } | 781 | } |
782 | idtab_init(); | ||
657 | signal(SIGINT, SIG_IGN); | 783 | signal(SIGINT, SIG_IGN); |
658 | signal(SIGPIPE, SIG_IGN); | 784 | signal(SIGPIPE, SIG_IGN); |
659 | signal(SIGHUP, cleanup_exit); | 785 | signal(SIGHUP, cleanup_exit); |
diff --git a/ssh-keygen.c b/ssh-keygen.c index 8a03f0d8d..83450fe84 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -7,7 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "includes.h" | 9 | #include "includes.h" |
10 | RCSID("$OpenBSD: ssh-keygen.c,v 1.29 2000/07/15 04:01:37 djm Exp $"); | 10 | RCSID("$OpenBSD: ssh-keygen.c,v 1.30 2000/08/19 21:34:43 markus Exp $"); |
11 | 11 | ||
12 | #include <openssl/evp.h> | 12 | #include <openssl/evp.h> |
13 | #include <openssl/pem.h> | 13 | #include <openssl/pem.h> |
@@ -16,7 +16,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.29 2000/07/15 04:01:37 djm Exp $"); | |||
16 | 16 | ||
17 | #include "ssh.h" | 17 | #include "ssh.h" |
18 | #include "xmalloc.h" | 18 | #include "xmalloc.h" |
19 | #include "fingerprint.h" | ||
20 | #include "key.h" | 19 | #include "key.h" |
21 | #include "rsa.h" | 20 | #include "rsa.h" |
22 | #include "dsa.h" | 21 | #include "dsa.h" |
@@ -228,8 +227,9 @@ do_print_public(struct passwd *pw) | |||
228 | void | 227 | void |
229 | do_fingerprint(struct passwd *pw) | 228 | do_fingerprint(struct passwd *pw) |
230 | { | 229 | { |
230 | /* XXX RSA1 only */ | ||
231 | |||
231 | FILE *f; | 232 | FILE *f; |
232 | BIGNUM *e, *n; | ||
233 | Key *public; | 233 | Key *public; |
234 | char *comment = NULL, *cp, *ep, line[16*1024]; | 234 | char *comment = NULL, *cp, *ep, line[16*1024]; |
235 | int i, skip = 0, num = 1, invalid = 1; | 235 | int i, skip = 0, num = 1, invalid = 1; |
@@ -249,13 +249,9 @@ do_fingerprint(struct passwd *pw) | |||
249 | key_free(public); | 249 | key_free(public); |
250 | exit(0); | 250 | exit(0); |
251 | } | 251 | } |
252 | key_free(public); | ||
253 | 252 | ||
254 | /* XXX */ | ||
255 | f = fopen(identity_file, "r"); | 253 | f = fopen(identity_file, "r"); |
256 | if (f != NULL) { | 254 | if (f != NULL) { |
257 | n = BN_new(); | ||
258 | e = BN_new(); | ||
259 | while (fgets(line, sizeof(line), f)) { | 255 | while (fgets(line, sizeof(line), f)) { |
260 | i = strlen(line) - 1; | 256 | i = strlen(line) - 1; |
261 | if (line[i] != '\n') { | 257 | if (line[i] != '\n') { |
@@ -290,18 +286,17 @@ do_fingerprint(struct passwd *pw) | |||
290 | *cp++ = '\0'; | 286 | *cp++ = '\0'; |
291 | } | 287 | } |
292 | ep = cp; | 288 | ep = cp; |
293 | if (auth_rsa_read_key(&cp, &ignore, e, n)) { | 289 | if (auth_rsa_read_key(&cp, &ignore, public->rsa->e, public->rsa->n)) { |
294 | invalid = 0; | 290 | invalid = 0; |
295 | comment = *cp ? cp : comment; | 291 | comment = *cp ? cp : comment; |
296 | printf("%d %s %s\n", BN_num_bits(n), | 292 | printf("%d %s %s\n", key_size(public), |
297 | fingerprint(e, n), | 293 | key_fingerprint(public), |
298 | comment ? comment : "no comment"); | 294 | comment ? comment : "no comment"); |
299 | } | 295 | } |
300 | } | 296 | } |
301 | BN_free(e); | ||
302 | BN_free(n); | ||
303 | fclose(f); | 297 | fclose(f); |
304 | } | 298 | } |
299 | key_free(public); | ||
305 | if (invalid) { | 300 | if (invalid) { |
306 | printf("%s is not a valid key file.\n", identity_file); | 301 | printf("%s is not a valid key file.\n", identity_file); |
307 | exit(1); | 302 | exit(1); |
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "includes.h" | 13 | #include "includes.h" |
14 | RCSID("$OpenBSD: ssh.c,v 1.58 2000/07/16 08:27:22 markus Exp $"); | 14 | RCSID("$OpenBSD: ssh.c,v 1.61 2000/08/20 18:42:40 millert Exp $"); |
15 | 15 | ||
16 | #include <openssl/evp.h> | 16 | #include <openssl/evp.h> |
17 | #include <openssl/dsa.h> | 17 | #include <openssl/dsa.h> |
@@ -253,8 +253,8 @@ main(int ac, char **av) | |||
253 | cp = strrchr(av0, '/') + 1; | 253 | cp = strrchr(av0, '/') + 1; |
254 | else | 254 | else |
255 | cp = av0; | 255 | cp = av0; |
256 | if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 && | 256 | if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") && |
257 | strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0) | 257 | strcmp(cp, "slogin") && strcmp(cp, "remsh")) |
258 | host = cp; | 258 | host = cp; |
259 | 259 | ||
260 | for (optind = 1; optind < ac; optind++) { | 260 | for (optind = 1; optind < ac; optind++) { |
@@ -490,6 +490,9 @@ main(int ac, char **av) | |||
490 | pwcopy.pw_passwd = xstrdup(pw->pw_passwd); | 490 | pwcopy.pw_passwd = xstrdup(pw->pw_passwd); |
491 | pwcopy.pw_uid = pw->pw_uid; | 491 | pwcopy.pw_uid = pw->pw_uid; |
492 | pwcopy.pw_gid = pw->pw_gid; | 492 | pwcopy.pw_gid = pw->pw_gid; |
493 | #ifdef HAVE_PW_CLASS_IN_PASSWD | ||
494 | pwcopy.pw_class = xstrdup(pw->pw_class); | ||
495 | #endif | ||
493 | pwcopy.pw_dir = xstrdup(pw->pw_dir); | 496 | pwcopy.pw_dir = xstrdup(pw->pw_dir); |
494 | pwcopy.pw_shell = xstrdup(pw->pw_shell); | 497 | pwcopy.pw_shell = xstrdup(pw->pw_shell); |
495 | pw = &pwcopy; | 498 | pw = &pwcopy; |
@@ -871,7 +874,7 @@ ssh_session(void) | |||
871 | } | 874 | } |
872 | 875 | ||
873 | /* Enter the interactive session. */ | 876 | /* Enter the interactive session. */ |
874 | return client_loop(have_tty, tty_flag ? options.escape_char : -1); | 877 | return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); |
875 | } | 878 | } |
876 | 879 | ||
877 | void | 880 | void |
@@ -954,9 +957,16 @@ int | |||
954 | ssh_session2(void) | 957 | ssh_session2(void) |
955 | { | 958 | { |
956 | int window, packetmax, id; | 959 | int window, packetmax, id; |
957 | int in = dup(STDIN_FILENO); | 960 | int in, out, err; |
958 | int out = dup(STDOUT_FILENO); | 961 | |
959 | int err = dup(STDERR_FILENO); | 962 | /* If requested, let ssh continue in the background. */ |
963 | if (fork_after_authentication_flag) | ||
964 | if (daemon(1, 1) < 0) | ||
965 | fatal("daemon() failed: %.200s", strerror(errno)); | ||
966 | |||
967 | in = dup(STDIN_FILENO); | ||
968 | out = dup(STDOUT_FILENO); | ||
969 | err = dup(STDERR_FILENO); | ||
960 | 970 | ||
961 | if (in < 0 || out < 0 || err < 0) | 971 | if (in < 0 || out < 0 || err < 0) |
962 | fatal("dump in/out/err failed"); | 972 | fatal("dump in/out/err failed"); |
@@ -972,13 +982,13 @@ ssh_session2(void) | |||
972 | packetmax = window/2; | 982 | packetmax = window/2; |
973 | } | 983 | } |
974 | 984 | ||
985 | /*XXX MAXPACK */ | ||
975 | id = channel_new( | 986 | id = channel_new( |
976 | "session", SSH_CHANNEL_OPENING, in, out, err, | 987 | "session", SSH_CHANNEL_OPENING, in, out, err, |
977 | window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session")); | 988 | window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session")); |
978 | 989 | ||
979 | |||
980 | channel_open(id); | 990 | channel_open(id); |
981 | channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0); | 991 | channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0); |
982 | 992 | ||
983 | return client_loop(tty_flag, tty_flag ? options.escape_char : -1); | 993 | return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); |
984 | } | 994 | } |
@@ -13,7 +13,7 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | /* RCSID("$OpenBSD: ssh.h,v 1.48 2000/07/13 22:53:21 provos Exp $"); */ | 16 | /* RCSID("$OpenBSD: ssh.h,v 1.49 2000/08/19 18:48:11 markus Exp $"); */ |
17 | 17 | ||
18 | #ifndef SSH_H | 18 | #ifndef SSH_H |
19 | #define SSH_H | 19 | #define SSH_H |
@@ -105,7 +105,11 @@ | |||
105 | #endif /* SSH_PROGRAM */ | 105 | #endif /* SSH_PROGRAM */ |
106 | 106 | ||
107 | #ifndef LOGIN_PROGRAM | 107 | #ifndef LOGIN_PROGRAM |
108 | #define LOGIN_PROGRAM "/usr/bin/login" | 108 | # ifdef LOGIN_PROGRAM_FALLBACK |
109 | # define LOGIN_PROGRAM LOGIN_PROGRAM_FALLBACK | ||
110 | # else | ||
111 | # define LOGIN_PROGRAM "/usr/bin/login" | ||
112 | # endif | ||
109 | #endif /* LOGIN_PROGRAM */ | 113 | #endif /* LOGIN_PROGRAM */ |
110 | 114 | ||
111 | #ifndef ASKPASS_PROGRAM | 115 | #ifndef ASKPASS_PROGRAM |
@@ -506,7 +510,7 @@ void server_loop(pid_t pid, int fdin, int fdout, int fderr); | |||
506 | void server_loop2(void); | 510 | void server_loop2(void); |
507 | 511 | ||
508 | /* Client side main loop for the interactive session. */ | 512 | /* Client side main loop for the interactive session. */ |
509 | int client_loop(int have_pty, int escape_char); | 513 | int client_loop(int have_pty, int escape_char, int id); |
510 | 514 | ||
511 | /* Linked list of custom environment strings (see auth-rsa.c). */ | 515 | /* Linked list of custom environment strings (see auth-rsa.c). */ |
512 | struct envstring { | 516 | struct envstring { |
diff --git a/sshconnect1.c b/sshconnect1.c index aaebf17ff..7b60d6276 100644 --- a/sshconnect1.c +++ b/sshconnect1.c | |||
@@ -9,7 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "includes.h" | 11 | #include "includes.h" |
12 | RCSID("$OpenBSD: sshconnect1.c,v 1.4 2000/07/16 08:27:22 markus Exp $"); | 12 | RCSID("$OpenBSD: sshconnect1.c,v 1.5 2000/08/19 21:34:44 markus Exp $"); |
13 | 13 | ||
14 | #include <openssl/bn.h> | 14 | #include <openssl/bn.h> |
15 | #include <openssl/dsa.h> | 15 | #include <openssl/dsa.h> |
@@ -44,27 +44,27 @@ extern char *__progname; | |||
44 | int | 44 | int |
45 | try_agent_authentication() | 45 | try_agent_authentication() |
46 | { | 46 | { |
47 | int status, type; | 47 | int type; |
48 | char *comment; | 48 | char *comment; |
49 | AuthenticationConnection *auth; | 49 | AuthenticationConnection *auth; |
50 | unsigned char response[16]; | 50 | unsigned char response[16]; |
51 | unsigned int i; | 51 | unsigned int i; |
52 | BIGNUM *e, *n, *challenge; | 52 | int plen, clen; |
53 | Key *key; | ||
54 | BIGNUM *challenge; | ||
53 | 55 | ||
54 | /* Get connection to the agent. */ | 56 | /* Get connection to the agent. */ |
55 | auth = ssh_get_authentication_connection(); | 57 | auth = ssh_get_authentication_connection(); |
56 | if (!auth) | 58 | if (!auth) |
57 | return 0; | 59 | return 0; |
58 | 60 | ||
59 | e = BN_new(); | ||
60 | n = BN_new(); | ||
61 | challenge = BN_new(); | 61 | challenge = BN_new(); |
62 | key = key_new(KEY_RSA); | ||
62 | 63 | ||
63 | /* Loop through identities served by the agent. */ | 64 | /* Loop through identities served by the agent. */ |
64 | for (status = ssh_get_first_identity(auth, e, n, &comment); | 65 | for (key = ssh_get_first_identity(auth, &comment, 1); |
65 | status; | 66 | key != NULL; |
66 | status = ssh_get_next_identity(auth, e, n, &comment)) { | 67 | key = ssh_get_next_identity(auth, &comment, 1)) { |
67 | int plen, clen; | ||
68 | 68 | ||
69 | /* Try this identity. */ | 69 | /* Try this identity. */ |
70 | debug("Trying RSA authentication via agent with '%.100s'", comment); | 70 | debug("Trying RSA authentication via agent with '%.100s'", comment); |
@@ -72,7 +72,7 @@ try_agent_authentication() | |||
72 | 72 | ||
73 | /* Tell the server that we are willing to authenticate using this key. */ | 73 | /* Tell the server that we are willing to authenticate using this key. */ |
74 | packet_start(SSH_CMSG_AUTH_RSA); | 74 | packet_start(SSH_CMSG_AUTH_RSA); |
75 | packet_put_bignum(n); | 75 | packet_put_bignum(key->rsa->n); |
76 | packet_send(); | 76 | packet_send(); |
77 | packet_write_wait(); | 77 | packet_write_wait(); |
78 | 78 | ||
@@ -83,6 +83,7 @@ try_agent_authentication() | |||
83 | does not support RSA authentication. */ | 83 | does not support RSA authentication. */ |
84 | if (type == SSH_SMSG_FAILURE) { | 84 | if (type == SSH_SMSG_FAILURE) { |
85 | debug("Server refused our key."); | 85 | debug("Server refused our key."); |
86 | key_free(key); | ||
86 | continue; | 87 | continue; |
87 | } | 88 | } |
88 | /* Otherwise it should have sent a challenge. */ | 89 | /* Otherwise it should have sent a challenge. */ |
@@ -97,13 +98,16 @@ try_agent_authentication() | |||
97 | debug("Received RSA challenge from server."); | 98 | debug("Received RSA challenge from server."); |
98 | 99 | ||
99 | /* Ask the agent to decrypt the challenge. */ | 100 | /* Ask the agent to decrypt the challenge. */ |
100 | if (!ssh_decrypt_challenge(auth, e, n, challenge, | 101 | if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) { |
101 | session_id, 1, response)) { | 102 | /* |
102 | /* The agent failed to authenticate this identifier although it | 103 | * The agent failed to authenticate this identifier |
103 | advertised it supports this. Just return a wrong value. */ | 104 | * although it advertised it supports this. Just |
105 | * return a wrong value. | ||
106 | */ | ||
104 | log("Authentication agent failed to decrypt challenge."); | 107 | log("Authentication agent failed to decrypt challenge."); |
105 | memset(response, 0, sizeof(response)); | 108 | memset(response, 0, sizeof(response)); |
106 | } | 109 | } |
110 | key_free(key); | ||
107 | debug("Sending response to RSA challenge."); | 111 | debug("Sending response to RSA challenge."); |
108 | 112 | ||
109 | /* Send the decrypted challenge back to the server. */ | 113 | /* Send the decrypted challenge back to the server. */ |
@@ -118,10 +122,8 @@ try_agent_authentication() | |||
118 | 122 | ||
119 | /* The server returns success if it accepted the authentication. */ | 123 | /* The server returns success if it accepted the authentication. */ |
120 | if (type == SSH_SMSG_SUCCESS) { | 124 | if (type == SSH_SMSG_SUCCESS) { |
121 | debug("RSA authentication accepted by server."); | ||
122 | BN_clear_free(e); | ||
123 | BN_clear_free(n); | ||
124 | BN_clear_free(challenge); | 125 | BN_clear_free(challenge); |
126 | debug("RSA authentication accepted by server."); | ||
125 | return 1; | 127 | return 1; |
126 | } | 128 | } |
127 | /* Otherwise it should return failure. */ | 129 | /* Otherwise it should return failure. */ |
@@ -129,11 +131,7 @@ try_agent_authentication() | |||
129 | packet_disconnect("Protocol error waiting RSA auth response: %d", | 131 | packet_disconnect("Protocol error waiting RSA auth response: %d", |
130 | type); | 132 | type); |
131 | } | 133 | } |
132 | |||
133 | BN_clear_free(e); | ||
134 | BN_clear_free(n); | ||
135 | BN_clear_free(challenge); | 134 | BN_clear_free(challenge); |
136 | |||
137 | debug("RSA authentication using agent refused."); | 135 | debug("RSA authentication using agent refused."); |
138 | return 0; | 136 | return 0; |
139 | } | 137 | } |
diff --git a/sshconnect2.c b/sshconnect2.c index 22ad39e7f..1f49067ad 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -28,7 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "includes.h" | 30 | #include "includes.h" |
31 | RCSID("$OpenBSD: sshconnect2.c,v 1.16 2000/07/16 08:27:22 markus Exp $"); | 31 | RCSID("$OpenBSD: sshconnect2.c,v 1.17 2000/08/19 21:34:44 markus Exp $"); |
32 | 32 | ||
33 | #include <openssl/bn.h> | 33 | #include <openssl/bn.h> |
34 | #include <openssl/rsa.h> | 34 | #include <openssl/rsa.h> |
@@ -54,6 +54,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.16 2000/07/16 08:27:22 markus Exp $"); | |||
54 | #include "dsa.h" | 54 | #include "dsa.h" |
55 | #include "sshconnect.h" | 55 | #include "sshconnect.h" |
56 | #include "authfile.h" | 56 | #include "authfile.h" |
57 | #include "authfd.h" | ||
57 | 58 | ||
58 | /* import */ | 59 | /* import */ |
59 | extern char *client_version_string; | 60 | extern char *client_version_string; |
@@ -291,7 +292,7 @@ typedef int sign_fn( | |||
291 | unsigned char **sigp, int *lenp, | 292 | unsigned char **sigp, int *lenp, |
292 | unsigned char *data, int datalen); | 293 | unsigned char *data, int datalen); |
293 | 294 | ||
294 | void | 295 | int |
295 | ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, | 296 | ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, |
296 | const char *server_user, const char *host, const char *service) | 297 | const char *server_user, const char *host, const char *service) |
297 | { | 298 | { |
@@ -299,6 +300,7 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, | |||
299 | unsigned char *blob, *signature; | 300 | unsigned char *blob, *signature; |
300 | int bloblen, slen; | 301 | int bloblen, slen; |
301 | int skip = 0; | 302 | int skip = 0; |
303 | int ret = -1; | ||
302 | 304 | ||
303 | dsa_make_key_blob(k, &blob, &bloblen); | 305 | dsa_make_key_blob(k, &blob, &bloblen); |
304 | 306 | ||
@@ -323,8 +325,12 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, | |||
323 | buffer_put_string(&b, blob, bloblen); | 325 | buffer_put_string(&b, blob, bloblen); |
324 | 326 | ||
325 | /* generate signature */ | 327 | /* generate signature */ |
326 | do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); | 328 | ret = do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); |
327 | key_free(k); /* XXX */ | 329 | if (ret == -1) { |
330 | xfree(blob); | ||
331 | buffer_free(&b); | ||
332 | return 0; | ||
333 | } | ||
328 | #ifdef DEBUG_DSS | 334 | #ifdef DEBUG_DSS |
329 | buffer_dump(&b); | 335 | buffer_dump(&b); |
330 | #endif | 336 | #endif |
@@ -357,6 +363,8 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, | |||
357 | /* send */ | 363 | /* send */ |
358 | packet_send(); | 364 | packet_send(); |
359 | packet_write_wait(); | 365 | packet_write_wait(); |
366 | |||
367 | return 1; | ||
360 | } | 368 | } |
361 | 369 | ||
362 | int | 370 | int |
@@ -364,6 +372,7 @@ ssh2_try_pubkey(char *filename, | |||
364 | const char *server_user, const char *host, const char *service) | 372 | const char *server_user, const char *host, const char *service) |
365 | { | 373 | { |
366 | Key *k; | 374 | Key *k; |
375 | int ret = 0; | ||
367 | struct stat st; | 376 | struct stat st; |
368 | 377 | ||
369 | if (stat(filename, &st) != 0) { | 378 | if (stat(filename, &st) != 0) { |
@@ -389,13 +398,53 @@ ssh2_try_pubkey(char *filename, | |||
389 | return 0; | 398 | return 0; |
390 | } | 399 | } |
391 | } | 400 | } |
392 | ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service); | 401 | ret = ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service); |
393 | return 1; | 402 | key_free(k); |
403 | return ret; | ||
404 | } | ||
405 | |||
406 | int agent_sign( | ||
407 | Key *key, | ||
408 | unsigned char **sigp, int *lenp, | ||
409 | unsigned char *data, int datalen) | ||
410 | { | ||
411 | int ret = -1; | ||
412 | AuthenticationConnection *ac = ssh_get_authentication_connection(); | ||
413 | if (ac != NULL) { | ||
414 | ret = ssh_agent_sign(ac, key, sigp, lenp, data, datalen); | ||
415 | ssh_close_authentication_connection(ac); | ||
416 | } | ||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | int | ||
421 | ssh2_try_agent(AuthenticationConnection *ac, | ||
422 | const char *server_user, const char *host, const char *service) | ||
423 | { | ||
424 | static int called = 0; | ||
425 | char *comment; | ||
426 | Key *k; | ||
427 | int ret; | ||
428 | |||
429 | if (called == 0) { | ||
430 | k = ssh_get_first_identity(ac, &comment, 2); | ||
431 | called ++; | ||
432 | } else { | ||
433 | k = ssh_get_next_identity(ac, &comment, 2); | ||
434 | } | ||
435 | if (k == NULL) | ||
436 | return 0; | ||
437 | debug("trying DSA agent key %s", comment); | ||
438 | xfree(comment); | ||
439 | ret = ssh2_sign_and_send_pubkey(k, agent_sign, server_user, host, service); | ||
440 | key_free(k); | ||
441 | return ret; | ||
394 | } | 442 | } |
395 | 443 | ||
396 | void | 444 | void |
397 | ssh_userauth2(const char *server_user, char *host) | 445 | ssh_userauth2(const char *server_user, char *host) |
398 | { | 446 | { |
447 | AuthenticationConnection *ac = ssh_get_authentication_connection(); | ||
399 | int type; | 448 | int type; |
400 | int plen; | 449 | int plen; |
401 | int sent; | 450 | int sent; |
@@ -450,12 +499,17 @@ ssh_userauth2(const char *server_user, char *host) | |||
450 | debug("partial success"); | 499 | debug("partial success"); |
451 | if (options.dsa_authentication && | 500 | if (options.dsa_authentication && |
452 | strstr(auths, "publickey") != NULL) { | 501 | strstr(auths, "publickey") != NULL) { |
453 | while (i < options.num_identity_files2) { | 502 | if (ac != NULL) |
454 | sent = ssh2_try_pubkey( | 503 | sent = ssh2_try_agent(ac, |
455 | options.identity_files2[i++], | ||
456 | server_user, host, service); | 504 | server_user, host, service); |
457 | if (sent) | 505 | if (!sent) { |
458 | break; | 506 | while (i < options.num_identity_files2) { |
507 | sent = ssh2_try_pubkey( | ||
508 | options.identity_files2[i++], | ||
509 | server_user, host, service); | ||
510 | if (sent) | ||
511 | break; | ||
512 | } | ||
459 | } | 513 | } |
460 | } | 514 | } |
461 | if (!sent) { | 515 | if (!sent) { |
@@ -469,6 +523,8 @@ ssh_userauth2(const char *server_user, char *host) | |||
469 | fatal("Permission denied (%s).", auths); | 523 | fatal("Permission denied (%s).", auths); |
470 | xfree(auths); | 524 | xfree(auths); |
471 | } | 525 | } |
526 | if (ac != NULL) | ||
527 | ssh_close_authentication_connection(ac); | ||
472 | packet_done(); | 528 | packet_done(); |
473 | debug("ssh-userauth2 successfull"); | 529 | debug("ssh-userauth2 successfull"); |
474 | } | 530 | } |