Mercurial > dropbear
comparison cli-authpubkey.c @ 1733:d529a52b2f7c coverity coverity
merge coverity from main
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 26 Jun 2020 21:07:34 +0800 |
parents | d18fa38c1fd4 |
children | 8dc43b30c6bf |
comparison
equal
deleted
inserted
replaced
1643:b59623a64678 | 1733:d529a52b2f7c |
---|---|
31 #include "runopts.h" | 31 #include "runopts.h" |
32 #include "auth.h" | 32 #include "auth.h" |
33 #include "agentfwd.h" | 33 #include "agentfwd.h" |
34 | 34 |
35 #if DROPBEAR_CLI_PUBKEY_AUTH | 35 #if DROPBEAR_CLI_PUBKEY_AUTH |
36 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign); | 36 static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign); |
37 | 37 |
38 /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request. | 38 /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request. |
39 * We use it to remove the key we tried from the list */ | 39 * We use it to remove the key we tried from the list */ |
40 void cli_pubkeyfail() { | 40 void cli_pubkeyfail() { |
41 m_list_elem *iter; | 41 m_list_elem *iter; |
57 m_list_elem *iter; | 57 m_list_elem *iter; |
58 buffer* keybuf = NULL; | 58 buffer* keybuf = NULL; |
59 char* algotype = NULL; | 59 char* algotype = NULL; |
60 unsigned int algolen; | 60 unsigned int algolen; |
61 enum signkey_type keytype; | 61 enum signkey_type keytype; |
62 enum signature_type sigtype; | |
62 unsigned int remotelen; | 63 unsigned int remotelen; |
63 | 64 |
64 TRACE(("enter recv_msg_userauth_pk_ok")) | 65 TRACE(("enter recv_msg_userauth_pk_ok")) |
65 | 66 |
66 algotype = buf_getstring(ses.payload, &algolen); | 67 algotype = buf_getstring(ses.payload, &algolen); |
67 keytype = signkey_type_from_name(algotype, algolen); | 68 sigtype = signature_type_from_name(algotype, algolen); |
68 TRACE(("recv_msg_userauth_pk_ok: type %d", keytype)) | 69 keytype = signkey_type_from_signature(sigtype); |
70 TRACE(("recv_msg_userauth_pk_ok: type %d", sigtype)) | |
69 m_free(algotype); | 71 m_free(algotype); |
70 | 72 |
71 keybuf = buf_new(MAX_PUBKEY_SIZE); | 73 keybuf = buf_new(MAX_PUBKEY_SIZE); |
72 | 74 |
73 remotelen = buf_getint(ses.payload); | 75 remotelen = buf_getint(ses.payload); |
110 | 112 |
111 if (iter != NULL) { | 113 if (iter != NULL) { |
112 TRACE(("matching key")) | 114 TRACE(("matching key")) |
113 /* XXX TODO: if it's an encrypted key, here we ask for their | 115 /* XXX TODO: if it's an encrypted key, here we ask for their |
114 * password */ | 116 * password */ |
115 send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1); | 117 send_msg_userauth_pubkey((sign_key*)iter->item, sigtype, 1); |
116 } else { | 118 } else { |
117 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")) | 119 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")) |
118 } | 120 } |
119 | 121 |
120 TRACE(("leave recv_msg_userauth_pk_ok")) | 122 TRACE(("leave recv_msg_userauth_pk_ok")) |
121 } | 123 } |
122 | 124 |
123 void cli_buf_put_sign(buffer* buf, sign_key *key, int type, | 125 static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, |
124 const buffer *data_buf) { | 126 const buffer *data_buf) { |
125 #if DROPBEAR_CLI_AGENTFWD | 127 #if DROPBEAR_CLI_AGENTFWD |
128 // TODO: rsa-sha256 agent | |
126 if (key->source == SIGNKEY_SOURCE_AGENT) { | 129 if (key->source == SIGNKEY_SOURCE_AGENT) { |
127 /* Format the agent signature ourselves, as buf_put_sign would. */ | 130 /* Format the agent signature ourselves, as buf_put_sign would. */ |
128 buffer *sigblob; | 131 buffer *sigblob; |
129 sigblob = buf_new(MAX_PUBKEY_SIZE); | 132 sigblob = buf_new(MAX_PUBKEY_SIZE); |
130 agent_buf_sign(sigblob, key, data_buf); | 133 agent_buf_sign(sigblob, key, data_buf, sigtype); |
131 buf_putbufstring(buf, sigblob); | 134 buf_putbufstring(buf, sigblob); |
132 buf_free(sigblob); | 135 buf_free(sigblob); |
133 } else | 136 } else |
134 #endif /* DROPBEAR_CLI_AGENTFWD */ | 137 #endif /* DROPBEAR_CLI_AGENTFWD */ |
135 { | 138 { |
136 buf_put_sign(buf, key, type, data_buf); | 139 buf_put_sign(buf, key, sigtype, data_buf); |
137 } | 140 } |
138 } | 141 } |
139 | 142 |
140 /* TODO: make it take an agent reference to use as well */ | 143 static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign) { |
141 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) { | |
142 | 144 |
143 const char *algoname = NULL; | 145 const char *algoname = NULL; |
144 unsigned int algolen; | 146 unsigned int algolen; |
145 buffer* sigbuf = NULL; | 147 buffer* sigbuf = NULL; |
146 | 148 enum signkey_type keytype = signkey_type_from_signature(sigtype); |
147 TRACE(("enter send_msg_userauth_pubkey")) | 149 |
150 TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype)) | |
148 CHECKCLEARTOWRITE(); | 151 CHECKCLEARTOWRITE(); |
149 | 152 |
150 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); | 153 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); |
151 | 154 |
152 buf_putstring(ses.writepayload, cli_opts.username, | 155 buf_putstring(ses.writepayload, cli_opts.username, |
158 buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY, | 161 buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY, |
159 AUTH_METHOD_PUBKEY_LEN); | 162 AUTH_METHOD_PUBKEY_LEN); |
160 | 163 |
161 buf_putbyte(ses.writepayload, realsign); | 164 buf_putbyte(ses.writepayload, realsign); |
162 | 165 |
163 algoname = signkey_name_from_type(type, &algolen); | 166 algoname = signature_name_from_type(sigtype, &algolen); |
164 | |
165 buf_putstring(ses.writepayload, algoname, algolen); | 167 buf_putstring(ses.writepayload, algoname, algolen); |
166 buf_put_pub_key(ses.writepayload, key, type); | 168 buf_put_pub_key(ses.writepayload, key, keytype); |
167 | 169 |
168 if (realsign) { | 170 if (realsign) { |
169 TRACE(("realsign")) | 171 TRACE(("realsign")) |
170 /* We put the signature as well - this contains string(session id), then | 172 /* We put the signature as well - this contains string(session id), then |
171 * the contents of the write payload to this point */ | 173 * the contents of the write payload to this point */ |
172 sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len); | 174 sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len); |
173 buf_putbufstring(sigbuf, ses.session_id); | 175 buf_putbufstring(sigbuf, ses.session_id); |
174 buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len); | 176 buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len); |
175 cli_buf_put_sign(ses.writepayload, key, type, sigbuf); | 177 cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf); |
176 buf_free(sigbuf); /* Nothing confidential in the buffer */ | 178 buf_free(sigbuf); /* Nothing confidential in the buffer */ |
177 } | 179 } |
178 | 180 |
179 encrypt_packet(); | 181 encrypt_packet(); |
180 TRACE(("leave send_msg_userauth_pubkey")) | 182 TRACE(("leave send_msg_userauth_pubkey")) |
181 } | 183 } |
182 | 184 |
183 /* Returns 1 if a key was tried */ | 185 /* Returns 1 if a key was tried */ |
184 int cli_auth_pubkey() { | 186 int cli_auth_pubkey() { |
185 | 187 enum signature_type sigtype = DROPBEAR_SIGNATURE_NONE; |
186 TRACE(("enter cli_auth_pubkey")) | 188 TRACE(("enter cli_auth_pubkey")) |
187 | 189 |
188 #if DROPBEAR_CLI_AGENTFWD | 190 #if DROPBEAR_CLI_AGENTFWD |
189 if (!cli_opts.agent_keys_loaded) { | 191 if (!cli_opts.agent_keys_loaded) { |
190 /* get the list of available keys from the agent */ | 192 /* get the list of available keys from the agent */ |
191 cli_load_agent_keys(cli_opts.privkeys); | 193 cli_load_agent_keys(cli_opts.privkeys); |
192 cli_opts.agent_keys_loaded = 1; | 194 cli_opts.agent_keys_loaded = 1; |
195 TRACE(("cli_auth_pubkey: agent keys loaded")) | |
193 } | 196 } |
194 #endif | 197 #endif |
198 | |
199 /* iterate through privkeys to remove ones not allowed in server-sig-algs */ | |
200 while (cli_opts.privkeys->first) { | |
201 sign_key * key = (sign_key*)cli_opts.privkeys->first->item; | |
202 if (cli_ses.server_sig_algs) { | |
203 #if DROPBEAR_RSA | |
204 if (key->type == DROPBEAR_SIGNKEY_RSA) { | |
205 #if DROPBEAR_RSA_SHA256 | |
206 if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNATURE_RSA_SHA256) | |
207 == DROPBEAR_SUCCESS) { | |
208 sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; | |
209 TRACE(("server-sig-algs allows rsa sha256")) | |
210 break; | |
211 } | |
212 #endif /* DROPBEAR_RSA_SHA256 */ | |
213 #if DROPBEAR_RSA_SHA1 | |
214 if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNKEY_RSA) | |
215 == DROPBEAR_SUCCESS) { | |
216 sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; | |
217 TRACE(("server-sig-algs allows rsa sha1")) | |
218 break; | |
219 } | |
220 #endif /* DROPBEAR_RSA_SHA256 */ | |
221 } else | |
222 #endif /* DROPBEAR_RSA */ | |
223 { | |
224 /* Not RSA */ | |
225 const char *name = NULL; | |
226 sigtype = signature_type_from_signkey(key->type); | |
227 name = signature_name_from_type(sigtype, NULL); | |
228 if (buf_has_algo(cli_ses.server_sig_algs, name) | |
229 == DROPBEAR_SUCCESS) { | |
230 TRACE(("server-sig-algs allows %s", name)) | |
231 break; | |
232 } | |
233 } | |
234 | |
235 /* No match, skip this key */ | |
236 TRACE(("server-sig-algs no match keytype %d, skipping", key->type)) | |
237 key = list_remove(cli_opts.privkeys->first); | |
238 sign_key_free(key); | |
239 continue; | |
240 } else { | |
241 /* Server didn't provide a server-sig-algs list, we'll | |
242 assume all except rsa-sha256 are OK. */ | |
243 #if DROPBEAR_RSA | |
244 if (key->type == DROPBEAR_SIGNKEY_RSA) { | |
245 #if DROPBEAR_RSA_SHA1 | |
246 sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; | |
247 TRACE(("no server-sig-algs, using rsa sha1")) | |
248 break; | |
249 #else | |
250 /* only support rsa-sha256, skip this key */ | |
251 TRACE(("no server-sig-algs, skipping rsa sha256")) | |
252 key = list_remove(cli_opts.privkeys->first); | |
253 sign_key_free(key); | |
254 continue; | |
255 #endif | |
256 } /* key->type == DROPBEAR_SIGNKEY_RSA */ | |
257 #endif /* DROPBEAR_RSA */ | |
258 sigtype = signature_type_from_signkey(key->type); | |
259 TRACE(("no server-sig-algs, using key")) | |
260 break; | |
261 } | |
262 } | |
195 | 263 |
196 if (cli_opts.privkeys->first) { | 264 if (cli_opts.privkeys->first) { |
197 sign_key * key = (sign_key*)cli_opts.privkeys->first->item; | 265 sign_key * key = (sign_key*)cli_opts.privkeys->first->item; |
198 /* Send a trial request */ | 266 /* Send a trial request */ |
199 send_msg_userauth_pubkey(key, key->type, 0); | 267 send_msg_userauth_pubkey(key, sigtype, 0); |
200 cli_ses.lastprivkey = key; | 268 cli_ses.lastprivkey = key; |
201 TRACE(("leave cli_auth_pubkey-success")) | 269 TRACE(("leave cli_auth_pubkey-success")) |
202 return 1; | 270 return 1; |
203 } else { | 271 } else { |
204 /* no more keys left */ | 272 /* no more keys left */ |