aboutsummaryrefslogtreecommitdiff
path: root/src/messages.c
diff options
context:
space:
mode:
authormilo <milo@r0ot.me>2011-02-08 00:40:18 +0100
committermilo <milo@r0ot.me>2011-02-10 14:39:20 +0100
commit3c0a4781e49a4912e191b20ea8ccaeb884eb9dcd (patch)
tree12da3549867512351a797bfa571f841b1d214708 /src/messages.c
parent32e23a25da4e7d23bdede1cee4cadc6c80306c23 (diff)
downloadlibssh-3c0a4781e49a4912e191b20ea8ccaeb884eb9dcd.tar.gz
libssh-3c0a4781e49a4912e191b20ea8ccaeb884eb9dcd.tar.xz
libssh-3c0a4781e49a4912e191b20ea8ccaeb884eb9dcd.zip
Added the keyboard-interactive authentication method
Diffstat (limited to 'src/messages.c')
-rw-r--r--src/messages.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/messages.c b/src/messages.c
index 48e1acb5..64daf7f3 100644
--- a/src/messages.c
+++ b/src/messages.c
@@ -336,6 +336,38 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
goto end;
}
+ if (strncmp(method_c, "keyboard-interactive", method_size) == 0) {
+ ssh_string lang = NULL;
+ ssh_string submethods = NULL;
+
+ msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
+ SAFE_FREE(service_c);
+ SAFE_FREE(method_c);
+ lang = buffer_get_ssh_string(packet);
+ if (lang == NULL) {
+ goto error;
+ }
+ /* from the RFC 4256
+ * 3.1. Initial Exchange
+ * "The language tag is deprecated and SHOULD be the empty string."
+ */
+ ssh_string_free(lang);
+
+ submethods = buffer_get_ssh_string(packet);
+ if (submethods == NULL) {
+ goto error;
+ }
+ /* from the RFC 4256
+ * 3.1. Initial Exchange
+ * "One possible implementation strategy of the submethods field on the
+ * server is that, unless the user may use multiple different
+ * submethods, the server ignores this field."
+ */
+ ssh_string_free(submethods);
+
+ goto end;
+ }
+
if (strncmp(method_c, "publickey", method_size) == 0) {
ssh_string algo = NULL;
ssh_string publickey = NULL;
@@ -432,6 +464,129 @@ end:
return SSH_PACKET_USED;
}
+/**
+ * @internal
+ *
+ * @brief Handle a SSH_MSG_MSG_USERAUTH_INFO_RESPONSE packet and queue a
+ * SSH Message
+ */
+#ifndef WITH_SERVER
+SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
+ (void)session;
+ (void)type;
+ (void)packet;
+ (void)user;
+ return SSH_PACKET_USED;
+}
+#else
+SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
+ uint32_t nanswers;
+ uint32_t i;
+ ssh_string tmp;
+
+ ssh_message msg = NULL;
+
+ enter_function();
+
+ (void)user;
+ (void)type;
+
+ msg = ssh_message_new(session);
+ if (msg == NULL) {
+ ssh_set_error_oom(session);
+ goto error;
+ }
+
+ /* HACK: we forge a message to be able to handle it in the
+ * same switch() as other auth methods */
+ msg->type = SSH_REQUEST_AUTH;
+ msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
+ msg->auth_request.kbdint_response = 1;
+#if 0 // should we wipe the username ?
+ msg->auth_request.username = NULL;
+#endif
+
+ buffer_get_u32(packet, &nanswers);
+
+ if (session->kbdint == NULL) {
+ ssh_log(session, SSH_LOG_PROTOCOL, "Warning: Got a keyboard-interactive "
+ "response but it seems we didn't send the request.");
+
+ session->kbdint = kbdint_new();
+ if (session->kbdint == NULL) {
+ ssh_set_error_oom(session);
+
+ leave_function();
+ return SSH_PACKET_USED;
+ }
+ }
+
+ nanswers = ntohl(nanswers);
+ ssh_log(session,SSH_LOG_PACKET,"kbdint: %d answers",nanswers);
+ if (nanswers > KBDINT_MAX_PROMPT) {
+ ssh_set_error(session, SSH_FATAL,
+ "Too much answers received from client: %u (0x%.4x)",
+ nanswers, nanswers);
+ kbdint_free(session->kbdint);
+ session->kbdint = NULL;
+ leave_function();
+ return SSH_PACKET_USED;
+ }
+
+ if(nanswers != session->kbdint->nprompts) {
+ /* warn but let the application handle this case */
+ ssh_log(session, SSH_LOG_PROTOCOL, "Warning: Number of prompts and answers"
+ " mismatch: p=%u a=%u", session->kbdint->nprompts, nanswers);
+ }
+ session->kbdint->nanswers = nanswers;
+ session->kbdint->answers = malloc(nanswers * sizeof(char *));
+ if (session->kbdint->answers == NULL) {
+ session->kbdint->nanswers = 0;
+ ssh_set_error_oom(session);
+ kbdint_free(session->kbdint);
+ session->kbdint = NULL;
+ leave_function();
+ return SSH_PACKET_USED;
+ }
+ memset(session->kbdint->answers, 0, nanswers * sizeof(char *));
+
+ for (i = 0; i < nanswers; i++) {
+ tmp = buffer_get_ssh_string(packet);
+ if (tmp == NULL) {
+ ssh_set_error(session, SSH_FATAL, "Short INFO_RESPONSE packet");
+ session->kbdint->nanswers = i;
+ kbdint_free(session->kbdint);
+ session->kbdint = NULL;
+ leave_function();
+ return SSH_PACKET_USED;
+ }
+ session->kbdint->answers[i] = ssh_string_to_char(tmp);
+ ssh_string_free(tmp);
+ if (session->kbdint->answers[i] == NULL) {
+ ssh_set_error_oom(session);
+ session->kbdint->nanswers = i;
+ kbdint_free(session->kbdint);
+ session->kbdint = NULL;
+ leave_function();
+ return SSH_PACKET_USED;
+ }
+ }
+
+ goto end;
+
+error:
+ ssh_message_free(msg);
+
+ leave_function();
+ return SSH_PACKET_USED;
+
+end:
+ ssh_message_queue(session,msg);
+ leave_function();
+ return SSH_PACKET_USED;
+}
+#endif
+
SSH_PACKET_CALLBACK(ssh_packet_channel_open){
ssh_message msg = NULL;
ssh_string type_s = NULL, originator = NULL, destination = NULL;