comparison cli-auth.c @ 249:efbaf6b03837

added keyboard-interactive client support
author Matt Johnston <matt@ucc.asn.au>
date Tue, 20 Sep 2005 17:35:21 +0000
parents 161557a9dde8
children 29afa62b5450 475a818dd6e7
comparison
equal deleted inserted replaced
248:bf64e666f99b 249:efbaf6b03837
30 #include "buffer.h" 30 #include "buffer.h"
31 #include "ssh.h" 31 #include "ssh.h"
32 #include "packet.h" 32 #include "packet.h"
33 #include "runopts.h" 33 #include "runopts.h"
34 34
35
36 void cli_authinitialise() { 35 void cli_authinitialise() {
37 36
38 memset(&ses.authstate, 0, sizeof(ses.authstate)); 37 memset(&ses.authstate, 0, sizeof(ses.authstate));
39 } 38 }
40 39
97 out: 96 out:
98 m_free(banner); 97 m_free(banner);
99 TRACE(("leave recv_msg_userauth_banner")) 98 TRACE(("leave recv_msg_userauth_banner"))
100 } 99 }
101 100
101 /* This handles the message-specific types which
102 * all have a value of 60. These are
103 * SSH_MSG_USERAUTH_PASSWD_CHANGEREQ,
104 * SSH_MSG_USERAUTH_PK_OK, &
105 * SSH_MSG_USERAUTH_INFO_REQUEST. */
106 void recv_msg_userauth_specific_60() {
107
108 #ifdef ENABLE_CLI_PUBKEY_AUTH
109 if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
110 recv_msg_userauth_pk_ok();
111 return;
112 }
113 #endif
114
115 #ifdef ENABLE_CLI_INTERACT_AUTH
116 if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT) {
117 recv_msg_userauth_info_request();
118 return;
119 }
120 #endif
121
122 #ifdef ENABLE_CLI_PASSWORD_AUTH
123 if (cli_ses.lastauthtype == AUTH_TYPE_PASSWORD) {
124 /* Eventually there could be proper password-changing
125 * support. However currently few servers seem to
126 * implement it, and password auth is last-resort
127 * regardless - keyboard-interactive is more likely
128 * to be used anyway. */
129 dropbear_close("Your password has expired.");
130 }
131 #endif
132
133 dropbear_exit("Unexpected userauth packet");
134 }
102 135
103 void recv_msg_userauth_failure() { 136 void recv_msg_userauth_failure() {
104 137
105 unsigned char * methods = NULL; 138 unsigned char * methods = NULL;
106 unsigned char * tok = NULL; 139 unsigned char * tok = NULL;
111 TRACE(("<- MSG_USERAUTH_FAILURE")) 144 TRACE(("<- MSG_USERAUTH_FAILURE"))
112 TRACE(("enter recv_msg_userauth_failure")) 145 TRACE(("enter recv_msg_userauth_failure"))
113 146
114 if (cli_ses.state != USERAUTH_REQ_SENT) { 147 if (cli_ses.state != USERAUTH_REQ_SENT) {
115 /* Perhaps we should be more fatal? */ 148 /* Perhaps we should be more fatal? */
116 TRACE(("But we didn't send a userauth request!!!!!!")) 149 dropbear_exit("Unexpected userauth failure");
117 return;
118 } 150 }
119 151
120 #ifdef ENABLE_CLI_PUBKEY_AUTH 152 #ifdef ENABLE_CLI_PUBKEY_AUTH
121 /* If it was a pubkey auth request, we should cross that key 153 /* If it was a pubkey auth request, we should cross that key
122 * off the list. */ 154 * off the list. */
123 if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) { 155 if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
124 cli_pubkeyfail(); 156 cli_pubkeyfail();
125 } 157 }
126 #endif 158 #endif
127 159
160 #ifdef ENABLE_CLI_INTERACT_AUTH
161 /* If we get a failure message for keyboard interactive without
162 * receiving any request info packet, then we don't bother trying
163 * keyboard interactive again */
164 if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT
165 && !cli_ses.interact_request_received) {
166 TRACE(("setting auth_interact_failed = 1"))
167 cli_ses.auth_interact_failed = 1;
168 }
169 #endif
170
171 cli_ses.lastauthtype = AUTH_TYPE_NONE;
172
128 methods = buf_getstring(ses.payload, &methlen); 173 methods = buf_getstring(ses.payload, &methlen);
129 174
130 partial = buf_getbool(ses.payload); 175 partial = buf_getbool(ses.payload);
131 176
132 if (partial) { 177 if (partial) {
155 if (strncmp(AUTH_METHOD_PUBKEY, tok, 200 if (strncmp(AUTH_METHOD_PUBKEY, tok,
156 AUTH_METHOD_PUBKEY_LEN) == 0) { 201 AUTH_METHOD_PUBKEY_LEN) == 0) {
157 ses.authstate.authtypes |= AUTH_TYPE_PUBKEY; 202 ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
158 } 203 }
159 #endif 204 #endif
205 #ifdef ENABLE_CLI_INTERACT_AUTH
206 if (strncmp(AUTH_METHOD_INTERACT, tok,
207 AUTH_METHOD_INTERACT_LEN) == 0) {
208 ses.authstate.authtypes |= AUTH_TYPE_INTERACT;
209 }
210 #endif
160 #ifdef ENABLE_CLI_PASSWORD_AUTH 211 #ifdef ENABLE_CLI_PASSWORD_AUTH
161 if (strncmp(AUTH_METHOD_PASSWORD, tok, 212 if (strncmp(AUTH_METHOD_PASSWORD, tok,
162 AUTH_METHOD_PASSWORD_LEN) == 0) { 213 AUTH_METHOD_PASSWORD_LEN) == 0) {
163 ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; 214 ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
164 } 215 }
178 229
179 void recv_msg_userauth_success() { 230 void recv_msg_userauth_success() {
180 TRACE(("received msg_userauth_success")) 231 TRACE(("received msg_userauth_success"))
181 ses.authstate.authdone = 1; 232 ses.authstate.authdone = 1;
182 cli_ses.state = USERAUTH_SUCCESS_RCVD; 233 cli_ses.state = USERAUTH_SUCCESS_RCVD;
234 cli_ses.lastauthtype = AUTH_TYPE_NONE;
183 } 235 }
184 236
185 void cli_auth_try() { 237 void cli_auth_try() {
186 238
187 TRACE(("enter cli_auth_try")) 239 TRACE(("enter cli_auth_try"))
188 int finished = 0; 240 int finished = 0;
189 241
190 CHECKCLEARTOWRITE(); 242 CHECKCLEARTOWRITE();
191 243
192 /* XXX We hardcode that we try a pubkey first */ 244 /* Order to try is pubkey, interactive, password.
245 * As soon as "finished" is set for one, we don't do any more. */
193 #ifdef ENABLE_CLI_PUBKEY_AUTH 246 #ifdef ENABLE_CLI_PUBKEY_AUTH
194 if (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) { 247 if (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
195 finished = cli_auth_pubkey(); 248 finished = cli_auth_pubkey();
196 cli_ses.lastauthtype = AUTH_TYPE_PUBKEY; 249 cli_ses.lastauthtype = AUTH_TYPE_PUBKEY;
197 } 250 }
198 #endif 251 #endif
199 252
253 #ifdef ENABLE_CLI_INTERACT_AUTH
254 if (!finished && ses.authstate.authtypes & AUTH_TYPE_INTERACT) {
255 if (cli_ses.auth_interact_failed) {
256 finished = 0;
257 } else {
258 cli_auth_interactive();
259 cli_ses.lastauthtype = AUTH_TYPE_INTERACT;
260 finished = 1;
261 }
262 }
263 #endif
264
200 #ifdef ENABLE_CLI_PASSWORD_AUTH 265 #ifdef ENABLE_CLI_PASSWORD_AUTH
201 if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) { 266 if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
202 finished = cli_auth_password(); 267 cli_auth_password();
268 finished = 1;
203 cli_ses.lastauthtype = AUTH_TYPE_PASSWORD; 269 cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
204 } 270 }
205 #endif 271 #endif
272
273 TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
206 274
207 if (!finished) { 275 if (!finished) {
208 dropbear_exit("No auth methods could be used."); 276 dropbear_exit("No auth methods could be used.");
209 } 277 }
210 278