1
1
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Этот коммит содержится в:
Anderson Toshiyuki Sasaki 2018-07-12 13:42:23 +02:00
родитель 6e74c6c1dc
Коммит d85827f646

Просмотреть файл

@ -77,18 +77,18 @@ static int ssh_userauth_request_service(ssh_session session) {
return rc; return rc;
} }
static int ssh_auth_response_termination(void *user){ static int ssh_auth_response_termination(void *user) {
ssh_session session=(ssh_session)user; ssh_session session = (ssh_session)user;
switch(session->auth_state){ switch (session->auth_state) {
case SSH_AUTH_STATE_NONE: case SSH_AUTH_STATE_NONE:
case SSH_AUTH_STATE_KBDINT_SENT: case SSH_AUTH_STATE_KBDINT_SENT:
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT: case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
case SSH_AUTH_STATE_GSSAPI_TOKEN: case SSH_AUTH_STATE_GSSAPI_TOKEN:
case SSH_AUTH_STATE_GSSAPI_MIC_SENT: case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
return 0; return 0;
default: default:
return 1; return 1;
} }
} }
/** /**
@ -110,10 +110,10 @@ static int ssh_userauth_get_response(ssh_session session) {
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
ssh_auth_response_termination, session); ssh_auth_response_termination, session);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
if (!ssh_auth_response_termination(session)){ if (!ssh_auth_response_termination(session)) {
return SSH_AUTH_AGAIN; return SSH_AUTH_AGAIN;
} }
switch(session->auth_state) { switch(session->auth_state) {
@ -133,7 +133,7 @@ static int ssh_userauth_get_response(ssh_session session) {
case SSH_AUTH_STATE_SUCCESS: case SSH_AUTH_STATE_SUCCESS:
rc = SSH_AUTH_SUCCESS; rc = SSH_AUTH_SUCCESS;
break; break;
case SSH_AUTH_STATE_KBDINT_SENT: case SSH_AUTH_STATE_KBDINT_SENT:
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT: case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
case SSH_AUTH_STATE_GSSAPI_TOKEN: case SSH_AUTH_STATE_GSSAPI_TOKEN:
case SSH_AUTH_STATE_GSSAPI_MIC_SENT: case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
@ -153,24 +153,24 @@ static int ssh_userauth_get_response(ssh_session session) {
* *
* This banner should be shown to user prior to authentication * This banner should be shown to user prior to authentication
*/ */
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner){ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner) {
ssh_string banner; ssh_string banner;
(void)type; (void)type;
(void)user; (void)user;
banner = ssh_buffer_get_ssh_string(packet); banner = ssh_buffer_get_ssh_string(packet);
if (banner == NULL) { if (banner == NULL) {
SSH_LOG(SSH_LOG_WARN, SSH_LOG(SSH_LOG_WARN,
"Invalid SSH_USERAUTH_BANNER packet"); "Invalid SSH_USERAUTH_BANNER packet");
} else { } else {
SSH_LOG(SSH_LOG_DEBUG, SSH_LOG(SSH_LOG_DEBUG,
"Received SSH_USERAUTH_BANNER packet"); "Received SSH_USERAUTH_BANNER packet");
if(session->banner != NULL) if (session->banner != NULL)
ssh_string_free(session->banner); ssh_string_free(session->banner);
session->banner = banner; session->banner = banner;
} }
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }
/** /**
@ -180,57 +180,57 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner){
* *
* This handles the complete or partial authentication failure. * This handles the complete or partial authentication failure.
*/ */
SSH_PACKET_CALLBACK(ssh_packet_userauth_failure){ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) {
char *auth_methods = NULL; char *auth_methods = NULL;
uint8_t partial = 0; uint8_t partial = 0;
int rc; int rc;
(void) type; (void) type;
(void) user; (void) user;
rc = ssh_buffer_unpack(packet, "sb", &auth_methods, &partial); rc = ssh_buffer_unpack(packet, "sb", &auth_methods, &partial);
if (rc != SSH_OK) { if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Invalid SSH_MSG_USERAUTH_FAILURE message"); "Invalid SSH_MSG_USERAUTH_FAILURE message");
session->auth_state=SSH_AUTH_STATE_ERROR; session->auth_state=SSH_AUTH_STATE_ERROR;
goto end; goto end;
} }
if (partial) { if (partial) {
session->auth_state=SSH_AUTH_STATE_PARTIAL; session->auth_state=SSH_AUTH_STATE_PARTIAL;
SSH_LOG(SSH_LOG_INFO, SSH_LOG(SSH_LOG_INFO,
"Partial success. Authentication that can continue: %s", "Partial success. Authentication that can continue: %s",
auth_methods); auth_methods);
} else { } else {
session->auth_state=SSH_AUTH_STATE_FAILED; session->auth_state=SSH_AUTH_STATE_FAILED;
SSH_LOG(SSH_LOG_INFO, SSH_LOG(SSH_LOG_INFO,
"Access denied. Authentication that can continue: %s", "Access denied. Authentication that can continue: %s",
auth_methods); auth_methods);
ssh_set_error(session, SSH_REQUEST_DENIED, ssh_set_error(session, SSH_REQUEST_DENIED,
"Access denied. Authentication that can continue: %s", "Access denied. Authentication that can continue: %s",
auth_methods); auth_methods);
} }
session->auth_methods = 0; session->auth_methods = 0;
if (strstr(auth_methods, "password") != NULL) { if (strstr(auth_methods, "password") != NULL) {
session->auth_methods |= SSH_AUTH_METHOD_PASSWORD; session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
} }
if (strstr(auth_methods, "keyboard-interactive") != NULL) { if (strstr(auth_methods, "keyboard-interactive") != NULL) {
session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE; session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE;
} }
if (strstr(auth_methods, "publickey") != NULL) { if (strstr(auth_methods, "publickey") != NULL) {
session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY; session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY;
} }
if (strstr(auth_methods, "hostbased") != NULL) { if (strstr(auth_methods, "hostbased") != NULL) {
session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED; session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED;
} }
if (strstr(auth_methods, "gssapi-with-mic") != NULL) { if (strstr(auth_methods, "gssapi-with-mic") != NULL) {
session->auth_methods |= SSH_AUTH_METHOD_GSSAPI_MIC; session->auth_methods |= SSH_AUTH_METHOD_GSSAPI_MIC;
} }
end: end:
SAFE_FREE(auth_methods); SAFE_FREE(auth_methods);
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }
/** /**
@ -240,7 +240,7 @@ end:
* *
* It is also used to communicate the new to the upper levels. * It is also used to communicate the new to the upper levels.
*/ */
SSH_PACKET_CALLBACK(ssh_packet_userauth_success){ SSH_PACKET_CALLBACK(ssh_packet_userauth_success) {
(void)packet; (void)packet;
(void)type; (void)type;
(void)user; (void)user;
@ -248,17 +248,17 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success){
SSH_LOG(SSH_LOG_DEBUG, "Authentication successful"); SSH_LOG(SSH_LOG_DEBUG, "Authentication successful");
SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_SUCCESS"); SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_SUCCESS");
session->auth_state=SSH_AUTH_STATE_SUCCESS; session->auth_state = SSH_AUTH_STATE_SUCCESS;
session->session_state=SSH_SESSION_STATE_AUTHENTICATED; session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
session->flags |= SSH_SESSION_FLAG_AUTHENTICATED; session->flags |= SSH_SESSION_FLAG_AUTHENTICATED;
if(session->current_crypto && session->current_crypto->delayed_compress_out){ if (session->current_crypto && session->current_crypto->delayed_compress_out) {
SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression OUT"); SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression OUT");
session->current_crypto->do_compress_out=1; session->current_crypto->do_compress_out = 1;
} }
if(session->current_crypto && session->current_crypto->delayed_compress_in){ if (session->current_crypto && session->current_crypto->delayed_compress_in) {
SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression IN"); SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression IN");
session->current_crypto->do_compress_in=1; session->current_crypto->do_compress_in = 1;
} }
return SSH_PACKET_USED; return SSH_PACKET_USED;
@ -272,24 +272,24 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success){
* Since the two types of packets share the same code, additional work is done * Since the two types of packets share the same code, additional work is done
* to understand if we are in a public key or keyboard-interactive context. * to understand if we are in a public key or keyboard-interactive context.
*/ */
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok){ SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok) {
int rc; int rc;
SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE"); SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
if(session->auth_state==SSH_AUTH_STATE_KBDINT_SENT){ if (session->auth_state==SSH_AUTH_STATE_KBDINT_SENT) {
/* Assuming we are in keyboard-interactive context */ /* Assuming we are in keyboard-interactive context */
SSH_LOG(SSH_LOG_TRACE, SSH_LOG(SSH_LOG_TRACE,
"keyboard-interactive context, assuming SSH_USERAUTH_INFO_REQUEST"); "keyboard-interactive context, assuming SSH_USERAUTH_INFO_REQUEST");
rc=ssh_packet_userauth_info_request(session,type,packet,user); rc = ssh_packet_userauth_info_request(session,type,packet,user);
#ifdef WITH_GSSAPI #ifdef WITH_GSSAPI
} else if (session->auth_state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT){ } else if (session->auth_state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
rc = ssh_packet_userauth_gssapi_response(session, type, packet, user); rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
#endif #endif
} else { } else {
session->auth_state=SSH_AUTH_STATE_PK_OK; session->auth_state = SSH_AUTH_STATE_PK_OK;
SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK"); SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
rc=SSH_PACKET_USED; rc = SSH_PACKET_USED;
} }
return rc; return rc;
@ -348,7 +348,7 @@ int ssh_userauth_list(ssh_session session, const char *username)
int ssh_userauth_none(ssh_session session, const char *username) { int ssh_userauth_none(ssh_session session, const char *username) {
int rc; int rc;
switch(session->pending_call_state){ switch(session->pending_call_state) {
case SSH_PENDING_CALL_NONE: case SSH_PENDING_CALL_NONE:
break; break;
case SSH_PENDING_CALL_AUTH_NONE: case SSH_PENDING_CALL_AUTH_NONE:
@ -727,6 +727,7 @@ struct ssh_agent_state_struct {
/* Internal function */ /* Internal function */
void ssh_agent_state_free(void *data) { void ssh_agent_state_free(void *data) {
struct ssh_agent_state_struct *state = data; struct ssh_agent_state_struct *state = data;
if (state) { if (state) {
ssh_string_free_char(state->comment); ssh_string_free_char(state->comment);
ssh_key_free(state->pubkey); ssh_key_free(state->pubkey);
@ -760,6 +761,7 @@ int ssh_userauth_agent(ssh_session session,
const char *username) { const char *username) {
int rc = SSH_AUTH_ERROR; int rc = SSH_AUTH_ERROR;
struct ssh_agent_state_struct *state; struct ssh_agent_state_struct *state;
if (session == NULL) { if (session == NULL) {
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
@ -767,30 +769,33 @@ int ssh_userauth_agent(ssh_session session,
if (!ssh_agent_is_running(session)) { if (!ssh_agent_is_running(session)) {
return SSH_AUTH_DENIED; return SSH_AUTH_DENIED;
} }
if (!session->agent_state){
if (!session->agent_state) {
session->agent_state = malloc(sizeof(struct ssh_agent_state_struct)); session->agent_state = malloc(sizeof(struct ssh_agent_state_struct));
if (!session->agent_state){ if (!session->agent_state) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
ZERO_STRUCTP(session->agent_state); ZERO_STRUCTP(session->agent_state);
session->agent_state->state=SSH_AGENT_STATE_NONE; session->agent_state->state=SSH_AGENT_STATE_NONE;
} }
state = session->agent_state; state = session->agent_state;
if (state->pubkey == NULL) if (state->pubkey == NULL) {
state->pubkey = ssh_agent_get_first_ident(session, &state->comment); state->pubkey = ssh_agent_get_first_ident(session, &state->comment);
}
if (state->pubkey == NULL) { if (state->pubkey == NULL) {
return SSH_AUTH_DENIED; return SSH_AUTH_DENIED;
} }
while (state->pubkey != NULL) { while (state->pubkey != NULL) {
if(state->state == SSH_AGENT_STATE_NONE){ if (state->state == SSH_AGENT_STATE_NONE) {
SSH_LOG(SSH_LOG_DEBUG, SSH_LOG(SSH_LOG_DEBUG,
"Trying identity %s", state->comment); "Trying identity %s", state->comment);
} }
if(state->state == SSH_AGENT_STATE_NONE || if (state->state == SSH_AGENT_STATE_NONE ||
state->state == SSH_AGENT_STATE_PUBKEY){ state->state == SSH_AGENT_STATE_PUBKEY) {
rc = ssh_userauth_try_publickey(session, username, state->pubkey); rc = ssh_userauth_try_publickey(session, username, state->pubkey);
if (rc == SSH_AUTH_ERROR) { if (rc == SSH_AUTH_ERROR) {
ssh_agent_state_free (state); ssh_agent_state_free (state);
@ -814,7 +819,7 @@ int ssh_userauth_agent(ssh_session session,
"Public key of %s accepted by server", state->comment); "Public key of %s accepted by server", state->comment);
state->state = SSH_AGENT_STATE_AUTH; state->state = SSH_AGENT_STATE_AUTH;
} }
if (state->state == SSH_AGENT_STATE_AUTH){ if (state->state == SSH_AGENT_STATE_AUTH) {
rc = ssh_userauth_agent_publickey(session, username, state->pubkey); rc = ssh_userauth_agent_publickey(session, username, state->pubkey);
if (rc == SSH_AUTH_AGAIN) if (rc == SSH_AUTH_AGAIN)
return rc; return rc;
@ -845,7 +850,7 @@ int ssh_userauth_agent(ssh_session session,
#endif #endif
enum ssh_auth_auto_state_e { enum ssh_auth_auto_state_e {
SSH_AUTH_AUTO_STATE_NONE=0, SSH_AUTH_AUTO_STATE_NONE = 0,
SSH_AUTH_AUTO_STATE_PUBKEY, SSH_AUTH_AUTO_STATE_PUBKEY,
SSH_AUTH_AUTO_STATE_KEY_IMPORTED, SSH_AUTH_AUTO_STATE_KEY_IMPORTED,
SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED
@ -907,10 +912,10 @@ int ssh_userauth_publickey_auto(ssh_session session,
auth_fn = session->common.callbacks->auth_function; auth_fn = session->common.callbacks->auth_function;
auth_data = session->common.callbacks->userdata; auth_data = session->common.callbacks->userdata;
} }
if (!session->auth_auto_state){ if (!session->auth_auto_state) {
session->auth_auto_state = session->auth_auto_state =
malloc(sizeof(struct ssh_auth_auto_state_struct)); malloc(sizeof(struct ssh_auth_auto_state_struct));
if (!session->auth_auto_state){ if (!session->auth_auto_state) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
@ -933,10 +938,10 @@ int ssh_userauth_publickey_auto(ssh_session session,
state->it = ssh_list_get_iterator(session->opts.identity); state->it = ssh_list_get_iterator(session->opts.identity);
} }
while (state->it != NULL){ while (state->it != NULL) {
const char *privkey_file = state->it->data; const char *privkey_file = state->it->data;
char pubkey_file[1024] = {0}; char pubkey_file[1024] = {0};
if (state->state == SSH_AUTH_AUTO_STATE_PUBKEY){ if (state->state == SSH_AUTH_AUTO_STATE_PUBKEY) {
SSH_LOG(SSH_LOG_DEBUG, SSH_LOG(SSH_LOG_DEBUG,
"Trying to authenticate with %s", privkey_file); "Trying to authenticate with %s", privkey_file);
state->privkey = NULL; state->privkey = NULL;
@ -990,7 +995,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
} }
state->state = SSH_AUTH_AUTO_STATE_KEY_IMPORTED; state->state = SSH_AUTH_AUTO_STATE_KEY_IMPORTED;
} }
if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED){ if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED) {
rc = ssh_userauth_try_publickey(session, username, state->pubkey); rc = ssh_userauth_try_publickey(session, username, state->pubkey);
if (rc == SSH_AUTH_ERROR) { if (rc == SSH_AUTH_ERROR) {
SSH_LOG(SSH_LOG_WARN, SSH_LOG(SSH_LOG_WARN,
@ -1000,7 +1005,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
ssh_key_free(state->pubkey); ssh_key_free(state->pubkey);
SAFE_FREE(session->auth_auto_state); SAFE_FREE(session->auth_auto_state);
return rc; return rc;
} else if (rc == SSH_AUTH_AGAIN){ } else if (rc == SSH_AUTH_AGAIN) {
return rc; return rc;
} else if (rc != SSH_AUTH_SUCCESS) { } else if (rc != SSH_AUTH_SUCCESS) {
SSH_LOG(SSH_LOG_DEBUG, SSH_LOG(SSH_LOG_DEBUG,
@ -1016,7 +1021,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
} }
state->state = SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED; state->state = SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED;
} }
if (state->state == SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED){ if (state->state == SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED) {
/* Public key has been accepted by the server */ /* Public key has been accepted by the server */
if (state->privkey == NULL) { if (state->privkey == NULL) {
rc = ssh_pki_import_privkey_file(privkey_file, rc = ssh_pki_import_privkey_file(privkey_file,
@ -1037,11 +1042,11 @@ int ssh_userauth_publickey_auto(ssh_session session,
} else if (rc == SSH_EOF) { } else if (rc == SSH_EOF) {
/* If the file doesn't exist, continue */ /* If the file doesn't exist, continue */
ssh_key_free(state->pubkey); ssh_key_free(state->pubkey);
state->pubkey=NULL; state->pubkey = NULL;
SSH_LOG(SSH_LOG_INFO, SSH_LOG(SSH_LOG_INFO,
"Private key %s doesn't exist.", "Private key %s doesn't exist.",
privkey_file); privkey_file);
state->it=state->it->next; state->it = state->it->next;
state->state = SSH_AUTH_AUTO_STATE_PUBKEY; state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
continue; continue;
} }
@ -1059,14 +1064,14 @@ int ssh_userauth_publickey_auto(ssh_session session,
} }
return rc; return rc;
} }
if (rc == SSH_AUTH_AGAIN){ if (rc == SSH_AUTH_AGAIN) {
return rc; return rc;
} }
SSH_LOG(SSH_LOG_WARN, SSH_LOG(SSH_LOG_WARN,
"The server accepted the public key but refused the signature"); "The server accepted the public key but refused the signature");
state->it=state->it->next; state->it = state->it->next;
state->state=SSH_AUTH_AUTO_STATE_PUBKEY; state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
/* continue */ /* continue */
} }
} }
@ -1283,15 +1288,19 @@ static int ssh_userauth_kbdint_init(ssh_session session,
const char *submethods) const char *submethods)
{ {
int rc; int rc;
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_INIT)
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_INIT) {
goto pending; goto pending;
if (session->pending_call_state != SSH_PENDING_CALL_NONE){ }
if (session->pending_call_state != SSH_PENDING_CALL_NONE) {
ssh_set_error_invalid(session); ssh_set_error_invalid(session);
return SSH_ERROR; return SSH_ERROR;
} }
rc = ssh_userauth_request_service(session); rc = ssh_userauth_request_service(session);
if (rc == SSH_AGAIN) if (rc == SSH_AGAIN) {
return SSH_AUTH_AGAIN; return SSH_AUTH_AGAIN;
}
if (rc != SSH_OK) { if (rc != SSH_OK) {
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
@ -1349,7 +1358,7 @@ static int ssh_userauth_kbdint_send(ssh_session session)
int rc; int rc;
if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_SEND) if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_SEND)
goto pending; goto pending;
if (session->pending_call_state != SSH_PENDING_CALL_NONE){ if (session->pending_call_state != SSH_PENDING_CALL_NONE) {
ssh_set_error_invalid(session); ssh_set_error_invalid(session);
return SSH_ERROR; return SSH_ERROR;
} }
@ -1400,91 +1409,91 @@ fail:
* authentication state. * authentication state.
*/ */
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) { SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
ssh_string tmp = NULL; ssh_string tmp = NULL;
uint32_t nprompts; uint32_t nprompts;
uint32_t i; uint32_t i;
int rc; int rc;
(void)user; (void)user;
(void)type; (void)type;
if (session->kbdint == NULL) {
session->kbdint = ssh_kbdint_new();
if (session->kbdint == NULL) { if (session->kbdint == NULL) {
ssh_set_error_oom(session); session->kbdint = ssh_kbdint_new();
return SSH_PACKET_USED; if (session->kbdint == NULL) {
ssh_set_error_oom(session);
return SSH_PACKET_USED;
}
} else {
ssh_kbdint_clean(session->kbdint);
} }
} else {
ssh_kbdint_clean(session->kbdint);
}
rc = ssh_buffer_unpack(packet, "ssSd", rc = ssh_buffer_unpack(packet, "ssSd",
&session->kbdint->name, /* name of the "asking" window shown to client */ &session->kbdint->name, /* name of the "asking" window shown to client */
&session->kbdint->instruction, &session->kbdint->instruction,
&tmp, /* to ignore */ &tmp, /* to ignore */
&nprompts &nprompts
); );
/* We don't care about tmp */ /* We don't care about tmp */
ssh_string_free(tmp); ssh_string_free(tmp);
if (rc != SSH_OK) { if (rc != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg"); ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg");
ssh_kbdint_free(session->kbdint); ssh_kbdint_free(session->kbdint);
session->kbdint = NULL; session->kbdint = NULL;
return SSH_PACKET_USED; return SSH_PACKET_USED;
}
SSH_LOG(SSH_LOG_DEBUG,
"%d keyboard-interactive prompts", nprompts);
if (nprompts > KBDINT_MAX_PROMPT) {
ssh_set_error(session, SSH_FATAL,
"Too much prompts requested by the server: %u (0x%.4x)",
nprompts, nprompts);
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
}
session->kbdint->nprompts = nprompts;
session->kbdint->nanswers = nprompts;
session->kbdint->prompts = calloc(nprompts, sizeof(char *));
if (session->kbdint->prompts == NULL) {
session->kbdint->nprompts = 0;
ssh_set_error_oom(session);
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
}
session->kbdint->echo = malloc(nprompts);
if (session->kbdint->echo == NULL) {
session->kbdint->nprompts = 0;
ssh_set_error_oom(session);
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
}
memset(session->kbdint->echo, 0, nprompts);
for (i = 0; i < nprompts; i++) {
rc = ssh_buffer_unpack(packet, "sb",
&session->kbdint->prompts[i],
&session->kbdint->echo[i]);
if (rc == SSH_ERROR) {
ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet");
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
} }
}
session->auth_state=SSH_AUTH_STATE_INFO;
return SSH_PACKET_USED; SSH_LOG(SSH_LOG_DEBUG,
"%d keyboard-interactive prompts", nprompts);
if (nprompts > KBDINT_MAX_PROMPT) {
ssh_set_error(session, SSH_FATAL,
"Too much prompts requested by the server: %u (0x%.4x)",
nprompts, nprompts);
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
}
session->kbdint->nprompts = nprompts;
session->kbdint->nanswers = nprompts;
session->kbdint->prompts = calloc(nprompts, sizeof(char *));
if (session->kbdint->prompts == NULL) {
session->kbdint->nprompts = 0;
ssh_set_error_oom(session);
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
}
session->kbdint->echo = malloc(nprompts);
if (session->kbdint->echo == NULL) {
session->kbdint->nprompts = 0;
ssh_set_error_oom(session);
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
}
memset(session->kbdint->echo, 0, nprompts);
for (i = 0; i < nprompts; i++) {
rc = ssh_buffer_unpack(packet, "sb",
&session->kbdint->prompts[i],
&session->kbdint->echo[i]);
if (rc == SSH_ERROR) {
ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet");
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
return SSH_PACKET_USED;
}
}
session->auth_state=SSH_AUTH_STATE_INFO;
return SSH_PACKET_USED;
} }
/** /**
@ -1558,13 +1567,14 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
* @returns The number of prompts. * @returns The number of prompts.
*/ */
int ssh_userauth_kbdint_getnprompts(ssh_session session) { int ssh_userauth_kbdint_getnprompts(ssh_session session) {
if(session==NULL) if (session == NULL) {
return SSH_ERROR; return SSH_ERROR;
if(session->kbdint == NULL) { }
ssh_set_error_invalid(session); if (session->kbdint == NULL) {
return SSH_ERROR; ssh_set_error_invalid(session);
} return SSH_ERROR;
return session->kbdint->nprompts; }
return session->kbdint->nprompts;
} }
/** /**
@ -1579,13 +1589,14 @@ int ssh_userauth_kbdint_getnprompts(ssh_session session) {
* @returns The name of the message block. Do not free it. * @returns The name of the message block. Do not free it.
*/ */
const char *ssh_userauth_kbdint_getname(ssh_session session) { const char *ssh_userauth_kbdint_getname(ssh_session session) {
if(session==NULL) if (session == NULL) {
return NULL; return NULL;
if(session->kbdint == NULL) { }
ssh_set_error_invalid(session); if (session->kbdint == NULL) {
return NULL; ssh_set_error_invalid(session);
} return NULL;
return session->kbdint->name; }
return session->kbdint->name;
} }
/** /**
@ -1601,13 +1612,13 @@ const char *ssh_userauth_kbdint_getname(ssh_session session) {
*/ */
const char *ssh_userauth_kbdint_getinstruction(ssh_session session) { const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
if(session==NULL) if (session == NULL)
return NULL; return NULL;
if(session->kbdint == NULL) { if (session->kbdint == NULL) {
ssh_set_error_invalid(session); ssh_set_error_invalid(session);
return NULL; return NULL;
} }
return session->kbdint->instruction; return session->kbdint->instruction;
} }
/** /**
@ -1637,22 +1648,22 @@ const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
*/ */
const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i, const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
char *echo) { char *echo) {
if(session==NULL) if (session == NULL)
return NULL; return NULL;
if(session->kbdint == NULL) { if (session->kbdint == NULL) {
ssh_set_error_invalid(session); ssh_set_error_invalid(session);
return NULL; return NULL;
} }
if (i > session->kbdint->nprompts) { if (i > session->kbdint->nprompts) {
ssh_set_error_invalid(session); ssh_set_error_invalid(session);
return NULL; return NULL;
} }
if (echo) { if (echo) {
*echo = session->kbdint->echo[i]; *echo = session->kbdint->echo[i];
} }
return session->kbdint->prompts[i]; return session->kbdint->prompts[i];
} }
#ifdef WITH_SERVER #ifdef WITH_SERVER
@ -1664,9 +1675,10 @@ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
* @returns The number of answers. * @returns The number of answers.
*/ */
int ssh_userauth_kbdint_getnanswers(ssh_session session) { int ssh_userauth_kbdint_getnanswers(ssh_session session) {
if(session==NULL || session->kbdint == NULL) if (session == NULL || session->kbdint == NULL) {
return SSH_ERROR; return SSH_ERROR;
return session->kbdint->nanswers; }
return session->kbdint->nanswers;
} }
/** /**
@ -1679,15 +1691,15 @@ int ssh_userauth_kbdint_getnanswers(ssh_session session) {
* @return 0 on success, < 0 on error. * @return 0 on success, < 0 on error.
*/ */
const char *ssh_userauth_kbdint_getanswer(ssh_session session, unsigned int i) { const char *ssh_userauth_kbdint_getanswer(ssh_session session, unsigned int i) {
if(session==NULL || session->kbdint == NULL if (session == NULL || session->kbdint == NULL
|| session->kbdint->answers == NULL) { || session->kbdint->answers == NULL) {
return NULL; return NULL;
} }
if (i >= session->kbdint->nanswers) { if (i >= session->kbdint->nanswers) {
return NULL; return NULL;
} }
return session->kbdint->answers[i]; return session->kbdint->answers[i];
} }
#endif #endif
@ -1711,35 +1723,36 @@ const char *ssh_userauth_kbdint_getanswer(ssh_session session, unsigned int i) {
*/ */
int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i, int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
const char *answer) { const char *answer) {
if (session == NULL) if (session == NULL) {
return -1; return -1;
if (answer == NULL || session->kbdint == NULL || }
i >= session->kbdint->nprompts) { if (answer == NULL || session->kbdint == NULL ||
ssh_set_error_invalid(session); i >= session->kbdint->nprompts) {
return -1; ssh_set_error_invalid(session);
} return -1;
if (session->kbdint->answers == NULL) {
session->kbdint->answers = calloc(session->kbdint->nprompts, sizeof(char *));
if (session->kbdint->answers == NULL) {
ssh_set_error_oom(session);
return -1;
} }
}
if (session->kbdint->answers[i]) { if (session->kbdint->answers == NULL) {
explicit_bzero(session->kbdint->answers[i], session->kbdint->answers = calloc(session->kbdint->nprompts, sizeof(char *));
strlen(session->kbdint->answers[i])); if (session->kbdint->answers == NULL) {
SAFE_FREE(session->kbdint->answers[i]); ssh_set_error_oom(session);
} return -1;
}
}
session->kbdint->answers[i] = strdup(answer); if (session->kbdint->answers[i]) {
if (session->kbdint->answers[i] == NULL) { explicit_bzero(session->kbdint->answers[i],
ssh_set_error_oom(session); strlen(session->kbdint->answers[i]));
return -1; SAFE_FREE(session->kbdint->answers[i]);
} }
return 0; session->kbdint->answers[i] = strdup(answer);
if (session->kbdint->answers[i] == NULL) {
ssh_set_error_oom(session);
return -1;
}
return 0;
} }
/** /**
@ -1756,47 +1769,47 @@ int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
* later. * later.
*/ */
int ssh_userauth_gssapi(ssh_session session) { int ssh_userauth_gssapi(ssh_session session) {
int rc = SSH_AUTH_DENIED; int rc = SSH_AUTH_DENIED;
#ifdef WITH_GSSAPI #ifdef WITH_GSSAPI
switch(session->pending_call_state) { switch(session->pending_call_state) {
case SSH_PENDING_CALL_NONE: case SSH_PENDING_CALL_NONE:
break; break;
case SSH_PENDING_CALL_AUTH_GSSAPI_MIC: case SSH_PENDING_CALL_AUTH_GSSAPI_MIC:
goto pending; goto pending;
default: default:
ssh_set_error(session, ssh_set_error(session,
SSH_FATAL, SSH_FATAL,
"Wrong state (%d) during pending SSH call", "Wrong state (%d) during pending SSH call",
session->pending_call_state); session->pending_call_state);
return SSH_ERROR; return SSH_ERROR;
} }
rc = ssh_userauth_request_service(session); rc = ssh_userauth_request_service(session);
if (rc == SSH_AGAIN) { if (rc == SSH_AGAIN) {
return SSH_AUTH_AGAIN; return SSH_AUTH_AGAIN;
} else if (rc == SSH_ERROR) { } else if (rc == SSH_ERROR) {
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi-with-mic"); SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi-with-mic");
session->auth_state = SSH_AUTH_STATE_NONE; session->auth_state = SSH_AUTH_STATE_NONE;
session->pending_call_state = SSH_PENDING_CALL_AUTH_GSSAPI_MIC; session->pending_call_state = SSH_PENDING_CALL_AUTH_GSSAPI_MIC;
rc = ssh_gssapi_auth_mic(session); rc = ssh_gssapi_auth_mic(session);
if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_DENIED) { if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_DENIED) {
session->auth_state = SSH_AUTH_STATE_NONE; session->auth_state = SSH_AUTH_STATE_NONE;
session->pending_call_state = SSH_PENDING_CALL_NONE; session->pending_call_state = SSH_PENDING_CALL_NONE;
return rc; return rc;
} }
pending: pending:
rc = ssh_userauth_get_response(session); rc = ssh_userauth_get_response(session);
if (rc != SSH_AUTH_AGAIN) { if (rc != SSH_AUTH_AGAIN) {
session->pending_call_state = SSH_PENDING_CALL_NONE; session->pending_call_state = SSH_PENDING_CALL_NONE;
} }
#else #else
(void) session; /* unused */ (void) session; /* unused */
#endif #endif
return rc; return rc;
} }
/** @} */ /** @} */