Mercurial > dropbear
comparison cli-agentfwd.c @ 552:de3653483ac0 agent-client
- Client auth using an agent's key works. Still need to implement client
agent forwarding.
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 06 Jul 2009 14:02:45 +0000 |
parents | c3f2ec71e3d4 |
children | 52d7301e46bd |
comparison
equal
deleted
inserted
replaced
551:c3f2ec71e3d4 | 552:de3653483ac0 |
---|---|
100 4 bytes Length, msb first. Does not include length itself. | 100 4 bytes Length, msb first. Does not include length itself. |
101 1 byte Packet type. The value 255 is reserved for future extensions. | 101 1 byte Packet type. The value 255 is reserved for future extensions. |
102 data Any data, depending on packet type. Encoding as in the ssh packet | 102 data Any data, depending on packet type. Encoding as in the ssh packet |
103 protocol. | 103 protocol. |
104 */ | 104 */ |
105 static buffer * agent_request(int fd, unsigned char type) { | 105 static buffer * agent_request(unsigned char type, buffer *data) { |
106 | 106 |
107 buffer * payload = NULL; | 107 buffer * payload = NULL; |
108 buffer * inbuf = NULL; | 108 buffer * inbuf = NULL; |
109 size_t readlen = 0; | 109 size_t readlen = 0; |
110 ssize_t ret; | 110 ssize_t ret; |
111 | 111 const int fd = cli_opts.agent_fd; |
112 payload = buf_new(4 + 1); | 112 unsigned int data_len = 0; |
113 | 113 if (data) |
114 buf_putint(payload, 1); | 114 { |
115 data_len = data->len; | |
116 } | |
117 | |
118 payload = buf_new(4 + 1 + data_len); | |
119 | |
120 buf_putint(payload, 1 + data_len); | |
115 buf_putbyte(payload, type); | 121 buf_putbyte(payload, type); |
122 if (data) { | |
123 buf_putbytes(payload, data->data, data->len); | |
124 } | |
116 buf_setpos(payload, 0); | 125 buf_setpos(payload, 0); |
117 | 126 |
118 ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len); | 127 ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len); |
119 if ((size_t)ret != payload->len) { | 128 if ((size_t)ret != payload->len) { |
120 TRACE(("write failed fd %d for agent_request, %s", fd, strerror(errno))) | 129 TRACE(("write failed fd %d for agent_request, %s", fd, strerror(errno))) |
158 buf_free(payload); | 167 buf_free(payload); |
159 | 168 |
160 return inbuf; | 169 return inbuf; |
161 } | 170 } |
162 | 171 |
163 static void agent_get_key_list(int fd, m_list * ret_list) | 172 static void agent_get_key_list(m_list * ret_list) |
164 { | 173 { |
165 buffer * inbuf = NULL; | 174 buffer * inbuf = NULL; |
166 unsigned int num = 0; | 175 unsigned int num = 0; |
167 unsigned char packet_type; | 176 unsigned char packet_type; |
168 unsigned int i; | 177 unsigned int i; |
169 int ret; | 178 int ret; |
170 | 179 |
171 inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); | 180 inbuf = agent_request(SSH2_AGENTC_REQUEST_IDENTITIES, NULL); |
172 if (!inbuf) { | 181 if (!inbuf) { |
173 TRACE(("agent_request returned no identities")) | 182 TRACE(("agent_request failed returning identities")) |
174 goto out; | 183 goto out; |
175 } | 184 } |
176 | 185 |
177 /* The reply has a format of: | 186 /* The reply has a format of: |
178 byte SSH2_AGENT_IDENTITIES_ANSWER | 187 byte SSH2_AGENT_IDENTITIES_ANSWER |
189 num = buf_getint(inbuf); | 198 num = buf_getint(inbuf); |
190 for (i = 0; i < num; i++) { | 199 for (i = 0; i < num; i++) { |
191 sign_key * pubkey = NULL; | 200 sign_key * pubkey = NULL; |
192 int key_type = DROPBEAR_SIGNKEY_ANY; | 201 int key_type = DROPBEAR_SIGNKEY_ANY; |
193 buffer * key_buf; | 202 buffer * key_buf; |
194 struct SignKeyList *nextkey = NULL; | |
195 | 203 |
196 /* each public key is encoded as a string */ | 204 /* each public key is encoded as a string */ |
197 key_buf = buf_getstringbuf(inbuf); | 205 key_buf = buf_getstringbuf(inbuf); |
198 pubkey = new_sign_key(); | 206 pubkey = new_sign_key(); |
199 ret = buf_get_pub_key(key_buf, pubkey, &key_type); | 207 ret = buf_get_pub_key(key_buf, pubkey, &key_type); |
220 | 228 |
221 /* Returned keys are prepended to ret_list, which will | 229 /* Returned keys are prepended to ret_list, which will |
222 be updated. */ | 230 be updated. */ |
223 void load_agent_keys(m_list *ret_list) | 231 void load_agent_keys(m_list *ret_list) |
224 { | 232 { |
225 int fd; | 233 /* agent_fd will be closed after successful auth */ |
226 fd = connect_agent(); | 234 cli_opts.agent_fd = connect_agent(); |
227 if (fd < 0) { | 235 if (cli_opts.agent_fd < 0) { |
228 dropbear_log(LOG_INFO, "Failed to connect to agent"); | 236 dropbear_log(LOG_INFO, "Failed to connect to agent"); |
229 return; | 237 return; |
230 } | 238 } |
231 | 239 |
232 agent_get_key_list(fd, ret_list); | 240 agent_get_key_list(ret_list); |
233 close(fd); | |
234 } | 241 } |
235 | 242 |
236 void agent_buf_sign(buffer *sigblob, sign_key *key, | 243 void agent_buf_sign(buffer *sigblob, sign_key *key, |
237 const unsigned char *data, unsigned int len) { | 244 const unsigned char *data, unsigned int len) { |
245 buffer *request_data = buf_new(MAX_PUBKEY_SIZE + len + 12); | |
246 buffer *response; | |
247 unsigned int keylen, siglen; | |
248 int packet_type; | |
249 | |
250 /* Request format | |
251 byte SSH2_AGENTC_SIGN_REQUEST | |
252 string key_blob | |
253 string data | |
254 uint32 flags | |
255 */ | |
256 /* We write the key, then figure how long it was and write that */ | |
257 //buf_putint(request_data, 0); | |
258 buf_put_pub_key(request_data, key, key->type); | |
259 keylen = request_data->len - 4; | |
260 //buf_setpos(request_data, 0); | |
261 //buf_putint(request_data, keylen); | |
262 | |
263 //buf_setpos(request_data, request_data->len); | |
264 buf_putstring(request_data, data, len); | |
265 buf_putint(request_data, 0); | |
266 | |
267 response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data); | |
268 buf_free(request_data); | |
269 | |
270 if (!response) { | |
271 goto fail; | |
272 } | |
273 | |
274 packet_type = buf_getbyte(response); | |
275 if (packet_type != SSH2_AGENT_SIGN_RESPONSE) { | |
276 goto fail; | |
277 } | |
278 | |
279 /* Response format | |
280 byte SSH2_AGENT_SIGN_RESPONSE | |
281 string signature_blob | |
282 */ | |
283 siglen = buf_getint(response); | |
284 buf_putbytes(sigblob, buf_getptr(response, siglen), siglen); | |
285 buf_free(response); | |
286 | |
287 return; | |
288 fail: | |
289 /* XXX don't fail badly here. instead propagate a failure code back up to | |
290 the cli auth pubkey code, and just remove this key from the list of | |
291 ones to try. */ | |
292 dropbear_exit("Agent failed signing key"); | |
238 } | 293 } |
239 | 294 |
240 #endif | 295 #endif |