1852 lines
58 KiB
C
1852 lines
58 KiB
C
/*
|
|
******************************************************************************
|
|
* SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_auth.c,v $ $Revision: 1.77.10.12 $
|
|
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_auth.c,v $
|
|
* $Author: xjiang1 $ $Date: 2018-11-09 10:31:10 $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Roger Boden <roger@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipssh_h.h"
|
|
#include "ipssh_transport.h"
|
|
#include "ipssh_auth.h"
|
|
#include "ipssh_sftp.h"
|
|
#include "ipssh_buffer.h"
|
|
|
|
#include <ipcom_clib.h>
|
|
#include <ipssh_config.h>
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_buffer.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_shell.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_sock2.h>
|
|
|
|
#include <openssl/evp.h>
|
|
#ifdef IP_PORT_VXWORKS
|
|
#include <shellHook.h>
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_EXTERN int ipssh_dsa_verify(int type, const unsigned char *dgst, int dgst_len,
|
|
unsigned char *sigbuf, int siglen, DSA *dsa);
|
|
IP_EXTERN EVP_MD *ipssh_evp_dss1(void);
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPSSH_AUTH_PW_DONE 1
|
|
#define IPSSH_AUTH_PUBKEY_DONE 2
|
|
#define IPSSH_AUTH_HOSTBASED_DONE 4
|
|
|
|
#define IPSSH_AUTH_FAILED 0
|
|
#define IPSSH_AUTH_OK 1
|
|
#define IPSSH_AUTH_PUBKEY_OK 2
|
|
#define IPSSH_AUTH_FATAL 3
|
|
|
|
|
|
#define IPSSH_FQDN_MAXLEN 256
|
|
#define IPSSH_SIG_BUF_LEN 2048
|
|
/*
|
|
****************************************************************************
|
|
* 6 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_GLOBAL Ip_err ipssh_send_userauth_failure_msg(Ipssh_conn* ssh_conn, char* supported_meths, Ip_u8 success);
|
|
IP_GLOBAL Ip_err ipssh_send_userauth_passwd_changereq(Ipssh_conn* ssh_conn);
|
|
IP_GLOBAL Ip_err ipssh_send_userauth_success_msg(Ipssh_conn* ssh_conn);
|
|
IP_GLOBAL Ip_err ipssh_send_msg_userauth_pk_ok(Ipssh_conn* ssh_conn, char* alg_name, Ip_u8* pub_key, Ip_size_t pub_key_len);
|
|
IP_GLOBAL Ip_err ipssh_send_userauth_banner_msg(Ipssh_conn* ssh_conn, const char* auth_banner);
|
|
|
|
IP_STATIC Ip_bool ipssh_more_auth_needed(Ipssh_conn* ssh_conn);
|
|
IP_STATIC void ipssh_get_auth_methods(Ipssh_conn* ssh_conn, char* buf, int buf_size);
|
|
IP_STATIC Ip_s32 ipssh_handle_publickey_auth(Ipssh_conn* ssh_conn, char* user);
|
|
IP_STATIC Ip_s32 ipssh_handle_hostbased_auth(Ipssh_conn* ssh_conn, char* user);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_more_auth_needed
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipssh_more_auth_needed(Ipssh_conn* ssh_conn)
|
|
{
|
|
if (ssh_conn->config.auth_none_allowed != 0)
|
|
return IP_FALSE;
|
|
|
|
if (ssh_conn->auth_state == 0)
|
|
return IP_TRUE;
|
|
if (ssh_conn->config.pw_required && !(ssh_conn->auth_state & IPSSH_AUTH_PW_DONE))
|
|
return IP_TRUE;
|
|
if (ssh_conn->config.pub_key_required && !(ssh_conn->auth_state & IPSSH_AUTH_PUBKEY_DONE))
|
|
return IP_TRUE;
|
|
if (ssh_conn->config.hostbased_required && !(ssh_conn->auth_state & IPSSH_AUTH_HOSTBASED_DONE))
|
|
return IP_TRUE;
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_get_auth_methods
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipssh_get_auth_methods(Ipssh_conn* ssh_conn, char* buf, int buf_size)
|
|
{
|
|
int pw_on, pub_key_on;
|
|
int pw_req, pub_key_req;
|
|
int pub_key_first;
|
|
int hb_on;
|
|
int hb_req;
|
|
Ip_bool has_one = IP_FALSE;
|
|
|
|
ipcom_memset(buf, 0, buf_size);
|
|
|
|
pw_on = ssh_conn->config.pw_allowed;
|
|
pw_req = ssh_conn->config.pw_required;
|
|
pub_key_on = ssh_conn->config.pub_key_allowed;
|
|
pub_key_req = ssh_conn->config.pub_key_required;
|
|
pub_key_first = ssh_conn->config.pub_key_first;
|
|
hb_on = ssh_conn->config.hostbased_allowed;
|
|
hb_req = ssh_conn->config.hostbased_required;
|
|
|
|
/* Remove authentication methods already used. */
|
|
if (ssh_conn->auth_state & IPSSH_AUTH_PW_DONE)
|
|
pw_on = 0;
|
|
if (ssh_conn->auth_state & IPSSH_AUTH_PUBKEY_DONE)
|
|
pub_key_on = 0;
|
|
if (ssh_conn->auth_state & IPSSH_AUTH_HOSTBASED_DONE)
|
|
hb_on = 0;
|
|
|
|
/* Check if several auth methods are required and pub key shall be
|
|
* the first method to use */
|
|
if (pw_on && pw_req
|
|
&& hb_on && hb_req
|
|
&& pub_key_on && pub_key_req
|
|
&& pub_key_first)
|
|
{
|
|
if (ssh_conn->auth_state == 0)
|
|
{
|
|
pw_on = 0;
|
|
hb_on = 0;
|
|
}
|
|
}
|
|
|
|
if (pub_key_on == 1)
|
|
{
|
|
has_one = IP_TRUE;
|
|
ipcom_strncat(buf, IPSSH_PUBKEY_AUTH_STR, buf_size);
|
|
}
|
|
|
|
if (pw_on == 1)
|
|
{
|
|
if(has_one)
|
|
{
|
|
ipcom_strncat(buf, ",", buf_size);
|
|
}
|
|
has_one = IP_TRUE;
|
|
ipcom_strncat(buf, IPSSH_PW_AUTH_STR, buf_size);
|
|
}
|
|
|
|
if (hb_on == 1)
|
|
{
|
|
if(has_one)
|
|
{
|
|
ipcom_strncat(buf, ",", buf_size);
|
|
}
|
|
has_one = IP_TRUE;
|
|
ipcom_strncat(buf, IPSSH_HOSTBASED_AUTH_STR, buf_size);
|
|
}
|
|
|
|
if (!has_one)
|
|
{
|
|
ipcom_strncat(buf, IPSSH_NONE_STR, buf_size);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_unpack_signature
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u8*
|
|
ipssh_unpack_signature(Ipcom_buffer* buf, Ip_u32* len)
|
|
{
|
|
char* sig_type;
|
|
Ip_u32 dummy;
|
|
|
|
*len = 0;
|
|
|
|
if (ipssh_buffer_get_uint(buf, &dummy) != IPCOM_SUCCESS)
|
|
return IP_NULL;
|
|
sig_type = ipssh_buffer_get_sshstr(buf);
|
|
if (!sig_type)
|
|
return IP_NULL;
|
|
|
|
if (ipcom_strcmp(sig_type, IPSSH_DSA_STR) == 0)
|
|
{
|
|
/* Convert to openssl DSA_SIG binary format */
|
|
DSA_SIG* dsa_sig;
|
|
Ip_u8* dsa_sig_der = IP_NULL;
|
|
Ip_u8* tmp_dsa_sig_der;
|
|
Ip_u32 sig_len;
|
|
Ip_s32 tmp_len;
|
|
|
|
ipcom_free(sig_type);
|
|
|
|
if (ipssh_buffer_get_uint(buf, &sig_len) != IPCOM_SUCCESS)
|
|
return IP_NULL;
|
|
if (sig_len != 40 || ipcom_buffer_len(buf)<40)
|
|
return IP_NULL;
|
|
|
|
dsa_sig = DSA_SIG_new();
|
|
if (!dsa_sig)
|
|
return IP_NULL;
|
|
|
|
dsa_sig->r = BN_bin2bn(ipcom_buffer_start_ptr(buf), 20, dsa_sig->r);
|
|
dsa_sig->s = BN_bin2bn(ipcom_buffer_start_ptr(buf)+20, 20, dsa_sig->s);
|
|
if (!dsa_sig->r || !dsa_sig->s)
|
|
goto cleanup;
|
|
(void)ipcom_buffer_consume(buf, 40);
|
|
dsa_sig_der = ipcom_malloc(64);
|
|
if (!dsa_sig_der)
|
|
goto cleanup;
|
|
tmp_dsa_sig_der = dsa_sig_der;
|
|
tmp_len = i2d_DSA_SIG(dsa_sig, &tmp_dsa_sig_der);
|
|
if (tmp_len < 0)
|
|
{
|
|
ipcom_free(dsa_sig_der);
|
|
dsa_sig_der = IP_NULL;
|
|
goto cleanup;
|
|
}
|
|
*len = (Ip_u32)tmp_len;
|
|
|
|
cleanup:
|
|
DSA_SIG_free(dsa_sig);
|
|
return dsa_sig_der;
|
|
}
|
|
else
|
|
{
|
|
ipcom_free(sig_type);
|
|
return ipssh_buffer_get_sshbuf(buf, len);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_unpack_dsa_key
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC EVP_PKEY*
|
|
ipssh_unpack_dsa_key(Ipcom_buffer* buf, Ip_u8** pub_key, Ip_u32* key_len)
|
|
{
|
|
EVP_PKEY* pkey;
|
|
DSA* dsa;
|
|
char* key_type = IP_NULL;
|
|
|
|
pkey = EVP_PKEY_new();
|
|
dsa = DSA_new();
|
|
|
|
if (!pkey || !dsa)
|
|
{
|
|
goto err;
|
|
}
|
|
|
|
*pub_key = (Ip_u8*)ipcom_buffer_ptr2pos(buf, 4); /* Make pointer point to pub key value and not to the length field. */
|
|
if (ipssh_buffer_get_uint(buf, key_len) ||
|
|
(key_type = ipssh_buffer_get_sshstr(buf)) == IP_NULL ||
|
|
ipssh_buffer_get_ssh_mpint2(buf, &(dsa->p)) ||
|
|
ipssh_buffer_get_ssh_mpint2(buf, &(dsa->q)) ||
|
|
ipssh_buffer_get_ssh_mpint2(buf, &(dsa->g)) ||
|
|
ipssh_buffer_get_ssh_mpint2(buf, &(dsa->pub_key)))
|
|
{
|
|
IPCOM_LOG0(ERR,"ipssh_unpack_dsa_key :: failed to unpack key");
|
|
goto err;
|
|
}
|
|
|
|
ipcom_free(key_type);
|
|
(void)EVP_PKEY_assign_DSA(pkey, dsa);
|
|
return pkey;
|
|
|
|
err:
|
|
if (pkey)
|
|
EVP_PKEY_free(pkey);
|
|
if (dsa)
|
|
DSA_free(dsa);
|
|
if (key_type)
|
|
ipcom_free(key_type);
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_unpack_rsa_key
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
#ifdef IPSSH_USE_RSA
|
|
IP_STATIC EVP_PKEY*
|
|
ipssh_unpack_rsa_key(Ipcom_buffer* buf, Ip_u8** pub_key, Ip_u32* key_len)
|
|
{
|
|
EVP_PKEY* pkey;
|
|
RSA* rsa;
|
|
char* key_type = IP_NULL;
|
|
|
|
pkey = EVP_PKEY_new();
|
|
rsa = RSA_new();
|
|
|
|
if (!pkey || !rsa)
|
|
{
|
|
if (rsa)
|
|
RSA_free(rsa);
|
|
if (pkey)
|
|
EVP_PKEY_free(pkey);
|
|
return IP_NULL;
|
|
}
|
|
|
|
*pub_key = (Ip_u8*)ipcom_buffer_ptr2pos(buf, 4);/* Make pointer point to pub key value and not to the length field. */
|
|
if (ipssh_buffer_get_uint(buf, key_len) ||
|
|
(key_type = ipssh_buffer_get_sshstr(buf)) == IP_NULL ||
|
|
ipssh_buffer_get_ssh_mpint2(buf, &(rsa->e)) ||
|
|
ipssh_buffer_get_ssh_mpint2(buf, &(rsa->n)))
|
|
{
|
|
IPCOM_LOG0(ERR,"ipssh_unpack_rsa_key :: failed to unpack key");
|
|
goto fail;
|
|
}
|
|
|
|
ipcom_free(key_type);
|
|
(void)EVP_PKEY_assign_RSA(pkey, rsa);
|
|
|
|
return pkey;
|
|
|
|
fail:
|
|
if (pkey)
|
|
EVP_PKEY_free(pkey);
|
|
if (rsa)
|
|
RSA_free(rsa);
|
|
if (key_type)
|
|
ipcom_free(key_type);
|
|
return IP_NULL;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_handle_password_auth
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipssh_handle_password_auth(Ipssh_conn* ssh_conn, char* user)
|
|
{
|
|
Ip_u8 flag;
|
|
Ip_s32 rc = IPSSH_AUTH_FAILED, pw_result;
|
|
char* pw;
|
|
char* new_pw = IP_NULL;
|
|
|
|
if (ipcom_buffer_get_char(ssh_conn->recv_plain_buf, &flag) != IPCOM_SUCCESS)
|
|
return IPSSH_AUTH_FATAL;
|
|
pw = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
|
|
if (flag)
|
|
new_pw = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
|
|
|
|
if (!pw || (!new_pw && flag))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_password_auth :: out of memory");
|
|
rc = IPSSH_AUTH_FATAL;
|
|
goto cleanup;
|
|
}
|
|
IPCOM_LOG2(DEBUG2, "ipssh_handle_password_auth :: pw=%s, new pw=%s", pw, new_pw ? new_pw : "");
|
|
pw_result = ipssh_validate_userid_pw_cb(user, pw, ssh_conn->sh_ctx);
|
|
|
|
switch(pw_result)
|
|
{
|
|
case IPCOM_SUCCESS:
|
|
rc = IPSSH_AUTH_OK;
|
|
ssh_conn->auth_state |= IPSSH_AUTH_PW_DONE;
|
|
break;
|
|
case IPCOM_ERR_AUTH_FAILED:
|
|
default:
|
|
ssh_conn->auth_failure_count++;
|
|
IPCOM_LOG2(INFO, "ipssh_handle_password_auth :: pw authentication failed, userid=%s, count=%d",
|
|
user, ssh_conn->auth_failure_count);
|
|
}
|
|
|
|
ssh_conn->auth_meth = IPSSH_AUTH_METH_PW;
|
|
|
|
cleanup:
|
|
if (pw)
|
|
ipcom_free(pw);
|
|
if (new_pw)
|
|
ipcom_free(new_pw);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_handle_publickey_auth
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipssh_handle_publickey_auth(Ipssh_conn* ssh_conn, char* user)
|
|
{
|
|
Ip_u8 flag;
|
|
char* pk_alg_name = IP_NULL;
|
|
Ip_u8* pub_key;
|
|
Ip_u32 pub_key_len;
|
|
Ip_s32 rc = IPSSH_AUTH_FATAL;
|
|
EVP_PKEY* clt_pub_key = IP_NULL;
|
|
EVP_MD_CTX md_ctx;
|
|
Ip_u8* sig = IP_NULL;
|
|
Ip_u32 sig_len;
|
|
Ipcom_buffer* sig_buf = IP_NULL;
|
|
|
|
ipcom_memset(&md_ctx, 0, sizeof(md_ctx));
|
|
|
|
/* Unpack message, except the public key */
|
|
if (ipcom_buffer_get_char(ssh_conn->recv_plain_buf, &flag) ||
|
|
(pk_alg_name = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf)) == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: failed to unpack algorithm name");
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef IPSSH_USE_RSA
|
|
if (ipcom_strcmp(pk_alg_name, IPSSH_RSA_STR) == 0)
|
|
{
|
|
clt_pub_key = ipssh_unpack_rsa_key(ssh_conn->recv_plain_buf, &pub_key, &pub_key_len);
|
|
if (IP_NULL == clt_pub_key)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: ipssh_unpack_rsa_key() failed");
|
|
goto cleanup;
|
|
}
|
|
if (!EVP_VerifyInit(&md_ctx, EVP_sha1()))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: EVP_VerifyInit() failed");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if (ipcom_strcmp(pk_alg_name, IPSSH_DSA_STR) == 0)
|
|
{
|
|
clt_pub_key = ipssh_unpack_dsa_key(ssh_conn->recv_plain_buf, &pub_key, &pub_key_len);
|
|
if (IP_NULL == clt_pub_key)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: ipssh_unpack_dsa_key() failed");
|
|
goto cleanup;
|
|
}
|
|
if (!EVP_VerifyInit(&md_ctx, EVP_dss1()))
|
|
{
|
|
rc = IPSSH_AUTH_FAILED;
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: EVP_VerifyInit() failed");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG1(ERR, "ipssh_handle_publickey_auth :: unknown keytype: %s", pk_alg_name);
|
|
rc = IPSSH_AUTH_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Verify public key */
|
|
if (ipssh_validate_pubkey_cb(user, clt_pub_key, ssh_conn->sh_ctx) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: failed to validate public key");
|
|
rc = IPSSH_AUTH_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (flag)
|
|
{
|
|
/* Unpack signature */
|
|
sig = ipssh_unpack_signature(ssh_conn->recv_plain_buf, &sig_len);
|
|
if (!sig)
|
|
{
|
|
IPCOM_LOG0(ERR,"ipssh_handle_publickey_auth :: failed to unpack signature");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Verify signature */
|
|
sig_buf = ipcom_buffer_new(2048);
|
|
if (!sig_buf)
|
|
{
|
|
IPCOM_LOG0(ERR,"ipssh_handle_publickey_auth :: out of memory");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
if (ipssh_buffer_put_sshbuf(sig_buf, ssh_conn->sess_id, ssh_conn->sess_id_len) ||
|
|
ipcom_buffer_put_char(sig_buf, IPSSH_MSG_USERAUTH_REQUEST) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, ssh_conn->user) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, ssh_conn->service) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, IPSSH_PUBKEY_AUTH_STR) ||
|
|
ipcom_buffer_put_char(sig_buf, 1) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, pk_alg_name) ||
|
|
ipssh_buffer_put_sshbuf(sig_buf, pub_key, pub_key_len))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: failed to pack signature data");
|
|
rc = IPCOM_ERR_FAILED; /* Disconnect client */
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef IPSSH_DEBUG_PK_AUTH
|
|
ipcom_buffer_dump(sig_buf);
|
|
#endif
|
|
|
|
if (EVP_VerifyUpdate(&md_ctx, ipcom_buffer_start_ptr(sig_buf), ipcom_buffer_len(sig_buf)) == 0)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: EVP_VerifyUpdate");
|
|
(void)ipssh_send_userauth_failure_msg(ssh_conn, IPSSH_NONE_STR, 0);
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
if (EVP_VerifyFinal(&md_ctx, sig, sig_len, clt_pub_key) != 1)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: failed to verify signature");
|
|
(void)ipssh_send_userauth_failure_msg(ssh_conn, IPSSH_NONE_STR, 0);
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
ssh_conn->auth_state |= IPSSH_AUTH_PUBKEY_DONE;
|
|
ssh_conn->auth_meth = IPSSH_AUTH_METH_PUBLIC_KEY;
|
|
rc = IPSSH_AUTH_OK;
|
|
}
|
|
else
|
|
{
|
|
/* The client only sent the public key and no signature */
|
|
rc = IPSSH_AUTH_PUBKEY_OK;
|
|
|
|
if (ipssh_send_msg_userauth_pk_ok(ssh_conn, pk_alg_name, pub_key, pub_key_len))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_publickey_auth :: ipssh_send_msg_userauth_pk_ok() failed");
|
|
rc = IPSSH_AUTH_PUBKEY_OK;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (clt_pub_key)
|
|
EVP_PKEY_free(clt_pub_key);
|
|
if (pk_alg_name)
|
|
ipcom_free(pk_alg_name);
|
|
if (sig_buf)
|
|
ipcom_buffer_free(sig_buf);
|
|
if (sig)
|
|
ipcom_free(sig);
|
|
(void)EVP_MD_CTX_cleanup(&md_ctx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_handle_hostbased_auth
|
|
*===========================================================================
|
|
* Description: ssh server parses the hostbased authentication msg and
|
|
* check if the authentication passes.
|
|
* Parameters: ssh_conn - The pointer for the ssh connection structure.
|
|
* user - user name for client.
|
|
* Returns: IPSSH_AUTH_OK - authentication passes
|
|
* IPSSH_AUTH_FATAL - authentication fails
|
|
*/
|
|
IP_STATIC Ip_s32
|
|
ipssh_handle_hostbased_auth(Ipssh_conn* ssh_conn, char* user)
|
|
{
|
|
/* byte SSH_MSG_USERAUTH_REQUEST
|
|
* string user name
|
|
* string service name
|
|
* string "hostbased"
|
|
* string public key algorithm for host key
|
|
* string public host key and certificates for client host
|
|
* string client host name expressed as the FQDN in US-ASCII
|
|
* string user name on the client host in ISO-10646 UTF-8 encoding
|
|
* [RFC3629]
|
|
* string signature
|
|
*/
|
|
char* pk_alg_name = IP_NULL;
|
|
char* cl_host_name = IP_NULL;
|
|
char* cl_user_name = IP_NULL;
|
|
Ip_u8* pub_key;
|
|
Ip_u32 pub_key_len;
|
|
Ip_s32 rc = IPSSH_AUTH_FATAL;
|
|
EVP_PKEY* clt_pub_key = IP_NULL;
|
|
EVP_MD_CTX md_ctx;
|
|
Ip_u8* sig = IP_NULL;
|
|
Ip_u32 sig_len;
|
|
Ipcom_buffer* sig_buf = IP_NULL;
|
|
|
|
ipcom_memset(&md_ctx, 0, sizeof(md_ctx));
|
|
/* Unpack message */
|
|
if ((pk_alg_name = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf)) == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: failed to unpack algorithm name");
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef IPSSH_USE_RSA
|
|
if (ipcom_strcmp(pk_alg_name, IPSSH_RSA_STR) == 0)
|
|
{
|
|
clt_pub_key = ipssh_unpack_rsa_key(ssh_conn->recv_plain_buf, &pub_key, &pub_key_len);
|
|
if (IP_NULL == clt_pub_key)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: ipssh_unpack_rsa_key() failed");
|
|
goto cleanup;
|
|
}
|
|
if (!EVP_VerifyInit(&md_ctx, EVP_sha1()))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: EVP_VerifyInit() failed");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if (ipcom_strcmp(pk_alg_name, IPSSH_DSA_STR) == 0)
|
|
{
|
|
clt_pub_key = ipssh_unpack_dsa_key(ssh_conn->recv_plain_buf, &pub_key, &pub_key_len);
|
|
if (IP_NULL == clt_pub_key)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: ipssh_unpack_dsa_key() failed");
|
|
goto cleanup;
|
|
}
|
|
if (!EVP_VerifyInit(&md_ctx, EVP_dss1()))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: EVP_VerifyInit() failed");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG1(ERR, "ipssh_handle_hostbased_auth :: unknown keytype: %s", pk_alg_name);
|
|
rc = IPSSH_AUTH_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Unpack the client hostname */
|
|
if ((cl_host_name = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf)) == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: failed to unpack client host name");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Unpack the client username */
|
|
if ((cl_user_name = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf)) == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: failed to unpack client user name");
|
|
goto cleanup;
|
|
}
|
|
/* Unpack signature */
|
|
sig = ipssh_unpack_signature(ssh_conn->recv_plain_buf, &sig_len);
|
|
if (!sig)
|
|
{
|
|
IPCOM_LOG0(ERR,"ipssh_handle_hostbased_auth :: failed to unpack signature");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Verify signature */
|
|
sig_buf = ipcom_buffer_new(IPSSH_SIG_BUF_LEN);
|
|
if (!sig_buf)
|
|
{
|
|
IPCOM_LOG0(ERR,"ipssh_handle_hostbased_auth :: out of memory");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
if (ipssh_buffer_put_sshbuf(sig_buf, ssh_conn->sess_id, (Ip_size_t)ssh_conn->sess_id_len) ||
|
|
ipcom_buffer_put_char(sig_buf, IPSSH_MSG_USERAUTH_REQUEST) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, ssh_conn->user) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, ssh_conn->service) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, IPSSH_HOSTBASED_AUTH_STR) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, pk_alg_name) ||
|
|
ipssh_buffer_put_sshbuf(sig_buf, pub_key, (Ip_size_t)pub_key_len) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, cl_host_name) ||
|
|
ipssh_buffer_put_sshstr(sig_buf, cl_user_name))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: failed to pack signature data");
|
|
rc = IPCOM_ERR_FAILED; /* Disconnect client */
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef IPSSH_DEBUG_PK_AUTH
|
|
ipcom_buffer_dump(sig_buf);
|
|
#endif
|
|
/* Verify hostbased information including user name, hostname & public key */
|
|
if (ipssh_validate_hostbased_cb(user, cl_host_name, clt_pub_key, ssh_conn->sh_ctx) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: failed to validate public key");
|
|
rc = IPSSH_AUTH_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (EVP_VerifyUpdate(&md_ctx, ipcom_buffer_start_ptr(sig_buf), ipcom_buffer_len(sig_buf)) == 0)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: EVP_VerifyUpdate");
|
|
(void)ipssh_send_userauth_failure_msg(ssh_conn, IPSSH_NONE_STR, 0);
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
if (EVP_VerifyFinal(&md_ctx, sig, sig_len, clt_pub_key) == 0)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_handle_hostbased_auth :: failed to verify signature");
|
|
(void)ipssh_send_userauth_failure_msg(ssh_conn, IPSSH_NONE_STR, 0);
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
ssh_conn->auth_state |= IPSSH_AUTH_HOSTBASED_DONE;
|
|
ssh_conn->auth_meth = IPSSH_AUTH_METH_HOSTBASED;
|
|
rc = IPSSH_AUTH_OK;
|
|
|
|
cleanup:
|
|
if (clt_pub_key)
|
|
EVP_PKEY_free(clt_pub_key);
|
|
if (pk_alg_name)
|
|
ipcom_free(pk_alg_name);
|
|
if (cl_host_name)
|
|
ipcom_free(cl_host_name);
|
|
if (cl_user_name)
|
|
ipcom_free(cl_user_name);
|
|
if (sig_buf)
|
|
ipcom_buffer_free(sig_buf);
|
|
if (sig)
|
|
ipcom_free(sig);
|
|
(void)EVP_MD_CTX_cleanup(&md_ctx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_send_userauth_req_pubkey
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err
|
|
ipssh_send_userauth_req_pubkey(Ipssh_conn* ssh_conn)
|
|
{
|
|
Ip_size_t sig_blob_len_pos;
|
|
unsigned int sig_len;
|
|
Ip_u32 len;
|
|
Ip_size_t buf_size;
|
|
Ipcom_buffer* sig_buf = IP_NULL;
|
|
Ipcom_buffer* pkt = IP_NULL;
|
|
EVP_MD_CTX md_ctx;
|
|
Ip_err rc = IPCOM_ERR_FAILED;
|
|
char* key_type_str;
|
|
int sig_len_pos = 0;
|
|
char* dsa_sig_buf = IP_NULL;
|
|
unsigned char* tmp_dsa_sig_buf;
|
|
DSA_SIG* dsa_sig = IP_NULL;
|
|
|
|
ipcom_memset(&md_ctx, 0, sizeof(md_ctx));
|
|
|
|
buf_size = 512 + EVP_PKEY_bits(ssh_conn->data.clt.key)/2;
|
|
pkt = ipssh_buffer_new_v2_pkt(buf_size, IPSSH_MSG_USERAUTH_REQUEST);
|
|
sig_buf = ipcom_buffer_new(buf_size);
|
|
if (!sig_buf || !pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: out of memory");
|
|
goto cleanup;
|
|
}
|
|
|
|
switch (ssh_conn->data.clt.key->type)
|
|
{
|
|
case NID_dsa:
|
|
key_type_str = IPSSH_DSA_STR;
|
|
break;
|
|
case NID_rsaEncryption:
|
|
key_type_str = IPSSH_RSA_STR;
|
|
break;
|
|
|
|
default:
|
|
IP_PANIC();
|
|
key_type_str = "Unknown key type";
|
|
}
|
|
/* Create first part of message */
|
|
if (ipssh_buffer_put_sshstr(pkt, ssh_conn->data.clt.userid)
|
|
|| ipssh_buffer_put_sshstr(pkt, IPSSH_CONNECTION_STR)
|
|
|| ipssh_buffer_put_sshstr(pkt, IPSSH_PUBKEY_AUTH_STR)
|
|
|| ipcom_buffer_put_char(pkt, 1)
|
|
|| ipssh_buffer_put_sshstr(pkt, key_type_str)
|
|
|| ipssh_buffer_put_pub_key(pkt, ssh_conn->data.clt.key))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: failed to assemble USERAUTH_REQ for pubkey");
|
|
goto cleanup;
|
|
}
|
|
sig_blob_len_pos = ipcom_buffer_len(pkt);
|
|
if (ipcom_buffer_decr_cap(pkt, 4) || ipssh_buffer_put_sshstr(pkt, key_type_str))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: failed to assemble USERAUTH_REQ for pubkey");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Create signature */
|
|
if (ipssh_buffer_put_sshbuf(sig_buf, ssh_conn->sess_id, ssh_conn->sess_id_len)
|
|
|| ipcom_buffer_put_char(sig_buf, IPSSH_MSG_USERAUTH_REQUEST)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, ssh_conn->data.clt.userid)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, IPSSH_CONNECTION_STR)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, IPSSH_PUBKEY_AUTH_STR)
|
|
|| ipcom_buffer_put_char(sig_buf, 1)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, key_type_str)
|
|
|| ipssh_buffer_put_pub_key(sig_buf, ssh_conn->data.clt.key))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: failed to assemble sig data");
|
|
goto cleanup;
|
|
}
|
|
#ifdef IPSSH_DEBUG_PK_AUTH
|
|
ipcom_buffer_dump(sig_buf);
|
|
#endif
|
|
sig_len_pos = ipcom_buffer_len(pkt);
|
|
|
|
if (ipcom_buffer_decr_cap(pkt, 4))
|
|
goto cleanup;
|
|
|
|
switch (ssh_conn->data.clt.key->type)
|
|
{
|
|
case NID_dsa:
|
|
dsa_sig_buf = ipcom_malloc(EVP_PKEY_size(ssh_conn->data.clt.key));
|
|
if (!dsa_sig_buf)
|
|
goto cleanup;
|
|
tmp_dsa_sig_buf = dsa_sig_buf;
|
|
if (!EVP_SignInit(&md_ctx, EVP_dss1()) ||
|
|
!EVP_SignUpdate(&md_ctx, ipcom_buffer_start_ptr(sig_buf), ipcom_buffer_len(sig_buf)) ||
|
|
!EVP_SignFinal(&md_ctx, dsa_sig_buf , &sig_len, ssh_conn->data.clt.key))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: EVP_Sign*(&md_ctx, EVP_dss1())) failed");
|
|
goto cleanup;
|
|
}
|
|
ip_assert(sig_len <= EVP_PKEY_size(ssh_conn->data.clt.key));
|
|
dsa_sig = d2i_DSA_SIG(IP_NULL, &tmp_dsa_sig_buf, sig_len);
|
|
if (!dsa_sig)
|
|
goto cleanup;
|
|
if (ipssh_buffer_put_dsa_sig(pkt, dsa_sig))
|
|
goto cleanup;
|
|
IP_SET_32ON8(ipcom_buffer_ptr2pos(pkt, sig_len_pos), ip_htonl(ipcom_buffer_len(pkt)-sig_len_pos-4));
|
|
|
|
break;
|
|
case NID_rsaEncryption:
|
|
if (!EVP_SignInit(&md_ctx, EVP_sha1()) ||
|
|
!EVP_SignUpdate(&md_ctx, ipcom_buffer_start_ptr(sig_buf), ipcom_buffer_len(sig_buf)) ||
|
|
!EVP_SignFinal(&md_ctx, ipcom_buffer_end_ptr(pkt), &sig_len, ssh_conn->data.clt.key))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: sign operation failed");
|
|
goto cleanup;
|
|
}
|
|
if (ipcom_buffer_decr_cap(pkt, sig_len))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: failed to assemble USERAUTH_REQ for pubkey");
|
|
goto cleanup;
|
|
}
|
|
IP_SET_32ON8(ipcom_buffer_ptr2pos(pkt, sig_len_pos), ip_htonl(sig_len));
|
|
|
|
break;
|
|
|
|
default:
|
|
IP_PANIC();
|
|
goto cleanup;
|
|
}
|
|
|
|
len = (Ip_u32)(ipcom_buffer_len(pkt) - sig_blob_len_pos);
|
|
IP_SET_32ON8(ipcom_buffer_ptr2pos(pkt, sig_blob_len_pos), ip_htonl(len-4));
|
|
|
|
if (ipssh_send_pkt(ssh_conn, pkt, IP_FALSE) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_pubkey :: ipssh_send_pkt failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = IPCOM_SUCCESS;
|
|
|
|
cleanup:
|
|
if (dsa_sig)
|
|
DSA_SIG_free(dsa_sig);
|
|
if (dsa_sig_buf)
|
|
ipcom_free(dsa_sig_buf);
|
|
|
|
ipcom_free(sig_buf);
|
|
ipcom_free(pkt);
|
|
(void)EVP_MD_CTX_cleanup(&md_ctx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_send_userauth_req_hostbased
|
|
*===========================================================================
|
|
* Description: Send the hostbased authentication request msg.
|
|
* Parameters:ssh_conn - ssh connection pointer
|
|
* Returns:IPCOM_SUCCESS for send ok
|
|
* <0 for failure
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err
|
|
ipssh_send_userauth_req_hostbased(Ipssh_conn* ssh_conn)
|
|
{
|
|
/* byte SSH_MSG_USERAUTH_REQUEST
|
|
* string user name
|
|
* string service name
|
|
* string "hostbased"
|
|
* string public key algorithm for host key
|
|
* string public host key and certificates for client host
|
|
* string client host name expressed as the FQDN in US-ASCII
|
|
* string user name on the client host in ISO-10646 UTF-8 encoding
|
|
[RFC3629]
|
|
* string signature
|
|
*/
|
|
|
|
Ip_size_t sig_blob_len_pos;
|
|
unsigned int sig_len;
|
|
Ip_u32 len;
|
|
Ip_size_t buf_size;
|
|
Ipcom_buffer* sig_buf = IP_NULL;
|
|
Ipcom_buffer* pkt = IP_NULL;
|
|
EVP_MD_CTX md_ctx;
|
|
Ip_err rc = IPCOM_ERR_FAILED;
|
|
char* key_type_str;
|
|
int sig_len_pos = 0;
|
|
char hostname[IPSSH_FQDN_MAXLEN];
|
|
char *domain = IP_NULL;
|
|
char* dsa_sig_buf = IP_NULL;
|
|
char* tmp_dsa_sig_buf;
|
|
DSA_SIG* dsa_sig = IP_NULL;
|
|
|
|
ipcom_memset(&md_ctx, 0, sizeof(md_ctx));
|
|
ipcom_memset(hostname, 0, IPSSH_FQDN_MAXLEN);
|
|
|
|
buf_size = 512 + EVP_PKEY_bits(ssh_conn->data.clt.host_key)/2;
|
|
pkt = ipssh_buffer_new_v2_pkt(buf_size, IPSSH_MSG_USERAUTH_REQUEST);
|
|
sig_buf = ipcom_buffer_new(buf_size);
|
|
if (!sig_buf || !pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: out of memory");
|
|
goto cleanup;
|
|
}
|
|
|
|
switch (ssh_conn->data.clt.host_key->type)
|
|
{
|
|
case NID_dsa:
|
|
key_type_str = IPSSH_DSA_STR;
|
|
break;
|
|
case NID_rsaEncryption:
|
|
key_type_str = IPSSH_RSA_STR;
|
|
break;
|
|
|
|
default:
|
|
IP_PANIC();
|
|
key_type_str = "Unknown key type";
|
|
}
|
|
|
|
/* Get domain name */
|
|
domain = ipcom_sysvar_get("ipdnsc.domainname", IP_NULL, IP_NULL);
|
|
if (IP_NULL == domain)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: get domain name failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get local hostname first */
|
|
if (ipcom_gethostname(hostname, sizeof(hostname)) != 0)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: get hostname failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* We must consider the "." between domain name and host name and also the "." in the end */
|
|
if (ipcom_strlen (domain) + ipcom_strlen (hostname) > IPSSH_FQDN_MAXLEN - 2)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: fqdn hostname too long");
|
|
goto cleanup;
|
|
}
|
|
|
|
ipcom_strcat(hostname, ".");
|
|
ipcom_strcat(hostname, domain);
|
|
/* The fqdn is ended by a "." */
|
|
ipcom_strcat(hostname, ".");
|
|
|
|
/* Create first part of message */
|
|
if (ipssh_buffer_put_sshstr(pkt, ssh_conn->data.clt.userid)
|
|
|| ipssh_buffer_put_sshstr(pkt, IPSSH_CONNECTION_STR)
|
|
|| ipssh_buffer_put_sshstr(pkt, IPSSH_HOSTBASED_AUTH_STR)
|
|
|| ipssh_buffer_put_sshstr(pkt, key_type_str)
|
|
|| ipssh_buffer_put_pub_key(pkt, ssh_conn->data.clt.host_key)
|
|
|| ipssh_buffer_put_sshstr(pkt, hostname)
|
|
|| ipssh_buffer_put_sshstr(pkt, ssh_conn->data.clt.userid))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: failed to assemble USERAUTH_REQ for hostbased");
|
|
goto cleanup;
|
|
}
|
|
|
|
sig_blob_len_pos = ipcom_buffer_len(pkt);
|
|
if (ipcom_buffer_decr_cap(pkt, 4) || ipssh_buffer_put_sshstr(pkt, key_type_str))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: failed to assemble USERAUTH_REQ for hostbased");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Create signature */
|
|
if (ipssh_buffer_put_sshbuf(sig_buf, ssh_conn->sess_id, (Ip_size_t)ssh_conn->sess_id_len)
|
|
|| ipcom_buffer_put_char(sig_buf, IPSSH_MSG_USERAUTH_REQUEST)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, ssh_conn->data.clt.userid)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, IPSSH_CONNECTION_STR)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, IPSSH_HOSTBASED_AUTH_STR)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, key_type_str)
|
|
|| ipssh_buffer_put_pub_key(sig_buf, ssh_conn->data.clt.host_key)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, hostname)
|
|
|| ipssh_buffer_put_sshstr(sig_buf, ssh_conn->data.clt.userid))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: failed to assemble sig data");
|
|
goto cleanup;
|
|
}
|
|
|
|
sig_len_pos = ipcom_buffer_len(pkt);
|
|
if (ipcom_buffer_decr_cap(pkt, 4))
|
|
goto cleanup;
|
|
|
|
switch (ssh_conn->data.clt.host_key->type)
|
|
{
|
|
case NID_dsa:
|
|
dsa_sig_buf = ipcom_malloc(EVP_PKEY_size(ssh_conn->data.clt.host_key));
|
|
if (!dsa_sig_buf)
|
|
goto cleanup;
|
|
tmp_dsa_sig_buf = dsa_sig_buf;
|
|
|
|
if (!EVP_SignInit(&md_ctx, EVP_dss1())
|
|
|| !EVP_SignUpdate(&md_ctx, ipcom_buffer_start_ptr(sig_buf), ipcom_buffer_len(sig_buf))
|
|
|| !EVP_SignFinal(&md_ctx, dsa_sig_buf, &sig_len, ssh_conn->data.clt.host_key))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: DSA sign operation failed");
|
|
goto cleanup;
|
|
}
|
|
ip_assert(sig_len <= EVP_PKEY_size(ssh_conn->data.clt.host_key));
|
|
dsa_sig = d2i_DSA_SIG(IP_NULL, &tmp_dsa_sig_buf, sig_len);
|
|
if (!dsa_sig)
|
|
goto cleanup;
|
|
if (ipssh_buffer_put_dsa_sig(pkt, dsa_sig))
|
|
goto cleanup;
|
|
IP_SET_32ON8(ipcom_buffer_ptr2pos(pkt, sig_len_pos), ip_htonl(ipcom_buffer_len(pkt)-sig_len_pos-4));
|
|
|
|
break;
|
|
case NID_rsaEncryption:
|
|
if (!EVP_SignInit(&md_ctx, EVP_sha1())
|
|
|| !EVP_SignUpdate(&md_ctx, ipcom_buffer_start_ptr(sig_buf), ipcom_buffer_len(sig_buf))
|
|
|| !EVP_SignFinal(&md_ctx, ipcom_buffer_end_ptr(pkt), &sig_len, ssh_conn->data.clt.host_key))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: RSA sign operation failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
IP_SET_32ON8(ipcom_buffer_ptr2pos(pkt, (Ip_size_t)sig_len_pos), ip_htonl(sig_len));
|
|
|
|
if (ipcom_buffer_decr_cap(pkt, (Ip_size_t)sig_len))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: failed to assemble USERAUTH_REQ for pubkey");
|
|
goto cleanup;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
IP_PANIC();
|
|
goto cleanup;
|
|
}
|
|
|
|
len = (Ip_u32)(ipcom_buffer_len(pkt) - sig_blob_len_pos);
|
|
IP_SET_32ON8(ipcom_buffer_ptr2pos(pkt, sig_blob_len_pos), ip_htonl(len-4));
|
|
|
|
if (ipssh_send_pkt(ssh_conn, pkt, IP_FALSE) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_hostbased :: ipssh_send_pkt failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = IPCOM_SUCCESS;
|
|
|
|
cleanup:
|
|
if (domain)
|
|
{
|
|
ipcom_free(domain);
|
|
}
|
|
if (sig_buf)
|
|
{
|
|
ipcom_free(sig_buf);
|
|
}
|
|
if (pkt)
|
|
{
|
|
ipcom_free(pkt);
|
|
}
|
|
if (dsa_sig_buf)
|
|
ipcom_free(dsa_sig_buf);
|
|
if (dsa_sig)
|
|
DSA_SIG_free(dsa_sig);
|
|
|
|
(void)EVP_MD_CTX_cleanup(&md_ctx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_send_msg_userauth_pk_ok
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_send_msg_userauth_pk_ok(Ipssh_conn* ssh_conn, char* alg_name, Ip_u8* pub_key, Ip_size_t pub_key_len)
|
|
{
|
|
Ipcom_buffer* pkt;
|
|
IPCOM_LOG0(DEBUG, "ipssh_send_msg_userauth_pk_ok :: ");
|
|
|
|
pkt = ipssh_buffer_new_v2_pkt(128 + pub_key_len, IPSSH_MSG_USERAUTH_PK_OK);
|
|
if (!pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_pk_ok :: out of memory");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
(void)ipssh_buffer_put_sshstr(pkt, alg_name);
|
|
(void)ipssh_buffer_put_sshbuf(pkt, pub_key, pub_key_len);
|
|
|
|
if (ipssh_send_pkt(ssh_conn, pkt, IP_TRUE))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_pk_ok :: ipssh_send_pkt() failed");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_send_userauth_failure_msg
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_send_userauth_failure_msg(Ipssh_conn* ssh_conn, char* supported_meths, Ip_u8 success)
|
|
{
|
|
Ipcom_buffer* pkt;
|
|
|
|
IPCOM_LOG1(DEBUG, "ipssh_send_userauth_failure_msg :: success: %d", success);
|
|
|
|
pkt = ipssh_buffer_new_v2_pkt(128 + ipcom_strlen(supported_meths), IPSSH_MSG_USERAUTH_FAILURE);
|
|
if (!pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_failure_msg :: out of memory");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
(void)ipssh_buffer_put_sshstr(pkt, supported_meths);
|
|
(void)ipcom_buffer_put_char(pkt, success);
|
|
|
|
if (ipssh_send_pkt(ssh_conn, pkt, IP_TRUE))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_failure_msg :: ipssh_send_pkt() failed");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_send_userauth_success_msg
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_send_userauth_success_msg(Ipssh_conn* ssh_conn)
|
|
{
|
|
Ipcom_buffer* pkt;
|
|
|
|
IPCOM_LOG0(DEBUG, "ipssh_send_userauth_success_msg :: ");
|
|
|
|
pkt = ipssh_buffer_new_v2_pkt(128, IPSSH_MSG_USERAUTH_SUCCESS);
|
|
if (!pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_success_msg :: out of memory");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
if (ipssh_send_pkt(ssh_conn, pkt, IP_TRUE))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_success_msg :: ipssh_send_pkt() failed");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_msg_userauth_failure
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_msg_userauth_failure(Ipssh_conn* ssh_conn)
|
|
{
|
|
Ipcom_buffer* pkt = IP_NULL;
|
|
char* auth_methods;
|
|
char* auth_meth;
|
|
char* last;
|
|
Ip_u8 success;
|
|
Ip_err rc = IPCOM_ERR_FAILED;
|
|
Ip_bool pw_auth = IP_FALSE;
|
|
Ip_bool pubkey_auth = IP_FALSE;
|
|
Ip_bool hostbsd_auth = IP_FALSE;
|
|
EVP_MD_CTX md_ctx;
|
|
|
|
ipcom_memset(&md_ctx, 0, sizeof(md_ctx));
|
|
|
|
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
|
|
if ((auth_methods = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf)) == IP_NULL
|
|
|| ipcom_buffer_get_char(ssh_conn->recv_plain_buf, &success) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_failure :: failed to unpack msg");
|
|
goto cleanup;
|
|
}
|
|
|
|
IPCOM_LOG2(DEBUG, "ipssh_msg_userauth_failure :: methods: %s, success: %d", auth_methods, success);
|
|
|
|
for(auth_meth = ipcom_strtok_r(auth_methods, ",", &last);
|
|
auth_meth;
|
|
auth_meth = ipcom_strtok_r(IP_NULL, ",", &last))
|
|
{
|
|
if (ipcom_strcmp(auth_meth, IPSSH_PW_AUTH_STR) == 0)
|
|
pw_auth = IP_TRUE;
|
|
else if (ipcom_strcmp(auth_meth, IPSSH_PUBKEY_AUTH_STR) == 0)
|
|
pubkey_auth = IP_TRUE;
|
|
else if (ipcom_strcmp(auth_meth, IPSSH_HOSTBASED_AUTH_STR) == 0)
|
|
hostbsd_auth = IP_TRUE;
|
|
else
|
|
{
|
|
IPCOM_LOG1(DEBUG2, "ipssh_msg_userauth_failure :: unknown auth method: %s", auth_meth);
|
|
}
|
|
}
|
|
if (!pw_auth && !pubkey_auth && !hostbsd_auth)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_failure :: no supported auth methods offered by server");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (pubkey_auth /* Does server allow pubkey auth? */
|
|
&& ssh_conn->data.clt.key /* Do we have a pubkey? */
|
|
&& !(ssh_conn->data.clt.auth_flags & IPSSH_AUTH_METH_PUBLIC_KEY)) /* Have we tried pubkey auth already? */
|
|
{
|
|
if (ipssh_send_userauth_req_pubkey(ssh_conn) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_failure :: ipssh_send_userauth_req_pubkey() failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
ssh_conn->data.clt.auth_flags |= IPSSH_AUTH_METH_PUBLIC_KEY;
|
|
}
|
|
else if (pw_auth /* Does server accept password authentication?*/
|
|
&& ssh_conn->data.clt.userid[0] && ssh_conn->data.clt.pw[0] /* Do we have pw auth data? */
|
|
&& !(ssh_conn->data.clt.auth_flags & IPSSH_AUTH_METH_PW)) /* Have we tried pw auth already? */
|
|
{
|
|
pkt = ipssh_buffer_new_v2_pkt(128, IPSSH_MSG_USERAUTH_REQUEST);
|
|
if (!pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_failure :: no supported auth methods offered by server");
|
|
goto cleanup;
|
|
}
|
|
if (ipssh_buffer_put_sshstr(pkt, ssh_conn->data.clt.userid) != IPCOM_SUCCESS
|
|
|| ipssh_buffer_put_sshstr(pkt, IPSSH_CONNECTION_STR) != IPCOM_SUCCESS
|
|
|| ipssh_buffer_put_sshstr(pkt, IPSSH_PW_AUTH_STR) != IPCOM_SUCCESS
|
|
|| ipcom_buffer_put_char(pkt, 0) != IPCOM_SUCCESS
|
|
|| ipssh_buffer_put_sshstr(pkt, ssh_conn->data.clt.pw) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_failure :: failed to create USERAUTH_REQUEST msg (pw)");
|
|
goto cleanup;
|
|
}
|
|
ssh_conn->data.clt.auth_flags |= IPSSH_AUTH_METH_PW;
|
|
if (ipssh_send_pkt(ssh_conn, pkt, IP_FALSE) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_failure :: ipssh_send_pkt failed");
|
|
}
|
|
}
|
|
else if (hostbsd_auth /* Does server allow hostbased auth? */
|
|
&& ssh_conn->data.clt.host_key/* Do we have a hostbased pubkey? */
|
|
&& !(ssh_conn->data.clt.auth_flags & IPSSH_AUTH_METH_HOSTBASED)) /* Have we tried hostbased auth already? */
|
|
{
|
|
if (ipssh_send_userauth_req_hostbased(ssh_conn) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_failure :: ipssh_send_userauth_req_hostbased() failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
ssh_conn->data.clt.auth_flags |= IPSSH_AUTH_METH_HOSTBASED;
|
|
}
|
|
else
|
|
{
|
|
/* No auth method available, or all available methods failed */
|
|
rc = IPCOM_ERR_AUTH_FAILED;
|
|
goto cleanup;
|
|
}
|
|
rc = IPCOM_SUCCESS;
|
|
|
|
cleanup:
|
|
EVP_MD_CTX_cleanup(&md_ctx);
|
|
if (auth_methods)
|
|
ipcom_free(auth_methods);
|
|
if (pkt)
|
|
ipcom_buffer_free(pkt);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_msg_userauth_success
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_msg_userauth_success(Ipssh_conn* ssh_conn)
|
|
{
|
|
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
|
|
|
|
ssh_conn->conn_state = IPSSH_CONN_STATE_CLT_CONNECTED;
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_msg_userauth_req
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_msg_userauth_req(Ipssh_conn* ssh_conn)
|
|
{
|
|
Ip_s32 rc = IPCOM_SUCCESS;
|
|
char* user, *service, *auth_meth;
|
|
int auth_ret = IPSSH_AUTH_FAILED;
|
|
char auth_methods[29]; /* max length: "publickey,password,hostbased" */
|
|
#if defined(IP_PORT_VXWORKS) && defined(LOGINEVENT_CHECK_AUTH_STAT)
|
|
int event_err;
|
|
int auth_result = 0;
|
|
#endif
|
|
|
|
ipcom_memset(auth_methods, 0, sizeof(auth_methods));
|
|
|
|
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
|
|
user = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
|
|
service = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
|
|
auth_meth = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
|
|
|
|
if (!user || !service || !auth_meth)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: out of memory");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
IPCOM_LOG3(DEBUG, "ipssh_msg_userauth_req :: user: %s, service: %s, auth_meth: %s",
|
|
user, service, auth_meth);
|
|
|
|
if (!(ssh_conn->user))
|
|
{
|
|
ssh_conn->service = service;
|
|
service = IP_NULL;
|
|
ssh_conn->user = user;
|
|
user = IP_NULL;
|
|
}
|
|
else
|
|
{
|
|
if (ipcom_strcmp(ssh_conn->user, user) || ipcom_strcmp(ssh_conn->service, service))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: user or service changed, dropping connection");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if(!ssh_conn->auth_banner_sent)
|
|
ipssh_get_banner_config(&ssh_conn->config);
|
|
|
|
#ifdef IPSSH_SUPPORT_LONG_BANNER
|
|
if (!ssh_conn->auth_banner_sent && ssh_conn->config.auth_banner)
|
|
#else
|
|
if (!ssh_conn->auth_banner_sent && ssh_conn->config.auth_banner[0])
|
|
#endif
|
|
{
|
|
ssh_conn->auth_banner_sent = IP_TRUE;
|
|
if (ipssh_send_userauth_banner_msg(ssh_conn, ssh_conn->config.auth_banner) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_send_userauth_banner_msg failed");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
if (ipssh_send_userauth_banner_msg(ssh_conn, "\r\n") != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_send_userauth_banner_msg failed");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if (ipcom_strcmp(auth_meth, IPSSH_NONE_STR) == 0)
|
|
{
|
|
if (ssh_conn->config.auth_none_allowed != 0)
|
|
auth_ret = IPSSH_AUTH_OK;
|
|
}
|
|
else if (ipcom_strcmp(auth_meth, IPSSH_PW_AUTH_STR) == 0)
|
|
{
|
|
if (!ssh_conn->config.pw_allowed)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: password auth not turned on");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
auth_ret = ipssh_handle_password_auth(ssh_conn, ssh_conn->user);
|
|
|
|
#ifdef IP_PORT_VXWORKS
|
|
#ifdef LOGINEVENT_CHECK_AUTH_STAT
|
|
if (auth_ret == IPSSH_AUTH_FAILED)
|
|
auth_result = SEC_EVENT_AUTH_FAILED;
|
|
else
|
|
auth_result = SEC_EVENT_AUTH_SUCCESS;
|
|
|
|
if (_func_loginEvent != IP_NULL)
|
|
event_err = _func_loginEvent(SEC_EVENT_SSH_LOGIN, ssh_conn->user, ssh_conn->sock, SEC_EVENT_AUTH_PASSWD, auth_result);
|
|
if (event_err != 0)
|
|
auth_ret = IPSSH_AUTH_FAILED;
|
|
#else
|
|
if (auth_ret != IPSSH_AUTH_FAILED)
|
|
{
|
|
if (_func_loginEvent != IP_NULL)
|
|
_func_loginEvent(SEC_EVENT_SSH_LOGIN, ssh_conn->user, ssh_conn->sock, SEC_EVENT_AUTH_PASSWD);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
if (auth_ret == IPSSH_AUTH_FAILED)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_handle_password_auth() failed");
|
|
}
|
|
}
|
|
else if (ipcom_strcmp(auth_meth, IPSSH_PUBKEY_AUTH_STR) == 0)
|
|
{
|
|
if (!ssh_conn->config.pub_key_allowed)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: publickey auth not turned on");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
auth_ret = ipssh_handle_publickey_auth(ssh_conn, ssh_conn->user);
|
|
#ifdef IP_PORT_VXWORKS
|
|
#ifdef LOGINEVENT_CHECK_AUTH_STAT
|
|
if (auth_ret == IPSSH_AUTH_FAILED)
|
|
auth_result = SEC_EVENT_AUTH_FAILED;
|
|
else
|
|
auth_result = SEC_EVENT_AUTH_SUCCESS;
|
|
|
|
if (_func_loginEvent != IP_NULL)
|
|
event_err = _func_loginEvent(SEC_EVENT_SSH_LOGIN, ssh_conn->user, ssh_conn->sock, SEC_EVENT_AUTH_PUBKEY, auth_result);
|
|
if (event_err != 0)
|
|
auth_ret = IPSSH_AUTH_FAILED;
|
|
#else
|
|
if (auth_ret != IPSSH_AUTH_FAILED)
|
|
{
|
|
if (_func_loginEvent != IP_NULL)
|
|
_func_loginEvent(SEC_EVENT_SSH_LOGIN, ssh_conn->user, ssh_conn->sock, SEC_EVENT_AUTH_PUBKEY);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
if (auth_ret == IPSSH_AUTH_FAILED)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_handle_publickey_auth() failed");
|
|
}
|
|
}
|
|
else if (ipcom_strcmp(auth_meth, IPSSH_HOSTBASED_AUTH_STR) == 0)
|
|
{
|
|
if (!ssh_conn->config.hostbased_allowed)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: hostbased auth not turned on");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
auth_ret = ipssh_handle_hostbased_auth(ssh_conn, ssh_conn->user);
|
|
#ifdef IP_PORT_VXWORKS
|
|
#ifdef LOGINEVENT_CHECK_AUTH_STAT
|
|
if (auth_ret == IPSSH_AUTH_FAILED)
|
|
auth_result = SEC_EVENT_AUTH_FAILED;
|
|
else
|
|
auth_result = SEC_EVENT_AUTH_SUCCESS;
|
|
|
|
if (_func_loginEvent != IP_NULL)
|
|
event_err = _func_loginEvent(SEC_EVENT_SSH_LOGIN, ssh_conn->user, ssh_conn->sock, SEC_EVENT_AUTH_HOSTBASED, auth_result);
|
|
if (event_err != 0)
|
|
auth_ret = IPSSH_AUTH_FAILED;
|
|
#else
|
|
if (auth_ret != IPSSH_AUTH_FAILED)
|
|
{
|
|
if (_func_loginEvent != IP_NULL)
|
|
_func_loginEvent(SEC_EVENT_SSH_LOGIN, ssh_conn->user, ssh_conn->sock, SEC_EVENT_AUTH_HOSTBASED);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
if (auth_ret == IPSSH_AUTH_FAILED)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_handle_hostbased_auth() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG1(ERR, "ipssh_msg_userauth_req :: unknown authentication method requested: %s", auth_meth);
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
switch(auth_ret)
|
|
{
|
|
case IPSSH_AUTH_FAILED:
|
|
if (ssh_conn->config.max_fail != 0 && ssh_conn->auth_failure_count >= ssh_conn->config.max_fail)
|
|
{
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
/* Deliberate pass-through to next case */
|
|
case IPSSH_AUTH_OK:
|
|
if (ipssh_more_auth_needed(ssh_conn) == IP_TRUE)
|
|
{
|
|
ipssh_get_auth_methods(ssh_conn, auth_methods, sizeof(auth_methods));
|
|
if (ipssh_send_userauth_failure_msg(ssh_conn, auth_methods, (Ip_u8)auth_ret) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_send_userauth_failure_msg() failed");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Send success message and update the connection state, authentication is complete */
|
|
if (ipssh_send_userauth_success_msg(ssh_conn))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_send_userauth_success_msg() failed");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
(void)ipcom_shell_ctx_add_user(ssh_conn->sh_ctx, ssh_conn->user);
|
|
if (ipssh_auth_complete_cb(ssh_conn->user, ssh_conn->sh_ctx) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_msg_userauth_req :: ipssh_auth_complete_cb() failed");
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
ssh_conn->conn_state = IPSSH_CONN_STATE_SRV_TERM;
|
|
}
|
|
|
|
break;
|
|
case IPSSH_AUTH_PUBKEY_OK:
|
|
break;
|
|
case IPCOM_ERR_FAILED:
|
|
case IPSSH_AUTH_FATAL:
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
default:
|
|
IP_PANIC();
|
|
rc = IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
cleanup:
|
|
if (user)
|
|
ipcom_free(user);
|
|
if (service)
|
|
ipcom_free(service);
|
|
if (auth_meth)
|
|
ipcom_free(auth_meth);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_send_userauth_req_none
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_send_userauth_req_none(Ipssh_conn* ssh_conn, const char* user)
|
|
{
|
|
Ipcom_buffer* pkt;
|
|
|
|
IPCOM_LOG0(DEBUG, "ipssh_send_userauth_req_none :: ");
|
|
|
|
pkt = ipssh_buffer_new_v2_pkt(64+ipcom_strlen(user), IPSSH_MSG_USERAUTH_REQUEST);
|
|
if (!pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_none :: out of memory");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
(void)ipssh_buffer_put_sshstr(pkt, user);
|
|
(void)ipssh_buffer_put_sshstr(pkt, IPSSH_CONNECTION_STR);
|
|
(void)ipssh_buffer_put_sshstr(pkt, IPSSH_NONE_STR);
|
|
|
|
if (ipssh_send_pkt(ssh_conn, pkt, IP_TRUE))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_req_none :: ipssh_send_pkt() failed");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
ssh_conn->conn_state = IPSSH_CONN_STATE_CLT_USER_AUTH;
|
|
|
|
return IPCOM_SUCCESS;
|
|
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_do_user_auth_clt
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_do_user_auth_clt(Ipssh_conn* ssh_conn)
|
|
{
|
|
Ip_err rc;
|
|
while(ssh_conn->conn_state != IPSSH_CONN_STATE_CLT_CONNECTED)
|
|
{
|
|
switch(ssh_conn->conn_state)
|
|
{
|
|
case IPSSH_CONN_STATE_SERVICE_REQ:
|
|
rc = ipssh_send_service_request(ssh_conn, IPSSH_USERAUTH_STR);
|
|
if (rc != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_do_user_auth_clt :: ipssh_send_service_request");
|
|
return rc;
|
|
}
|
|
|
|
break;
|
|
case IPSSH_CONN_STATE_CLT_USER_AUTH:
|
|
case IPSSH_CONN_STATE_SERVICE_ACCEPT:
|
|
rc = ipssh_read_v2_pkt(ssh_conn);
|
|
if (rc != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_do_user_auth_clt :: ipssh_read_v2_pkt_type failed");
|
|
return rc;
|
|
}
|
|
rc = ipssh_pkt_dispatch(ssh_conn);
|
|
if (rc != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_do_user_auth_clt :: ipssh_pkt_dispatch failed");
|
|
return rc;
|
|
}
|
|
break;
|
|
|
|
case IPSSH_CONN_STATE_CLT_USER_AUTH_START:
|
|
rc = ipssh_send_userauth_req_none(ssh_conn, ssh_conn->data.clt.userid);
|
|
if (rc != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_do_user_auth_clt :: ipssh_send_userauth_req failed");
|
|
return rc;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_msg_userauth_banner
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_msg_userauth_banner(Ipssh_conn* ssh_conn)
|
|
{
|
|
char* msg;
|
|
char* lang_tag;
|
|
|
|
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
|
|
|
|
msg = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
|
|
lang_tag = ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
|
|
|
|
if(msg)
|
|
{
|
|
IPCOM_LOG1(DEBUG, "USERAUTH banner: msg %s", msg);
|
|
}
|
|
|
|
if(msg)
|
|
ipcom_free(msg);
|
|
if(lang_tag)
|
|
ipcom_free(lang_tag);
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_send_userauth_banner_msg
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipssh_send_userauth_banner_msg(Ipssh_conn* ssh_conn, const char* auth_banner)
|
|
{
|
|
Ipcom_buffer* pkt;
|
|
|
|
IPCOM_LOG0(DEBUG, "ipssh_send_userauth_banner_msg :: ");
|
|
|
|
pkt = ipssh_buffer_new_v2_pkt(64+ipcom_strlen(auth_banner), IPSSH_MSG_USERAUTH_BANNER);
|
|
if (!pkt)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipssh_send_userauth_banner_msg :: out of memory");
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
(void)ipssh_buffer_put_sshstr(pkt, auth_banner);
|
|
(void)ipssh_buffer_put_sshstr(pkt, ""); /* Language tag, not used */
|
|
|
|
return ipssh_send_pkt(ssh_conn, pkt, IP_TRUE);
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|