comparison cli-agentfwd.c @ 551:c3f2ec71e3d4 agent-client

New standard linked list to use, rather than adhoc SignKeyList or TCPFwdList
author Matt Johnston <matt@ucc.asn.au>
date Mon, 06 Jul 2009 12:59:13 +0000
parents 61c3513825b0
children de3653483ac0
comparison
equal deleted inserted replaced
550:61c3513825b0 551:c3f2ec71e3d4
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 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 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, 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 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE. */ 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 24
29 #include "includes.h" 25 #include "includes.h"
30 26
31 #ifdef ENABLE_CLI_AGENTFWD 27 #ifdef ENABLE_CLI_AGENTFWD
32 28
43 #include "runopts.h" 39 #include "runopts.h"
44 #include "atomicio.h" 40 #include "atomicio.h"
45 #include "signkey.h" 41 #include "signkey.h"
46 #include "auth.h" 42 #include "auth.h"
47 43
44 /* The protocol implemented to talk to OpenSSH's SSH2 agent is documented in
45 PROTOCOL.agent in recent OpenSSH source distributions (5.1p1 has it). */
46
48 static int new_agent_chan(struct Channel * channel); 47 static int new_agent_chan(struct Channel * channel);
49 48
50 const struct ChanType cli_chan_agent = { 49 const struct ChanType cli_chan_agent = {
51 0, /* sepfds */ 50 0, /* sepfds */
52 "[email protected]", 51 "[email protected]",
159 buf_free(payload); 158 buf_free(payload);
160 159
161 return inbuf; 160 return inbuf;
162 } 161 }
163 162
164 static void agent_get_key_list(int fd, struct SignKeyList * ret_list) 163 static void agent_get_key_list(int fd, m_list * ret_list)
165 { 164 {
166 buffer * inbuf = NULL; 165 buffer * inbuf = NULL;
167 unsigned int num = 0; 166 unsigned int num = 0;
168 unsigned char packet_type; 167 unsigned char packet_type;
169 unsigned int i; 168 unsigned int i;
170 struct SignKeyList *key = NULL;
171 int ret; 169 int ret;
172 170
173 inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); 171 inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES);
174 if (!inbuf) { 172 if (!inbuf) {
175 TRACE(("agent_request returned no identities")) 173 TRACE(("agent_request returned no identities"))
176 goto out; 174 goto out;
177 } 175 }
178 176
179 /* The reply has a format of: 177 /* The reply has a format of:
180 * byte packet_type 178 byte SSH2_AGENT_IDENTITIES_ANSWER
181 * int num_keys 179 uint32 num_keys
182 * 180 Followed by zero or more consecutive keys, encoded as:
183 * string keyblob1 181 string key_blob
184 * string comment1 182 string key_comment
185 * ...
186 * string keyblob(n)
187 * string comment(n)
188 */ 183 */
189 packet_type = buf_getbyte(inbuf); 184 packet_type = buf_getbyte(inbuf);
190 if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) { 185 if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) {
191 goto out; 186 goto out;
192 } 187 }
193 188
194 num = buf_getint(inbuf); 189 num = buf_getint(inbuf);
195 for (i = 0; i < num; i++) { 190 for (i = 0; i < num; i++) {
196 sign_key * pubkey = NULL; 191 sign_key * pubkey = NULL;
197 int key_type = DROPBEAR_SIGNKEY_ANY; 192 int key_type = DROPBEAR_SIGNKEY_ANY;
193 buffer * key_buf;
198 struct SignKeyList *nextkey = NULL; 194 struct SignKeyList *nextkey = NULL;
199 195
200 nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); 196 /* each public key is encoded as a string */
201 ret_list->next = nextkey; 197 key_buf = buf_getstringbuf(inbuf);
202 ret_list = nextkey;
203
204 pubkey = new_sign_key(); 198 pubkey = new_sign_key();
205 ret = buf_get_pub_key(inbuf, pubkey, &key_type); 199 ret = buf_get_pub_key(key_buf, pubkey, &key_type);
200 buf_free(key_buf);
206 if (ret != DROPBEAR_SUCCESS) { 201 if (ret != DROPBEAR_SUCCESS) {
207 /* This is slack, properly would cleanup vars etc */ 202 /* This is slack, properly would cleanup vars etc */
208 dropbear_exit("Bad pubkey received from agent"); 203 dropbear_exit("Bad pubkey received from agent");
209 } 204 }
210 205 pubkey->type = key_type;
211 key->key = pubkey; 206 pubkey->source = SIGNKEY_SOURCE_AGENT;
212 key->next = NULL; 207
213 key->type = key_type; 208 list_append(ret_list, pubkey);
214 key->source = SIGNKEY_SOURCE_AGENT; 209
215 210 /* We'll ignore the comment for now. might want it later.*/
216 /* We'll ignore the comment */
217 buf_eatstring(inbuf); 211 buf_eatstring(inbuf);
218 } 212 }
219 213
220 out: 214 out:
221 if (inbuf) { 215 if (inbuf) {
222 buf_free(inbuf); 216 buf_free(inbuf);
223 inbuf = NULL; 217 inbuf = NULL;
224 } 218 }
225 } 219 }
226 220
227 /* Returned keys are appended to ret_list */ 221 /* Returned keys are prepended to ret_list, which will
228 void load_agent_keys(struct SignKeyList * ret_list) 222 be updated. */
223 void load_agent_keys(m_list *ret_list)
229 { 224 {
230 int fd; 225 int fd;
231 fd = connect_agent(); 226 fd = connect_agent();
232 if (fd < 0) { 227 if (fd < 0) {
233 dropbear_log(LOG_INFO, "Failed to connect to agent"); 228 dropbear_log(LOG_INFO, "Failed to connect to agent");
235 } 230 }
236 231
237 agent_get_key_list(fd, ret_list); 232 agent_get_key_list(fd, ret_list);
238 close(fd); 233 close(fd);
239 } 234 }
240 235
241 // general procedure: 236 void agent_buf_sign(buffer *sigblob, sign_key *key,
242 // - get the list of keys from the agent 237 const unsigned char *data, unsigned int len) {
243 // - foreach, send a dummy userauth_pubkey message to the server and see 238 }
244 // if it lets us in
245 // - if it does, sign and auth
246 // - if not, repeat.
247 //
248 239
249 #endif 240 #endif