Mercurial > dropbear
comparison cli-agentfwd.c @ 225:ca7e76d981d9 agent-client
- progress towards client agent forwarding
(incomplete and does not compile)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 18 Jul 2005 14:32:52 +0000 |
parents | |
children | cf376c696dfc |
comparison
equal
deleted
inserted
replaced
224:1dbd2473482f | 225:ca7e76d981d9 |
---|---|
1 /* | |
2 * Dropbear - a SSH2 server | |
3 * | |
4 * Copyright (c) 2005 Matt Johnston | |
5 * All rights reserved. | |
6 * | |
7 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 * of this software and associated documentation files (the "Software"), to deal | |
9 * in the Software without restriction, including without limitation the rights | |
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 * copies of the Software, and to permit persons to whom the Software is | |
12 * furnished to do so, subject to the following conditions: | |
13 * | |
14 * The above copyright notice and this permission notice shall be included in | |
15 * all copies or substantial portions of the Software. | |
16 * | |
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
23 * SOFTWARE. */ | |
24 | |
25 /* The basic protocol use to communicate with the agent is defined in | |
26 * draft-ylonen-ssh-protocol-00.txt, with the ssh2 extensions defined through | |
27 * openssh's implementation. */ | |
28 | |
29 #include "includes.h" | |
30 | |
31 #ifdef ENABLE_CLI_AGENTFWD | |
32 | |
33 #include "agentfwd.h" | |
34 #include "session.h" | |
35 #include "ssh.h" | |
36 #include "dbutil.h" | |
37 #include "chansession.h" | |
38 #include "channel.h" | |
39 #include "packet.h" | |
40 #include "buffer.h" | |
41 #include "random.h" | |
42 #include "listener.h" | |
43 #include "runopts.h" | |
44 #include "atomicio.h" | |
45 #include "signkey.h" | |
46 #include "auth.h" | |
47 | |
48 static int new_agent_chan(struct Channel * channel); | |
49 | |
50 const struct ChanType chan_cli_agent = { | |
51 0, /* sepfds */ | |
52 "[email protected]", | |
53 new_agent_chan, | |
54 NULL, | |
55 NULL, | |
56 NULL | |
57 }; | |
58 | |
59 static int connect_agent() { | |
60 | |
61 int fd = -1; | |
62 char* agent_sock = NULL; | |
63 | |
64 agent_sock = getenv("SSH_AUTH_SOCK"); | |
65 if (agent_sock == NULL) | |
66 return -1; | |
67 | |
68 fd = connect_unix(agent_sock); | |
69 | |
70 return fd; | |
71 } | |
72 | |
73 // handle a request for a connection to the locally running ssh-agent | |
74 // or forward. | |
75 static int new_agent_chan(struct Channel * channel) { | |
76 | |
77 int fd = -1; | |
78 | |
79 if (!cli_opts.agent_fwd) | |
80 return SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; | |
81 | |
82 fd = connect_agent(); | |
83 | |
84 setnonblocking(fd); | |
85 | |
86 ses.maxfd = MAX(ses.maxfd, fd); | |
87 | |
88 channel->infd = fd; | |
89 channel->outfd = fd; | |
90 | |
91 // success | |
92 return 0; | |
93 } | |
94 | |
95 /* Sends a request to the agent, returning a newly allocated buffer | |
96 * with the response */ | |
97 /* Packet format (from draft-ylonen) | |
98 4 bytes Length, msb first. Does not include length itself. | |
99 1 byte Packet type. The value 255 is reserved for future extensions. | |
100 data Any data, depending on packet type. Encoding as in the ssh packet | |
101 protocol. | |
102 | |
103 In this case, data is always empty | |
104 */ | |
105 static buffer * agent_request(int fd, unsigned char type) { | |
106 | |
107 buffer * payload = NULL; | |
108 buffer * inbuf = NULL; | |
109 size_t readlen = 0; | |
110 ssize_t ret; | |
111 | |
112 payload = buf_new(4 + 1); | |
113 | |
114 buf_putint(payload, 1); | |
115 buf_putbyte(payload, type); | |
116 | |
117 ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len); | |
118 if ((size_t)ret != payload->len) { | |
119 TRACE(("write failed for agent_request")) | |
120 goto out; | |
121 } | |
122 | |
123 buf_free(payload); | |
124 payload = NULL; | |
125 | |
126 /* Now we read the response */ | |
127 inbuf = buf_new(4); | |
128 ret = atomicio(read, fd, buf_getwriteptr(inbuf, 4), 4); | |
129 if (ret != 4) { | |
130 TRACE(("read of length failed for agent_request")) | |
131 goto out; | |
132 } | |
133 | |
134 readlen = buf_getint(inbuf); | |
135 if (readlen > MAX_AGENT_REPLY) { | |
136 TRACE(("agent reply is too big")); | |
137 goto out; | |
138 } | |
139 | |
140 buf_resize(inbuf, readlen); | |
141 ret = atomicio(read, fd, buf_getwriteptr(inbuf, readlen), readlen); | |
142 if ((size_t)ret != readlen) { | |
143 TRACE(("read of data failed for agent_request")) | |
144 goto out; | |
145 } | |
146 | |
147 out: | |
148 if (payload) | |
149 buf_free(payload); | |
150 | |
151 return inbuf; | |
152 } | |
153 | |
154 static SignKeyList * agent_get_key_list(int fd) | |
155 { | |
156 buffer * inbuf = NULL; | |
157 unsigned int num = 0; | |
158 unsigned char packet_type; | |
159 unsigned int i; | |
160 struct SignKeyList *retkey = NULL, *key = NULL; | |
161 int ret; | |
162 | |
163 inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); | |
164 if (!inbuf) { | |
165 goto out; | |
166 } | |
167 | |
168 /* The reply has a format of: | |
169 * byte packet_type | |
170 * int num_keys | |
171 * | |
172 * string keyblob1 | |
173 * string comment1 | |
174 * ... | |
175 * string keyblob(n) | |
176 * string comment(n) | |
177 */ | |
178 packet_type = buf_getbyte(inbuf); | |
179 if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) { | |
180 goto out; | |
181 } | |
182 | |
183 num = buf_getint(inbuf); | |
184 for (i = 0; i < num; i++) { | |
185 sign_key * pubkey = NULL; | |
186 char key_type = DROPBEAR_SIGNKEY_ANY; | |
187 struct SignKeyList *nextkey = NULL; | |
188 | |
189 nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); | |
190 if (key) | |
191 key->next = nextkey; | |
192 else | |
193 retkey = nextkey; | |
194 key = nextkey; | |
195 | |
196 pubkey = new_sign_key(); | |
197 ret = buf_get_pub_key(inbuf, pubkey, &key_type); | |
198 if (ret != DROPBEAR_SUCCESS) { | |
199 /* This is slack, properly would cleanup vars etc */ | |
200 dropbear_exit("Bad pubkey received from agent"); | |
201 } | |
202 | |
203 key->key = pubkey; | |
204 key->next = NULL; | |
205 key->type = key_type; | |
206 key->source = SIGNKEY_SOURCE_AGENT; | |
207 | |
208 /* We'll ignore the comment */ | |
209 buf_eatstring(inbuf); | |
210 } | |
211 | |
212 out: | |
213 if (inbuf) { | |
214 buf_free(inbuf); | |
215 inbuf = NULL; | |
216 } | |
217 | |
218 return retkey; | |
219 } | |
220 | |
221 /* return DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ | |
222 SignKeyList * load_agent_keys() | |
223 { | |
224 | |
225 SignKeyList * ret_list; | |
226 int fd; | |
227 fd = connect_agent(); | |
228 if (fd < 0) { | |
229 dropbear_log(LOG_INFO, "Failed to connect to agent"); | |
230 return NULL; | |
231 } | |
232 | |
233 ret_list = agent_get_key_list(fd); | |
234 close(fd); | |
235 } | |
236 | |
237 // general procedure: | |
238 // - get the list of keys from the agent | |
239 // - foreach, send a dummy userauth_pubkey message to the server and see | |
240 // if it lets us in | |
241 // - if it does, sign and auth | |
242 // - if not, repeat. | |
243 // | |
244 | |
245 #endif |