1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-12-17 06:18:58 +03:00

Public key authentication server side

This commit is contained in:
milo
2009-07-27 17:59:02 +02:00
committed by Andreas Schneider
parent cdde79418a
commit e8f7801540
6 changed files with 165 additions and 5 deletions

View File

@@ -422,6 +422,8 @@ struct ssh_auth_request {
char *username;
int method;
char *password;
struct ssh_public_key_struct *public_key;
char signature_state;
};
struct ssh_channel_request_open {
@@ -608,6 +610,8 @@ int make_sessionid(SSH_SESSION *session);
int hashbufin_add_cookie(SSH_SESSION *session, unsigned char *cookie);
int hashbufout_add_cookie(SSH_SESSION *session);
int generate_session_keys(SSH_SESSION *session);
int sig_verify(SSH_SESSION *session, ssh_public_key pubkey,
SIGNATURE *signature, unsigned char *digest, int size);
/* returns 1 if server signature ok, 0 otherwise. The NEXT crypto is checked, not the current one */
int signature_verify(SSH_SESSION *session,ssh_string signature);
bignum make_string_bn(ssh_string string);
@@ -659,6 +663,7 @@ ssh_string try_publickey_from_file(SSH_SESSION *session,
/* in keys.c */
const char *ssh_type_to_char(int type);
int ssh_type_from_name(const char *name);
ssh_buffer ssh_userauth_build_digest(SSH_SESSION *session, struct ssh_message *msg, char *service);
ssh_private_key privatekey_make_dss(SSH_SESSION *session, ssh_buffer buffer);
ssh_private_key privatekey_make_rsa(SSH_SESSION *session, ssh_buffer buffer,

View File

@@ -159,7 +159,9 @@ void ssh_message_free(SSH_MESSAGE *msg);
char *ssh_message_auth_user(SSH_MESSAGE *msg);
char *ssh_message_auth_password(SSH_MESSAGE *msg);
ssh_public_key ssh_message_auth_publickey(SSH_MESSAGE *msg);
int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial);
int ssh_message_auth_reply_pk_ok(SSH_MESSAGE *msg, ssh_string algo, ssh_string pubkey);
int ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods);
ssh_channel ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg);

View File

@@ -26,6 +26,7 @@
#define SSH2_MSG_USERAUTH_PK_OK 60
#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60
#define SSH2_MSG_USERAUTH_INFO_REQUEST 60
#define SSH2_MSG_USERAUTH_PK_OK 60
#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61
#define SSH2_MSG_GLOBAL_REQUEST 80
#define SSH2_MSG_REQUEST_SUCCESS 81

View File

@@ -891,8 +891,8 @@ static int match(const char *group, const char *object){
return 0;
}
static int sig_verify(SSH_SESSION *session, ssh_public_key pubkey,
SIGNATURE *signature, unsigned char *digest) {
int sig_verify(SSH_SESSION *session, ssh_public_key pubkey,
SIGNATURE *signature, unsigned char *digest, int size) {
#ifdef HAVE_LIBGCRYPT
gcry_error_t valid = 0;
gcry_sexp_t gcryhash;
@@ -901,7 +901,7 @@ static int sig_verify(SSH_SESSION *session, ssh_public_key pubkey,
#endif
unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
sha1(digest,SHA_DIGEST_LEN, hash + 1);
sha1(digest, size, hash + 1);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash to be verified with dsa", hash + 1, SHA_DIGEST_LEN);
@@ -1027,7 +1027,8 @@ int signature_verify(SSH_SESSION *session, ssh_string signature) {
ssh_log(session, SSH_LOG_FUNCTIONS,
"Going to verify a %s type signature", pubkey->type_c);
err = sig_verify(session,pubkey,sign,session->next_crypto->session_id);
err = sig_verify(session,pubkey,sign,
session->next_crypto->session_id,SHA_DIGEST_LEN);
signature_free(sign);
session->next_crypto->server_pubkey_type = pubkey->type_c;
publickey_free(pubkey);

View File

@@ -28,6 +28,8 @@
#include <openssl/rsa.h>
#endif
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/server.h"
/** \addtogroup ssh_auth
* @{
@@ -1147,6 +1149,70 @@ ssh_string ssh_do_sign_with_agent(ssh_session session,
}
#endif /* _WIN32 */
/*
* This function concats in a buffer the values needed to do a signature
* verification. */
ssh_buffer ssh_userauth_build_digest(SSH_SESSION *session, struct ssh_message *msg, char *service) {
/*
The value of 'signature' is a signature by the corresponding private
key over the following data, in the following order:
string session identifier
byte SSH_MSG_USERAUTH_REQUEST
string user name
string service name
string "publickey"
boolean TRUE
string public key algorithm name
string public key to be used for authentication
*/
CRYPTO *crypto = session->current_crypto ? session->current_crypto :
session->next_crypto;
ssh_buffer buffer = NULL;
ssh_string session_id = NULL;
uint8_t type = SSH2_MSG_USERAUTH_REQUEST;
ssh_string username = string_from_char(msg->auth_request.username);
ssh_string servicename = string_from_char(service);
ssh_string method = string_from_char("publickey");
uint8_t has_sign = 1;
ssh_string algo = string_from_char(msg->auth_request.public_key->type_c);
ssh_string publickey = publickey_to_string(msg->auth_request.public_key);
buffer = buffer_new();
if (buffer == NULL) {
goto error;
}
session_id = string_new(SHA_DIGEST_LEN);
if (session_id == NULL) {
buffer_free(buffer);
buffer = NULL;
goto error;
}
string_fill(session_id, crypto->session_id, SHA_DIGEST_LEN);
if(buffer_add_ssh_string(buffer, session_id) < 0 ||
buffer_add_u8(buffer, type) < 0 ||
buffer_add_ssh_string(buffer, username) < 0 ||
buffer_add_ssh_string(buffer, servicename) < 0 ||
buffer_add_ssh_string(buffer, method) < 0 ||
buffer_add_u8(buffer, has_sign) < 0 ||
buffer_add_ssh_string(buffer, algo) < 0 ||
buffer_add_ssh_string(buffer, publickey) < 0) {
buffer_free(buffer);
buffer = NULL;
goto error;
}
error:
if(session_id) string_free(session_id);
if(username) string_free(username);
if(servicename) string_free(servicename);
if(method) string_free(method);
if(algo) string_free(algo);
if(publickey) string_free(publickey);
return buffer;
}
/*
* This function signs the session id (known as H) as a string then
* the content of sigbuf */

View File

@@ -182,10 +182,10 @@ static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){
service_c, method_c,
msg->auth_request.username);
SAFE_FREE(service_c);
if (strcmp(method_c, "none") == 0) {
msg->auth_request.method = SSH_AUTH_NONE;
SAFE_FREE(service_c);
SAFE_FREE(method_c);
leave_function();
return msg;
@@ -196,6 +196,7 @@ static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){
uint8_t tmp;
msg->auth_request.method = SSH_AUTH_PASSWORD;
SAFE_FREE(service_c);
SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &tmp);
pass = buffer_get_ssh_string(session->in_buffer);
@@ -211,6 +212,66 @@ static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){
return msg;
}
if (strcmp(method_c, "publickey") == 0) {
ssh_string algo = NULL;
ssh_string publickey = NULL;
uint8_t has_sign;
msg->auth_request.method = SSH_AUTH_PUBLICKEY;
SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &has_sign);
algo = buffer_get_ssh_string(session->in_buffer);
if (algo == NULL) {
goto error;
}
publickey = buffer_get_ssh_string(session->in_buffer);
if (publickey == NULL) {
string_free(algo);
algo = NULL;
goto error;
}
msg->auth_request.public_key = publickey_from_string(session, publickey);
string_free(algo);
algo = NULL;
string_free(publickey);
publickey = NULL;
if (msg->auth_request.public_key == NULL) {
goto error;
}
msg->auth_request.signature_state = 0;
// has a valid signature ?
if(has_sign) {
SIGNATURE *signature = NULL;
ssh_public_key public_key = msg->auth_request.public_key;
ssh_string sign = NULL;
ssh_buffer digest = NULL;
sign = buffer_get_ssh_string(session->in_buffer);
if(sign == NULL) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature packet from peer");
msg->auth_request.signature_state = -2;
goto error;
}
signature = signature_from_string(session, sign, public_key,
public_key->type);
digest = ssh_userauth_build_digest(session, msg, service_c);
if(sig_verify(session, public_key, signature,
buffer_get(digest), buffer_get_len(digest)) < 0) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature from peer");
msg->auth_request.signature_state = -1;
string_free(sign);
sign = NULL;
goto error;
}
else
ssh_log(session, SSH_LOG_PACKET, "Valid signature received");
msg->auth_request.signature_state = 1;
}
SAFE_FREE(service_c);
leave_function();
return msg;
}
msg->auth_request.method = SSH_AUTH_UNKNOWN;
SAFE_FREE(method_c);
@@ -246,6 +307,15 @@ char *ssh_message_auth_password(SSH_MESSAGE *msg){
return msg->auth_request.password;
}
/* Get the publickey of an auth request */
ssh_public_key ssh_message_auth_publickey(SSH_MESSAGE *msg){
if (msg == NULL) {
return NULL;
}
return msg->auth_request.public_key;
}
int ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods) {
if (msg == NULL || msg->session == NULL) {
return -1;
@@ -333,6 +403,21 @@ int ssh_message_auth_reply_success(SSH_MESSAGE *msg, int partial) {
return packet_send(msg->session);
}
/* Answer OK to a pubkey auth request */
int ssh_message_auth_reply_pk_ok(SSH_MESSAGE *msg, ssh_string algo, ssh_string pubkey) {
if (msg == NULL) {
return SSH_ERROR;
}
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_USERAUTH_PK_OK) < 0 ||
buffer_add_ssh_string(msg->session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(msg->session->out_buffer, pubkey) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session) {
SSH_MESSAGE *msg = NULL;
ssh_string type = NULL;