diff options
author | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
commit | 95def09838fc61b37b6ea7cd5c234a465b4b129b (patch) | |
tree | 042744f76f40a326b873cb1c3690a6d7d966bc3e /authfd.c | |
parent | 4d2f15f895f4c795afc008aeff3fd2ceffbc44f4 (diff) |
- Merged very large OpenBSD source code reformat
- OpenBSD CVS updates
- [channels.c cipher.c compat.c log-client.c scp.c serverloop.c]
[ssh.h sshd.8 sshd.c]
syslog changes:
* Unified Logmessage for all auth-types, for success and for failed
* Standard connections get only ONE line in the LOG when level==LOG:
Auth-attempts are logged only, if authentication is:
a) successfull or
b) with passwd or
c) we had more than AUTH_FAIL_LOG failues
* many log() became verbose()
* old behaviour with level=VERBOSE
- [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c]
tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE
messages. allows use of s/key in windows (ttssh, securecrt) and
ssh-1.2.27 clients without 'ssh -v', ok: niels@
- [sshd.8]
-V, for fallback to openssh in SSH2 compatibility mode
- [sshd.c]
fix sigchld race; cjc5@po.cwru.edu
Diffstat (limited to 'authfd.c')
-rw-r--r-- | authfd.c | 921 |
1 files changed, 444 insertions, 477 deletions
@@ -1,20 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | 2 | * | |
3 | authfd.c | 3 | * authfd.c |
4 | 4 | * | |
5 | Author: Tatu Ylonen <ylo@cs.hut.fi> | 5 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
6 | 6 | * | |
7 | Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 7 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
8 | All rights reserved | 8 | * All rights reserved |
9 | 9 | * | |
10 | Created: Wed Mar 29 01:30:28 1995 ylo | 10 | * Created: Wed Mar 29 01:30:28 1995 ylo |
11 | 11 | * | |
12 | Functions for connecting the local authentication agent. | 12 | * Functions for connecting the local authentication agent. |
13 | 13 | * | |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$Id: authfd.c,v 1.6 1999/11/18 21:25:48 damien Exp $"); | 17 | RCSID("$Id: authfd.c,v 1.7 1999/11/24 13:26:21 damien Exp $"); |
18 | 18 | ||
19 | #include "ssh.h" | 19 | #include "ssh.h" |
20 | #include "rsa.h" | 20 | #include "rsa.h" |
@@ -36,45 +36,42 @@ RCSID("$Id: authfd.c,v 1.6 1999/11/18 21:25:48 damien Exp $"); | |||
36 | int | 36 | int |
37 | ssh_get_authentication_socket() | 37 | ssh_get_authentication_socket() |
38 | { | 38 | { |
39 | const char *authsocket; | 39 | const char *authsocket; |
40 | int sock; | 40 | int sock; |
41 | struct sockaddr_un sunaddr; | 41 | struct sockaddr_un sunaddr; |
42 | 42 | ||
43 | authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); | 43 | authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); |
44 | if (!authsocket) | 44 | if (!authsocket) |
45 | return -1; | 45 | return -1; |
46 | 46 | ||
47 | sunaddr.sun_family = AF_UNIX; | 47 | sunaddr.sun_family = AF_UNIX; |
48 | strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); | 48 | strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); |
49 | 49 | ||
50 | sock = socket(AF_UNIX, SOCK_STREAM, 0); | 50 | sock = socket(AF_UNIX, SOCK_STREAM, 0); |
51 | if (sock < 0) | 51 | if (sock < 0) |
52 | return -1; | 52 | return -1; |
53 | 53 | ||
54 | /* close on exec */ | 54 | /* close on exec */ |
55 | if (fcntl(sock, F_SETFD, 1) == -1) | 55 | if (fcntl(sock, F_SETFD, 1) == -1) { |
56 | { | 56 | close(sock); |
57 | close(sock); | 57 | return -1; |
58 | return -1; | 58 | } |
59 | } | 59 | if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { |
60 | 60 | close(sock); | |
61 | if (connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) | 61 | return -1; |
62 | { | 62 | } |
63 | close(sock); | 63 | return sock; |
64 | return -1; | ||
65 | } | ||
66 | |||
67 | return sock; | ||
68 | } | 64 | } |
69 | 65 | ||
70 | /* Closes the agent socket if it should be closed (depends on how it was | 66 | /* Closes the agent socket if it should be closed (depends on how it was |
71 | obtained). The argument must have been returned by | 67 | obtained). The argument must have been returned by |
72 | ssh_get_authentication_socket(). */ | 68 | ssh_get_authentication_socket(). */ |
73 | 69 | ||
74 | void ssh_close_authentication_socket(int sock) | 70 | void |
71 | ssh_close_authentication_socket(int sock) | ||
75 | { | 72 | { |
76 | if (getenv(SSH_AUTHSOCKET_ENV_NAME)) | 73 | if (getenv(SSH_AUTHSOCKET_ENV_NAME)) |
77 | close(sock); | 74 | close(sock); |
78 | } | 75 | } |
79 | 76 | ||
80 | /* Opens and connects a private socket for communication with the | 77 | /* Opens and connects a private socket for communication with the |
@@ -83,38 +80,39 @@ void ssh_close_authentication_socket(int sock) | |||
83 | Returns NULL if an error occurred and the connection could not be | 80 | Returns NULL if an error occurred and the connection could not be |
84 | opened. */ | 81 | opened. */ |
85 | 82 | ||
86 | AuthenticationConnection *ssh_get_authentication_connection() | 83 | AuthenticationConnection * |
84 | ssh_get_authentication_connection() | ||
87 | { | 85 | { |
88 | AuthenticationConnection *auth; | 86 | AuthenticationConnection *auth; |
89 | int sock; | 87 | int sock; |
90 | 88 | ||
91 | sock = ssh_get_authentication_socket(); | 89 | sock = ssh_get_authentication_socket(); |
92 | 90 | ||
93 | /* Fail if we couldn't obtain a connection. This happens if we exited | 91 | /* Fail if we couldn't obtain a connection. This happens if we |
94 | due to a timeout. */ | 92 | exited due to a timeout. */ |
95 | if (sock < 0) | 93 | if (sock < 0) |
96 | return NULL; | 94 | return NULL; |
97 | 95 | ||
98 | /* Applocate the connection structure and initialize it. */ | 96 | /* Applocate the connection structure and initialize it. */ |
99 | auth = xmalloc(sizeof(*auth)); | 97 | auth = xmalloc(sizeof(*auth)); |
100 | auth->fd = sock; | 98 | auth->fd = sock; |
101 | buffer_init(&auth->packet); | 99 | buffer_init(&auth->packet); |
102 | buffer_init(&auth->identities); | 100 | buffer_init(&auth->identities); |
103 | auth->howmany = 0; | 101 | auth->howmany = 0; |
104 | 102 | ||
105 | return auth; | 103 | return auth; |
106 | } | 104 | } |
107 | 105 | ||
108 | /* Closes the connection to the authentication agent and frees any associated | 106 | /* Closes the connection to the authentication agent and frees any associated |
109 | memory. */ | 107 | memory. */ |
110 | 108 | ||
111 | void ssh_close_authentication_connection(AuthenticationConnection *ac) | 109 | void |
110 | ssh_close_authentication_connection(AuthenticationConnection *ac) | ||
112 | { | 111 | { |
113 | buffer_free(&ac->packet); | 112 | buffer_free(&ac->packet); |
114 | buffer_free(&ac->identities); | 113 | buffer_free(&ac->identities); |
115 | close(ac->fd); | 114 | close(ac->fd); |
116 | /* Free the connection data structure. */ | 115 | xfree(ac); |
117 | xfree(ac); | ||
118 | } | 116 | } |
119 | 117 | ||
120 | /* Returns the first authentication identity held by the agent. | 118 | /* Returns the first authentication identity held by the agent. |
@@ -126,67 +124,62 @@ int | |||
126 | ssh_get_first_identity(AuthenticationConnection *auth, | 124 | ssh_get_first_identity(AuthenticationConnection *auth, |
127 | BIGNUM *e, BIGNUM *n, char **comment) | 125 | BIGNUM *e, BIGNUM *n, char **comment) |
128 | { | 126 | { |
129 | unsigned char msg[8192]; | 127 | unsigned char msg[8192]; |
130 | int len, l; | 128 | int len, l; |
131 | 129 | ||
132 | /* Send a message to the agent requesting for a list of the identities | 130 | /* Send a message to the agent requesting for a list of the |
133 | it can represent. */ | 131 | identities it can represent. */ |
134 | msg[0] = 0; | 132 | msg[0] = 0; |
135 | msg[1] = 0; | 133 | msg[1] = 0; |
136 | msg[2] = 0; | 134 | msg[2] = 0; |
137 | msg[3] = 1; | 135 | msg[3] = 1; |
138 | msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; | 136 | msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; |
139 | if (write(auth->fd, msg, 5) != 5) | 137 | if (write(auth->fd, msg, 5) != 5) { |
140 | { | 138 | error("write auth->fd: %.100s", strerror(errno)); |
141 | error("write auth->fd: %.100s", strerror(errno)); | 139 | return 0; |
142 | return 0; | 140 | } |
143 | } | 141 | /* Read the length of the response. XXX implement timeouts here. */ |
144 | 142 | len = 4; | |
145 | /* Read the length of the response. XXX implement timeouts here. */ | 143 | while (len > 0) { |
146 | len = 4; | 144 | l = read(auth->fd, msg + 4 - len, len); |
147 | while (len > 0) | 145 | if (l <= 0) { |
148 | { | 146 | error("read auth->fd: %.100s", strerror(errno)); |
149 | l = read(auth->fd, msg + 4 - len, len); | 147 | return 0; |
150 | if (l <= 0) | 148 | } |
151 | { | 149 | len -= l; |
152 | error("read auth->fd: %.100s", strerror(errno)); | 150 | } |
153 | return 0; | 151 | |
152 | /* Extract the length, and check it for sanity. (We cannot trust | ||
153 | authentication agents). */ | ||
154 | len = GET_32BIT(msg); | ||
155 | if (len < 1 || len > 256 * 1024) | ||
156 | fatal("Authentication reply message too long: %d\n", len); | ||
157 | |||
158 | /* Read the packet itself. */ | ||
159 | buffer_clear(&auth->identities); | ||
160 | while (len > 0) { | ||
161 | l = len; | ||
162 | if (l > sizeof(msg)) | ||
163 | l = sizeof(msg); | ||
164 | l = read(auth->fd, msg, l); | ||
165 | if (l <= 0) | ||
166 | fatal("Incomplete authentication reply."); | ||
167 | buffer_append(&auth->identities, (char *) msg, l); | ||
168 | len -= l; | ||
154 | } | 169 | } |
155 | len -= l; | 170 | |
156 | } | 171 | /* Get message type, and verify that we got a proper answer. */ |
157 | 172 | buffer_get(&auth->identities, (char *) msg, 1); | |
158 | /* Extract the length, and check it for sanity. (We cannot trust | 173 | if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER) |
159 | authentication agents). */ | 174 | fatal("Bad authentication reply message type: %d", msg[0]); |
160 | len = GET_32BIT(msg); | 175 | |
161 | if (len < 1 || len > 256*1024) | 176 | /* Get the number of entries in the response and check it for sanity. */ |
162 | fatal("Authentication reply message too long: %d\n", len); | 177 | auth->howmany = buffer_get_int(&auth->identities); |
163 | 178 | if (auth->howmany > 1024) | |
164 | /* Read the packet itself. */ | 179 | fatal("Too many identities in authentication reply: %d\n", auth->howmany); |
165 | buffer_clear(&auth->identities); | 180 | |
166 | while (len > 0) | 181 | /* Return the first entry (if any). */ |
167 | { | 182 | return ssh_get_next_identity(auth, e, n, comment); |
168 | l = len; | ||
169 | if (l > sizeof(msg)) | ||
170 | l = sizeof(msg); | ||
171 | l = read(auth->fd, msg, l); | ||
172 | if (l <= 0) | ||
173 | fatal("Incomplete authentication reply."); | ||
174 | buffer_append(&auth->identities, (char *)msg, l); | ||
175 | len -= l; | ||
176 | } | ||
177 | |||
178 | /* Get message type, and verify that we got a proper answer. */ | ||
179 | buffer_get(&auth->identities, (char *)msg, 1); | ||
180 | if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER) | ||
181 | fatal("Bad authentication reply message type: %d", msg[0]); | ||
182 | |||
183 | /* Get the number of entries in the response and check it for sanity. */ | ||
184 | auth->howmany = buffer_get_int(&auth->identities); | ||
185 | if (auth->howmany > 1024) | ||
186 | fatal("Too many identities in authentication reply: %d\n", auth->howmany); | ||
187 | |||
188 | /* Return the first entry (if any). */ | ||
189 | return ssh_get_next_identity(auth, e, n, comment); | ||
190 | } | 183 | } |
191 | 184 | ||
192 | /* Returns the next authentication identity for the agent. Other functions | 185 | /* Returns the next authentication identity for the agent. Other functions |
@@ -198,27 +191,27 @@ int | |||
198 | ssh_get_next_identity(AuthenticationConnection *auth, | 191 | ssh_get_next_identity(AuthenticationConnection *auth, |
199 | BIGNUM *e, BIGNUM *n, char **comment) | 192 | BIGNUM *e, BIGNUM *n, char **comment) |
200 | { | 193 | { |
201 | unsigned int bits; | 194 | unsigned int bits; |
202 | 195 | ||
203 | /* Return failure if no more entries. */ | 196 | /* Return failure if no more entries. */ |
204 | if (auth->howmany <= 0) | 197 | if (auth->howmany <= 0) |
205 | return 0; | 198 | return 0; |
206 | 199 | ||
207 | /* Get the next entry from the packet. These will abort with a fatal | 200 | /* Get the next entry from the packet. These will abort with a |
208 | error if the packet is too short or contains corrupt data. */ | 201 | fatal error if the packet is too short or contains corrupt data. */ |
209 | bits = buffer_get_int(&auth->identities); | 202 | bits = buffer_get_int(&auth->identities); |
210 | buffer_get_bignum(&auth->identities, e); | 203 | buffer_get_bignum(&auth->identities, e); |
211 | buffer_get_bignum(&auth->identities, n); | 204 | buffer_get_bignum(&auth->identities, n); |
212 | *comment = buffer_get_string(&auth->identities, NULL); | 205 | *comment = buffer_get_string(&auth->identities, NULL); |
213 | 206 | ||
214 | if (bits != BN_num_bits(n)) | 207 | if (bits != BN_num_bits(n)) |
215 | error("Warning: keysize mismatch: actual %d, announced %u", | 208 | error("Warning: keysize mismatch: actual %d, announced %u", |
216 | BN_num_bits(n), bits); | 209 | BN_num_bits(n), bits); |
217 | 210 | ||
218 | /* Decrement the number of remaining entries. */ | 211 | /* Decrement the number of remaining entries. */ |
219 | auth->howmany--; | 212 | auth->howmany--; |
220 | 213 | ||
221 | return 1; | 214 | return 1; |
222 | } | 215 | } |
223 | 216 | ||
224 | /* Generates a random challenge, sends it to the agent, and waits for response | 217 | /* Generates a random challenge, sends it to the agent, and waits for response |
@@ -229,355 +222,329 @@ ssh_get_next_identity(AuthenticationConnection *auth, | |||
229 | 222 | ||
230 | int | 223 | int |
231 | ssh_decrypt_challenge(AuthenticationConnection *auth, | 224 | ssh_decrypt_challenge(AuthenticationConnection *auth, |
232 | BIGNUM *e, BIGNUM *n, BIGNUM *challenge, | 225 | BIGNUM* e, BIGNUM *n, BIGNUM *challenge, |
233 | unsigned char session_id[16], | 226 | unsigned char session_id[16], |
234 | unsigned int response_type, | 227 | unsigned int response_type, |
235 | unsigned char response[16]) | 228 | unsigned char response[16]) |
236 | { | 229 | { |
237 | Buffer buffer; | 230 | Buffer buffer; |
238 | unsigned char buf[8192]; | 231 | unsigned char buf[8192]; |
239 | int len, l, i; | 232 | int len, l, i; |
240 | 233 | ||
241 | /* Response type 0 is no longer supported. */ | 234 | /* Response type 0 is no longer supported. */ |
242 | if (response_type == 0) | 235 | if (response_type == 0) |
243 | fatal("Compatibility with ssh protocol version 1.0 no longer supported."); | 236 | fatal("Compatibility with ssh protocol version 1.0 no longer supported."); |
244 | 237 | ||
245 | /* Format a message to the agent. */ | 238 | /* Format a message to the agent. */ |
246 | buf[0] = SSH_AGENTC_RSA_CHALLENGE; | 239 | buf[0] = SSH_AGENTC_RSA_CHALLENGE; |
247 | buffer_init(&buffer); | 240 | buffer_init(&buffer); |
248 | buffer_append(&buffer, (char *)buf, 1); | 241 | buffer_append(&buffer, (char *) buf, 1); |
249 | buffer_put_int(&buffer, BN_num_bits(n)); | 242 | buffer_put_int(&buffer, BN_num_bits(n)); |
250 | buffer_put_bignum(&buffer, e); | 243 | buffer_put_bignum(&buffer, e); |
251 | buffer_put_bignum(&buffer, n); | 244 | buffer_put_bignum(&buffer, n); |
252 | buffer_put_bignum(&buffer, challenge); | 245 | buffer_put_bignum(&buffer, challenge); |
253 | buffer_append(&buffer, (char *)session_id, 16); | 246 | buffer_append(&buffer, (char *) session_id, 16); |
254 | buffer_put_int(&buffer, response_type); | 247 | buffer_put_int(&buffer, response_type); |
255 | 248 | ||
256 | /* Get the length of the message, and format it in the buffer. */ | 249 | /* Get the length of the message, and format it in the buffer. */ |
257 | len = buffer_len(&buffer); | 250 | len = buffer_len(&buffer); |
258 | PUT_32BIT(buf, len); | 251 | PUT_32BIT(buf, len); |
259 | 252 | ||
260 | /* Send the length and then the packet to the agent. */ | 253 | /* Send the length and then the packet to the agent. */ |
261 | if (write(auth->fd, buf, 4) != 4 || | 254 | if (write(auth->fd, buf, 4) != 4 || |
262 | write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != | 255 | write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
263 | buffer_len(&buffer)) | 256 | buffer_len(&buffer)) { |
264 | { | 257 | error("Error writing to authentication socket."); |
265 | error("Error writing to authentication socket."); | 258 | error_cleanup: |
266 | error_cleanup: | 259 | buffer_free(&buffer); |
267 | buffer_free(&buffer); | 260 | return 0; |
268 | return 0; | 261 | } |
269 | } | 262 | /* Wait for response from the agent. First read the length of the |
270 | 263 | response packet. */ | |
271 | /* Wait for response from the agent. First read the length of the | 264 | len = 4; |
272 | response packet. */ | 265 | while (len > 0) { |
273 | len = 4; | 266 | l = read(auth->fd, buf + 4 - len, len); |
274 | while (len > 0) | 267 | if (l <= 0) { |
275 | { | 268 | error("Error reading response length from authentication socket."); |
276 | l = read(auth->fd, buf + 4 - len, len); | 269 | goto error_cleanup; |
277 | if (l <= 0) | 270 | } |
278 | { | 271 | len -= l; |
279 | error("Error reading response length from authentication socket."); | 272 | } |
280 | goto error_cleanup; | 273 | |
274 | /* Extract the length, and check it for sanity. */ | ||
275 | len = GET_32BIT(buf); | ||
276 | if (len > 256 * 1024) | ||
277 | fatal("Authentication response too long: %d", len); | ||
278 | |||
279 | /* Read the rest of the response in tothe buffer. */ | ||
280 | buffer_clear(&buffer); | ||
281 | while (len > 0) { | ||
282 | l = len; | ||
283 | if (l > sizeof(buf)) | ||
284 | l = sizeof(buf); | ||
285 | l = read(auth->fd, buf, l); | ||
286 | if (l <= 0) { | ||
287 | error("Error reading response from authentication socket."); | ||
288 | goto error_cleanup; | ||
289 | } | ||
290 | buffer_append(&buffer, (char *) buf, l); | ||
291 | len -= l; | ||
281 | } | 292 | } |
282 | len -= l; | 293 | |
283 | } | 294 | /* Get the type of the packet. */ |
284 | 295 | buffer_get(&buffer, (char *) buf, 1); | |
285 | /* Extract the length, and check it for sanity. */ | 296 | |
286 | len = GET_32BIT(buf); | 297 | /* Check for agent failure message. */ |
287 | if (len > 256*1024) | 298 | if (buf[0] == SSH_AGENT_FAILURE) { |
288 | fatal("Authentication response too long: %d", len); | 299 | log("Agent admitted failure to authenticate using the key."); |
289 | 300 | goto error_cleanup; | |
290 | /* Read the rest of the response in tothe buffer. */ | ||
291 | buffer_clear(&buffer); | ||
292 | while (len > 0) | ||
293 | { | ||
294 | l = len; | ||
295 | if (l > sizeof(buf)) | ||
296 | l = sizeof(buf); | ||
297 | l = read(auth->fd, buf, l); | ||
298 | if (l <= 0) | ||
299 | { | ||
300 | error("Error reading response from authentication socket."); | ||
301 | goto error_cleanup; | ||
302 | } | 301 | } |
303 | buffer_append(&buffer, (char *)buf, l); | 302 | /* Now it must be an authentication response packet. */ |
304 | len -= l; | 303 | if (buf[0] != SSH_AGENT_RSA_RESPONSE) |
305 | } | 304 | fatal("Bad authentication response: %d", buf[0]); |
306 | 305 | ||
307 | /* Get the type of the packet. */ | 306 | /* Get the response from the packet. This will abort with a fatal |
308 | buffer_get(&buffer, (char *)buf, 1); | 307 | error if the packet is corrupt. */ |
309 | 308 | for (i = 0; i < 16; i++) | |
310 | /* Check for agent failure message. */ | 309 | response[i] = buffer_get_char(&buffer); |
311 | if (buf[0] == SSH_AGENT_FAILURE) | 310 | |
312 | { | 311 | /* The buffer containing the packet is no longer needed. */ |
313 | log("Agent admitted failure to authenticate using the key."); | 312 | buffer_free(&buffer); |
314 | goto error_cleanup; | 313 | |
315 | } | 314 | /* Correct answer. */ |
316 | 315 | return 1; | |
317 | /* Now it must be an authentication response packet. */ | 316 | } |
318 | if (buf[0] != SSH_AGENT_RSA_RESPONSE) | ||
319 | fatal("Bad authentication response: %d", buf[0]); | ||
320 | |||
321 | /* Get the response from the packet. This will abort with a fatal error | ||
322 | if the packet is corrupt. */ | ||
323 | for (i = 0; i < 16; i++) | ||
324 | response[i] = buffer_get_char(&buffer); | ||
325 | |||
326 | /* The buffer containing the packet is no longer needed. */ | ||
327 | buffer_free(&buffer); | ||
328 | |||
329 | /* Correct answer. */ | ||
330 | return 1; | ||
331 | } | ||
332 | 317 | ||
333 | /* Adds an identity to the authentication server. This call is not meant to | 318 | /* Adds an identity to the authentication server. This call is not meant to |
334 | be used by normal applications. */ | 319 | be used by normal applications. */ |
335 | 320 | ||
336 | int ssh_add_identity(AuthenticationConnection *auth, | 321 | int |
337 | RSA *key, const char *comment) | 322 | ssh_add_identity(AuthenticationConnection *auth, |
323 | RSA * key, const char *comment) | ||
338 | { | 324 | { |
339 | Buffer buffer; | 325 | Buffer buffer; |
340 | unsigned char buf[8192]; | 326 | unsigned char buf[8192]; |
341 | int len, l, type; | 327 | int len, l, type; |
342 | 328 | ||
343 | /* Format a message to the agent. */ | 329 | /* Format a message to the agent. */ |
344 | buffer_init(&buffer); | 330 | buffer_init(&buffer); |
345 | buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY); | 331 | buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY); |
346 | buffer_put_int(&buffer, BN_num_bits(key->n)); | 332 | buffer_put_int(&buffer, BN_num_bits(key->n)); |
347 | buffer_put_bignum(&buffer, key->n); | 333 | buffer_put_bignum(&buffer, key->n); |
348 | buffer_put_bignum(&buffer, key->e); | 334 | buffer_put_bignum(&buffer, key->e); |
349 | buffer_put_bignum(&buffer, key->d); | 335 | buffer_put_bignum(&buffer, key->d); |
350 | /* To keep within the protocol: p < q for ssh. in SSL p > q */ | 336 | /* To keep within the protocol: p < q for ssh. in SSL p > q */ |
351 | buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */ | 337 | buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */ |
352 | buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */ | 338 | buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */ |
353 | buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */ | 339 | buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */ |
354 | buffer_put_string(&buffer, comment, strlen(comment)); | 340 | buffer_put_string(&buffer, comment, strlen(comment)); |
355 | 341 | ||
356 | /* Get the length of the message, and format it in the buffer. */ | 342 | /* Get the length of the message, and format it in the buffer. */ |
357 | len = buffer_len(&buffer); | 343 | len = buffer_len(&buffer); |
358 | PUT_32BIT(buf, len); | 344 | PUT_32BIT(buf, len); |
359 | 345 | ||
360 | /* Send the length and then the packet to the agent. */ | 346 | /* Send the length and then the packet to the agent. */ |
361 | if (write(auth->fd, buf, 4) != 4 || | 347 | if (write(auth->fd, buf, 4) != 4 || |
362 | write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != | 348 | write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
363 | buffer_len(&buffer)) | 349 | buffer_len(&buffer)) { |
364 | { | 350 | error("Error writing to authentication socket."); |
365 | error("Error writing to authentication socket."); | 351 | error_cleanup: |
366 | error_cleanup: | 352 | buffer_free(&buffer); |
367 | buffer_free(&buffer); | 353 | return 0; |
368 | return 0; | 354 | } |
369 | } | 355 | /* Wait for response from the agent. First read the length of the |
370 | 356 | response packet. */ | |
371 | /* Wait for response from the agent. First read the length of the | 357 | len = 4; |
372 | response packet. */ | 358 | while (len > 0) { |
373 | len = 4; | 359 | l = read(auth->fd, buf + 4 - len, len); |
374 | while (len > 0) | 360 | if (l <= 0) { |
375 | { | 361 | error("Error reading response length from authentication socket."); |
376 | l = read(auth->fd, buf + 4 - len, len); | 362 | goto error_cleanup; |
377 | if (l <= 0) | 363 | } |
378 | { | 364 | len -= l; |
379 | error("Error reading response length from authentication socket."); | 365 | } |
380 | goto error_cleanup; | 366 | |
367 | /* Extract the length, and check it for sanity. */ | ||
368 | len = GET_32BIT(buf); | ||
369 | if (len > 256 * 1024) | ||
370 | fatal("Add identity response too long: %d", len); | ||
371 | |||
372 | /* Read the rest of the response in tothe buffer. */ | ||
373 | buffer_clear(&buffer); | ||
374 | while (len > 0) { | ||
375 | l = len; | ||
376 | if (l > sizeof(buf)) | ||
377 | l = sizeof(buf); | ||
378 | l = read(auth->fd, buf, l); | ||
379 | if (l <= 0) { | ||
380 | error("Error reading response from authentication socket."); | ||
381 | goto error_cleanup; | ||
382 | } | ||
383 | buffer_append(&buffer, (char *) buf, l); | ||
384 | len -= l; | ||
381 | } | 385 | } |
382 | len -= l; | 386 | |
383 | } | 387 | /* Get the type of the packet. */ |
384 | 388 | type = buffer_get_char(&buffer); | |
385 | /* Extract the length, and check it for sanity. */ | 389 | switch (type) { |
386 | len = GET_32BIT(buf); | 390 | case SSH_AGENT_FAILURE: |
387 | if (len > 256*1024) | 391 | buffer_free(&buffer); |
388 | fatal("Add identity response too long: %d", len); | 392 | return 0; |
389 | 393 | case SSH_AGENT_SUCCESS: | |
390 | /* Read the rest of the response in tothe buffer. */ | 394 | buffer_free(&buffer); |
391 | buffer_clear(&buffer); | 395 | return 1; |
392 | while (len > 0) | 396 | default: |
393 | { | 397 | fatal("Bad response to add identity from authentication agent: %d", |
394 | l = len; | 398 | type); |
395 | if (l > sizeof(buf)) | ||
396 | l = sizeof(buf); | ||
397 | l = read(auth->fd, buf, l); | ||
398 | if (l <= 0) | ||
399 | { | ||
400 | error("Error reading response from authentication socket."); | ||
401 | goto error_cleanup; | ||
402 | } | 399 | } |
403 | buffer_append(&buffer, (char *)buf, l); | 400 | /* NOTREACHED */ |
404 | len -= l; | 401 | return 0; |
405 | } | 402 | } |
406 | 403 | ||
407 | /* Get the type of the packet. */ | 404 | /* Removes an identity from the authentication server. This call is not meant |
408 | type = buffer_get_char(&buffer); | ||
409 | switch (type) | ||
410 | { | ||
411 | case SSH_AGENT_FAILURE: | ||
412 | buffer_free(&buffer); | ||
413 | return 0; | ||
414 | case SSH_AGENT_SUCCESS: | ||
415 | buffer_free(&buffer); | ||
416 | return 1; | ||
417 | default: | ||
418 | fatal("Bad response to add identity from authentication agent: %d", | ||
419 | type); | ||
420 | } | ||
421 | /*NOTREACHED*/ | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | /* Removes an identity from the authentication server. This call is not meant | ||
426 | to be used by normal applications. */ | 405 | to be used by normal applications. */ |
427 | 406 | ||
428 | int ssh_remove_identity(AuthenticationConnection *auth, RSA *key) | 407 | int |
408 | ssh_remove_identity(AuthenticationConnection *auth, RSA *key) | ||
429 | { | 409 | { |
430 | Buffer buffer; | 410 | Buffer buffer; |
431 | unsigned char buf[8192]; | 411 | unsigned char buf[8192]; |
432 | int len, l, type; | 412 | int len, l, type; |
433 | 413 | ||
434 | /* Format a message to the agent. */ | 414 | /* Format a message to the agent. */ |
435 | buffer_init(&buffer); | 415 | buffer_init(&buffer); |
436 | buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); | 416 | buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); |
437 | buffer_put_int(&buffer, BN_num_bits(key->n)); | 417 | buffer_put_int(&buffer, BN_num_bits(key->n)); |
438 | buffer_put_bignum(&buffer, key->e); | 418 | buffer_put_bignum(&buffer, key->e); |
439 | buffer_put_bignum(&buffer, key->n); | 419 | buffer_put_bignum(&buffer, key->n); |
440 | 420 | ||
441 | /* Get the length of the message, and format it in the buffer. */ | 421 | /* Get the length of the message, and format it in the buffer. */ |
442 | len = buffer_len(&buffer); | 422 | len = buffer_len(&buffer); |
443 | PUT_32BIT(buf, len); | 423 | PUT_32BIT(buf, len); |
444 | 424 | ||
445 | /* Send the length and then the packet to the agent. */ | 425 | /* Send the length and then the packet to the agent. */ |
446 | if (write(auth->fd, buf, 4) != 4 || | 426 | if (write(auth->fd, buf, 4) != 4 || |
447 | write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != | 427 | write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
448 | buffer_len(&buffer)) | 428 | buffer_len(&buffer)) { |
449 | { | 429 | error("Error writing to authentication socket."); |
450 | error("Error writing to authentication socket."); | 430 | error_cleanup: |
451 | error_cleanup: | 431 | buffer_free(&buffer); |
452 | buffer_free(&buffer); | 432 | return 0; |
453 | return 0; | 433 | } |
454 | } | 434 | /* Wait for response from the agent. First read the length of the |
455 | 435 | response packet. */ | |
456 | /* Wait for response from the agent. First read the length of the | 436 | len = 4; |
457 | response packet. */ | 437 | while (len > 0) { |
458 | len = 4; | 438 | l = read(auth->fd, buf + 4 - len, len); |
459 | while (len > 0) | 439 | if (l <= 0) { |
460 | { | 440 | error("Error reading response length from authentication socket."); |
461 | l = read(auth->fd, buf + 4 - len, len); | 441 | goto error_cleanup; |
462 | if (l <= 0) | 442 | } |
463 | { | 443 | len -= l; |
464 | error("Error reading response length from authentication socket."); | 444 | } |
465 | goto error_cleanup; | 445 | |
446 | /* Extract the length, and check it for sanity. */ | ||
447 | len = GET_32BIT(buf); | ||
448 | if (len > 256 * 1024) | ||
449 | fatal("Remove identity response too long: %d", len); | ||
450 | |||
451 | /* Read the rest of the response in tothe buffer. */ | ||
452 | buffer_clear(&buffer); | ||
453 | while (len > 0) { | ||
454 | l = len; | ||
455 | if (l > sizeof(buf)) | ||
456 | l = sizeof(buf); | ||
457 | l = read(auth->fd, buf, l); | ||
458 | if (l <= 0) { | ||
459 | error("Error reading response from authentication socket."); | ||
460 | goto error_cleanup; | ||
461 | } | ||
462 | buffer_append(&buffer, (char *) buf, l); | ||
463 | len -= l; | ||
466 | } | 464 | } |
467 | len -= l; | 465 | |
468 | } | 466 | /* Get the type of the packet. */ |
469 | 467 | type = buffer_get_char(&buffer); | |
470 | /* Extract the length, and check it for sanity. */ | 468 | switch (type) { |
471 | len = GET_32BIT(buf); | 469 | case SSH_AGENT_FAILURE: |
472 | if (len > 256*1024) | 470 | buffer_free(&buffer); |
473 | fatal("Remove identity response too long: %d", len); | 471 | return 0; |
474 | 472 | case SSH_AGENT_SUCCESS: | |
475 | /* Read the rest of the response in tothe buffer. */ | 473 | buffer_free(&buffer); |
476 | buffer_clear(&buffer); | 474 | return 1; |
477 | while (len > 0) | 475 | default: |
478 | { | 476 | fatal("Bad response to remove identity from authentication agent: %d", |
479 | l = len; | 477 | type); |
480 | if (l > sizeof(buf)) | ||
481 | l = sizeof(buf); | ||
482 | l = read(auth->fd, buf, l); | ||
483 | if (l <= 0) | ||
484 | { | ||
485 | error("Error reading response from authentication socket."); | ||
486 | goto error_cleanup; | ||
487 | } | 478 | } |
488 | buffer_append(&buffer, (char *)buf, l); | 479 | /* NOTREACHED */ |
489 | len -= l; | 480 | return 0; |
490 | } | 481 | } |
491 | 482 | ||
492 | /* Get the type of the packet. */ | 483 | /* Removes all identities from the agent. This call is not meant |
493 | type = buffer_get_char(&buffer); | ||
494 | switch (type) | ||
495 | { | ||
496 | case SSH_AGENT_FAILURE: | ||
497 | buffer_free(&buffer); | ||
498 | return 0; | ||
499 | case SSH_AGENT_SUCCESS: | ||
500 | buffer_free(&buffer); | ||
501 | return 1; | ||
502 | default: | ||
503 | fatal("Bad response to remove identity from authentication agent: %d", | ||
504 | type); | ||
505 | } | ||
506 | /*NOTREACHED*/ | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | /* Removes all identities from the agent. This call is not meant | ||
511 | to be used by normal applications. */ | 484 | to be used by normal applications. */ |
512 | 485 | ||
513 | int ssh_remove_all_identities(AuthenticationConnection *auth) | 486 | int |
487 | ssh_remove_all_identities(AuthenticationConnection *auth) | ||
514 | { | 488 | { |
515 | Buffer buffer; | 489 | Buffer buffer; |
516 | unsigned char buf[8192]; | 490 | unsigned char buf[8192]; |
517 | int len, l, type; | 491 | int len, l, type; |
518 | 492 | ||
519 | /* Get the length of the message, and format it in the buffer. */ | 493 | /* Get the length of the message, and format it in the buffer. */ |
520 | PUT_32BIT(buf, 1); | 494 | PUT_32BIT(buf, 1); |
521 | buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES; | 495 | buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES; |
522 | 496 | ||
523 | /* Send the length and then the packet to the agent. */ | 497 | /* Send the length and then the packet to the agent. */ |
524 | if (write(auth->fd, buf, 5) != 5) | 498 | if (write(auth->fd, buf, 5) != 5) { |
525 | { | 499 | error("Error writing to authentication socket."); |
526 | error("Error writing to authentication socket."); | 500 | return 0; |
527 | return 0; | 501 | } |
528 | } | 502 | /* Wait for response from the agent. First read the length of the |
529 | 503 | response packet. */ | |
530 | /* Wait for response from the agent. First read the length of the | 504 | len = 4; |
531 | response packet. */ | 505 | while (len > 0) { |
532 | len = 4; | 506 | l = read(auth->fd, buf + 4 - len, len); |
533 | while (len > 0) | 507 | if (l <= 0) { |
534 | { | 508 | error("Error reading response length from authentication socket."); |
535 | l = read(auth->fd, buf + 4 - len, len); | 509 | return 0; |
536 | if (l <= 0) | 510 | } |
537 | { | 511 | len -= l; |
538 | error("Error reading response length from authentication socket."); | 512 | } |
539 | return 0; | 513 | |
514 | /* Extract the length, and check it for sanity. */ | ||
515 | len = GET_32BIT(buf); | ||
516 | if (len > 256 * 1024) | ||
517 | fatal("Remove identity response too long: %d", len); | ||
518 | |||
519 | /* Read the rest of the response into the buffer. */ | ||
520 | buffer_init(&buffer); | ||
521 | while (len > 0) { | ||
522 | l = len; | ||
523 | if (l > sizeof(buf)) | ||
524 | l = sizeof(buf); | ||
525 | l = read(auth->fd, buf, l); | ||
526 | if (l <= 0) { | ||
527 | error("Error reading response from authentication socket."); | ||
528 | buffer_free(&buffer); | ||
529 | return 0; | ||
530 | } | ||
531 | buffer_append(&buffer, (char *) buf, l); | ||
532 | len -= l; | ||
540 | } | 533 | } |
541 | len -= l; | 534 | |
542 | } | 535 | /* Get the type of the packet. */ |
543 | 536 | type = buffer_get_char(&buffer); | |
544 | /* Extract the length, and check it for sanity. */ | 537 | switch (type) { |
545 | len = GET_32BIT(buf); | 538 | case SSH_AGENT_FAILURE: |
546 | if (len > 256*1024) | 539 | buffer_free(&buffer); |
547 | fatal("Remove identity response too long: %d", len); | 540 | return 0; |
548 | 541 | case SSH_AGENT_SUCCESS: | |
549 | /* Read the rest of the response into the buffer. */ | 542 | buffer_free(&buffer); |
550 | buffer_init(&buffer); | 543 | return 1; |
551 | while (len > 0) | 544 | default: |
552 | { | 545 | fatal("Bad response to remove identity from authentication agent: %d", |
553 | l = len; | 546 | type); |
554 | if (l > sizeof(buf)) | ||
555 | l = sizeof(buf); | ||
556 | l = read(auth->fd, buf, l); | ||
557 | if (l <= 0) | ||
558 | { | ||
559 | error("Error reading response from authentication socket."); | ||
560 | buffer_free(&buffer); | ||
561 | return 0; | ||
562 | } | 547 | } |
563 | buffer_append(&buffer, (char *)buf, l); | 548 | /* NOTREACHED */ |
564 | len -= l; | 549 | return 0; |
565 | } | 550 | } |
566 | |||
567 | /* Get the type of the packet. */ | ||
568 | type = buffer_get_char(&buffer); | ||
569 | switch (type) | ||
570 | { | ||
571 | case SSH_AGENT_FAILURE: | ||
572 | buffer_free(&buffer); | ||
573 | return 0; | ||
574 | case SSH_AGENT_SUCCESS: | ||
575 | buffer_free(&buffer); | ||
576 | return 1; | ||
577 | default: | ||
578 | fatal("Bad response to remove identity from authentication agent: %d", | ||
579 | type); | ||
580 | } | ||
581 | /*NOTREACHED*/ | ||
582 | return 0; | ||
583 | } | ||