version 1.4.2.4, 2002/06/02 22:56:09 |
version 1.5, 2001/05/18 14:13:28 |
|
|
|
|
#include "ssh2.h" |
#include "ssh2.h" |
#include "auth.h" |
#include "auth.h" |
#include "buffer.h" |
|
#include "packet.h" |
#include "packet.h" |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "dispatch.h" |
#include "dispatch.h" |
#include "auth.h" |
#include "auth.h" |
#include "log.h" |
#include "log.h" |
|
|
static int auth2_challenge_start(Authctxt *); |
static int auth2_challenge_start(Authctxt *authctxt); |
static int send_userauth_info_request(Authctxt *); |
static int send_userauth_info_request(Authctxt *authctxt); |
static void input_userauth_info_response(int, u_int32_t, void *); |
static void input_userauth_info_response(int type, int plen, void *ctxt); |
|
|
#ifdef BSD_AUTH |
#ifdef BSD_AUTH |
extern KbdintDevice bsdauth_device; |
extern KbdintDevice bsdauth_device; |
|
|
KbdintDevice *device; |
KbdintDevice *device; |
}; |
}; |
|
|
static KbdintAuthctxt * |
KbdintAuthctxt * |
kbdint_alloc(const char *devs) |
kbdint_alloc(const char *devs) |
{ |
{ |
KbdintAuthctxt *kbdintctxt; |
KbdintAuthctxt *kbdintctxt; |
Buffer b; |
|
int i; |
int i; |
|
char buf[1024]; |
|
|
kbdintctxt = xmalloc(sizeof(KbdintAuthctxt)); |
kbdintctxt = xmalloc(sizeof(KbdintAuthctxt)); |
if (strcmp(devs, "") == 0) { |
if (strcmp(devs, "") == 0) { |
buffer_init(&b); |
buf[0] = '\0'; |
for (i = 0; devices[i]; i++) { |
for (i = 0; devices[i]; i++) { |
if (buffer_len(&b) > 0) |
if (i != 0) |
buffer_append(&b, ",", 1); |
strlcat(buf, ",", sizeof(buf)); |
buffer_append(&b, devices[i]->name, |
strlcat(buf, devices[i]->name, sizeof(buf)); |
strlen(devices[i]->name)); |
|
} |
} |
buffer_append(&b, "\0", 1); |
debug("kbdint_alloc: devices '%s'", buf); |
kbdintctxt->devices = xstrdup(buffer_ptr(&b)); |
kbdintctxt->devices = xstrdup(buf); |
buffer_free(&b); |
|
} else { |
} else { |
kbdintctxt->devices = xstrdup(devs); |
kbdintctxt->devices = xstrdup(devs); |
} |
} |
debug("kbdint_alloc: devices '%s'", kbdintctxt->devices); |
|
kbdintctxt->ctxt = NULL; |
kbdintctxt->ctxt = NULL; |
kbdintctxt->device = NULL; |
kbdintctxt->device = NULL; |
|
|
return kbdintctxt; |
return kbdintctxt; |
} |
} |
static void |
void |
kbdint_reset_device(KbdintAuthctxt *kbdintctxt) |
kbdint_reset_device(KbdintAuthctxt *kbdintctxt) |
{ |
{ |
if (kbdintctxt->ctxt) { |
if (kbdintctxt->ctxt) { |
|
|
} |
} |
kbdintctxt->device = NULL; |
kbdintctxt->device = NULL; |
} |
} |
static void |
void |
kbdint_free(KbdintAuthctxt *kbdintctxt) |
kbdint_free(KbdintAuthctxt *kbdintctxt) |
{ |
{ |
if (kbdintctxt->device) |
if (kbdintctxt->device) |
|
|
xfree(kbdintctxt); |
xfree(kbdintctxt); |
} |
} |
/* get next device */ |
/* get next device */ |
static int |
int |
kbdint_next_device(KbdintAuthctxt *kbdintctxt) |
kbdint_next_device(KbdintAuthctxt *kbdintctxt) |
{ |
{ |
size_t len; |
size_t len; |
|
|
} |
} |
|
|
/* |
/* |
* try challenge-response, set authctxt->postponed if we have to |
* try challenge-reponse, set authctxt->postponed if we have to |
* wait for the response. |
* wait for the response. |
*/ |
*/ |
int |
int |
|
|
authctxt->user ? authctxt->user : "<nouser>", |
authctxt->user ? authctxt->user : "<nouser>", |
devs ? devs : "<no devs>"); |
devs ? devs : "<no devs>"); |
|
|
if (authctxt->user == NULL || !devs) |
if (!authctxt->valid || authctxt->user == NULL || !devs) |
return 0; |
return 0; |
if (authctxt->kbdintctxt == NULL) |
if (authctxt->kbdintctxt == NULL) |
authctxt->kbdintctxt = kbdint_alloc(devs); |
authctxt->kbdintctxt = kbdint_alloc(devs); |
return auth2_challenge_start(authctxt); |
return auth2_challenge_start(authctxt); |
} |
} |
|
|
/* unregister kbd-int callbacks and context */ |
|
void |
|
auth2_challenge_stop(Authctxt *authctxt) |
|
{ |
|
/* unregister callback */ |
|
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); |
|
if (authctxt->kbdintctxt != NULL) { |
|
kbdint_free(authctxt->kbdintctxt); |
|
authctxt->kbdintctxt = NULL; |
|
} |
|
} |
|
|
|
/* side effect: sets authctxt->postponed if a reply was sent*/ |
/* side effect: sets authctxt->postponed if a reply was sent*/ |
static int |
static int |
auth2_challenge_start(Authctxt *authctxt) |
auth2_challenge_start(Authctxt *authctxt) |
|
|
kbdintctxt->devices ? kbdintctxt->devices : "<empty>"); |
kbdintctxt->devices ? kbdintctxt->devices : "<empty>"); |
|
|
if (kbdint_next_device(kbdintctxt) == 0) { |
if (kbdint_next_device(kbdintctxt) == 0) { |
auth2_challenge_stop(authctxt); |
kbdint_free(kbdintctxt); |
|
authctxt->kbdintctxt = NULL; |
return 0; |
return 0; |
} |
} |
debug("auth2_challenge_start: trying authentication method '%s'", |
debug("auth2_challenge_start: trying authentication method '%s'", |
kbdintctxt->device->name); |
kbdintctxt->device->name); |
|
|
if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { |
if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { |
auth2_challenge_stop(authctxt); |
kbdint_free(kbdintctxt); |
|
authctxt->kbdintctxt = NULL; |
return 0; |
return 0; |
} |
} |
if (send_userauth_info_request(authctxt) == 0) { |
if (send_userauth_info_request(authctxt) == 0) { |
auth2_challenge_stop(authctxt); |
kbdint_free(kbdintctxt); |
|
authctxt->kbdintctxt = NULL; |
return 0; |
return 0; |
} |
} |
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, |
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, |
|
|
} |
} |
|
|
static void |
static void |
input_userauth_info_response(int type, u_int32_t seq, void *ctxt) |
input_userauth_info_response(int type, int plen, void *ctxt) |
{ |
{ |
Authctxt *authctxt = ctxt; |
Authctxt *authctxt = ctxt; |
KbdintAuthctxt *kbdintctxt; |
KbdintAuthctxt *kbdintctxt; |
|
|
for (i = 0; i < nresp; i++) |
for (i = 0; i < nresp; i++) |
response[i] = packet_get_string(NULL); |
response[i] = packet_get_string(NULL); |
} |
} |
packet_check_eom(); |
packet_done(); |
|
|
if (authctxt->valid) { |
if (authctxt->valid) { |
res = kbdintctxt->device->respond(kbdintctxt->ctxt, |
res = kbdintctxt->device->respond(kbdintctxt->ctxt, |
|
|
break; |
break; |
case 1: |
case 1: |
/* Authentication needs further interaction */ |
/* Authentication needs further interaction */ |
if (send_userauth_info_request(authctxt) == 1) |
authctxt->postponed = 1; |
authctxt->postponed = 1; |
if (send_userauth_info_request(authctxt) == 0) { |
|
authctxt->postponed = 0; |
|
} |
break; |
break; |
default: |
default: |
/* Failure! */ |
/* Failure! */ |
|
|
len = strlen("keyboard-interactive") + 2 + |
len = strlen("keyboard-interactive") + 2 + |
strlen(kbdintctxt->device->name); |
strlen(kbdintctxt->device->name); |
method = xmalloc(len); |
method = xmalloc(len); |
snprintf(method, len, "keyboard-interactive/%s", |
method[0] = '\0'; |
kbdintctxt->device->name); |
strlcat(method, "keyboard-interactive", len); |
|
strlcat(method, "/", len); |
|
strlcat(method, kbdintctxt->device->name, len); |
|
|
if (!authctxt->postponed) { |
if (!authctxt->postponed) { |
|
/* unregister callback */ |
|
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); |
|
|
if (authenticated) { |
if (authenticated) { |
auth2_challenge_stop(authctxt); |
kbdint_free(kbdintctxt); |
|
authctxt->kbdintctxt = NULL; |
} else { |
} else { |
/* start next device */ |
/* start next device */ |
/* may set authctxt->postponed */ |
/* may set authctxt->postponed */ |
|
|
} |
} |
userauth_finish(authctxt, authenticated, method); |
userauth_finish(authctxt, authenticated, method); |
xfree(method); |
xfree(method); |
} |
|
|
|
void |
|
privsep_challenge_enable(void) |
|
{ |
|
#ifdef BSD_AUTH |
|
extern KbdintDevice mm_bsdauth_device; |
|
#endif |
|
#ifdef SKEY |
|
extern KbdintDevice mm_skey_device; |
|
#endif |
|
/* As long as SSHv1 has devices[0] hard coded this is fine */ |
|
#ifdef BSD_AUTH |
|
devices[0] = &mm_bsdauth_device; |
|
#else |
|
#ifdef SKEY |
|
devices[0] = &mm_skey_device; |
|
#endif |
|
#endif |
|
} |
} |