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