Mercurial > dropbear
comparison cli-authpubkey.c @ 45:9ee8996a375f
Pubkey auth is mostly there for the client. Something strange with
remote hostkey verification though.
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 03 Aug 2004 17:26:56 +0000 |
parents | |
children | 4b53a43f0082 |
comparison
equal
deleted
inserted
replaced
44:45edf30ea0a6 | 45:9ee8996a375f |
---|---|
1 #include "includes.h" | |
2 #include "buffer.h" | |
3 #include "dbutil.h" | |
4 #include "session.h" | |
5 #include "ssh.h" | |
6 #include "runopts.h" | |
7 #include "auth.h" | |
8 | |
9 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign); | |
10 | |
11 /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request. | |
12 * We use it to remove the key we tried from the list */ | |
13 void cli_pubkeyfail() { | |
14 | |
15 struct PubkeyList *keyitem; | |
16 | |
17 TRACE(("enter cli_pubkeyfail")); | |
18 /* Find the key we failed with, and remove it */ | |
19 for (keyitem = cli_ses.pubkeys; keyitem != NULL; keyitem = keyitem->next) { | |
20 if (keyitem->next == cli_ses.lastpubkey) { | |
21 keyitem->next = cli_ses.lastpubkey->next; | |
22 } | |
23 } | |
24 | |
25 sign_key_free(cli_ses.lastpubkey->key); /* It won't be used again */ | |
26 m_free(cli_ses.lastpubkey); | |
27 TRACE(("leave cli_pubkeyfail")); | |
28 } | |
29 | |
30 void recv_msg_userauth_pk_ok() { | |
31 | |
32 struct PubkeyList *keyitem; | |
33 buffer* keybuf; | |
34 char* algotype = NULL; | |
35 unsigned int algolen; | |
36 int keytype; | |
37 unsigned int remotelen; | |
38 | |
39 TRACE(("enter recv_msg_userauth_pk_ok")); | |
40 | |
41 algotype = buf_getstring(ses.payload, &algolen); | |
42 keytype = signkey_type_from_name(algotype, algolen); | |
43 m_free(algotype); | |
44 | |
45 keybuf = buf_new(MAX_PUBKEY_SIZE); | |
46 | |
47 remotelen = buf_getint(ses.payload); | |
48 | |
49 /* Iterate through our keys, find which one it was that matched, and | |
50 * send a real request with that key */ | |
51 for (keyitem = cli_ses.pubkeys; keyitem != NULL; keyitem = keyitem->next) { | |
52 | |
53 if (keyitem->type != keytype) { | |
54 /* Types differed */ | |
55 continue; | |
56 } | |
57 | |
58 /* Now we compare the contents of the key */ | |
59 keybuf->pos = keybuf->len = 0; | |
60 buf_put_pub_key(keybuf, keyitem->key, keytype); | |
61 | |
62 if (keybuf->len != remotelen) { | |
63 /* Lengths differed */ | |
64 continue; | |
65 } | |
66 | |
67 if (memcmp(keybuf->data, | |
68 buf_getptr(ses.payload, remotelen), remotelen) != 0) { | |
69 /* Data didn't match this key */ | |
70 continue; | |
71 } | |
72 | |
73 /* Success */ | |
74 break; | |
75 } | |
76 | |
77 if (keyitem != NULL) { | |
78 TRACE(("matching key")); | |
79 /* XXX TODO: if it's an encrypted key, here we ask for their | |
80 * password */ | |
81 send_msg_userauth_pubkey(keyitem->key, keytype, 1); | |
82 } else { | |
83 TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part")); | |
84 } | |
85 | |
86 TRACE(("leave recv_msg_userauth_pk_ok")); | |
87 } | |
88 | |
89 /* TODO: make it take an agent reference to use as well */ | |
90 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) { | |
91 | |
92 const char *algoname = NULL; | |
93 int algolen; | |
94 buffer* sigbuf = NULL; | |
95 | |
96 TRACE(("enter send_msg_userauth_pubkey")); | |
97 CHECKCLEARTOWRITE(); | |
98 | |
99 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); | |
100 | |
101 buf_putstring(ses.writepayload, cli_opts.username, | |
102 strlen(cli_opts.username)); | |
103 | |
104 buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION, | |
105 SSH_SERVICE_CONNECTION_LEN); | |
106 | |
107 buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY, | |
108 AUTH_METHOD_PUBKEY_LEN); | |
109 | |
110 buf_putbyte(ses.writepayload, realsign); | |
111 | |
112 algoname = signkey_name_from_type(type, &algolen); | |
113 | |
114 buf_putstring(ses.writepayload, algoname, algolen); | |
115 buf_put_pub_key(ses.writepayload, key, type); | |
116 | |
117 if (realsign) { | |
118 TRACE(("realsign")); | |
119 /* We put the signature as well - this contains string(session id), then | |
120 * the contents of the write payload to this point */ | |
121 sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len); | |
122 buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE); | |
123 buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len); | |
124 buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len); | |
125 buf_free(sigbuf); /* Nothing confidential in the buffer */ | |
126 } | |
127 | |
128 encrypt_packet(); | |
129 TRACE(("leave send_msg_userauth_pubkey")); | |
130 } | |
131 | |
132 int cli_auth_pubkey() { | |
133 | |
134 TRACE(("enter cli_auth_pubkey")); | |
135 | |
136 if (cli_ses.pubkeys != NULL) { | |
137 /* Send a trial request */ | |
138 send_msg_userauth_pubkey(cli_ses.pubkeys->key, | |
139 cli_ses.pubkeys->type, 0); | |
140 TRACE(("leave cli_auth_pubkey-success")); | |
141 return 1; | |
142 } else { | |
143 TRACE(("leave cli_auth_pubkey-failure")); | |
144 return 0; | |
145 } | |
146 } |