version 1.48, 2017/05/30 14:29:59 |
version 1.49, 2018/07/09 21:35:50 |
|
|
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "ssh2.h" |
#include "ssh2.h" |
#include "key.h" |
#include "sshkey.h" |
#include "hostfile.h" |
#include "hostfile.h" |
#include "auth.h" |
#include "auth.h" |
#include "buffer.h" |
#include "sshbuf.h" |
#include "packet.h" |
#include "packet.h" |
#include "dispatch.h" |
#include "dispatch.h" |
|
#include "ssherr.h" |
#include "log.h" |
#include "log.h" |
|
|
static int auth2_challenge_start(struct ssh *); |
static int auth2_challenge_start(struct ssh *); |
static int send_userauth_info_request(Authctxt *); |
static int send_userauth_info_request(struct ssh *); |
static int input_userauth_info_response(int, u_int32_t, struct ssh *); |
static int input_userauth_info_response(int, u_int32_t, struct ssh *); |
|
|
extern KbdintDevice bsdauth_device; |
extern KbdintDevice bsdauth_device; |
|
|
kbdint_alloc(const char *devs) |
kbdint_alloc(const char *devs) |
{ |
{ |
KbdintAuthctxt *kbdintctxt; |
KbdintAuthctxt *kbdintctxt; |
Buffer b; |
struct sshbuf *b; |
int i; |
int i, r; |
|
|
kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt)); |
kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt)); |
if (strcmp(devs, "") == 0) { |
if (strcmp(devs, "") == 0) { |
buffer_init(&b); |
if ((b = sshbuf_new()) == NULL) |
|
fatal("%s: sshbuf_new failed", __func__); |
for (i = 0; devices[i]; i++) { |
for (i = 0; devices[i]; i++) { |
if (buffer_len(&b) > 0) |
if ((r = sshbuf_putf(b, "%s%s", |
buffer_append(&b, ",", 1); |
sshbuf_len(b) ? "," : "", devices[i]->name)) != 0) |
buffer_append(&b, devices[i]->name, |
fatal("%s: buffer error: %s", |
strlen(devices[i]->name)); |
__func__, ssh_err(r)); |
} |
} |
if ((kbdintctxt->devices = sshbuf_dup_string(&b)) == NULL) |
if ((kbdintctxt->devices = sshbuf_dup_string(b)) == NULL) |
fatal("%s: sshbuf_dup_string failed", __func__); |
fatal("%s: sshbuf_dup_string failed", __func__); |
buffer_free(&b); |
sshbuf_free(b); |
} else { |
} else { |
kbdintctxt->devices = xstrdup(devs); |
kbdintctxt->devices = xstrdup(devs); |
} |
} |
|
|
auth2_challenge_stop(ssh); |
auth2_challenge_stop(ssh); |
return 0; |
return 0; |
} |
} |
if (send_userauth_info_request(authctxt) == 0) { |
if (send_userauth_info_request(ssh) == 0) { |
auth2_challenge_stop(ssh); |
auth2_challenge_stop(ssh); |
return 0; |
return 0; |
} |
} |
|
|
} |
} |
|
|
static int |
static int |
send_userauth_info_request(Authctxt *authctxt) |
send_userauth_info_request(struct ssh *ssh) |
{ |
{ |
|
Authctxt *authctxt = ssh->authctxt; |
KbdintAuthctxt *kbdintctxt; |
KbdintAuthctxt *kbdintctxt; |
char *name, *instr, **prompts; |
char *name, *instr, **prompts; |
u_int i, *echo_on; |
u_int r, i, *echo_on; |
|
|
kbdintctxt = authctxt->kbdintctxt; |
kbdintctxt = authctxt->kbdintctxt; |
if (kbdintctxt->device->query(kbdintctxt->ctxt, |
if (kbdintctxt->device->query(kbdintctxt->ctxt, |
&name, &instr, &kbdintctxt->nreq, &prompts, &echo_on)) |
&name, &instr, &kbdintctxt->nreq, &prompts, &echo_on)) |
return 0; |
return 0; |
|
|
packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); |
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST)) != 0 || |
packet_put_cstring(name); |
(r = sshpkt_put_cstring(ssh, name)) != 0 || |
packet_put_cstring(instr); |
(r = sshpkt_put_cstring(ssh, instr)) != 0 || |
packet_put_cstring(""); /* language not used */ |
(r = sshpkt_put_cstring(ssh, "")) != 0 || /* language not used */ |
packet_put_int(kbdintctxt->nreq); |
(r = sshpkt_put_u32(ssh, kbdintctxt->nreq)) != 0) |
|
fatal("%s: %s", __func__, ssh_err(r)); |
for (i = 0; i < kbdintctxt->nreq; i++) { |
for (i = 0; i < kbdintctxt->nreq; i++) { |
packet_put_cstring(prompts[i]); |
if ((r = sshpkt_put_cstring(ssh, prompts[i])) != 0 || |
packet_put_char(echo_on[i]); |
(r = sshpkt_put_u8(ssh, echo_on[i])) != 0) |
|
fatal("%s: %s", __func__, ssh_err(r)); |
} |
} |
packet_send(); |
if ((r = sshpkt_send(ssh)) != 0) |
packet_write_wait(); |
fatal("%s: %s", __func__, ssh_err(r)); |
|
ssh_packet_write_wait(ssh); |
|
|
for (i = 0; i < kbdintctxt->nreq; i++) |
for (i = 0; i < kbdintctxt->nreq; i++) |
free(prompts[i]); |
free(prompts[i]); |
|
|
Authctxt *authctxt = ssh->authctxt; |
Authctxt *authctxt = ssh->authctxt; |
KbdintAuthctxt *kbdintctxt; |
KbdintAuthctxt *kbdintctxt; |
int authenticated = 0, res; |
int authenticated = 0, res; |
|
int r; |
u_int i, nresp; |
u_int i, nresp; |
const char *devicename = NULL; |
const char *devicename = NULL; |
char **response = NULL; |
char **response = NULL; |
|
|
fatal("input_userauth_info_response: no device"); |
fatal("input_userauth_info_response: no device"); |
|
|
authctxt->postponed = 0; /* reset */ |
authctxt->postponed = 0; /* reset */ |
nresp = packet_get_int(); |
if ((r = sshpkt_get_u32(ssh, &nresp)) != 0) |
|
fatal("%s: %s", __func__, ssh_err(r)); |
if (nresp != kbdintctxt->nreq) |
if (nresp != kbdintctxt->nreq) |
fatal("input_userauth_info_response: wrong number of replies"); |
fatal("input_userauth_info_response: wrong number of replies"); |
if (nresp > 100) |
if (nresp > 100) |
|
|
if (nresp > 0) { |
if (nresp > 0) { |
response = xcalloc(nresp, sizeof(char *)); |
response = xcalloc(nresp, sizeof(char *)); |
for (i = 0; i < nresp; i++) |
for (i = 0; i < nresp; i++) |
response[i] = packet_get_string(NULL); |
if ((r = sshpkt_get_cstring(ssh, &response[i], |
|
NULL)) != 0) |
|
fatal("%s: %s", __func__, ssh_err(r)); |
} |
} |
packet_check_eom(); |
if ((r = sshpkt_get_end(ssh)) != 0) |
|
fatal("%s: %s", __func__, ssh_err(r)); |
|
|
res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response); |
res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response); |
|
|
|
|
break; |
break; |
case 1: |
case 1: |
/* Authentication needs further interaction */ |
/* Authentication needs further interaction */ |
if (send_userauth_info_request(authctxt) == 1) |
if (send_userauth_info_request(ssh) == 1) |
authctxt->postponed = 1; |
authctxt->postponed = 1; |
break; |
break; |
default: |
default: |