7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
|
}
} else if (s->can_keyb_inter && !s->kbd_inter_refused) {
/*
* Keyboard-interactive authentication.
*/
char *name, *inst, *lang;
int name_len, inst_len, lang_len;
int i;
s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
ssh->pkt_ctx |= SSH2_PKTCTX_KBDINTER;
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(s->pktout, s->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "keyboard-interactive");
/* method */
ssh2_pkt_addstring(s->pktout, ""); /* lang */
ssh2_pkt_addstring(s->pktout, ""); /* submethods */
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_USERAUTH_INFO_REQUEST) {
/* Server is not willing to do keyboard-interactive
* at all. Give up on it entirely. */
s->gotit = TRUE;
if (pktin->type == SSH2_MSG_USERAUTH_FAILURE)
logevent("Keyboard-interactive authentication refused");
s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET;
s->kbd_inter_refused = TRUE; /* don't try it again */
continue;
}
/*
* We've got a fresh USERAUTH_INFO_REQUEST.
* Get the preamble and start building a prompt.
*/
ssh_pkt_getstring(pktin, &name, &name_len);
ssh_pkt_getstring(pktin, &inst, &inst_len);
ssh_pkt_getstring(pktin, &lang, &lang_len);
s->cur_prompt = new_prompts(ssh->frontend);
s->cur_prompt->to_server = TRUE;
if (name_len) {
/* FIXME: better prefix to distinguish from
* local prompts? */
s->cur_prompt->name = dupprintf("SSH server: %.*s",
name_len, name);
s->cur_prompt->name_reqd = TRUE;
} else {
s->cur_prompt->name = dupstr("SSH server authentication");
s->cur_prompt->name_reqd = FALSE;
}
s->cur_prompt->instruction =
dupprintf("Using keyboard-interactive authentication.%s%.*s",
inst_len ? "\n" : "", inst_len, inst);
s->cur_prompt->instr_reqd = TRUE;
/*
* Get the prompts from the packet.
*/
s->num_prompts = ssh_pkt_getuint32(pktin);
for (i = 0; i < s->num_prompts; i++) {
char *prompt;
int prompt_len;
int echo;
static char noprompt[] =
"<server failed to send prompt>: ";
ssh_pkt_getstring(pktin, &prompt, &prompt_len);
echo = ssh2_pkt_getbool(pktin);
if (!prompt_len) {
prompt = noprompt;
prompt_len = lenof(noprompt)-1;
}
add_prompt(s->cur_prompt,
dupprintf("%.*s", prompt_len, prompt),
echo, SSH_MAX_PASSWORD_LEN);
}
/*
* Get the user's responses.
*/
if (s->num_prompts) {
int ret; /* not live over crReturn */
ret = get_userpass_input(s->cur_prompt, NULL, 0);
while (ret < 0) {
ssh->send_ok = 1;
crWaitUntilV(!pktin);
ret = get_userpass_input(s->cur_prompt, in, inlen);
ssh->send_ok = 0;
}
if (!ret) {
/*
* Failed to get responses. Terminate.
*/
free_prompts(s->cur_prompt);
ssh_disconnect(ssh, NULL, "Unable to authenticate",
SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
TRUE);
crStopV;
}
}
/*
* Send the responses to the server.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
s->pktout->forcepad = 256;
ssh2_pkt_adduint32(s->pktout, s->num_prompts);
for (i=0; i < s->num_prompts; i++) {
dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
ssh2_pkt_addstring(s->pktout,
s->cur_prompt->prompts[i]->result);
end_log_omission(ssh, s->pktout);
}
ssh2_pkt_send(ssh, s->pktout);
s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
} else if (s->can_passwd) {
/*
* Plain old password authentication.
*/
int ret; /* not live over crReturn */
|
<
<
<
>
>
|
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
|
}
} else if (s->can_keyb_inter && !s->kbd_inter_refused) {
/*
* Keyboard-interactive authentication.
*/
s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
ssh->pkt_ctx |= SSH2_PKTCTX_KBDINTER;
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(s->pktout, s->username);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
/* service requested */
ssh2_pkt_addstring(s->pktout, "keyboard-interactive");
/* method */
ssh2_pkt_addstring(s->pktout, ""); /* lang */
ssh2_pkt_addstring(s->pktout, ""); /* submethods */
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_USERAUTH_INFO_REQUEST) {
/* Server is not willing to do keyboard-interactive
* at all (or, bizarrely but legally, accepts the
* user without actually issuing any prompts).
* Give up on it entirely. */
s->gotit = TRUE;
if (pktin->type == SSH2_MSG_USERAUTH_FAILURE)
logevent("Keyboard-interactive authentication refused");
s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET;
s->kbd_inter_refused = TRUE; /* don't try it again */
continue;
}
/*
* Loop while the server continues to send INFO_REQUESTs.
*/
while (pktin->type == SSH2_MSG_USERAUTH_INFO_REQUEST) {
char *name, *inst, *lang;
int name_len, inst_len, lang_len;
int i;
/*
* We've got a fresh USERAUTH_INFO_REQUEST.
* Get the preamble and start building a prompt.
*/
ssh_pkt_getstring(pktin, &name, &name_len);
ssh_pkt_getstring(pktin, &inst, &inst_len);
ssh_pkt_getstring(pktin, &lang, &lang_len);
s->cur_prompt = new_prompts(ssh->frontend);
s->cur_prompt->to_server = TRUE;
if (name_len) {
/* FIXME: better prefix to distinguish from
* local prompts? */
s->cur_prompt->name =
dupprintf("SSH server: %.*s", name_len, name);
s->cur_prompt->name_reqd = TRUE;
} else {
s->cur_prompt->name =
dupstr("SSH server authentication");
s->cur_prompt->name_reqd = FALSE;
}
/* FIXME: ugly to print "Using..." in prompt _every_
* time round. Can this be done more subtly? */
s->cur_prompt->instruction =
dupprintf("Using keyboard-interactive authentication.%s%.*s",
inst_len ? "\n" : "", inst_len, inst);
s->cur_prompt->instr_reqd = TRUE;
/*
* Get the prompts from the packet.
*/
s->num_prompts = ssh_pkt_getuint32(pktin);
for (i = 0; i < s->num_prompts; i++) {
char *prompt;
int prompt_len;
int echo;
static char noprompt[] =
"<server failed to send prompt>: ";
ssh_pkt_getstring(pktin, &prompt, &prompt_len);
echo = ssh2_pkt_getbool(pktin);
if (!prompt_len) {
prompt = noprompt;
prompt_len = lenof(noprompt)-1;
}
add_prompt(s->cur_prompt,
dupprintf("%.*s", prompt_len, prompt),
echo, SSH_MAX_PASSWORD_LEN);
}
/*
* Get the user's responses.
*/
if (s->num_prompts) {
int ret; /* not live over crReturn */
ret = get_userpass_input(s->cur_prompt, NULL, 0);
while (ret < 0) {
ssh->send_ok = 1;
crWaitUntilV(!pktin);
ret = get_userpass_input(s->cur_prompt, in, inlen);
ssh->send_ok = 0;
}
if (!ret) {
/*
* Failed to get responses. Terminate.
*/
free_prompts(s->cur_prompt);
ssh_disconnect(ssh, NULL, "Unable to authenticate",
SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
TRUE);
crStopV;
}
}
/*
* Send the responses to the server.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
s->pktout->forcepad = 256;
ssh2_pkt_adduint32(s->pktout, s->num_prompts);
for (i=0; i < s->num_prompts; i++) {
dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
ssh2_pkt_addstring(s->pktout,
s->cur_prompt->prompts[i]->result);
end_log_omission(ssh, s->pktout);
}
ssh2_pkt_send(ssh, s->pktout);
/*
* Get the next packet in case it's another
* INFO_REQUEST.
*/
crWaitUntilV(pktin);
}
/*
* We should have SUCCESS or FAILURE now.
*/
s->gotit = TRUE;
} else if (s->can_passwd) {
/*
* Plain old password authentication.
*/
int ret; /* not live over crReturn */
|