original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,80 @@
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_auth.h,v $ $Revision: 1.9 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_auth.h,v $
* $Author: roger $ $Date: 2006-06-21 13:39:51 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef ipssh_auth_h
#define ipssh_auth_h
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_cstyle.h>
#include "ipssh_h.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipssh_sock_handler ipssh_user_auth_get_handler(Ip_s32 pkt_type);
IP_GLOBAL Ip_err ipssh_msg_userauth_req(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_userauth_failure(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_userauth_success(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_do_user_auth_clt(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_userauth_banner(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_userauth_req_none(Ipssh_conn* ssh_conn, const char* user);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,354 @@
/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_auth_v1.c,v $ $Revision: 1.38.10.2 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_auth_v1.c,v $
* $Author: svc-cmnet $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include <ipssh_config.h>
#ifdef IPSSH_USE_V1
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipssh_h.h"
#include "ipssh_buffer.h"
#include "ipssh_auth.h"
#include "ipssh_transport_v1.h"
#include <ipcom_clib.h>
#include <ipcom_config.h>
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_shell.h>
#include <openssl/rsa.h>
#include <openssl/md5.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_v1_msg_auth_rsa_response(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_auth_rsa(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_user(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_auth_pw(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_v1_msg_auth_rsa_response
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_v1_msg_auth_rsa_response(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt)
{
Ip_u8 response[16];
Ip_u8 expected_response[16];
if (ipcom_buffer_get(pkt, response, 16) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_v1_msg_auth_rsa_response :: failed to unpack message");
return IPCOM_ERR_FAILED;
}
/* Verify response */
{
MD5_CTX md;
if (!MD5_Init(&md) ||
!MD5_Update(&md, ssh_conn->rsa_challenge, 32) ||
!MD5_Update(&md, ssh_conn->session_id_v1, 16) ||
!MD5_Final(expected_response, &md))
{
(void) ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_FAILURE);
return IPCOM_ERR_FAILED;
}
}
if (ipcom_memcmp(response, expected_response, 16) == 0)
{
ssh_conn->conn_state = IPSSH_CONN_STATE_SRV_PENDING_REQUEST;
(void)ipcom_shell_ctx_add_user(ssh_conn->sh_ctx, ssh_conn->user);
if (ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_SUCCESS))
return IPCOM_ERR_FAILED;
}
else
{
if (ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_FAILURE))
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_v1_msg_auth_rsa
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_v1_msg_auth_rsa(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt)
{
BIGNUM* pub_key_mod;
Ip_err rc = IPCOM_SUCCESS;
Ip_u8* enc_ch = IP_NULL;
Ipcom_buffer* out_pkt;
int pos, len;
pub_key_mod = ipssh_buffer_get_v1_bn(pkt);
if (!pub_key_mod)
{
IPCOM_LOG0(ERR, "ipssh_v1_msg_user :: failed to unpack message");
return IPCOM_ERR_FAILED;
}
if (!ssh_conn->config.pub_key_allowed)
{
IPCOM_LOG0(ERR, "ipssh_v1_msg_auth_rsa :: public key authentication not turned on");
rc = ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_FAILURE);
goto cleanup;
}
ssh_conn->client_pub_key = ipssh_validate_rsa_pubkey_v1_cb(ssh_conn->user, pub_key_mod, ssh_conn->sh_ctx);
if (!ssh_conn->client_pub_key)
{
if (ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_FAILURE) != IPCOM_SUCCESS)
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
ssh_conn->auth_meth = IPSSH_AUTH_METH_PUBLIC_KEY;
/* Generate challenge */
for(pos=0; pos<(int)sizeof(ssh_conn->rsa_challenge); pos+=4)
{
Ip_u32 tmp;
tmp = ipcom_random();
ipcom_memcpy(&(ssh_conn->rsa_challenge[pos]), &tmp, 4);
}
/* Encrypt challenge */
enc_ch = ipcom_malloc(BN_num_bytes(ssh_conn->client_pub_key->n));
if (!enc_ch)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
len = RSA_public_encrypt(32, ssh_conn->rsa_challenge, enc_ch, ssh_conn->client_pub_key, RSA_PKCS1_PADDING);
if (len < 0)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
/* Send MSG_AUTH_RSA_CHALLENGE */
out_pkt = ipssh_buffer_new_v1_pkt(BN_num_bytes(ssh_conn->client_pub_key->n)+64, IPSSH_SMSG_V1_AUTH_RSA_CHALLENGE);
if (!out_pkt)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
if (ipssh_buffer_put_bn2_v1(out_pkt, enc_ch, (Ip_u16)BN_num_bits(ssh_conn->client_pub_key->n)))
{
rc = IPCOM_ERR_FAILED;
ipcom_buffer_free(out_pkt);
goto cleanup;
}
if (ipssh_send_v1_pkt(ssh_conn, out_pkt) != IPCOM_SUCCESS)
rc = IPCOM_ERR_FAILED;
cleanup:
if (pub_key_mod)
BN_free(pub_key_mod);
if (enc_ch)
ipcom_free(enc_ch);
return rc;
}
/*
*===========================================================================
* ipssh_v1_msg_user
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_v1_msg_user(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt)
{
char* user;
/* Unpack message */
if ( !(user=ipssh_buffer_get_sshstr(pkt)) )
{
IPCOM_LOG0(ERR, "ipssh_v1_msg_user :: failed to unpack message");
return IPCOM_ERR_FAILED;
}
IPCOM_LOG1(DEBUG, "ipssh_v1_msg_user :: user=%s", user);
ssh_conn->user = user;
if (ssh_conn->config.auth_none_allowed)
{
ssh_conn->conn_state = IPSSH_CONN_STATE_SRV_PENDING_REQUEST;
if (ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_SUCCESS) != IPCOM_SUCCESS)
return IPCOM_ERR_FAILED;
}
else
{
/* Request authentication */
if (ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_FAILURE) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_v1_msg_user :: failed to send failure message");
return IPCOM_ERR_FAILED;
}
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_v1_msg_auth_pw
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_v1_msg_auth_pw(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt)
{
char* pw;
Ip_err rc = IPCOM_SUCCESS;
Ip_err auth_result;
/* Unpack message */
if ( !(pw=ipssh_buffer_get_sshstr(pkt)) )
{
IPCOM_LOG0(ERR, "ipssh_v1_msg_auth_pw :: failed to unpack message");
return IPCOM_ERR_FAILED;
}
IPCOM_LOG1(DEBUG, "ipssh_v1_msg_auth_pw :: pw=%s", pw);
if (!ssh_conn->config.pw_allowed)
{
IPCOM_LOG0(ERR, "ipssh_v1_msg_auth_pw :: password authentication not turned on");
rc = ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_FAILURE);
goto cleanup;
}
auth_result = ipssh_validate_userid_pw_cb(ssh_conn->user, pw, ssh_conn->sh_ctx);
switch(auth_result)
{
case IPCOM_SUCCESS:
(void)ipcom_shell_ctx_add_user(ssh_conn->sh_ctx, ssh_conn->user);
if (ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_SUCCESS) != IPCOM_SUCCESS)
rc = IPCOM_ERR_FAILED;
ssh_conn->conn_state = IPSSH_CONN_STATE_SRV_PENDING_REQUEST;
ssh_conn->auth_meth = IPSSH_AUTH_METH_PW;
break;
case IPCOM_ERR_AUTH_FAILED:
default:
if (ipssh_send_msg_v1_no_body(ssh_conn, IPSSH_SMSG_V1_FAILURE) != IPCOM_SUCCESS)
rc = IPCOM_ERR_FAILED;
ssh_conn->auth_failure_count++;
if (ssh_conn->auth_failure_count >= ssh_conn->config.max_fail)
rc = IPCOM_ERR_FAILED;
break;
}
cleanup:
if (pw)
ipcom_free(pw);
return rc;
}
#else
int ipssh_auth_v1_empty_file;
#endif /* IPSSH_USE_V1 */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,69 @@
/*
******************************************************************************
* INTERPEAK HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_auth_v1.h,v $ $Revision: 1.4 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_auth_v1.h,v $
* $Author: roger $ $Date: 2006-06-21 13:39:51 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef IPSSH_AUTH_V1_H
#define IPSSH_AUTH_V1_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_v1_msg_user(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_auth_pw(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_auth_rsa(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_auth_rsa_response(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,88 @@
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ipssh_h.h"
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
IP_GLOBAL char *
ipssh_key_fingerprint_bubblebabble(Ip_u8* dgst_raw, unsigned int dgst_raw_len)
{
char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
unsigned int i, j = 0, rounds, seed = 1;
char *retval;
rounds = (dgst_raw_len / 2) + 1;
retval = ipcom_malloc(sizeof(char) * (rounds*6));
if (retval == IP_NULL)
return IP_NULL;
retval[j++] = 'x';
for (i = 0; i < rounds; i++) {
unsigned int idx0, idx1, idx2, idx3, idx4;
if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
idx0 = (((((unsigned int)(dgst_raw[2 * i])) >> 6) & 3) +
seed) % 6;
idx1 = (((unsigned int)(dgst_raw[2 * i])) >> 2) & 15;
idx2 = ((((unsigned int)(dgst_raw[2 * i])) & 3) +
(seed / 6)) % 6;
retval[j++] = vowels[idx0];
retval[j++] = consonants[idx1];
retval[j++] = vowels[idx2];
if ((i + 1) < rounds) {
idx3 = (((unsigned int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
idx4 = (((unsigned int)(dgst_raw[(2 * i) + 1]))) & 15;
retval[j++] = consonants[idx3];
retval[j++] = '-';
retval[j++] = consonants[idx4];
seed = ((seed * 5) +
((((unsigned int)(dgst_raw[2 * i])) * 7) +
((unsigned int)(dgst_raw[(2 * i) + 1])))) % 36;
}
} else {
idx0 = seed % 6;
idx1 = 16;
idx2 = seed / 6;
retval[j++] = vowels[idx0];
retval[j++] = consonants[idx1];
retval[j++] = vowels[idx2];
}
}
retval[j++] = 'x';
retval[j] = '\0';
return retval;
}
@@ -0,0 +1,910 @@
/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_buffer.c,v $ $Revision: 1.53.10.5 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_buffer.c,v $
* $Author: jren $ $Date: 2016-10-31 08:49:42 $
* $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_buffer.h"
#include <ipcom_clib.h>
#include <ipcom_sock.h>
#include <ipcom_err.h>
#include <ipcom_buffer.h>
#include <ipcom_syslog.h>
/*
****************************************************************************
* 4 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 5 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 6 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_buffer_get_sshstr
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC char*
#if defined(IPCOM_USE_DMALLOC) && !defined(IPCOM_DMALLOC_C)
ipssh_buffer_get_sshstr_d(Ipcom_buffer* buf, const char *file, const char *function, Ip_u32 line)
#else
ipssh_buffer_get_sshstr(Ipcom_buffer* buf)
#endif
{
Ip_u32 len;
char* str;
if(ipssh_buffer_get_uint(buf, &len) != IPCOM_SUCCESS)
return IP_NULL;
if(len > ipcom_buffer_len(buf))
return IP_NULL;
#if defined(IPCOM_USE_DMALLOC) && !defined(IPCOM_DMALLOC_C)
str = ipcom_dmalloc(len+1, file, function, line);
#else
str = ipcom_malloc(len+1);
#endif
if(!str)
return IP_NULL;
if(ipcom_buffer_get(buf, (Ip_u8*)str, len) != IPCOM_SUCCESS)
{
ipcom_free(str);
return IP_NULL;
}
str[len] = 0;
return str;
}
/*
*===========================================================================
* ipssh_buffer_get_sshbuf
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_u8*
ipssh_buffer_get_sshbuf(Ipcom_buffer* buf, Ip_u32* len)
{
char* data;
if(ipssh_buffer_get_uint(buf, len) != IPCOM_SUCCESS)
return IP_NULL;
if(*len == 0)
return IP_NULL;
if(*len>ipcom_buffer_len(buf))
return IP_NULL;
data = ipcom_malloc(*len);
if(!data)
return IP_NULL;
if(ipcom_buffer_get(buf, (Ip_u8*)data, *len) != IPCOM_SUCCESS)
{
ipcom_free(data);
return IP_NULL;
}
return (Ip_u8*)data;
}
/*
*===========================================================================
* ipssh_buffer_put_sshstr
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_put_sshstr(Ipcom_buffer* buf, const char* str)
{
Ip_size_t len;
if(!str)
return ipcom_buffer_put_int(buf, 0);
len = ipcom_strlen(str);
if(ipcom_buffer_put_int(buf, ip_htonl(len)))
return IPCOM_ERR_FAILED;
return ipcom_buffer_put(buf, (Ip_u8*)str, len);
}
/*
*===========================================================================
* ipssh_buffer_put_sshbuf
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_put_sshbuf(Ipcom_buffer* buf, const Ip_u8* str, Ip_size_t len)
{
if ( ipcom_buffer_put_int(buf, ip_htonl(len)))
return IPCOM_ERR_FAILED;
return ipcom_buffer_put(buf, (Ip_u8*)str, len);
}
/*
*===========================================================================
* ipssh_buffer_put_bn
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_put_bn(Ipcom_buffer* buf, BIGNUM* bn)
{
int len;
Ip_u8* tmp_bn;
Ip_s32 rc;
len = BN_num_bytes(bn);
if (len == 0)
return IPCOM_ERR_FAILED;
if(!(tmp_bn = ipcom_malloc(len+1)))
return IPCOM_ERR_FAILED;
tmp_bn[0] = 0;
if(BN_bn2bin(bn, tmp_bn+1) != len)
{
ipcom_free(tmp_bn);
return IPCOM_ERR_FAILED;
}
if(tmp_bn[1] & 0x80) /* if most significant bit is set, a zero byte must be added */
{
len++;
rc = ipssh_buffer_put_ssh_mpint(buf, tmp_bn, len);
}
else
rc = ipssh_buffer_put_ssh_mpint(buf, &(tmp_bn[1]), len);
ipcom_free(tmp_bn);
if(rc != IPCOM_SUCCESS)
return IPCOM_ERR_FAILED;
else
return len;
}
/*
*===========================================================================
* ipssh_buffer_get_ssh_mpint2
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_get_ssh_mpint2(Ipcom_buffer* buf, BIGNUM** bnp)
{
Ip_u32 len;
BIGNUM* bn = *bnp;
if(ipssh_buffer_get_uint(buf, &len) != IPCOM_SUCCESS)
return IPCOM_ERR_FAILED;
if(len>ipcom_buffer_len(buf))
return IPCOM_ERR_FAILED;
bn = BN_bin2bn(ipcom_buffer_start_ptr(buf), len, bn);
if(IP_NULL == bn)
return IPCOM_ERR_FAILED;
(void)ipcom_buffer_consume(buf, len);
*bnp = bn;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_buffer_put_ssh_mpint
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_put_ssh_mpint(Ipcom_buffer* buf, Ip_u8* mpint, Ip_size_t len)
{
/* If most significant bit is set, a zero byte must be added */
if(mpint[0] & 0x80)
{
if ( ipcom_buffer_put_int(buf, ip_htonl(len+1)) ||
ipcom_buffer_put_char(buf, 0))
{
return IPCOM_ERR_FAILED;
}
}
else
{
if ( ipcom_buffer_put_int(buf, ip_htonl(len)))
{
return IPCOM_ERR_FAILED;
}
}
return ipcom_buffer_put(buf, mpint, len);
}
/*
*===========================================================================
* ipssh_buffer_get_int
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_get_int(Ipcom_buffer* buf, Ip_s32* val)
{
if(ipcom_buffer_get_int(buf, val))
return IPCOM_ERR_FAILED;
*val = ip_ntohl(*val);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_buffer_get_u64
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_get_u64(Ipcom_buffer* buf, Ip_u64* val)
{
Ip_u32 hi, lo;
if(ipcom_buffer_get_int(buf, (Ip_s32*)&hi) ||
ipcom_buffer_get_int(buf, (Ip_s32*)&lo))
{
return IPCOM_ERR_FAILED;
}
IP_U64_SET(*val, ip_ntohl(hi), ip_ntohl(lo));
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_buffer_get_u64
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
/*
*===========================================================================
* ipssh_buffer_put_u64
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_buffer_put_u64(Ipcom_buffer* buf, Ip_u64 val)
{
Ip_u32 hi, lo;
hi = IP_U64_GETHI(val);
lo = IP_U64_GETLO(val);
if(ipssh_buffer_put_uint(buf, hi) ||
ipssh_buffer_put_uint(buf, lo))
{
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_append_list
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_append_list(Ipcom_buffer* buf, Ip_u8* alg_ids)
{
Ip_size_t len;
Ip_size_t org_len;
Ip_size_t len_pos;
char* len_ptr;
len_pos = ipcom_buffer_len(buf);
org_len = ipcom_buffer_len(buf);
if(ipcom_buffer_decr_cap(buf, 4) != IPCOM_SUCCESS) /* Proceed past length field */
return IPCOM_ERR_FAILED;
for(;*alg_ids != IPSSH_ID_END; alg_ids++)
{
const char* str;
str = ipssh_alg_id2str(*alg_ids);
if(!str || ipcom_buffer_put(buf, (Ip_u8*)str, (Ip_u32)ipcom_strlen(str)))
{
return IPCOM_ERR_FAILED;
}
if(alg_ids[1] != IPSSH_ID_END) /* Add a comma if there is an additional item in the list */
{
if(ipcom_buffer_put(buf, (Ip_u8*)",", 1))
{
return IPCOM_ERR_FAILED;
}
}
}
/* Update length */
len = ipcom_buffer_len(buf) - org_len - 4;
len_ptr = ipcom_buffer_ptr2pos(buf, len_pos);
IP_SET_32ON8(len_ptr, ip_htonl(len));
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_buffer_put_dsa_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ipssh_buffer_put_dsa_key(Ipcom_buffer* buf, DSA* dsa)
{
Ip_size_t len;
Ip_size_t len_pos;
char* len_ptr;
len_pos = ipcom_buffer_len(buf);
len = ipcom_buffer_len(buf);
if(ipcom_buffer_put_int(buf, 0)
|| ipssh_buffer_put_sshstr(buf, IPSSH_DSA_STR)
|| ipssh_buffer_put_bn(buf, dsa->p) < 0
|| ipssh_buffer_put_bn(buf, dsa->q) < 0
|| ipssh_buffer_put_bn(buf, dsa->g) < 0
|| ipssh_buffer_put_bn(buf, dsa->pub_key) < 0)
{
IPCOM_LOG0(ERR, "ipssh_buffer_put_dsa_key :: ipssh_buffer_put_bn() failed");
return IPCOM_ERR_FAILED;
}
len_ptr = ipcom_buffer_ptr2pos(buf, len_pos);
len = ipcom_buffer_len(buf)-len-4;
IP_SET_32ON8(len_ptr, (ip_htonl(len)));
return IPCOM_SUCCESS;
}
#ifdef IPSSH_USE_RSA
/*
*===========================================================================
* ipssh_buffer_put_rsa_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ipssh_buffer_put_rsa_key(Ipcom_buffer* buf, RSA* rsa)
{
Ip_u32 len;
Ip_size_t len_pos;
char* len_ptr;
len_pos = ipcom_buffer_len(buf);
len = (Ip_u32)ipcom_buffer_len(buf);
if(ipcom_buffer_put_int(buf, 0)
|| ipssh_buffer_put_sshstr(buf, IPSSH_RSA_STR)
|| ipssh_buffer_put_bn(buf, rsa->e) < 0
|| ipssh_buffer_put_bn(buf, rsa->n) < 0)
{
IPCOM_LOG0(ERR, "ipssh_buffer_put_rsa_key :: failed");
return IPCOM_ERR_FAILED;
}
len_ptr = ipcom_buffer_ptr2pos(buf, len_pos);
len = (Ip_u32)(ipcom_buffer_len(buf)-len-4);
IP_SET_32ON8(len_ptr, (ip_htonl(len)));
return IPCOM_SUCCESS;
}
#endif
/*
*===========================================================================
* ipssh_buffer_get_pub_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL EVP_PKEY*
ipssh_buffer_get_pub_key(Ipcom_buffer* buf)
{
char* key_type;
EVP_PKEY* key = IP_NULL;
DSA* dsa_key = IP_NULL;
RSA* rsa_key = IP_NULL;
Ip_s32 blob_len;
/* Read length of key blob */
if(ipssh_buffer_get_int(buf, &blob_len) != IPCOM_SUCCESS)
return IP_NULL;
key_type = ipssh_buffer_get_sshstr(buf);
if(!key_type)
return IP_NULL;
if(ipcom_strcmp(key_type, IPSSH_DSA_STR) == 0)
{
dsa_key = DSA_new();
if(!dsa_key)
goto cleanup;
if(ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->p) != IPCOM_SUCCESS
|| ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->q) != IPCOM_SUCCESS
|| ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->g) != IPCOM_SUCCESS
|| ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->pub_key) != IPCOM_SUCCESS)
{
goto cleanup;
}
key = EVP_PKEY_new();
if(!key)
goto cleanup;
if(!EVP_PKEY_assign_DSA(key, dsa_key))
{
EVP_PKEY_free(key);
key = IP_NULL;
goto cleanup;
}
(void)DSA_up_ref(dsa_key);
}
#ifdef IPSSH_USE_RSA
else if(ipcom_strcmp(key_type, IPSSH_RSA_STR) == 0)
{
rsa_key = RSA_new();
if(!rsa_key)
goto cleanup;
if(ipssh_buffer_get_ssh_mpint2(buf, &rsa_key->e) != IPCOM_SUCCESS
|| ipssh_buffer_get_ssh_mpint2(buf, &rsa_key->n) != IPCOM_SUCCESS)
{
goto cleanup;
}
key = EVP_PKEY_new();
if(!key)
goto cleanup;
if(!EVP_PKEY_assign_RSA(key, rsa_key))
{
EVP_PKEY_free(key);
key = IP_NULL;
goto cleanup;
}
(void)RSA_up_ref(rsa_key);
}
#endif /* IPSSH_USE_RSA */
else
goto cleanup;
cleanup:
ipcom_free(key_type);
if(rsa_key)
RSA_free(rsa_key);
if(dsa_key)
DSA_free(dsa_key);
return key;
}
/*
*===========================================================================
* ipssh_buffer_put_pub_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_buffer_put_pub_key(Ipcom_buffer* buf, EVP_PKEY* key)
{
Ip_size_t len_pos;
Ip_u32 blob_len;
switch(key->type)
{
case NID_dsa:
len_pos = ipcom_buffer_len(buf);
if(ipssh_buffer_put_int(buf, 0) /* Dummy key blob length */
||ipssh_buffer_put_sshstr(buf, IPSSH_DSA_STR))
{
return IPCOM_ERR_FAILED;
}
if(ipssh_buffer_put_bn(buf, key->pkey.dsa->p)<0
||ipssh_buffer_put_bn(buf, key->pkey.dsa->q)<0
||ipssh_buffer_put_bn(buf, key->pkey.dsa->g)<0
||ipssh_buffer_put_bn(buf, key->pkey.dsa->pub_key)<0)
{
return IPCOM_ERR_FAILED;
}
blob_len = (Ip_u32)(ipcom_buffer_len(buf) - len_pos - 4);
IP_SET_32ON8(ipcom_buffer_ptr2pos(buf, len_pos), ip_htonl(blob_len));
break;
#ifdef IPSSH_USE_RSA
case NID_rsaEncryption:
len_pos = ipcom_buffer_len(buf);
if(ipssh_buffer_put_int(buf, 0) /* Dummy key blob length */
|| ipssh_buffer_put_sshstr(buf, IPSSH_RSA_STR))
{
return IPCOM_ERR_FAILED;
}
if (ipssh_buffer_put_bn(buf, key->pkey.rsa->e) <0
|| ipssh_buffer_put_bn(buf, key->pkey.rsa->n) <0)
return IPCOM_ERR_FAILED;
blob_len = (Ip_u32)(ipcom_buffer_len(buf) - len_pos - 4);
IP_SET_32ON8(ipcom_buffer_ptr2pos(buf, len_pos), ip_htonl(blob_len));
break;
#endif
default:
IP_PANIC();
}
return IPCOM_SUCCESS;
}
IP_GLOBAL Ip_err
ipssh_buffer_put_dsa_sig(Ipcom_buffer* buf, DSA_SIG* dsa_sig)
{
Ip_s32 r_len;
Ip_s32 s_len;
int i;
int pad;
if (ipcom_buffer_capacity(buf) < (4+ipcom_strlen(IPSSH_DSA_STR)+4+2*IPSSH_SIG_LEN))
return IPCOM_ERR_INVALID_ARG;
r_len = BN_num_bytes(dsa_sig->r);
s_len = BN_num_bytes(dsa_sig->s);
if (r_len > IPSSH_MAX_INT_LEN || s_len > IPSSH_MAX_INT_LEN) {
IPCOM_LOG2(ERR, "ipssh_buffer_put_dsa_sig :: bad sig size %d %d", r_len, s_len);
return IPCOM_ERR_INVALID_ARG;
}
for(i=0,pad=IPSSH_SIG_LEN-r_len; i<pad; i++)
(void)ipcom_buffer_put_char(buf, 0);
(void)BN_bn2bin(dsa_sig->r, ipcom_buffer_end_ptr(buf));
(void)ipcom_buffer_decr_cap(buf, r_len);
for(i=0,pad=IPSSH_SIG_LEN-s_len; i<pad; i++)
(void)ipcom_buffer_put_char(buf, 0);
(void)BN_bn2bin(dsa_sig->s, ipcom_buffer_end_ptr(buf));
(void)ipcom_buffer_decr_cap(buf, s_len);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_buffer_put_bn_v1
*===========================================================================
* Description: Store a multiprecision integer in SSH v1 format
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ipssh_buffer_put_bn_v1(Ipcom_buffer* buf, BIGNUM* bn)
{
Ip_u16 bits;
int len;
Ip_u8* ptr;
bits = (Ip_u16) BN_num_bits(bn);
len = BN_num_bytes(bn);
if((int)ipcom_buffer_capacity(buf) < (len+2))
{
IPCOM_LOG2(ERR, "ipssh_buffer_put_bn_v1 :: buffer too small, buf size=%d, needed=%d",
ipcom_buffer_capacity(buf), len+2);
return IPCOM_ERR_FAILED;
}
ptr = ipcom_buffer_end_ptr(buf);
IPSSH_SET_16_PTR(ptr, bits);
(void)ipcom_buffer_decr_cap(buf, 2);
if(BN_bn2bin(bn, ipcom_buffer_end_ptr(buf)) < 0)
{
IPCOM_LOG0(ERR, "ipssh_buffer_put_bn_v1 :: BN_bn2bin() failed");
return IPCOM_ERR_FAILED;
}
return ipcom_buffer_decr_cap(buf, len);
}
/*
*===========================================================================
* ipssh_buffer_put_bn2_v1
*===========================================================================
* Description: Store a multiprecision integer in SSH v1 format
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ipssh_buffer_put_bn2_v1(Ipcom_buffer* buf, Ip_u8* value, Ip_u16 bits)
{
int len;
Ip_u8* ptr;
len = (bits+7)/8;
if(ipcom_buffer_capacity(buf) < ((Ip_u32)(len+2)))
{
IPCOM_LOG2(ERR, "ipssh_buffer_put_bn_v1 :: buffer too small, buf size=%d, needed=%d",
ipcom_buffer_capacity(buf), len+2);
return IPCOM_ERR_FAILED;
}
ptr = ipcom_buffer_end_ptr(buf);
IPSSH_SET_16_PTR(ptr, bits);
(void)ipcom_buffer_decr_cap(buf, 2);
if(ipcom_buffer_put(buf, value, len) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_buffer_put_bn2_v1 :: ipcom_buffer_put() failed");
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_buffer_new_v1_pkt
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipcom_buffer*
ipssh_buffer_new_v1_pkt(Ip_size_t size, Ip_u8 pkt_type)
{
Ipcom_buffer* pkt;
pkt = ipcom_buffer_new(size);
if(!pkt)
return IP_NULL;
(void)ipcom_buffer_decr_cap(pkt, 12); /* make room for length and padding fields */
(void)ipcom_buffer_put_char(pkt, pkt_type);
return pkt;
}
/*
*===========================================================================
* ipssh_buffer_new_v2_pkt
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipcom_buffer*
ipssh_buffer_new_v2_pkt(Ip_size_t size, Ip_u8 pkt_type)
{
Ipcom_buffer* pkt;
pkt = ipcom_buffer_new(size + 5 + IPSSH_MAX_PAD);
if(!pkt)
return IP_NULL;
(void)ipcom_buffer_decr_cap(pkt, 5); /* make room for packet length and pad length fields */
(void)ipcom_buffer_put_char(pkt, pkt_type);
return pkt;
}
/*
*===========================================================================
* ipssh_buffer_get_v1_bn
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL BIGNUM*
ipssh_buffer_get_v1_bn(Ipcom_buffer* buf)
{
BIGNUM* bn;
Ip_u16 bits;
Ip_u32 bytes;
if(ipcom_buffer_get(buf, (Ip_u8*)&bits, 2))
return IP_NULL;
bits = ip_ntohs(bits);
bytes = (bits+7) / 8;
if(bytes>ipcom_buffer_len(buf))
return IP_NULL;
bn = BN_bin2bn(ipcom_buffer_start_ptr(buf), bytes, IP_NULL);
if(IP_NULL == bn)
return IP_NULL;
(void)ipcom_buffer_consume(buf, bytes);
return bn;
}
/*
*===========================================================================
* ipssh_buffer_new_sftp_pkt
*===========================================================================
* Description: An sftp packet looks as follows:
* L1 P T ID L2 L3 M P
* | | | | | | | |
* transport +----+-+-+
* channel +----+----+
* sftp +----+-+----
*
* L1 - Length of packet (4 bytes)
* P - Pad length (1 byte)
* T - Packet type (Always CHANNEL_DATA) (1 byte)
* ID - Channel ID (4 bytes)
* L2 - Length of CHANNEL_DATA message (4 bytes)
* L3 - Length of sftp message (4bytes)
* M - sftp message type (1 byte)
* P - Payload of sftp message
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ipcom_buffer*
ipssh_buffer_new_sftp_pkt(Ip_size_t sftp_msg_size, Ip_u8 sftp_msg_type)
{
Ipcom_buffer* pkt;
pkt = ipcom_buffer_new(sftp_msg_size+6+8+5+IPSSH_MAX_PAD); /* transport overhead, channel overhead, sftp overhead, max padding */
if(!pkt)
return IP_NULL;
(void)ipcom_buffer_decr_cap(pkt, 18);
(void)ipcom_buffer_put_char(pkt, sftp_msg_type);
return pkt;
}
/*
*===========================================================================
* ipssh_buffer_new_channel_data_pkt
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ipcom_buffer*
ipssh_buffer_new_channel_data_pkt(Ip_size_t pkt_size, Ipssh_channel* channel)
{
Ipcom_buffer* pkt;
(void) channel;
pkt = ipcom_buffer_new(pkt_size+6+8+IPSSH_MAX_PAD); /* transport overhead, channel overhead, max padding */
if(!pkt)
return IP_NULL;
(void)ipcom_buffer_decr_cap(pkt, 14);
return pkt;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,109 @@
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_buffer.h,v $ $Revision: 1.11.10.1 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_buffer.h,v $
* $Author: ulf $ $Date: 2011-09-22 11:40:52 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger.boden@windriver.com>
******************************************************************************
*/
#ifndef ipssh_buffer_h
#define ipssh_buffer_h
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipcom_buffer.h"
#include "ipssh_list.h"
#include <openssl/bn.h>
#include <openssl/dsa.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define ipssh_buffer_get_uint(buf, val) ipssh_buffer_get_int(buf, (Ip_s32*)val)
#define ipssh_buffer_put_uint(buf, val) ipcom_buffer_put_int(buf, (Ip_s32)ip_htonl(val))
#define ipssh_buffer_put_int(buf, val) ipcom_buffer_put_int(buf, ip_htonl(val))
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_buffer_put_sshstr(Ipcom_buffer* buf, const char* str);
IP_GLOBAL Ip_err ipssh_buffer_put_sshbuf(Ipcom_buffer* buf, const Ip_u8* str, Ip_size_t len);
IP_GLOBAL char* ipssh_buffer_get_sshstr(Ipcom_buffer* buf);
IP_GLOBAL Ip_u8* ipssh_buffer_get_sshbuf(Ipcom_buffer* buf, Ip_u32* len);
IP_GLOBAL Ip_err ipssh_buffer_get_ssh_mpint(Ipcom_buffer* buf, Ip_u8* mpint, Ip_size_t len);
IP_GLOBAL Ip_err ipssh_buffer_get_ssh_mpint2(Ipcom_buffer* buf, BIGNUM** bn);
IP_GLOBAL Ip_err ipssh_buffer_put_ssh_mpint(Ipcom_buffer* buf, Ip_u8* mpint, Ip_size_t len);
IP_GLOBAL Ip_err ipssh_buffer_put_ssh_mpint2(Ipcom_buffer* buf, BIGNUM* bn);
IP_GLOBAL Ip_err ipssh_buffer_get_int(Ipcom_buffer* buf, Ip_s32* val);
IP_PUBLIC Ip_err ipssh_buffer_put_u64(Ipcom_buffer* buf, Ip_u64 val);
IP_GLOBAL Ip_err ipssh_buffer_get_u64(Ipcom_buffer* buf, Ip_u64* val);
IP_GLOBAL Ip_err ipssh_append_list(Ipcom_buffer* buf, Ip_u8* alg_ids);
IP_GLOBAL Ip_err ipssh_buffer_put_dsa_key(Ipcom_buffer* buf, DSA* dsa);
IP_GLOBAL Ip_err ipssh_buffer_put_rsa_key(Ipcom_buffer* buf, RSA* dsa);
IP_GLOBAL EVP_PKEY* ipssh_buffer_get_pub_key(Ipcom_buffer* buf);
IP_GLOBAL Ip_err ipssh_buffer_put_pub_key(Ipcom_buffer* buf, EVP_PKEY* key);
IP_GLOBAL Ip_err ipssh_buffer_put_bn(Ipcom_buffer* buf, BIGNUM* bn);
IP_GLOBAL Ip_err ipssh_buffer_put_bn_v1(Ipcom_buffer* buf, BIGNUM* bn);
IP_GLOBAL Ip_err ipssh_buffer_put_bn2_v1(Ipcom_buffer* buf, Ip_u8* value, Ip_u16 bits);
IP_GLOBAL BIGNUM* ipssh_buffer_get_v1_bn(Ipcom_buffer* buf);
IP_GLOBAL Ipcom_buffer* ipssh_buffer_new_v1_pkt(Ip_size_t size, Ip_u8 pkt_type);
IP_GLOBAL Ipcom_buffer* ipssh_buffer_new_v2_pkt(Ip_size_t size, Ip_u8 pkt_type);
IP_GLOBAL Ipcom_buffer* ipssh_buffer_new_sftp_pkt(Ip_size_t sftp_msg_size, Ip_u8 sftp_msg_type);
IP_GLOBAL Ipcom_buffer* ipssh_buffer_new_channel_data_pkt(Ip_size_t pkt_size, Ipssh_channel* channel);
#if defined(IPCOM_USE_DMALLOC) && !defined(IPCOM_DMALLOC_C)
IP_PUBLIC char* ipssh_buffer_get_sshstr_d(Ipcom_buffer* buf, const char *file, const char *function, Ip_u32 line);
#define ipssh_buffer_get_sshstr(b) ipssh_buffer_get_sshstr_d(b, __FILE__, __FUNCTION__, __LINE__)
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,461 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_c_api.c,v $ $Revision: 1.4.8.2 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_c_api.c,v $
* $Author: svc-cmnet $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger.boden@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include "ipcom_clib.h"
#include <ipcom_type.h>
#include "ipcom_cstyle.h"
#include "ipcom_err.h"
#include "ipcom_os.h"
#include "ipcom_sock.h"
#include "ipcom_sock2.h"
#include "ipcom_strlib.h"
#ifdef IPCOM_USE_SYSLOG
#undef IPCOM_USE_SYSLOG
#endif
#include "ipcom_syslog.h"
#include "ipssh.h"
/* #include "ipssh_h.h" */
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipssh_c_api_params_st
{
Ip_u16 port;
Ip_u16 pad;
int sh_param_len;
Ip_u8 sh_param[1];
};
typedef struct Ipssh_c_api_params_st Ipssh_c_api_params;
struct Ipssh_c_api_ctx_st
{
Ip_fd stdio_sock;
Ip_fd peer_sock;
};
typedef struct Ipssh_c_api_ctx_st Ipssh_c_api_ctx;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IPCOM_PROCESS(ipssh_c_api_proxy);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IPCOM_PROCESS(ipssh_c_api_proxy)
{
Ipssh_c_api_params *sinfo;
char read_buf[256];
struct Ip_addrinfo hints;
struct Ip_linger linger;
int enable = IP_TRUE;
char stdio_port_str[6];
struct Ip_addrinfo *res = IP_NULL;
int sockerr;
void* shell_handle;
Ipcom_shell_ctx* sh_ctx = IP_NULL;
Ipssh_c_api_ctx* proxy_ctx = IP_NULL;
char* user = IP_NULL;
ipcom_proc_init();
if (ipcom_ipc_install() != IPCOM_SUCCESS)
goto exit;
if (ipcom_ipc_receive(IP_NULL, &sinfo, IPC_TIMEOUT_INFINITE) != IPCOM_SUCCESS)
goto exit;
(void)ipcom_ipc_uninstall();
sh_ctx = ipcom_shell_ctx_new(sinfo->sh_param_len);
if (!sh_ctx)
goto exit;
sh_ctx->len = sinfo->sh_param_len;
ipcom_memcpy(sh_ctx->buf, sinfo->sh_param, sinfo->sh_param_len);
/* Get a tcp socket and connect to the SSH daemon listening port */
ipcom_memset(&hints, 0, sizeof(hints));
#ifdef IPCOM_USE_INET
hints.ai_family = IP_AF_INET;
#else
hints.ai_family = IP_AF_INET6;
#endif
hints.ai_socktype = IP_SOCK_STREAM;
ipcom_sprintf(stdio_port_str, "%d", (int)sinfo->port);
ipcom_ipc_free(sinfo);
if (ipcom_getaddrinfo(IP_NULL, stdio_port_str, &hints, &res) != 0)
{
IPCOM_LOG1(ERR, "ipssh_c_api_proxy :: ipcom_getaddrinfo() failed, errno = %d", ipcom_errno);
goto exit;
}
proxy_ctx = ipcom_malloc(sizeof(Ipssh_c_api_ctx));
if (!proxy_ctx)
goto exit;
proxy_ctx->stdio_sock = ipcom_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (proxy_ctx->stdio_sock == IP_INVALID_SOCKET)
{
IPCOM_LOG1(ERR, "ipssh_c_api_proxy :: ipcom_socket(IP_AF_INET) failed, errno = %d", ipcom_errno);
goto exit;
}
/* Note! the SSH daemon side will get a "connection reset by peer" when exiting the
shell since the linger time is set to 0 */
linger.l_onoff = 1;
linger.l_linger = 0;
(void)ipcom_setsockopt(proxy_ctx->stdio_sock, IP_SOL_SOCKET, IP_SO_LINGER, &linger, sizeof(linger));
/*
* Disable Nagle (enable no delay) on this socket since it is an
* interactive connection
*/
(void)ipcom_setsockopt(proxy_ctx->stdio_sock, IP_IPPROTO_TCP, IP_TCP_NODELAY, &enable, sizeof(enable));
sockerr = ipcom_connect(proxy_ctx->stdio_sock, res->ai_addr, res->ai_addrlen);
if (sockerr == IP_SOCKERR)
{
IPCOM_LOG2(ERR,
"ipssh_c_api_proxy :: ipcom_connect(IP_AF_INET%s) failed, errno = %d",
res->ai_family == IP_AF_INET ? "" : "6",
ipcom_errno);
goto exit;
}
if (ipcom_shell_ctx_get_int(sh_ctx, IPSSH_CLT_FD, &proxy_ctx->peer_sock) != IPCOM_SUCCESS)
goto exit;
user = ipcom_shell_ctx_get_user(sh_ctx);
shell_handle = ipssh_shell_start_cb(proxy_ctx, user, sh_ctx);
if (user)
ipcom_free(user);
if (!shell_handle)
goto exit;
if (ipssh_shell_welcome_msg_cb(proxy_ctx, shell_handle) != IPCOM_SUCCESS)
goto exit;
/* Main stdio proxy loop */
for (;;)
{
Ip_ssize_t read_bytes;
read_bytes = ipcom_socketread(proxy_ctx->stdio_sock, read_buf, sizeof(read_buf));
if (read_bytes <= 0)
{
(void)ipssh_shell_stop_cb(proxy_ctx, shell_handle);
goto exit;
}
if (ipssh_shell_stdin_cb(proxy_ctx, shell_handle, read_buf, read_bytes) != IPCOM_SUCCESS)
goto exit;
}
exit:
if (proxy_ctx)
{
if (proxy_ctx->stdio_sock != IP_INVALID_SOCKET)
ipcom_socketclose(proxy_ctx->stdio_sock);
ipcom_free(proxy_ctx);
}
if (res != IP_NULL)
ipcom_freeaddrinfo(res);
if (sh_ctx)
ipcom_shell_ctx_free(sh_ctx);
ipcom_proc_exit();
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
IP_PUBLIC Ip_err
ipssh_start_shell_c_api(Ip_fd *stdio_sock, const Ipcom_shell_ctx* sh_ctx)
{
Ip_fd mother = IP_INVALID_SOCKET;
Ip_fd shell_fd = IP_INVALID_SOCKET;
Ip_socklen_t addr_len;
Ipcom_ipc ipc;
Ipssh_c_api_params *sinfo;
char procname[40];
Ip_err retval;
Ipcom_proc_attr attr;
Ip_bool ipc_opened = IP_FALSE;
Ip_pid_t ppid, shell_pid;
Ip_u16 mother_port;
static Ip_u32 seqno = 0;
struct Ip_addrinfo hints;
struct Ip_addrinfo *res = IP_NULL;
union Ip_sockaddr_union sa;
Ip_size_t sh_len = (Ip_size_t) (sh_ctx ? sh_ctx->len : 0);
*stdio_sock = IP_INVALID_SOCKET;
sinfo = ipcom_ipc_malloc(sizeof(Ipssh_c_api_params)+sh_len);
if (sinfo == IP_NULL)
{
IPCOM_LOG0(ERR, "ipssh_start_shell_c_api :: ipcom_ipc_malloc() failed");
goto exit;
}
sinfo->sh_param_len = (int) sh_len;
if (sh_ctx)
ipcom_memcpy(sinfo->sh_param, sh_ctx->buf, (Ip_size_t)sh_ctx->len);
/* Get a tcp socket and let the stack pick a port */
ipcom_memset(&hints, 0, sizeof(hints));
#ifdef IPCOM_USE_INET
hints.ai_family = IP_AF_INET;
#else
hints.ai_family = IP_AF_INET6;
#endif
hints.ai_socktype = IP_SOCK_STREAM;
if (ipcom_getaddrinfo(IP_NULL, "0", &hints, &res) != 0)
{
IPCOM_LOG1(ERR, "ipssh_start_shell_c_api :: ipcom_getaddrinfo() failed, errno = %d", ipcom_errno);
goto exit;
}
mother = ipcom_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (mother == IP_INVALID_SOCKET)
{
IPCOM_LOG1(ERR, "ipssh_start_shell_c_api :: ipcom_socket(IP_AF_INET) failed, errno = %d", ipcom_errno);
goto exit;
}
if (ipcom_bind(mother, res->ai_addr, (Ip_socklen_t)res->ai_addrlen) == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "ipssh_start_shell_c_api :: ipcom_bind(IP_AF_INET) failed, errno = %d", ipcom_errno);
goto exit;
}
/* Find out which port was assigned. */
addr_len = sizeof(sa);
if (ipcom_getsockname(mother, (struct Ip_sockaddr *)&sa, &addr_len) == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "ipssh_start_shell_c_api :: ipcom_getsockname(IP_AF_INET) failed, errno = %d", ipcom_errno);
goto exit;
}
#ifdef IPCOM_USE_INET
if (sa.sa.sa_family == IP_AF_INET)
mother_port = ip_ntohs(sa.sin.sin_port);
#endif
#ifdef IPCOM_USE_INET6
if (sa.sa.sa_family == IP_AF_INET6)
mother_port = ip_ntohs(sa.sin6.sin6_port);
#endif
if (ipcom_listen(mother, 1) == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "ipssh_start_shell_c_api :: ipcom_listen() failed, errno = %d", ipcom_errno);
goto exit;
}
/* Create and start the shell process. */
ipcom_proc_attr_init(&attr);
#ifdef IP_PORT_VXWORKS
attr.stacksize = IPCOM_PROC_STACK_LARGE;
#else
attr.priority = IPCOM_PRIORITY_DEFAULT;
#endif /* IP_PORT_VXWORKS */
ppid = ipcom_getpid();
ipcom_sprintf(procname, "c_api_proxy_%lx_%d", (long)(ppid & 0xffffffff), (int)++seqno);
if (ipcom_proc_acreate(procname, (Ipcom_proc_func)ipssh_c_api_proxy, &attr, &shell_pid))
{
IPCOM_LOG0(ERR, "ipssh_start_shell_c_api :: ipcom_proc_acreate() failed");
goto exit;
}
/* Open IPC with c_api_proxy. */
retval = ipcom_ipc_open(&ipc, procname, -1);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG2(ERR, "ipssh_start_shell_c_api :: ipcom_ipc_open(%s) failed, ret = %d", procname, retval);
goto exit;
}
ipc_opened = IP_TRUE;
/* Send a message to ipcom_shell. */
sinfo->port = mother_port;
retval = ipcom_ipc_send(&ipc, sinfo);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "ipssh_start_shell_c_api :: ipcom_ipc_send() failed, ret = %d", retval);
goto exit;
}
/* Wait for the shell process to connect */
shell_fd = ipcom_accept(mother, IP_NULL, IP_NULL);
exit:
if (mother != IP_INVALID_SOCKET)
(void)ipcom_socketclose(mother);
if (res != IP_NULL)
ipcom_freeaddrinfo(res);
if (ipc_opened)
(void)ipcom_ipc_close(&ipc);
else if (sinfo != IP_NULL)
ipcom_ipc_free(sinfo);
if (shell_fd == IP_INVALID_SOCKET)
return IPCOM_ERR_FAILED;
else
{
int enable = IP_TRUE;
*stdio_sock = shell_fd;
#if IPCOM_USE_SOCK != IPCOM_SOCK_IPLITE
/*
* Disable Nagle (enable no delay) on this socket since it is an
* interactive connection
*/
(void)ipcom_setsockopt(shell_fd, IP_IPPROTO_TCP, IP_TCP_NODELAY, &enable, sizeof(enable));
#endif
return IPCOM_SUCCESS;
}
}
/*
*===========================================================================
* ipssh_shell_exit
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_shell_exit(void* ssh_ctx, void* shell_ctx)
{
Ipssh_c_api_ctx* proxy_ctx = ssh_ctx;
(void)shell_ctx;
if (ipcom_shutdown(proxy_ctx->stdio_sock, IP_SHUT_RDWR))
return IPCOM_ERR_FAILED;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_send_shell_stdout_data
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC int
ipssh_send_shell_stdout_data(void* ssh_ctx, void* shell_ctx, const char* data, Ip_ssize_t len)
{
Ipssh_c_api_ctx* proxy_ctx = ssh_ctx;
(void)shell_ctx;
if (ipcom_socketwrite(proxy_ctx->stdio_sock, data, len) != len)
return -1;
return (int)len;
}
/*
*===========================================================================
* ipssh_get_clt_fd
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_fd
ipssh_get_clt_fd(void* ssh_ctx)
{
Ipssh_c_api_ctx* proxy_ctx = ssh_ctx;
return proxy_ctx->peer_sock;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,248 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_channel.h,v $ $Revision: 1.15.10.5 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_channel.h,v $
* $Author: jren $ $Date: 2013-04-28 02:23:08 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef IPSSH_CHANNEL_H
#define IPSSH_CHANNEL_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_list.h>
#include "ipssh_h.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Channel types */
#define IPSSH_CH_TYPE_SFTP_CLT 1
#define IPSSH_CH_TYPE_SFTP_SRV 2
#define IPSSH_CH_TYPE_SHELL 3
#define IPSSH_CH_TYPE_PORT_FWD 4
#define IPSSH_CH_TYPE_SUBSYSTEM 5
/* Channel states */
#define IPSSH_CH_STATE_CH_INIT 1 << 1
#define IPSSH_CH_STATE_CH_OPEN_SENT 1 << 2
#define IPSSH_CH_STATE_OPENED 1 << 3
#define IPSSH_CH_STATE_CH_REQUEST_SENT 1 << 4
#define IPSSH_CH_STATE_CH_REQUEST_OK 1 << 5
#define IPSSH_CH_STATE_CLT_FXP_INIT_SENT 1 << 6
#define IPSSH_CH_STATE_CLT_SFTP 1 << 7
#define IPSSH_CH_STATE_ERR 1 << 8
#define IPSSH_CH_FLAG_WAITING_FOR_WIN_ADJUST_MSG 1
/* Channel shell types */
#define IPSSH_SHELL_NORMAL 0
#define IPSSH_SHELL_EXEC_CMD 1
/* Channel exec cmd shell default status(unknown cmd was found.) */
#define IPSSH_SHELL_EXEC_CMD_DEF_STATUS 1
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/* Forward declarations */
struct Ipssh_channel_st;
struct Ipssh_conn_st;
typedef Ip_err (*Ipssh_ch_data_handler)(struct Ipssh_channel_st* channel,
Ipcom_buffer* msg);
struct Ipssh_term_modes_st
{
Ip_u8 ONLCR; /* Map outgoing NL to CR-NL.*/
Ip_u8 ICRNL; /* Map incoming CR to NL */
Ip_u8 IXBSDEL; /* Map incoming BS (0x7f) to DEL (0x08) (Propr ext) */
};
typedef struct Ipssh_term_modes_st Ipssh_term_modes;
struct Ipssh_shell_data_st
{
/* Terminal specific data */
Ip_u8 last_chr;
Ip_fd shell_fd;
Ip_u32 init_term_cols;
Ip_u32 init_term_rows;
Ip_u32 shell_type; /* IPSSH_SHELL_NORMAL or IPSSH_SHELL_EXECCMD */
char return_value[64]; /* The return value string output from shell. The first byte is a flag
which is used to check whether shell has been initialized. */
Ip_s32 exit_status_val; /* default value is IPSSH_SHELL_EXEC_CMD_DEF_STATUS for unknown cmd. */
/* Terminal modes */
Ipssh_term_modes term_modes;
};
struct Ipssh_port_fwd_st
{
Ip_fd sock;
};
#ifdef IPSSH_USE_SFTP
struct Ipssh_sftp_data_st
{
/* sftp data */
Ipcom_list handle_map;
Ipcom_buffer* msg; /* Used to temporarily store sftp message fragments until a complete message has been received */
int msg_len;
int req_id;
char* cwd;
};
#endif
struct Ipssh_ch_data_entry_st
{
Ipcom_list list;
Ipcom_buffer* msg;
};
typedef struct Ipssh_ch_data_entry_st Ipssh_ch_data_entry;
union Ipssh_channel_data
{
struct Ipssh_shell_data_st shell;
#ifdef IPSSH_USE_SFTP
struct Ipssh_sftp_data_st sftp;
#endif
/* Port forward specific data */
struct Ipssh_port_fwd_st port_fwd;
};
struct Ipssh_channel_st
{
Ipcom_list list;
int type;
int state;
Ip_u32 my_ch_id;
Ip_u32 peer_ch_id;
Ip_s32 my_win;
Ip_u32 my_max_pkt_size;
Ip_s32 peer_win;
Ip_u32 peer_max_pkt_size;
Ipssh_ch_data_handler handler;
Ip_u8 eof_rec;
Ip_u8 eof_sent;
Ip_u8 close_rec;
Ip_u8 close_sent;
int flags;
union Ipssh_channel_data data;
Ipcom_list ch_data_list; /* List of cached CHANNEL_DATA_MSG */
struct Ipssh_conn_st* ssh_conn; /* This is the ssh connection the channel pertains to */
};
typedef struct Ipssh_channel_st Ipssh_channel;
typedef Ipcom_list Ipssh_channel_map;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/* Functions for sending ssh messages */
IP_GLOBAL Ip_err ipssh_send_ch_win_adjust_msg(Ipssh_channel* channel, Ip_u32 size_change);
IP_GLOBAL Ip_err ipssh_send_ch_open_conf_msg(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_channel_data_msg(Ipssh_channel* channel, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_send_channel_close_msg(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_channel_success(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_channel_failure(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_channel_exit(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_msg_channel_eof(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_channel_request_subsystem(Ipssh_channel* channel, Ip_u8 want_reply, const char* subsystem);
IP_GLOBAL Ip_err ipssh_send_channel_win_adjust_msg(Ipssh_channel* channel, Ip_u32 size_change);
IP_GLOBAL Ip_err ipssh_send_ch_open_fail_msg(struct Ipssh_conn_st* ssh_conn, Ip_u32 peer_ch_id, Ip_u32 reason_code, const char* reason_str);
IP_GLOBAL Ip_err ipssh_msg_channel_success(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_channel_open(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_channel_open_confirmation(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_channel_open_failure(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_channel_data(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_ch_win_adjust(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_channel_eof(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_channel_close(struct Ipssh_conn_st* ssh_conn);
/* Channel handling functions */
IP_GLOBAL Ipssh_channel* ipssh_channel_new(struct Ipssh_conn_st* ssh_conn, Ip_u32 peer_ch_id, Ipssh_ch_data_handler handler);
IP_GLOBAL Ipssh_channel* ipssh_channel_map_insert(struct Ipssh_conn_st* ssh_conn,
Ip_u32 my_ch_id,
Ip_u32 peer_ch_id,
Ip_u32 my_send_win,
Ip_u32 peer_send_win,
Ip_u32 my_max_pkt_size,
Ip_u32 peer_max_pkt_size,
Ipssh_ch_data_handler handler);
IP_GLOBAL Ipssh_channel* ipssh_sock2channel(Ipssh_channel_map* ch_map, Ip_fd sock);
IP_GLOBAL Ipssh_channel* ipssh_channel_id2ch(Ipssh_channel_map* ch_map, Ip_u32 ch_id);
IP_GLOBAL Ipssh_channel* ipssh_channel_map_lookup(Ipssh_channel_map* ch_map, Ip_fd shell_fd);
IP_GLOBAL Ipcom_buffer* ipssh_get_channel_open_pkt(Ipssh_channel* channel, const char* ch_type, int size);
IP_GLOBAL void ipssh_channel_close(Ipssh_channel* channel);
IP_GLOBAL Ip_u32 ipssh_channel_new_id(Ipssh_channel_map* map);
IP_GLOBAL Ip_err ipssh_channel_init_subsystem(const char* subsystem_name,
Ipssh_channel* channel,
Ip_fd* sock);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,929 @@
/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_cmds.c,v $ $Revision: 1.70.10.3 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_cmds.c,v $
* $Author: svc-cmnet $
* $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_config.h"
#include "ipssh.h"
#include "ipssh_sftp_clt.h"
#include <ipcom_clib.h>
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_shell.h>
#include <ipcom_getopt.h>
#include <ipcom_os.h>
#include <ipcom_sock2.h>
#include <ipcom_strlib.h>
#include <ipcom_shell.h>
#include <openssl/pem.h>
#include <openssl/err.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPSSH_SFTP_PROMPT "sftp> "
#define IPSSH_SFTP_PW_PROMPT "Enter password: "
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_GLOBAL int ipssh_stop_cmd(int argc, char** argv);
IP_GLOBAL int ipssh_list_cmd(int argc, char** argv);
IP_GLOBAL int ipssh_keyfp_cmd(int argc, char** argv);
IP_GLOBAL int ipssh_cmd_sftp(int argc, char** argv);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
#ifdef IPSSH_USE_SFTP_CLT_CMD
/*
*===========================================================================
* ipssh_cmd_sftp_sub_usage
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipssh_cmd_sftp_sub_usage(void)
{
ipcom_printf("cd path change remote directory"IP_LF);
ipcom_printf("get remote-path [local-path] download file"IP_LF);
ipcom_printf("put local-path [remote-path] upload file"IP_LF);
ipcom_printf("pwd print remote working directory"IP_LF);
ipcom_printf("ls remote directory listing"IP_LF);
ipcom_printf("rename rename remote file/directory"IP_LF);
ipcom_printf("rm path remove remote file"IP_LF);
ipcom_printf("mkdir path create remote direcory"IP_LF);
ipcom_printf("rmdir path remove remote directory"IP_LF);
ipcom_printf("lcd path change local directory"IP_LF);
ipcom_printf("lpwd print local working directory"IP_LF);
ipcom_printf("lls local directory listing"IP_LF);
ipcom_printf("lrm path remove local file"IP_LF);
ipcom_printf("lmkdir path create local directory"IP_LF);
ipcom_printf("lrmdir path remove local directory"IP_LF);
ipcom_printf("quit quit sftp"IP_LF);
ipcom_printf("exit quit sftp"IP_LF);
}
/*
*===========================================================================
* ipssh_cmd_sftp_usage
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipssh_cmd_sftp_usage(void)
{
ipcom_printf("sftp [-p <port>] [-i <public key file>] [-f <hostbased key file>] [-w <password>] -u <user> <srv addr>"IP_LF);
}
#endif /* IPSSH_USE_SFTP_CLT_CMD */
#ifdef IPSSH_USE_KEY_FINGERPRINT
/*
*===========================================================================
* ipssh_keyfp_usage
*===========================================================================
*/
IP_STATIC void
ipssh_keyfp_usage(void)
{
ipcom_printf("keyfp -f <file> [-1] {-h|-b}"IP_LF);
}
#endif
#ifdef IPSSH_USE_STOP_SPAWN
/*
*===========================================================================
* ipssh_stop_usage
*===========================================================================
*/
IP_STATIC void
ipssh_stop_usage(void)
{
ipcom_printf("ipssh_stop [-a] [-c <id>] [-h]"IP_LF);
ipcom_printf(" -a stop all logged in clients"IP_LF);
ipcom_printf(" -c stop the logged in client with the specified id"IP_LF);
ipcom_printf(" -h print usage information"IP_LF);
}
#endif
/*
*===========================================================================
* ipssh_list_usage
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipssh_list_usage(void)
{
ipcom_printf("ipssh_list [-lh]"IP_LF
" -l print all info"IP_LF
" -h print ipssh_list usage"IP_LF);
}
#ifdef IPSSH_USE_KEY_FINGERPRINT
/*
*===========================================================================
* ipssh_load_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC EVP_PKEY*
ipssh_load_key(const char* file)
{
BIO* bio;
EVP_PKEY* ret = IP_NULL;
if(!file)
return IP_NULL;
bio = BIO_new(BIO_s_file());
if(!bio)
{
IPCOM_LOG0(ERR, "ipssh_load_key :: out of memory");
return IP_NULL;
}
if( !BIO_read_filename(bio, file) )
{
IPCOM_LOG1(ERR, "ipssh_load_key :: failed to open %s", file);
goto cleanup;
}
ret = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, IP_NULL);
if(!ret)
{
IPCOM_LOG1(ERR, "ipssh_load_key :: failed to load key from file: %s", file);
}
cleanup:
if(bio)
(void)BIO_free(bio);
return ret;
}
#endif
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
#ifdef IPSSH_USE_STOP_SPAWN
/*
*===========================================================================
* ipssh_stop_cmd
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL int
ipssh_stop_cmd(int argc, char** argv)
{
Ipcom_getopt opt;
int rc;
Ip_pid_t pid;
char* options = "hc:a";
if(argc == 1)
{
ipssh_stop_usage();
return IPCOM_ERR_FAILED;
}
ipcom_getopt_clear_r(&opt);
while( (rc = ipcom_getopt_r(argc, argv, options, &opt)) != -1)
{
switch(rc)
{
case 'c':
pid = (Ip_pid_t) ipcom_strtoul(opt.optarg, IP_NULL, 0);
if(ipssh_stop_spawn(pid) != IPCOM_SUCCESS)
{
ipcom_printf("Failed to stop server"IP_LF);
return IPCOM_ERR_FAILED;
}
break;
case 'a':
if(ipssh_stop_all_spawns() != IPCOM_SUCCESS)
{
ipcom_printf("Failed to stop spawned ipssh processes"IP_LF);
return IPCOM_ERR_FAILED;
}
break;
case '?':
case 'h':
ipssh_stop_usage();
return IPCOM_SUCCESS;
default:
IP_PANIC();
ipssh_stop_usage();
return IPCOM_ERR_FAILED;
}
}
return IPCOM_SUCCESS;
}
#endif
/*
*===========================================================================
* ipssh_list_cmd
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL int
ipssh_list_cmd(int argc, char** argv)
{
Ipcom_getopt opt;
int rc;
int print_all = 0;
int pos = 0;
Ipssh_clt_info clt_info;
/* parse args */
ipcom_getopt_clear_r(&opt);
while((rc = ipcom_getopt_r(argc, argv, "hl", &opt)) != -1)
{
switch(rc)
{
case 'l':
print_all = 1;
break;
case '?':
case 'h':
ipssh_list_usage();
return IPCOM_SUCCESS;
default:
IP_PANIC();
}
}
if(ipssh_get_clt_info(&clt_info, pos) == IPCOM_SUCCESS)
{
ipcom_printf("Connected clients:"IP_LF);
if(print_all)
ipcom_printf("%-9s %-10s %-16s %-9s %-11s %-12s %-10s %s"IP_LF,
"ID", "User", "Clt Addr", "Service", "Auth Meth", "Encr Alg", "MAC Alg", "Clt SW");
else
ipcom_printf("%-9s %-10s %-16s %s"IP_LF, "ID", "User", "Clt Addr", "Service");
while(ipssh_get_clt_info(&clt_info, pos) == IPCOM_SUCCESS)
{
if(print_all)
ipcom_printf("%-9d %-10s %-16s %-9s %-11s %-12s %-10s %s"IP_LF,
clt_info.pid, clt_info.userid, clt_info.clt_addr, clt_info.service,
clt_info.auth_method, clt_info.cipher, clt_info.mac, clt_info.ssh_clt_sw);
else
ipcom_printf("%-9d %-10s %-16s %s"IP_LF,
clt_info.pid, clt_info.userid, clt_info.clt_addr, clt_info.service);
pos++;
}
}
else
{
ipcom_printf("No SSH clients connected"IP_LF);
}
return IPCOM_SUCCESS;
}
#ifdef IPSSH_USE_KEY_FINGERPRINT
/*
*===========================================================================
* ipssh_keyfp_cmd
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL int
ipssh_keyfp_cmd(int argc, char** argv)
{
Ipcom_getopt opt;
EVP_PKEY* key = IP_NULL;
int rc;
Ip_err ret_val = IPCOM_SUCCESS;
char* finger_print = IP_NULL;
int fp_type = 0;
Ip_bool v1 = IP_FALSE;
int key_type;
if (argc < 3 || argc > 6)
{
ipssh_keyfp_usage();
return IPCOM_ERR_FAILED;
}
ipcom_getopt_clear_r(&opt);
while((rc = ipcom_getopt_r(argc, argv, "f:hb1", &opt)) != -1)
{
switch(rc)
{
case 'f':
key = ipssh_load_key(opt.optarg);
break;
case 'h':
fp_type = IPSSH_HEX;
break;
case 'b':
fp_type = IPSSH_BUBBLE_BABBLE;
break;
case '1':
v1 = IP_TRUE;
break;
case '?':
ipssh_keyfp_usage();
return IPCOM_SUCCESS;
default:
IP_PANIC();
}
}
if(key == IP_NULL)
{
ipcom_printf("Key file must be specified with -f <file>" IP_LF);
return IPCOM_ERR_FAILED;
}
if(!fp_type)
{
ipcom_printf("Key fingerprint type must be specified [-b|-h]" IP_LF);
return IPCOM_ERR_FAILED;
}
if (v1)
key_type = IPSSH_V1_RSA_ID;
else
key_type = key->type;
if(ipssh_key_fingerprint2(key, key_type, &finger_print, fp_type) != IPCOM_SUCCESS)
{
ret_val =IPCOM_ERR_FAILED;
#ifdef OPENSSL_FIPS
if (FIPS_mode() && fp_type == IPSSH_HEX)
ipcom_printf("Hex fingerprints not allowed in FIPS mode\n");
#endif
ret_val = IPCOM_ERR_FAILED;
ipcom_printf("Failed" IP_LF);
goto cleanup;
}
ipcom_printf("%s" IP_LF, finger_print);
cleanup:
if(key)
EVP_PKEY_free(key);
if(finger_print)
ipcom_free(finger_print);
return ret_val;
}
#endif
#ifdef IPSSH_USE_SFTP_CLT_CMD
/*
*===========================================================================
* ipssh_cmd_sftp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL int
ipssh_cmd_sftp(int argc, char** argv)
{
Ipssh_conn* ssh_conn = IP_NULL;
Ipcom_getopt opt;
int rc;
int ret_val = IPCOM_ERR_FAILED;
char* options = "hp:u:w:i:f:";
char* host;
char* user = IP_NULL;
char* pw = IP_NULL;
int port = 22;
char* key_file = IP_NULL;
char* hostb_key_file = IP_NULL;
char pw_buf[32];
Ipcom_getline* gl;
BIO* bio = IP_NULL;
int sftp_argc;
char** sftp_argv = IP_NULL;
if(argc == 1)
{
ipssh_cmd_sftp_usage();
return IPCOM_ERR_FAILED;
}
ipcom_getopt_clear_r(&opt);
while( (rc = ipcom_getopt_r(argc, argv, options, &opt)) != -1)
{
switch(rc)
{
case 'p':
port = ipcom_atoi(opt.optarg);
if(port < 0 || port > 0xffff)
{
ipcom_printf("Invalid port"IP_LF);
return IPCOM_ERR_FAILED;
}
break;
case 'i':
key_file = opt.optarg;
break;
case 'f':
hostb_key_file = opt.optarg;
break;
case 'u':
user = opt.optarg;
break;
case 'w':
pw = opt.optarg;
break;
case 'h':
ipssh_cmd_sftp_usage();
return IPCOM_SUCCESS;
default:
ipssh_cmd_sftp_usage();
return IPCOM_ERR_FAILED;
}
}
if(opt.optind == argc - 1)
host = argv[opt.optind];
else
{
ipcom_printf("No host given"IP_LF);
return IPCOM_ERR_FAILED;
}
if(!user)
{
ipcom_printf("No user given"IP_LF);
return IPCOM_ERR_FAILED;
}
gl = ipcom_getline_init(10);
if(!gl)
return IPCOM_ERR_FAILED;
if(!pw && !key_file && !hostb_key_file)
{
ipcom_printf(IPSSH_SFTP_PW_PROMPT);
(void)ipcom_fflush(ip_stdout);
if(ipcom_getline(IP_INVALID_SOCKET, pw_buf, sizeof(pw_buf), IP_FALSE, gl, ipcom_strlen(IPSSH_SFTP_PW_PROMPT)))
{
ipcom_printf("Failed"IP_LF);
goto cleanup;
}
ipcom_printf(IP_LF);
(void)ipcom_fflush(ip_stdout);
pw = pw_buf;
}
ssh_conn = ipssh_conn_new();
if(!ssh_conn)
{
ipcom_printf("ipssh_cmd_sftp :: out of memory");
goto cleanup;
}
(void)ipssh_sftp_clt_set_userid(ssh_conn, user);
if(pw)
(void)ipssh_sftp_clt_set_pw(ssh_conn, pw);
if(key_file)
{
EVP_PKEY* key;
bio = BIO_new(BIO_s_file());
if(!bio)
{
ipcom_printf("out of memory"IP_LF);
goto cleanup;
}
if(!BIO_read_filename(bio, key_file))
{
ipcom_printf("Failed to open key file: %s"IP_LF, key_file);
goto cleanup;
}
key = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, IP_NULL);
if(!key)
{
ipcom_printf("Failed to read key from file: %s"IP_LF, key_file);
goto cleanup;
}
if (ipssh_sftp_clt_set_key(ssh_conn, key) != IPCOM_SUCCESS)
{
ipcom_printf("Invalid key type in %s"IP_LF, key_file);
EVP_PKEY_free(key);
goto cleanup;
}
EVP_PKEY_free(key);
}
if (hostb_key_file)
{
EVP_PKEY* key;
bio = BIO_new(BIO_s_file());
if(!bio)
{
ipcom_printf("out of memory"IP_LF);
goto cleanup;
}
if(!BIO_read_filename(bio, hostb_key_file))
{
ipcom_printf("Failed to open key file: %s"IP_LF, hostb_key_file);
goto cleanup;
}
key = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, IP_NULL);
if(!key)
{
ipcom_printf("Failed to read key from file: %s"IP_LF, hostb_key_file);
goto cleanup;
}
if (ipssh_sftp_clt_set_hostb_key(ssh_conn, key) != IPCOM_SUCCESS)
{
ipcom_printf("Invalid key type in %s"IP_LF, hostb_key_file);
EVP_PKEY_free(key);
goto cleanup;
}
EVP_PKEY_free(key);
}
if(ipssh_sftp_clt_open(ssh_conn, host, (Ip_u16)port) != IPCOM_SUCCESS)
{
ipcom_printf("Connection failed"IP_LF);
goto cleanup;
}
while(1)
{
char sftp_cmd[64];
if(sftp_argv)
{
ipcom_free(sftp_argv);
sftp_argv = IP_NULL;
}
ipcom_printf(IPSSH_SFTP_PROMPT);
(void)ipcom_fflush(ip_stdout);
if(ipcom_getline(IP_INVALID_SOCKET, sftp_cmd, sizeof(sftp_cmd), IP_TRUE, gl, ipcom_strlen(IPSSH_SFTP_PROMPT)))
{
ipcom_printf("Failed"IP_LF);
goto cleanup;
}
if(ipcom_parse_argstr(sftp_cmd, &sftp_argc, &sftp_argv) != IPCOM_SUCCESS)
{
ipcom_printf("Failed 2"IP_LF);
goto cleanup;
}
if(sftp_argc == 0)
{
continue;
}
if(ipcom_strcmp(sftp_argv[0], "get") == 0)
{
char* dst_file;
if(sftp_argc < 2 || sftp_argc > 3)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(sftp_argc == 2)
dst_file = sftp_argv[1];
else
dst_file = sftp_argv[2];
if(ipssh_sftp_clt_get(ssh_conn, sftp_argv[1], dst_file) != IPCOM_SUCCESS)
{
ipcom_printf("Failed to get file"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "put") == 0)
{
char* dst_file;
int append_mode = 0;
if(sftp_argc < 2 || sftp_argc > 4 || (ipcom_strcmp(sftp_argv[1], "-a")==0 && sftp_argc == 2))
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if (ipcom_strcmp(sftp_argv[1], "-a") == 0)
append_mode = 1;
if(sftp_argc == 2 + append_mode)
dst_file = sftp_argv[1+append_mode];
else
dst_file = sftp_argv[2+append_mode];
if (append_mode)
{
if(ipssh_sftp_clt_put_flags(ssh_conn, sftp_argv[2], dst_file,
IPSSH_FXF_WRITE|IPSSH_FXF_APPEND) != IPCOM_SUCCESS)
{
ipcom_printf("Failed to put file"IP_LF);
}
}
else
{
if(ipssh_sftp_clt_put(ssh_conn, sftp_argv[1], dst_file) != IPCOM_SUCCESS)
{
ipcom_printf("Failed to put file"IP_LF);
}
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "pwd") == 0)
{
char cwd[128];
if(sftp_argc != 1)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(ipssh_sftp_clt_get_cwd(ssh_conn, cwd, sizeof(cwd)) == IPCOM_SUCCESS)
ipcom_printf("%s"IP_LF, cwd);
else
ipcom_printf("Failed"IP_LF);
continue;
}
if(ipcom_strcmp(sftp_argv[0], "cd") == 0)
{
if(sftp_argc != 2)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(ipssh_sftp_clt_chdir(ssh_conn, sftp_argv[1]) != IPCOM_SUCCESS)
ipcom_printf("Failed"IP_LF);
continue;
}
if(ipcom_strcmp(sftp_argv[0], "ls") == 0)
{
char* path;
void* handle;
Ipssh_dirent* dir_entry;
if( sftp_argc > 2)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(sftp_argc == 2)
path = sftp_argv[1];
else
path = ".";
handle = ipssh_sftp_clt_opendir(ssh_conn, path);
if(!handle)
{
ipcom_printf("Failed"IP_LF);
continue;
}
while((dir_entry=ipssh_sftp_clt_readdir(ssh_conn, handle)) != IP_NULL)
ipcom_printf("%s"IP_LF, dir_entry->longname);
(void)ipssh_sftp_clt_closedir(ssh_conn, handle);
continue;
}
if(ipcom_strcmp(sftp_argv[0], "rm") == 0)
{
if(sftp_argc != 2)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(ipssh_sftp_clt_unlink(ssh_conn, sftp_argv[1]))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "mkdir") == 0)
{
if(sftp_argc != 2)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(ipssh_sftp_clt_mkdir(ssh_conn, sftp_argv[1], 0744))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "rename") == 0)
{
if(sftp_argc != 3)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(ipssh_sftp_clt_rename(ssh_conn, sftp_argv[1], sftp_argv[2]))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "rmdir") == 0)
{
if(sftp_argc != 2)
{
ipcom_printf("Bad args"IP_LF);
continue;
}
if(ipssh_sftp_clt_rmdir(ssh_conn, sftp_argv[1]))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "help") == 0 || ipcom_strcmp(sftp_argv[0], "?") == 0)
{
ipssh_cmd_sftp_sub_usage();
continue;
}
/* Operations on local file system */
if(ipcom_strcmp(sftp_argv[0], "lcd") == 0)
{
if(ipcom_cmd_cd(sftp_argc, sftp_argv))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "lpwd") == 0)
{
if(ipcom_cmd_pwd(sftp_argc, sftp_argv))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "lls") == 0)
{
if(ipcom_cmd_ls(sftp_argc, sftp_argv))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "lrm") == 0)
{
if(ipcom_cmd_rm(sftp_argc, sftp_argv))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "lmkdir") == 0)
{
if(ipcom_cmd_mkdir(sftp_argc, sftp_argv))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "lrmdir") == 0)
{
if(ipcom_cmd_rmdir(sftp_argc, sftp_argv))
{
ipcom_printf("Failed"IP_LF);
}
continue;
}
if(ipcom_strcmp(sftp_argv[0], "quit") == 0 || ipcom_strcmp(sftp_argv[0], "exit") == 0)
{
break;
}
ipcom_printf("Unknown command: %s"IP_LF, sftp_argv[0]);
}
ret_val = IPCOM_SUCCESS;
cleanup:
if(ssh_conn)
(void)ipssh_sftp_clt_close(ssh_conn);
if(gl)
ipcom_getline_exit(gl);
if(bio)
(void)BIO_free(bio);
if(sftp_argv)
ipcom_free(sftp_argv);
return ret_val;
}
#endif /* IPSSH_USE_SFTP_CLT_CMD */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,98 @@
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_connection.h,v $ $Revision: 1.6.52.1 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_connection.h,v $
* $Author: svc-cmnet $ $Date: 2013-03-13 07:45:43 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef ipssh_connection_h
#define ipssh_connection_h
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_list.h>
#include <ipcom_err.h>
#include <ipcom_type.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipssh_pkt_handler ipssh_connection_get_handler(Ip_s32 pkt_type);
/* Functions for processing incoming ssh messages */
IP_GLOBAL Ip_err ipssh_msg_channel_request(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_global_request(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_request_success_msg(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_request_failure_msg(Ipssh_conn* ssh_conn);
/* Misc */
IP_GLOBAL Ip_s32 ipssh_read_terminal_data(Ip_fd stdio_sock, Ipcom_buffer* pkt, Ipssh_channel* channel, Ip_s32 req_bytes);
IP_GLOBAL Ip_s32 ipssh_store_echo_char(Ipcom_buffer* buf, Ipssh_term_modes* term_modes, Ip_u8 chr, Ip_u8* last_chr);
/* Port forwarding */
IP_GLOBAL Ip_err ipssh_port_fwd_listen_handler(Ip_fd sock, Ipssh_conn_ctx* ctx, Ipssh_map_entry* map_entry);
IP_GLOBAL Ip_err ipssh_port_fwd_handler_s2c(Ip_fd sock, Ipssh_conn_ctx* ctx, Ipssh_map_entry* map_entry);
IP_GLOBAL Ip_err ipssh_channel2sock_handler(Ipssh_channel* channel, Ipcom_buffer* msg);
IP_GLOBAL Ip_err ipssh_open_tcp_conn(const char* host, Ip_u32 port, Ip_fd* sock);
IP_GLOBAL Ip_err ipssh_setup_listen_sock(const char* addr_str, Ip_u32 port, Ip_fd* sockp);
IP_GLOBAL void ipssh_set_default_term_modes(Ipssh_term_modes* term_modes);
IP_GLOBAL Ip_err ipssh_shell_exit2(Ipssh_conn* ssh_conn, Ip_fd shell_fd);
IP_GLOBAL Ip_err ipssh_handle_exec_cmd(Ipssh_conn* ssh_conn, Ipssh_channel* channel, const char* exec_cmd);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,83 @@
/*
******************************************************************************
* INTERPEAK HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_connection_v1.h,v $ $Revision: 1.6.52.1 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_connection_v1.h,v $
* $Author: svc-cmnet $ $Date: 2013-03-13 07:45:44 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef IPSSH_CONNECTION_V1_H
#define IPSSH_CONNECTION_V1_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_v1_msg_request_pty(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_exec_cmd(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_exec_shell(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_stdin_data(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_eof(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_window_size(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_port_open(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_port_forward_request(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_channel_close(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_channel_data(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_channel_close_confirmation(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_channel_open_confirmation(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_send_msg_v1_channel_close(Ipssh_conn* ssh_conn, Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_msg_v1_exit_status(Ipssh_conn* ssh_conn, Ip_u32 status);
IP_GLOBAL Ip_err ipssh_port_fwd_handler_s2c_v1(Ip_fd sock, Ipssh_conn_ctx* ctx, Ipssh_map_entry* map_entry);
IP_GLOBAL Ip_err ipssh_port_fwd_listen_handler_v1(Ip_fd sock, Ipssh_conn_ctx* ctx, Ipssh_map_entry* map_entry);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,119 @@
/*
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*
* First, the polynomial itself and its table of feedback terms. The
* polynomial is
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
*
* Note that we take it "backwards" and put the highest-order term in
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
* the MSB being 1
*
* Note that the usual hardware shift register implementation, which
* is what we're using (we're merely optimizing it by doing eight-bit
* chunks at a time) shifts bits into the lowest-order term. In our
* implementation, that means shifting towards the right. Why do we
* do it this way? Because the calculated CRC must be transmitted in
* order from highest-order term to lowest-order term. UARTs transmit
* characters in order from LSB to MSB. By storing the CRC this way
* we hand it to the UART in the order low-byte to high-byte; the UART
* sends each low-bit to hight-bit; and the result is transmission bit
* by bit from highest- to lowest-order term without requiring any bit
* shuffling on our part. Reception works similarly
*
* The feedback terms table consists of 256, 32-bit entries. Notes
*
* The table can be generated at runtime if desired; code to do so
* is shown later. It might not be obvious, but the feedback
* terms simply represent the results of eight shift/xor opera
* tions for all combinations of data and CRC register values
*
* The values must be right-shifted by eight bits by the "updcrc
* logic; the shift must be u_(bring in zeroes). On some
* hardware you could probably optimize the shift in assembler by
* using byte-swap instructions
* polynomial $edb88320
*/
#include "ipssh_h.h"
#ifndef IPCRYPTO
#include <ipcom_type.h>
static Ip_u32 crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/* Return a 32-bit CRC of the contents of the buffer. */
Ip_u32
ipssh_crc32(const Ip_u8* s, Ip_u32 len)
{
Ip_u32 i;
Ip_u32 crc32val;
crc32val = 0;
for (i = 0; i < len; i ++) {
crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
}
return crc32val;
}
#else
int ipssh_crc32_empty_file;
#endif
@@ -0,0 +1,390 @@
/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_evp.c,v $ $Revision: 1.34.12.2 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_evp.c,v $
* $Author: jren $
* $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.h"
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define SIGBLOB_LEN 20
#ifndef SHA_CBLOCK
#define SHA_CBLOCK (16*4)
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_GLOBAL int ipssh_dsa_verify(int type, const Ip_u8* data, unsigned int data_len,
const Ip_u8* sigbuf, unsigned int siglen, void* dsa);
IP_GLOBAL int ipssh_dsa_sign(int type, const unsigned char *dgst, unsigned int dlen,
unsigned char *sig_buf, unsigned int *sig_len, void *dsa);
IP_GLOBAL EVP_MD* ipssh_evp_dss1(void);
#ifdef IPSSH_USE_RSA
IP_GLOBAL Ip_s32 ipssh_rsa_cmp(RSA* key1, RSA* key2);
#endif
IP_GLOBAL Ip_s32 ipssh_dsa_cmp(DSA* key1, DSA* key2);
IP_GLOBAL EVP_CIPHER* ipssh_evp_v1_3des(void);
#ifdef IPSSH_USE_V1
/* SSH v1 ciphers */
IP_STATIC int ipssh_v1_3des_cbc_init(EVP_CIPHER_CTX* ctx, const unsigned char *key, const unsigned char *iv, int enc);
IP_STATIC int ipssh_v1_3des_cbc(EVP_CIPHER_CTX* ctx, unsigned char *out, const unsigned char *in, unsigned int inl);
IP_STATIC int ipssh_v1_3des_cbc_cleanup(EVP_CIPHER_CTX* ctx);
IP_STATIC int ipssh_v1_3des_cbc_ctrl(EVP_CIPHER_CTX* ctx, int type, int arg, void *ptr);
#endif
/****************************************************************************
* 8 DATA
****************************************************************************
*/
#ifdef IPSSH_USE_V1
IP_STATIC EVP_CIPHER ipssh_v1_3des_cbc_st =
{
0, /* NID */
8, /* Block size */
24, /* Key len */
16, /* IV len */
EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH , /* flags */
ipssh_v1_3des_cbc_init,
ipssh_v1_3des_cbc,
ipssh_v1_3des_cbc_cleanup,
256, /* ctx size */
IP_NULL, /* set_asn1_parameters */
IP_NULL, /* get_asn1_parameters */
ipssh_v1_3des_cbc_ctrl,
IP_NULL /* appl data */
};
struct Ipssh_v1_3des_ctx_st
{
EVP_CIPHER_CTX ctx1;
EVP_CIPHER_CTX ctx2;
EVP_CIPHER_CTX ctx3;
};
typedef struct Ipssh_v1_3des_ctx_st Ipssh_v1_3des_ctx;
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_v1_3des_cbc_init
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_v1_3des_cbc_init(EVP_CIPHER_CTX* ctx, const unsigned char *key, const unsigned char *iv, int enc)
{
const unsigned char* key1, *key2, *key3;
Ipssh_v1_3des_ctx* v1_3des_ctx;
v1_3des_ctx = EVP_CIPHER_CTX_get_app_data(ctx);
if(!v1_3des_ctx)
{
v1_3des_ctx = ipcom_malloc(sizeof(Ipssh_v1_3des_ctx));
if(v1_3des_ctx == IP_NULL)
return 0;
EVP_CIPHER_CTX_set_app_data(ctx, v1_3des_ctx);
}
if(!key)
return 0;
if(enc == -1)
enc = ctx->encrypt;
ctx->encrypt = enc;
EVP_CIPHER_CTX_init(&v1_3des_ctx->ctx1);
EVP_CIPHER_CTX_init(&v1_3des_ctx->ctx2);
EVP_CIPHER_CTX_init(&v1_3des_ctx->ctx3);
if(enc)
{
key1 = key;
key3 = key + 16;
}
else
{
key1 = key + 16;
key3 = key;
}
key2 = key + 8;
if(EVP_CipherInit(&v1_3des_ctx->ctx1, EVP_des_cbc(), key1, iv, enc) == 0 ||
EVP_CipherInit(&v1_3des_ctx->ctx2, EVP_des_cbc(), key2, iv+8, !enc) == 0 ||
EVP_CipherInit(&v1_3des_ctx->ctx3, EVP_des_cbc(), key3, iv+16, enc) == 0)
{
ipcom_memset(v1_3des_ctx, 0, sizeof(Ipssh_v1_3des_ctx));
ipcom_free(v1_3des_ctx);
EVP_CIPHER_CTX_set_app_data(ctx, IP_NULL);
return 0;
}
return 1;
}
/*
*===========================================================================
* ipssh_v1_3des_cbc_decrypt
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_v1_3des_cbc(EVP_CIPHER_CTX* ctx, unsigned char *out, const unsigned char *in, unsigned int len)
{
Ipssh_v1_3des_ctx *v1_3des_ctx;
v1_3des_ctx = EVP_CIPHER_CTX_get_app_data(ctx);
ip_assert(v1_3des_ctx);
if(!v1_3des_ctx)
{
IPCOM_LOG0(ERR, "ipssh_v1_3des_cbc_decrypt :: no app data");
return 0;
}
if(EVP_Cipher(&v1_3des_ctx->ctx1, out, in, len) == 0 ||
EVP_Cipher(&v1_3des_ctx->ctx2, out, out, len) == 0 ||
EVP_Cipher(&v1_3des_ctx->ctx3, out, out, len) == 0)
{
return 0;
}
return 1;
}
/*
*===========================================================================
* ipssh_v1_3des_cbc_cleanup
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_v1_3des_cbc_cleanup(EVP_CIPHER_CTX* ctx)
{
Ipssh_v1_3des_ctx *v1_3des_ctx;
v1_3des_ctx = EVP_CIPHER_CTX_get_app_data(ctx);
if(v1_3des_ctx)
{
(void)EVP_CIPHER_CTX_cleanup(&v1_3des_ctx->ctx1);
(void)EVP_CIPHER_CTX_cleanup(&v1_3des_ctx->ctx2);
(void)EVP_CIPHER_CTX_cleanup(&v1_3des_ctx->ctx3);
ipcom_memset(v1_3des_ctx, 0, sizeof(Ipssh_v1_3des_ctx));
ipcom_free(v1_3des_ctx);
EVP_CIPHER_CTX_set_app_data(ctx, IP_NULL);
}
return 1;
}
/*
*===========================================================================
* ipssh_v1_3des_cbc_ctrl
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_v1_3des_cbc_ctrl(EVP_CIPHER_CTX* ctx, int type, int arg, void *ptr)
{
(void) ctx;
(void) type;
(void) arg;
(void) ptr;
IP_PANIC();
return IPCOM_SUCCESS;
}
#endif /* IPSSH_USE_V1 */
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_rsa_cmp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
#ifdef IPSSH_USE_RSA
IP_GLOBAL Ip_s32
ipssh_rsa_cmp(RSA* key1, RSA* key2)
{
if(BN_cmp(key1->n, key2->n) || BN_cmp(key1->e, key2->e))
return 0;
else
return 1;
}
#endif
/*
*===========================================================================
* ipssh_dsa_cmp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_s32
ipssh_dsa_cmp(DSA* key1, DSA* key2)
{
if( BN_cmp(key1->p,key2->p) || BN_cmp(key1->q,key2->q) || BN_cmp(key1->g,key2->g) )
return 0;
if( BN_cmp(key1->pub_key, key2->pub_key) )
return 0;
else
return 1;
}
/*
*===========================================================================
* ipssh_evp_pkey_cmp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_s32
ipssh_evp_pkey_cmp(EVP_PKEY* key1, EVP_PKEY* key2)
{
if(key1->type != key2->type)
return 0;
switch(key1->type)
{
#ifdef IPSSH_USE_RSA
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
return ipssh_rsa_cmp(key1->pkey.rsa, key2->pkey.rsa);
#endif
case EVP_PKEY_DSA:
case EVP_PKEY_DSA2:
case EVP_PKEY_DSA3:
case EVP_PKEY_DSA4:
return ipssh_dsa_cmp(key1->pkey.dsa, key2->pkey.dsa);
default:
return -1;
}
}
/*
*===========================================================================
* ipssh_evp_v1_3des
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
#ifdef IPSSH_USE_V1
IP_GLOBAL EVP_CIPHER*
ipssh_evp_v1_3des(void)
{
return &ipssh_v1_3des_cbc_st;
}
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
+954
View File
@@ -0,0 +1,954 @@
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_h.h,v $ $Revision: 1.65.10.13 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_h.h,v $
* $Author: svc-cmnet $ $Date: 2018-09-12 23:36:06 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef ipssh_h_h
#define ipssh_h_h
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#if defined(IPCRYPTO) || defined(IP_PORT_OSE5)
#define IPCOM_USE_CLIB_PROTO
#endif
#include <ipssh_config.h>
#include <ipssh.h>
#include <ipcom_type.h>
#include <ipcom_list.h>
#include <ipcom_buffer.h>
#include <ipcom_sock.h>
#include <ipcom_os.h>
#include <ipcom_shell.h>
#include <ipcom_sysvar.h>
#include "ipssh_list.h"
#include "ipssh_channel.h"
#include <openssl/bn.h>
#ifdef IPSSH_USE_RSA
#include <openssl/rsa.h>
#endif
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPSSH
#define IPCOM_SYSLOG_PRIORITY IPSSH_SYSLOG_PRIORITY
/*
*===========================================================================
* IPSSH_MAX_LISTEN_PORTS
*===========================================================================
* Maximum number of ports the daemon shall be able to listen on.
*/
#define IPSSH_MAX_LISTEN_PORTS 5
/*
*===========================================================================
* IPSSH_MAX_PKT_SIZE
*===========================================================================
* Maximum size of SSH packets we accept.
*/
#define IPSSH_MAX_PKT_SIZE 35000
/*
*===========================================================================
* IPSSH_CH_WIN_SIZE
*===========================================================================
* The initial size of ssh channel window size.
*
* Reduce this with caution.
* Some SSH clients have bugs in the channel window size handling that will
* erroneusly truncate data if the window size is smaller than the data to
* be sent.
*/
#define IPSSH_CH_WIN_SIZE (64*1024)
/*
*===========================================================================
* IPSSH_CH_MAX_PKT
*===========================================================================
* When an SSH channel is opened both parties tell the peer the maximum
* packet size it can handle.
*/
#define IPSSH_CH_MAX_PKT (32*1024)
/*
*===========================================================================
* IPSSH_SFTP_MAX_PATH
*===========================================================================
* Maximum length of paths in the sftp protocol
*/
#define IPSSH_SFTP_MAX_PATH 256
/*
*===========================================================================
* IPSSH_MAX_PAD
*===========================================================================
* The maximum no of padding bytes: largest blocksize + 3
*
*/
#define IPSSH_MAX_PAD (16+3)
/*
*===========================================================================
* IPSSH_SUPPORT_LONG_BANNER
*===========================================================================
* Define to enable supporting long Login Banner on IPSSH, or its maximum
* length only can be 255 bytes.
#define IPSSH_SUPPORT_LONG_BANNER
*/
/* Maximum size in bytes of signature blob */
#define IPSSH_SIG_LEN 20 /* TODO: Rename this define? */
#define IPSSH_MAX_INT_LEN 100
#define IPSSH_VERSION "6.9.0"
#define IPSSH_VERSION_STRING_MAX_LEN 255
#define IPSSH_NONE_STR "none"
/* Ciphers */
#define IPSSH_ENC_NONE_STR IPSSH_NONE_STR
#define IPSSH_ENC_3DES_CBC_STR "3des-cbc"
#define IPSSH_ENC_DES_CBC_STR "des-cbc"
#define IPSSH_ENC_BLOWFISH_CBC_STR "blowfish-cbc"
#define IPSSH_ENC_TWOFISH_CBC_STR "twofish-cbc"
#define IPSSH_ENC_AES128_CBC_STR "aes128-cbc"
#define IPSSH_ENC_AES192_CBC_STR "aes192-cbc"
#define IPSSH_ENC_AES256_CBC_STR "aes256-cbc"
#define IPSSH_ENC_ARCFOUR_STR "arcfour"
#define IPSSH_ENC_ARCFOUR128_STR "arcfour128"
#define IPSSH_ENC_CAST128_CBC_STR "cast128-cbc"
#define IPSSH_ID_END 0
#define IPSSH_ID_UNKNOWN 0xfe
#define IPSSH_ID_ERR 0xff
#define IPSSH_NONE_ID 1
#define IPSSH_ENC_ID_BASE 10
#define IPSSH_ENC_NONE_ID 1 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_3DES_CBC_ID 2 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_DES_CBC_ID 3 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_BLOWFISH_CBC_ID 4 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_TWOFISH_CBC_ID 5 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_AES128_CBC_ID 6 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_AES192_CBC_ID 7 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_AES256_CBC_ID 8 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_ARCFOUR_ID 9 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_ARCFOUR_128_ID 10 + IPSSH_ENC_ID_BASE
#define IPSSH_ENC_CAST128_CBC_ID 11 + IPSSH_ENC_ID_BASE
#define IPSSH_V1_CIPHER_NONE 0
#define IPSSH_V1_CIPHER_IDEA 1
#define IPSSH_V1_CIPHER_DES 2
#define IPSSH_V1_CIPHER_3DES 3
#define IPSSH_V1_CIPHER_RC4 5
#define IPSSH_V1_CIPHER_BLOWFISH 6
/* Key exchange methods */
#define IPSSH_KEYEX_DH_GR1_SHA1_STR "diffie-hellman-group1-sha1"
#define IPSSH_KEYEX_DH_GR14_SHA1_STR "diffie-hellman-group14-sha1"
#define IPSSH_KEYEX_DH_GEX_SHA1_STR "diffie-hellman-group-exchange-sha1"
#define IPSSH_KEYEX_DH_GEX_SHA256_STR "diffie-hellman-group-exchange-sha256"
#define IPSSH_KEYEX_RSA1024_SHA1_STR "rsa1024-sha1"
#define IPSSH_KEYEX_RSA2048_SHA256_STR "rsa2048-sha256"
#define IPSSH_KEYEX_ID_BASE 30
#define IPSSH_KEYEX_DH_GR1_SHA1_ID (0 + IPSSH_KEYEX_ID_BASE)
#define IPSSH_KEYEX_DH_GR14_SHA1_ID (1 + IPSSH_KEYEX_ID_BASE)
#define IPSSH_KEYEX_DH_GEX_SHA1_ID (2 + IPSSH_KEYEX_ID_BASE)
#define IPSSH_KEYEX_DH_GEX_SHA256_ID (3 + IPSSH_KEYEX_ID_BASE)
#define IPSSH_KEYEX_RSA1024_SHA1_ID (4 + IPSSH_KEYEX_ID_BASE)
#define IPSSH_KEYEX_RSA2048_SHA256_ID (5 + IPSSH_KEYEX_ID_BASE)
/* Server key algorithms */
#define IPSSH_DSA_STR "ssh-dss"
#define IPSSH_RSA_STR "ssh-rsa"
#define IPSSH_SERVER_KEY_BASE 40
#define IPSSH_DSA_ID 0 + IPSSH_SERVER_KEY_BASE
#define IPSSH_RSA_ID 1 + IPSSH_SERVER_KEY_BASE
#define IPSSH_V1_RSA_ID 2 + IPSSH_SERVER_KEY_BASE
/* MAC algorithms */
#define IPSSH_MAC_SHA1_STR "hmac-sha1"
#define IPSSH_MAC_SHA1_96_STR "hmac-sha1-96"
#define IPSSH_MAC_SHA256_STR "hmac-sha2-256"
#define IPSSH_MAC_SHA512_STR "hmac-sha2-512"
#define IPSSH_MAC_MD5_STR "hmac-md5"
#define IPSSH_MAC_MD5_96_STR "hmac-md5-96"
#define IPSSH_MAC_NONE_STR IPSSH_NONE_STR
#define IPSSH_MAC_ID_BASE 50
#define IPSSH_MAC_NONE_ID 0 + IPSSH_MAC_ID_BASE
#define IPSSH_MAC_SHA1_ID 1 + IPSSH_MAC_ID_BASE
#define IPSSH_MAC_SHA1_96_ID 2 + IPSSH_MAC_ID_BASE
#define IPSSH_MAC_MD5_ID 3 + IPSSH_MAC_ID_BASE
#define IPSSH_MAC_MD5_96_ID 4 + IPSSH_MAC_ID_BASE
#define IPSSH_MAC_SHA256_ID 5 + IPSSH_MAC_ID_BASE
#define IPSSH_MAC_SHA512_ID 6 + IPSSH_MAC_ID_BASE
/* Compression methods */
#define IPSSH_COMPR_NONE_STR IPSSH_NONE_STR
#define IPSSH_COMPR_ID_BASE 60
#define IPSSH_COMPR_NONE_ID 0 + IPSSH_COMPR_ID_BASE
#define IPSSH_FLAG_ALG_ENC 1
#define IPSSH_FLAG_ALG_MAC 2
#define IPSSH_FLAG_ALG_KEX 4
#define IPSSH_FLAG_ALG_SRV_KEY 8
#define IPSSH_FLAG_ALG_COMPR 16
#define IPSSH_FLAG_ALG_NOT_ALLOWED_IN_FIPS_MODE 32
#define IPSSH_HANDSHAKE_MSG_FLAG_SAVE_VER_STR 1
/* Service names */
#define IPSSH_USERAUTH_STR "ssh-userauth"
#define IPSSH_CONNECTION_STR "ssh-connection"
#define IPSSH_SFTP_STR "sftp"
#define IPSSH_SUBSYSTEM_STR "subsystem"
/* Authentication methods */
#define IPSSH_PW_AUTH_STR "password"
#define IPSSH_PUBKEY_AUTH_STR "publickey"
#define IPSSH_HOSTBASED_AUTH_STR "hostbased"
#define IPSSH_AUTH_METH_NONE 0
#define IPSSH_AUTH_METH_PUBLIC_KEY 1
#define IPSSH_AUTH_METH_PW 2
#define IPSSH_AUTH_METH_HOSTBASED 4
#define IPSSH_V1_RSA_AUTH 2
#define IPSSH_V1_PW_AUTH 3
/* Channel types */
#define IPSSH_SESSION "session"
#define IPSSH_DIRECT_TCPIP "direct-tcpip"
#define IPSSH_TCPIP_FWD "tcpip-forward"
#define IPSSH_FORWARDED_TCPIP "forwarded-tcpip"
#define IPSSH_CANCEL_TCPIP_FWD "cancel-tcpip-forward"
/* Reason codes */
#define IPSSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
#define IPSSH_OPEN_CONNECT_FAILED 2
#define IPSSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
#define IPSSH_OPEN_RESOURCE_SHORTAGE 4
/* Message number, SSH version 1 */
#define IPSSH_MSG_V1_NONE 0
#define IPSSH_MSG_V1_DISCONNECT 1
#define IPSSH_SMSG_V1_PUBLIC_KEY 2
#define IPSSH_CMSG_V1_SESSION_KEY 3
#define IPSSH_CMSG_V1_USER 4
#define IPSSH_CMSG_V1_AUTH_RHOSTS 5
#define IPSSH_CMSG_V1_AUTH_RSA 6
#define IPSSH_SMSG_V1_AUTH_RSA_CHALLENGE 7
#define IPSSH_CMSG_V1_AUTH_RSA_RESPONSE 8
#define IPSSH_CMSG_V1_AUTH_PASSWORD 9
#define IPSSH_CMSG_V1_REQUEST_PTY 10
#define IPSSH_CMSG_V1_WINDOW_SIZE 11
#define IPSSH_CMSG_V1_EXEC_SHELL 12
#define IPSSH_CMSG_V1_EXEC_CMD 13
#define IPSSH_SMSG_V1_SUCCESS 14
#define IPSSH_SMSG_V1_FAILURE 15
#define IPSSH_CMSG_V1_STDIN_DATA 16
#define IPSSH_SMSG_V1_STDOUT_DATA 17
#define IPSSH_SMSG_V1_STDERR_DATA 18
#define IPSSH_CMSG_V1_EOF 19
#define IPSSH_SMSG_V1_EXITSTATUS 20
#define IPSSH_MSG_V1_CHANNEL_OPEN_CONFIRMATION 21
#define IPSSH_MSG_V1_CHANNEL_OPEN_FAILURE 22
#define IPSSH_MSG_V1_CHANNEL_DATA 23
#define IPSSH_MSG_V1_CHANNEL_CLOSE 24
#define IPSSH_MSG_V1_CHANNEL_CLOSE_CONFIRMATION 25
#define IPSSH_SMSG_V1_X11_OPEN 27
#define IPSSH_CMSG_V1_PORT_FORWARD_REQUEST 28
#define IPSSH_MSG_V1_PORT_OPEN 29
#define IPSSH_CMSG_V1_AGENT_REQUEST_FORWARDING 30
#define IPSSH_SMSG_V1_AGENT_OPEN 31
#define IPSSH_MSG_V1_IGNORE 32
#define IPSSH_CMSG_V1_EXIT_CONFIRMATION 33
#define IPSSH_CMSG_V1_X11_REQUEST_FORWARDING 34
#define IPSSH_CMSG_V1_AUTH_RHOSTS_RSA 35
#define IPSSH_MSG_V1_DEBUG 36
#define IPSSH_CMSG_V1_REQUEST_COMPRESSION 37
#define IPSSH_CMSG_V1_MAX_PACKET_SIZE 38
#define IPSSH_CMSG_V1_AUTH_TIS 39
#define IPSSH_SMSG_V1_AUTH_TIS_CHALLENGE 40
#define IPSSH_CMSG_V1_AUTH_TIS_RESPONSE 41
#define IPSSH_CMSG_V1_AUTH_KERBEROS 42
#define IPSSH_SMSG_V1_AUTH_KERBEROS_RESPONSE 43
#define IPSSH_CMSG_V1_HAVE_KERBEROS_TGT 44
/* Message numbers, transport protocol */
#define IPSSH_MSG_DISCONNECT 1
#define IPSSH_MSG_IGNORE 2
#define IPSSH_MSG_UNIMPLEMENTED 3
#define IPSSH_MSG_DEBUG 4
#define IPSSH_MSG_SERVICE_REQUEST 5
#define IPSSH_MSG_SERVICE_ACCEPT 6
#define IPSSH_MSG_KEXINIT 20
#define IPSSH_MSG_NEWKEYS 21
#define IPSSH_MSG_KEXDH_INIT 30
#define IPSSH_MSG_KEXDH_REPLY 31
#define IPSSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
#define IPSSH_MSG_KEX_DH_GEX_REQUEST 34
#define IPSSH_MSG_KEX_DH_GEX_GROUP 31
#define IPSSH_MSG_KEX_DH_GEX_INIT 32
#define IPSSH_MSG_KEX_DH_GEX_REPLY 33
/* RFC 4432 */
#define IPSSH_MSG_KEX_RSA_PUBKEY 30
#define IPSSH_MSG_KEX_RSA_SECRET 31
#define IPSSH_MSG_KEX_RSA_DONE 32
/* Message numbers, authentication protocol */
#define IPSSH_MSG_USERAUTH_REQUEST 50
#define IPSSH_MSG_USERAUTH_FAILURE 51
#define IPSSH_MSG_USERAUTH_SUCCESS 52
#define IPSSH_MSG_USERAUTH_BANNER 53
#define IPSSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60
#define IPSSH_MSG_USERAUTH_PK_OK 60
/* Message numbers, connect protocol */
#define IPSSH_MSG_GLOBAL_REQUEST 80
#define IPSSH_MSG_REQUEST_SUCCESS 81
#define IPSSH_MSG_REQUEST_FAILURE 82
#define IPSSH_MSG_CHANNEL_OPEN 90
#define IPSSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
#define IPSSH_MSG_CHANNEL_OPEN_FAILURE 92
#define IPSSH_MSG_CHANNEL_WINDOW_ADJUST 93
#define IPSSH_MSG_CHANNEL_DATA 94
#define IPSSH_MSG_CHANNEL_EXTENDED_DATA 95
#define IPSSH_MSG_CHANNEL_EOF 96
#define IPSSH_MSG_CHANNEL_CLOSE 97
#define IPSSH_MSG_CHANNEL_REQUEST 98
#define IPSSH_MSG_CHANNEL_SUCCESS 99
#define IPSSH_MSG_CHANNEL_FAILURE 100
/* Request types */
#define IPSSH_SHELL "shell"
#define IPSSH_PTY_REQ "pty-req"
#define IPSSH_WIN_CHANGE "window-change"
#define IPSSH_X11_REQ "x11-req"
#define IPSSH_EXEC "exec"
#define IPSSH_EXIT_STATUS "exit-status"
/* Reason codes, disconnect message */
#define IPSSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
#define IPSSH_DISCONNECT_PROTOCOL_ERROR 2
#define IPSSH_DISCONNECT_KEY_EXCHANGE_FAILED 3
#define IPSSH_DISCONNECT_RESERVED 4
#define IPSSH_DISCONNECT_MAC_ERROR 5
#define IPSSH_DISCONNECT_COMPRESSION_ERROR 6
#define IPSSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7
#define IPSSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8
#define IPSSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9
#define IPSSH_DISCONNECT_CONNECTION_LOST 10
#define IPSSH_DISCONNECT_BY_APPLICATION 11
#define IPSSH_DISCONNECT_TOO_MANY_CONNECTIONS 12
#define IPSSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13
#define IPSSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14
#define IPSSH_DISCONNECT_ILLEGAL_USER_NAME 15
/* Flags */
#define IPSSH_FLAG_NO_CLOSE 1
#define IPSSH_FLAG_BUG_UNRESTRICTED_SFTP_MSG_SIZE 1
/* Connection states */
#define IPSSH_CONN_STATE_SERVICE_REQ 1
#define IPSSH_CONN_STATE_SERVICE_ACCEPT 1 << 1
/* Version 2 states */
#define IPSSH_CONN_STATE_SRV_KEX_INIT 1 << 3
#define IPSSH_CONN_STATE_SRV_KEX_DH_INIT 1 << 4
#define IPSSH_CONN_STATE_SRV_KEX_GEX 1 << 5
#define IPSSH_CONN_STATE_SRV_KEX_RSA 1 << 6
#define IPSSH_CONN_STATE_SRV_NEW_KEY 1 << 7
#define IPSSH_CONN_STATE_SRV_SSH_SFTP 1 << 8
#define IPSSH_CONN_STATE_SRV_USER_AUTH 1 << 10
#define IPSSH_CONN_STATE_SRV_TERM 1 << 11
#define IPSSH_CONN_STATE_CLT_USER_AUTH_START 1 << 15
#define IPSSH_CONN_STATE_CLT_USER_AUTH 1 << 16
#define IPSSH_CONN_STATE_CLT_CONNECTED 1 << 17
/* Version 1 states */
#define IPSSH_CONN_STATE_SRV_KEY_EX_V1 1 << 28
#define IPSSH_CONN_STATE_SRV_PENDING_REQUEST 1 << 29
#define IPSSH_CONN_STATE_ALL -1
#define IPSSH_SET_LEN_PTR(ptr, len) do { \
ptr[0] = (Ip_u8) (((len) >> 24) & 0xff);\
ptr[1] = (Ip_u8) (((len) >> 16) & 0xff);\
ptr[2] = (Ip_u8) (((len) >> 8) & 0xff);\
ptr[3] = (Ip_u8) ((len) & 0xff); \
} while(0)
#define IPSSH_SET_32_PTR(ptr, len) do { \
((Ip_u8*)ptr)[0] = (Ip_u8) (((len) >> 24) & 0xff);\
((Ip_u8*)ptr)[1] = (Ip_u8) (((len) >> 16) & 0xff);\
((Ip_u8*)ptr)[2] = (Ip_u8) (((len) >> 8) & 0xff);\
((Ip_u8*)ptr)[3] = (Ip_u8) ((len) & 0xff); \
} while(0)
#define IPSSH_SET_16_PTR(ptr, value) do { \
((Ip_u8*)ptr)[0] = (Ip_u8) (((value) >> 8) & 0xff);\
((Ip_u8*)ptr)[1] = (Ip_u8) ((value) & 0xff);\
} while(0)
#define IPSSH_GET_32_PTR(ptr) \
(Ip_u32)((ptr)[0] << 24) + \
(Ip_u32)((ptr)[1] << 16) + \
(Ip_u32)((ptr)[2] << 8) + \
(Ip_u32)(ptr)[3]
#define IPSSH_GET_LEN(ptr) IPSSH_GET_32_PTR(ptr)
#define IPSSH_GET_STR_LEN(sshstr) ipssh_get_len(sshstr)
#define IPSSH_GET_STR_PTR(sshstr) (&(sshstr[4]))
#define IPSSH_GET_MPINT_LEN(mp_int) ipssh_get_len(mp_int)
#define IPSSH_GET_MPINT_VALUE(mp_int) (&(mp_int[4]))
#define IPSSH_SET_MPINT_LEN(mp_int, len) IPSSH_SET_LEN_PTR(mp_int, len)
/* Used to mark the type of data to hash, in the hash-data list */
#define IPSSH_MPINT 1
#define IPSSH_STR 2
#define IPSSH_CHAR 3
#define IPSSH_RAW 4
#define IPSSH_INT 5
#define IPSSH_NOT_COMPL_PKT 1
#define IPSSH_DISPATCH_PKT 2
#define IPSSH_ERR -1
#define IPSSH_BAD_MAC -2
/* Terminal modes SSH v1 */
#define IPSSH_TTY_OP_END 0
/* Terminal modes SSH */
#define IPSSH_INLCR 34 /* Map NL into CR on input. */
#define IPSSH_IGNCR 35 /* Ignore CR on input. */
#define IPSSH_ICRNL 36 /* Map CR to NL on input. */
#define IPSSH_ONLCR 72 /* Translate newline to carriage return-newline (output) */
/* Name of ipssh daemon process */
#define IPSSH_DAEMON_NAME "ipsshd"
#define IPSSH_MODE_UNDEF 0
#define IPSSH_MODE_CLT 1
#define IPSSH_MODE_SRV 2
#define IPSSH_PORT_FWD_EVENT_OPEN 1
#define IPSSH_PORT_FWD_EVENT_LISTEN 2
#define IPSSH_PORT_FWD_EVENT_CLOSE 3
#define IPSSH_PORT_FWD_EVENT_SEND_WINDOW_OPEN 4
#define IPSSH_PORT_FWD_EVENT_SEND_WINDOW_CLOSED 5
/*
*===========================================================================
* IPSSH code lock
*===========================================================================
*/
#ifdef IPSSH_ASSERT
#define IPSSH_CODE_ISLOCKED_ASSERT() ip_assert(g_ipssh.code_mutex_count == 1)
#define IPSSH_CODE_LOCK() do { ip_assert(g_ipssh.code_lock_owner != ipcom_getpid()); \
ipcom_mutex_lock(g_ipssh.code_mutex); \
g_ipssh.code_lock_owner = ipcom_getpid(); \
ip_assert(g_ipssh.code_mutex_count == 0); \
g_ipssh.code_mutex_count++; \
} while(0)
#define IPSSH_CODE_UNLOCK() do { ip_assert(g_ipssh.code_mutex_count == 1); \
g_ipssh.code_mutex_count--; \
g_ipssh.code_lock_owner = 0; \
ipcom_mutex_unlock(g_ipssh.code_mutex); \
} while(0)
#else
#define IPSSH_CODE_ISLOCKED_ASSERT() IP_NOOP
#define IPSSH_CODE_LOCK() ipcom_mutex_lock(g_ipssh.code_mutex)
#define IPSSH_CODE_UNLOCK() ipcom_mutex_unlock(g_ipssh.code_mutex)
#endif
#if defined(IPCOM_USE_INET) && defined(IPCOM_USE_INET6) && defined(IPLITE)
#define IPSSH_V6_MAPPED_V4_ADDR_NOT_SUPPORTED
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/* Forward declarations */
struct Ipssh_srv_ctx_st;
struct Ipssh_conn_st;
struct Ipssh_conn_ctx_st;
struct Ipssh_channel_st;
typedef struct
{
Ip_s32 len;
Ip_u8* value;
} Ipssh_mp_int;
typedef struct Ipssh_msg_list_st
{
Ipcom_list list;
Ip_u8 hash_pos;
Ip_u8 type;
Ip_size_t msg_len;
Ip_u8* value;
} Ipssh_msg_list;
#ifdef _WRS_CONFIG_COMPONENT_IPSSH_SUPPORT_SHA2
struct Ipssh_conn_prop_st
{
Ip_u8 kex_alg[16];
Ip_u8 srv_host_key_alg[8];
Ip_u8 enc_alg_clt2srv[32];
Ip_u8 enc_alg_srv2clt[32];
Ip_u8 mac_alg_clt2srv[16];
Ip_u8 mac_alg_srv2clt[16];
Ip_u8 compr_alg_clt2srv[8];
Ip_u8 compr_alg_srv2clt[8];
Ip_u8 lang_clt2srv[4];
Ip_u8 lang_srv2clt[4];
};
#else
struct Ipssh_conn_prop_st
{
Ip_u8 kex_alg[8];
Ip_u8 srv_host_key_alg[4];
Ip_u8 enc_alg_clt2srv[16];
Ip_u8 enc_alg_srv2clt[16];
Ip_u8 mac_alg_clt2srv[8];
Ip_u8 mac_alg_srv2clt[8];
Ip_u8 compr_alg_clt2srv[4];
Ip_u8 compr_alg_srv2clt[4];
Ip_u8 lang_clt2srv[4];
Ip_u8 lang_srv2clt[4];
};
#endif
typedef struct Ipssh_conn_prop_st Ipssh_conn_prop;
struct Ipssh_conn_config_st
{
/* Config */
Ip_u8 v1;
Ip_u8 v2;
/* Services, on/off */
Ip_u8 term;
Ip_u8 sftp;
Ip_u8 port_fwd;
/* Authentication */
Ip_u8 auth_none_allowed;
Ip_u8 pw_allowed;
Ip_u8 pw_required;
Ip_u8 pub_key_allowed;
Ip_u8 pub_key_required;
Ip_u8 pub_key_first;
Ip_u8 hostbased_allowed;
Ip_u8 hostbased_required;
Ip_u8 pad[3];
int max_fail;
int v1_auth_meth;
int max_channels;
/* v1 config */
int v1_enc_algs;
/* v2 config */
struct Ipssh_conn_prop_st v2_algs;
char sftp_start_dir[IPSSH_SFTP_MAX_PATH];
#ifdef IPSSH_SUPPORT_LONG_BANNER
char *auth_banner;
#else
char auth_banner[IPSSH_AUTH_BANNER_MAX_LEN];
#endif
/* Clt config parameters for group key exchange */
int gex_min;
int gex_n;
int gex_max;
};
typedef struct Ipssh_conn_config_st Ipssh_conn_config;
struct Ipssh_srv_ctx_st
{
#ifdef IPSSH_USE_RSA
RSA* rsa_key;
RSA* rsa_keyex_key;
#endif
DSA* dsa_key;
/* Config */
int port[IPSSH_MAX_LISTEN_PORTS];
int idle_timeout;
int max_clients;
Ipssh_conn_config config;
int ref;
};
typedef struct Ipssh_srv_ctx_st Ipssh_srv_ctx;
typedef struct Ipssh_data_st
{
Ipcom_list clt_list; /* A list of Ipssh_conn_ctx */
Ipcom_mutex code_mutex;
Ipcom_list subsystem_init_cb_list;
#ifdef IPSSH_ASSERT
int code_mutex_count;
Ip_pid_t code_lock_owner;
#endif
Ip_u16 task_name_id; /* To avoid same SSH task name, add once created a new task */
} Ipssh_data;
struct Ipssh_conn_ctx_st;
struct Ipssh_map_entry_st;
typedef Ip_err (*Ipssh_sock_handler)(Ip_fd sock,
struct Ipssh_conn_ctx_st* ctx,
struct Ipssh_map_entry_st* map_entry);
typedef Ip_err (*Ipssh_pkt_handler)(struct Ipssh_conn_st* ssh_conn);
struct Ipssh_map_entry_st
{
Ipcom_list list;
Ip_fd sock;
struct Ipssh_conn_ctx_st* ctx;
Ipssh_sock_handler handler;
int flags;
};
typedef struct Ipssh_map_entry_st Ipssh_map_entry;
typedef Ipcom_list Ipssh_ctx_map;
typedef struct
{
BIGNUM* e;
BIGNUM* f;
DH* dh;
} Ipssh_kex_dh_data;
typedef struct
{
Ip_u8* key;
Ip_s32 len;
Ip_s32 alloc;
} Ipssh_key;
typedef struct
{
Ipssh_key iv_c2s;
Ipssh_key iv_s2c;
Ipssh_key key_c2s;
Ipssh_key key_s2c;
Ipssh_key mac_key_c2s;
Ipssh_key mac_key_s2c;
Ipssh_key mac_key_c2s_active;
Ipssh_key mac_key_s2c_active;
} Ipssh_key_mtrl;
typedef struct Ipssh_port_fwd_addr_map_st
{
Ipcom_list list;
Ip_fd sock;
char* addr;
Ip_u32 port;
} Ipssh_port_fwd_addr_map;
struct Ipssh_conn_ctx_st
{
Ipcom_list list;
struct Ipssh_conn_st* ssh_conn;
Ip_pid_t pid;
char* version_str; /* Holds version string received from client */
char* clt_id; /* Holds name of clt implementation (from ver str) */
Ip_fd_set read_set;
Ip_fd_set write_set;
Ipssh_ctx_map ctx_map;
Ipssh_srv_ctx* srv_ctx;
#ifdef IPSSH_USE_STOP_SPAWN
/* Socket used to implement termination of spawned ipssh processes */
Ip_fd stop_sock;
Ip_u16 stop_port;
#endif
};
typedef struct Ipssh_conn_ctx_st Ipssh_conn_ctx;
typedef struct Ipssh_spawn_args_st
{
Ip_fd sock;
Ipssh_srv_ctx* srv_ctx;
} Ipssh_spawn_args;
typedef struct Ipssh_daemon_args_st
{
void* config;
} Ipssh_daemon_args;
typedef Ip_err (*Ipssh_port_fwd_cb)(struct Ipssh_conn_st* ssh_conn, Ip_fd port_fwd_sock, int event);
struct Ipssh_mac_st
{
const EVP_MD* md;
int use_bits;
};
typedef struct Ipssh_mac_st Ipssh_mac;
struct Ipssh_clt_conn_st
{
/* Authentication parameters */
char userid[32];
char pw[32];
int auth_flags;
EVP_PKEY* srv_pub_key;
EVP_PKEY* key; /* For public key authentication */
EVP_PKEY* host_key; /* For hostbased authentication */
struct Ipssh_channel_st* channel;
};
typedef struct Ipssh_clt_conn_st Ipssh_clt_conn;
struct Ipssh_srv_conn_st
{
#ifdef IPSSH_USE_RSA
struct rsa_st* rsa_key;
#endif
struct dsa_st* dsa_key;
};
typedef struct Ipssh_srv_conn_st Ipssh_srv_conn;
union Ipssh_clt_srv_st
{
Ipssh_clt_conn clt;
Ipssh_srv_conn srv;
};
struct Ipssh_conn_st
{
Ip_fd sock;
struct Ipssh_conn_config_st config;
Ipssh_conn_ctx* ssh_conn_ctx;
int conn_state;
int post_kex_conn_state;
int mode; /* clt or srv */
union Ipssh_clt_srv_st data;
/* Server keys */
#ifdef IPSSH_USE_RSA
RSA* srv_rsa_key;
RSA* srv_rsa_keyex_key;
#endif
DSA* srv_dsa_key;
Ipcom_buffer* recv_enc_buf; /* Holds received data. In encrypted form */
Ipcom_buffer* recv_plain_buf; /* Holds received data, decrypted */
Ip_bool complete_pkt_read;
EVP_CIPHER_CTX send_ctx;
EVP_CIPHER_CTX recv_ctx;
HMAC_CTX send_hmac_ctx;
HMAC_CTX recv_hmac_ctx;
Ipssh_mac send_mac;
Ipssh_mac recv_mac;
Ip_u8 first_kex_pkt_follows;
Ip_bool kexinit_sent;
Ip_bool kexinit_received;
Ip_u8 v2_cookie[16];
Ipssh_conn_prop conn_prop; /* These are the algs currently used */
Ipssh_conn_prop conn_prop_pending; /* These are the algs being negotiated */
Ipssh_conn_prop peer_proposal; /* These are the algs the peer proposed in the SSH handshake */
const EVP_MD* (*hash_func)(void);
Ip_u8* shared_secret; /* Denoted K in spec */
Ip_s32 secr_len; /* Length of shared secret */
Ip_u8* hash; /* Denoted H in spec */
Ip_u32 hash_len;
Ipssh_key_mtrl key_mtrl;
Ipcom_list handshake_msgs;
int ssh_version;
/* Session id */
Ip_u8* sess_id;
Ip_s32 sess_id_len;
/* Key exchange variables */
Ipssh_kex_dh_data* dh_data;
Ip_s32 skip_guessed_kex_pkt;
Ip_bool dh_gex_old; /* Client uses the old group exchange */
/* User authentication data */
char* user;
char* service;
int auth_meth;
int auth_failure_count;
int auth_state;
Ip_bool auth_banner_sent;
Ipcom_shell_ctx* sh_ctx;
Ip_u32 seq_no_recv;
Ip_u32 seq_no_send;
/* Channels pertaining to this ssh connection */
Ipssh_channel_map ch_map;
/* Port forwarding data */
Ipcom_list port_fwd_addr_map;
Ipssh_port_fwd_cb port_fwd_cb;
int no_channels; /* Number of currently open channels */
Ip_u32 flags;
/* Version 1 data */
#ifdef IPSSH_USE_V1
RSA* server_key;
RSA* client_pub_key;
Ip_u8 cipher;
Ip_u8 v1_cookie[8];
Ip_u8 session_key[32];
Ip_u8 session_id_v1[16];
Ip_u8 rsa_challenge[32];
Ipssh_channel* stdio_channel;
Ip_u32 v1_pad_len;
#endif
void* extra;
};
typedef struct Ipssh_conn_st Ipssh_conn;
IP_EXTERN Ipssh_data g_ipssh;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL void ipssh_conn_free(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL Ip_err ipssh_conn_init(struct Ipssh_conn_st* ssh_conn);
IP_GLOBAL const char* ipssh_alg_id2str(Ip_u8 id);
IP_GLOBAL Ip_err ipssh_alg_list_str2id(const char* str_list_org, Ip_u8* id_list, int id_list_len);
IP_GLOBAL Ip_err ipssh_make_version_str(int v1, int v2, char* buf, int buf_len);
IP_GLOBAL int ipssh_get_conn_version(int major_ver, int minor_ver, int v1, int v2, Ip_bool comp_mode);
IP_GLOBAL Ip_err ipssh_read_from_socket(Ip_fd sock, char* buf, Ip_size_t* buf_len, const char* delim);
IP_GLOBAL Ipssh_map_entry*
ipssh_store_map_entry(Ipssh_conn_ctx* ctx,
Ip_fd sock,
Ipssh_sock_handler handler,
int flags);
IP_GLOBAL void ipssh_register_shell_cmds(void);
IP_GLOBAL void ipssh_unregister_shell_cmds(void);
IP_GLOBAL void ipssh_free_handshake_msgs(Ipssh_conn* ssh_conn, int flags);
IP_PUBLIC Ip_err ipssh_validate_userid_pw(const char* user, const char* pw, void** cookie);
#ifdef IPSSH_USE_V1
IP_GLOBAL RSA* ipssh_generate_server_key(RSA* host_key);
#endif
IP_GLOBAL Ip_s32 ipssh_store_char(Ipcom_buffer* buf, Ipssh_term_modes* term_modes, Ip_u8 chr, Ip_u8* last_chr);
IP_GLOBAL char * ipssh_key_fingerprint_bubblebabble(Ip_u8* dgst_raw, unsigned int dgst_raw_len);
IP_GLOBAL Ip_err ipssh_get_config(Ipssh_conn_config* config);
IP_GLOBAL Ip_err ipssh_get_banner_config(Ipssh_conn_config* config);
IP_GLOBAL void ipssh_handle_term_modes(Ip_u8* buf, int len, Ipssh_term_modes *term_modes);
IP_GLOBAL int ipssh_get_no_clients(void);
IP_GLOBAL Ipssh_srv_ctx* ipssh_srv_ctx_new(void);
IP_GLOBAL void ipssh_srv_ctx_free(Ipssh_srv_ctx* srv_ctx);
IP_GLOBAL Ipssh_srv_ctx* ipssh_srv_ctx_dup(Ipssh_srv_ctx* srv_ctx);
IP_GLOBAL Ip_fd ipssh_sock_shell_start(Ipssh_conn* ssh_ctx, const char* user, Ipcom_shell_ctx* sh_ctx);
IP_GLOBAL Ip_err ipssh_sock_shell_stdin(Ip_fd shell_fd, const char* data, int len);
IP_GLOBAL int ipssh_send_shell_stdout_data2(Ipssh_conn* ssh_conn, Ip_fd shell_fd, const char* data, Ip_ssize_t len);
#ifdef IPTESTENGINE
IP_GLOBAL Ip_err ipssh_test_subsystem_init_cb(Ipssh_channel* channel, Ip_fd* sock);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,304 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_key_fingerprint.c,v $ $Revision: 1.12.10.1 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_key_fingerprint.c,v $
* $Author: jren $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef IPSSH_USE_KEY_FINGERPRINT
#include "ipssh_h.h"
#include "ipssh.h"
#include "ipssh_buffer.h"
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#ifdef IPCRYPTO
#include <ipcrypto.h>
#endif
#include <openssl/evp.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPSSH_MD5 1
#define IPSSH_SHA1 2
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_hash_data
*===========================================================================
*/
IP_STATIC Ip_u8*
ipssh_hash_data(Ip_u8* data, Ip_size_t data_len, int dgst_type, unsigned int* dgst_len)
{
const EVP_MD *md = IP_NULL;
EVP_MD_CTX ctx;
Ip_u8* retval;
switch(dgst_type)
{
case IPSSH_MD5:
md = EVP_md5();
break;
case IPSSH_SHA1:
md = EVP_sha1();
break;
default:
return IP_NULL;
}
if (!md)
return IP_NULL;
*dgst_len = 0;
retval = ipcom_malloc(EVP_MAX_MD_SIZE);
if(!retval)
return IP_NULL;
if (!EVP_DigestInit(&ctx, md)
|| !EVP_DigestUpdate(&ctx, (char*)data, data_len)
|| !EVP_DigestFinal(&ctx, retval, dgst_len))
{
ipcom_free(retval);
EVP_MD_CTX_cleanup(&ctx);
return IP_NULL;
}
EVP_MD_CTX_cleanup(&ctx);
return retval;
}
/*
*===========================================================================
* ipssh_key_fingerprint_hex
*===========================================================================
*/
IP_STATIC char*
ipssh_key_fingerprint_hex(Ip_u8* dgst, unsigned int dgst_len)
{
char *retval;
unsigned int i;
retval = ipcom_malloc(dgst_len * 3 + 1);
if (retval == IP_NULL)
return IP_NULL;
retval[0] = '\0';
for (i = 0; i < dgst_len; i++) {
char hex[4];
ipcom_snprintf(hex, sizeof(hex), "%02x:", dgst[i]);
ipcom_strncat(retval, hex, dgst_len*3 - ipcom_strlen(retval));
}
retval[(dgst_len * 3) - 1] = '\0';
return retval;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_key_fingerprint
*===========================================================================
*/
IP_PUBLIC Ip_err
ipssh_key_fingerprint2(EVP_PKEY* key, int key_type, char** fp, int fp_type)
{
Ipcom_buffer* buf;
Ip_err rc = IPCOM_SUCCESS;
Ip_u8* hash = IP_NULL;
unsigned int hash_len;
if (!key || !fp || (key_type == IPSSH_V1_RSA_ID && key->type != EVP_PKEY_RSA))
return IPCOM_ERR_INVALID_ARG;
buf = ipcom_buffer_new(512);
if(!buf)
return IPCOM_ERR_NO_MEMORY;
switch(key_type)
{
case EVP_PKEY_DSA:
if(ipssh_buffer_put_sshstr(buf, IPSSH_DSA_STR)
|| ipssh_buffer_put_bn(buf, key->pkey.dsa->p) < 0
|| ipssh_buffer_put_bn(buf, key->pkey.dsa->q) < 0
|| ipssh_buffer_put_bn(buf, key->pkey.dsa->g) < 0
|| ipssh_buffer_put_bn(buf, key->pkey.dsa->pub_key) < 0)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
break;
#ifdef IPSSH_USE_RSA
case IPSSH_V1_RSA_ID:
if (!BN_bn2bin(key->pkey.rsa->n, ipcom_buffer_end_ptr(buf))
|| ipcom_buffer_decr_cap(buf, BN_num_bytes(key->pkey.rsa->n)) != IPCOM_SUCCESS
|| !BN_bn2bin(key->pkey.rsa->e, ipcom_buffer_end_ptr(buf))
|| ipcom_buffer_decr_cap(buf, BN_num_bytes(key->pkey.rsa->e)) != IPCOM_SUCCESS)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
break;
case EVP_PKEY_RSA:
if(ipssh_buffer_put_sshstr(buf, IPSSH_RSA_STR)
|| ipssh_buffer_put_bn(buf, key->pkey.rsa->e) < 0
|| ipssh_buffer_put_bn(buf, key->pkey.rsa->n) < 0)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
break;
#endif
default:
rc = IPCOM_ERR_INVALID_ARG;
goto cleanup;
}
switch(fp_type)
{
case IPSSH_BUBBLE_BABBLE:
hash = ipssh_hash_data(ipcom_buffer_start_ptr(buf), ipcom_buffer_len(buf), IPSSH_SHA1, &hash_len);
if(!hash)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
#ifdef IPCRYPTO
*fp = ipcrypto_key_fingerprint_bubblebabble(hash, hash_len);
#else
*fp = ipssh_key_fingerprint_bubblebabble(hash, hash_len);
#endif
break;
case IPSSH_HEX:
hash = ipssh_hash_data(ipcom_buffer_start_ptr(buf), ipcom_buffer_len(buf), IPSSH_MD5, &hash_len);
if(!hash)
{
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
*fp = ipssh_key_fingerprint_hex(hash, hash_len);
break;
default:
IP_PANIC();
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
cleanup:
if(buf)
ipcom_buffer_free(buf);
if(hash)
ipcom_free(hash);
return rc;
}
/*
*===========================================================================
* ipssh_key_fingerprint
*===========================================================================
*/
IP_PUBLIC Ip_err
ipssh_key_fingerprint(EVP_PKEY* key, char** fp, int fp_type)
{
return ipssh_key_fingerprint2(key, key->type, fp, fp_type);
}
#else
void ipssh_key_fingerprint_empty_file(void);
void ipssh_key_fingerprint_empty_file(void) { }
#endif /* IPSSH_USE_KEY_FINGERPRINT */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_keyex_dh.h,v $ $Revision: 1.2.18.2 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_keyex_dh.h,v $
* $Author: yli10 $ $Date: 2018-06-20 02:32:55 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by FirstName LastName <email@interpeak.se>
******************************************************************************
*/
#ifndef IPSSH_KEYEX_DH_H
#define IPSSH_KEYEX_DH_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL DH* ipssh_create_dh_group(Ip_u8 dh_id);
IP_GLOBAL Ip_err ipssh_calc_hash(Ipssh_msg_list* msgs,
const EVP_MD* (*hash_func)(void),
int hash_comps,
Ip_u8** hash_value,
Ip_u32* hash_len);
IP_GLOBAL Ip_err ipssh_rsa_sign(Ipssh_conn* ssh_conn,
Ip_u8* data,
Ip_u32 data_len,
Ipcom_buffer* buf);
IP_GLOBAL Ip_err ipssh_dss_sign(Ipssh_conn* ssh_conn,
Ip_u8* data,
Ip_u32 data_len,
Ipcom_buffer* buf);
IP_GLOBAL Ip_err ipssh_sign_hash(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_verify_signature(EVP_PKEY* srv_key,
Ip_u8* data,
Ip_u32 data_len,
const char* sig_type,
Ip_u8* signature,
Ip_u32 sign_len);
IP_GLOBAL Ip_err ipssh_do_keyex_dh_clt(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_do_keyex_dh_gex_clt(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_dh_priv_key_set_length(Ipssh_conn* ssh_conn);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,511 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_keyex_dh_gex_clt.c,v $ $Revision: 1.3.12.2 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_keyex_dh_gex_clt.c,v $
* $Author: yli10 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger.boden@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
#ifdef IPSSH_USE_DH_GROUP_EX
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include "ipssh.h"
#include "ipssh_h.h"
#include "ipssh_buffer.h"
#include "ipssh_transport.h"
#include "ipssh_keyex_dh.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_send_kex_dh_gex_request
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_send_kex_dh_gex_request(Ipssh_conn* ssh_conn)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipcom_buffer* pkt;
IPCOM_LOG1(DEBUG, "ipssh_send_kex_dh_gex_request :: ssh_conn: %x", ssh_conn);
pkt = ipssh_buffer_new_v2_pkt(256, IPSSH_MSG_KEX_DH_GEX_REQUEST);
if(!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_request :: out of memory");
return IPCOM_ERR_FAILED;
}
if (ipssh_buffer_put_int(pkt, ssh_conn->config.gex_min) ||
ipssh_buffer_put_int(pkt, ssh_conn->config.gex_n) ||
ipssh_buffer_put_int(pkt, ssh_conn->config.gex_max))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_request :: failed to pack msg");
goto cleanup;
}
if(ipssh_msg2list_int((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), ssh_conn->config.gex_min, 5) ||
ipssh_msg2list_int((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), ssh_conn->config.gex_n, 6) ||
ipssh_msg2list_int((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), ssh_conn->config.gex_max, 7))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_request :: ipssh_msg2list_int failed");
goto cleanup;
}
rc = ipssh_send_pkt(ssh_conn, pkt, IP_FALSE);
cleanup:
if(pkt)
ipcom_buffer_free(pkt);
return rc;
}
/*
*===========================================================================
* ipssh_msg_kexdh_gex_group
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_msg_kexdh_gex_group(Ipssh_conn* ssh_conn)
{
Ip_ptrdiff_t len;
Ip_u8* ptr;
if (IPSSH_GET_PKT_TYPE(ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf))
!= IPSSH_MSG_KEX_DH_GEX_GROUP)
{
IPCOM_LOG1(ERR, "ipssh_msg_kexdh_gex_group :: unexpected pkt type: %d",
IPSSH_GET_PKT_TYPE(ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf)));
return IPCOM_ERR_FAILED;
}
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
ptr = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf);
if(ipssh_buffer_get_ssh_mpint2(ssh_conn->recv_plain_buf, &(ssh_conn->dh_data->dh->p)) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kexdh_gex_group :: failed to unpack p");
return IPCOM_ERR_FAILED;
}
ptr += 4; /* Skip length field */
len = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf) - ptr;
if(ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
ptr,
len,
8))
{
IPCOM_LOG0(ERR, "ipssh_msg_kexdh_gex_group :: ipssh_msg2list() failed for p");
return IPCOM_ERR_FAILED;
}
ptr = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf);
if(ipssh_buffer_get_ssh_mpint2(ssh_conn->recv_plain_buf, &(ssh_conn->dh_data->dh->g)) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kexdh_gex_group :: failed to unpack g");
return IPCOM_ERR_FAILED;
}
ptr += 4; /* Skip length field */
len = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf) - ptr;
if(ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
ptr,
len,
9))
{
IPCOM_LOG0(ERR, "ipssh_msg_kexdh_gex_group :: ipssh_msg2list() failed for p");
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
IP_STATIC Ip_err
ipssh_send_msg_key_dh_gex_init(Ipssh_conn* ssh_conn)
{
Ipcom_buffer* pkt;
Ip_err rc = IPCOM_ERR_FAILED;
Ip_size_t e_pos;
Ip_s32 len;
IPCOM_LOG1(DEBUG, "ipssh_send_msg_key_dh_gex_init :: ssh_conn: %x", ssh_conn);
pkt = ipssh_buffer_new_v2_pkt(64+BN_num_bytes(ssh_conn->dh_data->dh->pub_key), IPSSH_MSG_KEX_DH_GEX_INIT);
if (!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_key_dh_gex_init :: failed to allocate pkt");
return IPCOM_ERR_FAILED;
}
/* Add e */
e_pos = ipcom_buffer_len(pkt);
len = ipssh_buffer_put_bn(pkt, ssh_conn->dh_data->dh->pub_key);
if (len < 0)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_key_dh_gex_init :: failed to add e to pkt");
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
(Ip_u8*)IPSSH_GET_MPINT_VALUE(ipcom_buffer_ptr2pos(pkt, e_pos)),
ipcom_buffer_len(pkt) - e_pos - 4,
10))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_reply :: ipssh_msg2list() failed for e");
goto cleanup;
}
rc = ipssh_send_pkt(ssh_conn, pkt, IP_FALSE);
if (rc != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_key_dh_gex_init :: Ipssh_send_pkt() failed");
}
cleanup:
ipcom_buffer_free(pkt);
return rc;
}
/*
*===========================================================================
* ipssh_msg_kex_dh_gex_reply
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_msg_kex_dh_gex_reply(Ipssh_conn* ssh_conn)
{
Ip_err rc = IPCOM_ERR_FAILED;
EVP_PKEY* srv_pub_key = IP_NULL;
Ip_u8* ptr;
Ip_ptrdiff_t len;
char* sig_type = IP_NULL;
Ip_u8* signature = IP_NULL;
Ip_u32 sign_len;
union Ip_sockaddr_union peer_addr;
Ip_socklen_t peer_len;
if (IPSSH_GET_PKT_TYPE(ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf))
!= IPSSH_MSG_KEX_DH_GEX_REPLY)
{
IPCOM_LOG1(ERR, "ipssh_msg_kex_dh_gex_reply :: unexpected pkt type: %d",
IPSSH_GET_PKT_TYPE(ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf)));
return IPCOM_ERR_FAILED;
}
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
ptr = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf);
if ((srv_pub_key=ipssh_buffer_get_pub_key(ssh_conn->recv_plain_buf)) == IP_NULL)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: failed to unpack srv pub key");
return IPCOM_ERR_FAILED;
}
len = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf) - ptr;
if(ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_RAW,
ptr,
len,
4))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: ipssh_msg2list() failed for server key");
goto cleanup;
}
ptr = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf);
if(ipssh_buffer_get_ssh_mpint2(ssh_conn->recv_plain_buf, &(ssh_conn->dh_data->f)) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: failed to unpack f");
goto cleanup;
}
ptr += 4; /* Skip length field */
len = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf) - ptr;
if(ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
ptr,
len,
11))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: ipssh_msg2list() failed for f");
goto cleanup;
}
/* Verify server key */
ipcom_memset(&peer_addr, 0, sizeof(peer_addr));
peer_len = sizeof(peer_addr);
if(ipcom_getpeername(ssh_conn->sock, &peer_addr.sa, &peer_len) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: ipcom_getpeername() failed");
goto cleanup;
}
if(ipssh_validate_srv_public_key_cb(srv_pub_key, &peer_addr) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: ipssh_validate_srv_public_key_cb() failed");
goto cleanup;
}
/* Calculate shared secret */
ssh_conn->secr_len = DH_size(ssh_conn->dh_data->dh);
if (ssh_conn->shared_secret)
ipcom_free(ssh_conn->shared_secret); /* Re-keying: free old shared secret */
ssh_conn->shared_secret = ipcom_malloc(ssh_conn->secr_len+1);
if (!ssh_conn->shared_secret)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_dh_gex_clt :: out of memory");
goto cleanup;
}
ssh_conn->secr_len = DH_compute_key(ssh_conn->shared_secret, ssh_conn->dh_data->f, ssh_conn->dh_data->dh);
if(ssh_conn->secr_len < 0)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_dh_gex_clt :: DH_compute_key() failed");
goto cleanup;
}
/* If the shared secret is a negative number, we must add a zero byte */
if (ssh_conn->shared_secret[0] & 0x80)
{
ipcom_memmove(ssh_conn->shared_secret+1, ssh_conn->shared_secret, ssh_conn->secr_len);
ssh_conn->shared_secret[0] = 0;
ssh_conn->secr_len++;
}
if(ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), /* Store shared secret (K) for later hash calculation */
IPSSH_MPINT,
ssh_conn->shared_secret,
ssh_conn->secr_len,
12))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_init :: ipssh_msg2list() failed");
goto cleanup;
}
/* Calculate hash */
if (ssh_conn->hash)
ipcom_free(ssh_conn->hash);
if (ipssh_calc_hash((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), ssh_conn->hash_func, 13,
&(ssh_conn->hash), &(ssh_conn->hash_len)))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: ipssh_calc_hash() failed");
goto cleanup;
}
/* Process signature */
if(ipcom_buffer_consume(ssh_conn->recv_plain_buf, 4)) /* Skip blob len field */
goto cleanup;
sig_type=ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
signature=ipssh_buffer_get_sshbuf(ssh_conn->recv_plain_buf, &sign_len);
if(!sig_type || !signature)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: failed to unpack signature");
goto cleanup;
}
/* Verify signature */
if(ipssh_verify_signature(srv_pub_key, ssh_conn->hash, ssh_conn->hash_len, sig_type, signature, sign_len) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: ipssh_verify_signature() failed");
goto cleanup;;
}
if(ssh_conn->sess_id_len == 0)
{
ssh_conn->sess_id = ipcom_malloc(ssh_conn->hash_len);
if(!ssh_conn->sess_id)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_reply :: out of memory");
goto cleanup;;
}
ssh_conn->sess_id_len = ssh_conn->hash_len;
ipcom_memcpy(ssh_conn->sess_id, ssh_conn->hash, ssh_conn->sess_id_len);
}
rc = IPCOM_SUCCESS;
cleanup:
if (sig_type)
ipcom_free(sig_type);
if (signature)
ipcom_free(signature);
if (srv_pub_key)
EVP_PKEY_free(srv_pub_key);
return rc;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_do_keyex_dh_gex_clt
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_do_keyex_dh_gex_clt(Ipssh_conn* ssh_conn)
{
Ip_err rc = IPCOM_ERR_FAILED;
ssh_conn->dh_data->dh = DH_new();
if (!ssh_conn->dh_data->dh)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_dh_gex_clt :: DH_new() failed");
goto cleanup;
}
if (ipssh_send_kex_dh_gex_request(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
if (ipssh_read_v2_pkt(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
if (ipssh_msg_kexdh_gex_group(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
/* Reduce the size of the DH private key for large DH groups. It is unnecessarily big by
* default, which increases the connection time */
if (ipssh_dh_priv_key_set_length(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_dh_gex_clt :: ipssh_dh_priv_key_set_length() failed");
goto cleanup;
}
/* Generate random number x and create e = g^x mod p */
if(!DH_generate_key(ssh_conn->dh_data->dh))
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_dh_gex_clt :: DH_generate_key() failed");
goto cleanup;
}
if (ipssh_send_msg_key_dh_gex_init(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
if (ipssh_read_v2_pkt(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
if (ipssh_msg_kex_dh_gex_reply(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
if(ipssh_compute_keys(ssh_conn))
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_dh_gex_clt :: ipssh_compute_keys() failed");
goto cleanup;;
}
if(ipssh_send_new_key_msg(ssh_conn))
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_dh_gex_clt :: ipssh_send_new_key() failed");
goto cleanup;;
}
if (ipssh_read_v2_pkt(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
if (ipssh_msg_new_key(ssh_conn) != IPCOM_SUCCESS)
goto cleanup;
rc = IPCOM_SUCCESS;
cleanup:
return rc;
}
#else
int ipssh_keyex_dh_gex_clt_empty_file;
#endif /* IPSSH_USE_DH_GROUP_EX */
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,809 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_keyex_dh_gex_srv.c,v $ $Revision: 1.6.12.3 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_keyex_dh_gex_srv.c,v $
* $Author: yli10 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger.boden@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
#ifdef IPSSH_USE_DH_GROUP_EX
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_syslog.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_sysvar.h>
#include "ipssh.h"
#include "ipssh_h.h"
#include "ipssh_buffer.h"
#include "ipssh_transport.h"
#include "ipssh_keyex_dh.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPSSH_COMMENT_LINE 1
#define IPSSH_DH_GEX_MIN 1024
#define IPSSH_DH_GEX_MAX 8192
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_send_msg_kex_dh_gex_group(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_msg_kex_dh_gex_reply(Ipssh_conn* ssh_conn);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_parse_moduli_line
*===========================================================================
* Description: This function parses a line with the following syntax:
* Time Type Tests Tries Size Generator Modulus
* Only the Size, Generator and Modulus parameters are parsed.
* Parameters:
* Returns:
*/
IP_STATIC Ip_err
ipssh_parse_moduli_line(char* line, Ip_u32* size, BIGNUM** g, BIGNUM** p)
{
char* saveptr;
char* token;
while (line[0] == ' ' || line[0] == '\t')
line++;
if (line[0] == '#')
return IPSSH_COMMENT_LINE;
/* Time */
token=ipcom_strtok_r(line, " \t", &saveptr);
if (!token)
return IPCOM_ERR_FAILED;
/* Type */
token=ipcom_strtok_r(IP_NULL, " \t", &saveptr);
if (!token)
return IPCOM_ERR_FAILED;
/* Tests */
token=ipcom_strtok_r(IP_NULL, " \t", &saveptr);
if (!token)
return IPCOM_ERR_FAILED;
/* Tries */
token=ipcom_strtok_r(IP_NULL, " \t", &saveptr);
if (!token)
return IPCOM_ERR_FAILED;
/* Size */
token=ipcom_strtok_r(IP_NULL, " \t", &saveptr);
if (!token)
return IPCOM_ERR_FAILED;
*size = ipcom_atoi(token);
if (*size == 0)
return IPCOM_ERR_FAILED;
(*size)++;
/* Generator */
token=ipcom_strtok_r(IP_NULL, " \t", &saveptr);
if (!token)
return IPCOM_ERR_FAILED;
if (!BN_hex2bn(g, token))
goto failed;
/* Modulus */
token=ipcom_strtok_r(IP_NULL, " \t", &saveptr);
if (!token)
return IPCOM_ERR_FAILED;
if (!BN_hex2bn(p, token))
goto failed;
if ((int)*size != BN_num_bits(*p))
return IPCOM_ERR_FAILED;
return IPCOM_SUCCESS;
failed:
if (*g)
{
BN_free(*g);
*g = IP_NULL;
}
if (*p)
{
BN_free(*p);
*p = IP_NULL;
}
return IPCOM_ERR_FAILED;
}
/*
*===========================================================================
* ipssh_create_dh_group_gex
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC DH*
ipssh_create_dh_group_gex(Ip_u32 min, Ip_u32 n, Ip_u32 max)
{
IP_FILE *fp;
char line[4096];
int linenum = 0;
int match_count = 0;
Ip_u32 best_match = 0;
int selected = 0;
Ip_u32 size;
BIGNUM* g = IP_NULL;
BIGNUM* p = IP_NULL;
DH* dh = IP_NULL;
char* path;
path = ipcom_sysvar_get("ipssh.kex.dh_gex.moduli_file", IP_NULL, IP_NULL);
if (!path)
{
path = ipcom_strdup(IPCOM_FILE_ROOT"moduli");
if (!path)
return IP_NULL;
}
fp = ipcom_fopen(path, "r");
if (!fp)
{
IPCOM_LOG1(ERR, "ipssh_create_dh_group_gex:: failed to open moduli file: %s", path);
dh = ipssh_create_dh_group(IPSSH_KEYEX_DH_GR14_SHA1_ID);
goto cleanup;
}
g = BN_new();
p = BN_new();
if(!g || !p)
{
IPCOM_LOG0(ERR, "ipssh_create_dh_group_gex:: failed to create g and p (out of mem)");
goto cleanup;
}
while(ipcom_fgets(line, sizeof(line), fp))
{
Ip_err rc;
linenum++;
rc = ipssh_parse_moduli_line(line, &size, &g, &p);
if (rc == IPSSH_COMMENT_LINE)
continue;
if (rc != IPCOM_SUCCESS)
{
IPCOM_LOG1(DEBUG, "ipssh_create_dh_group_gex :: skipping line: %d", linenum);
continue;
}
if (size < min || size > max)
{
if(g)
BN_clear(g);
if (p)
BN_clear(p);
continue;
}
if ((size > n && size < best_match) ||
(size > best_match && best_match < n))
{
best_match = size;
match_count = 0;
}
if (size == best_match)
match_count++;
if(g)
BN_clear(g);
if (p)
BN_clear(p);
}
if (best_match == 0)
{
IPCOM_LOG3(ERR, "ipssh_create_dh_group_gex:: no matching group found (min=%d, n=%d, max=%d) using group 14",
min, n, max);
dh = ipssh_create_dh_group(IPSSH_KEYEX_DH_GR14_SHA1_ID);
goto cleanup;
}
/* Pick one of the matching groups */
selected = ipcom_random()/(0xffffffff/match_count)+1;
linenum=0;
match_count=0;
ipcom_rewind(fp);
while(ipcom_fgets(line, sizeof(line), fp))
{
linenum++;
if (ipssh_parse_moduli_line(line, &size, &g, &p) != IPCOM_SUCCESS)
continue;
if (size == best_match)
{
match_count++;
if (match_count == selected)
break;
}
}
if (match_count != selected)
{
IPCOM_LOG0(ERR, "ipssh_create_dh_group_gex:: selected group disappeared, using group 14");
dh = ipssh_create_dh_group(IPSSH_KEYEX_DH_GR14_SHA1_ID);
goto cleanup;
}
dh = DH_new();
if(!dh)
goto cleanup;
dh->g = BN_dup(g);
dh->p = BN_dup(p);
if (!dh->g || !dh->p)
{
DH_free(dh);
dh = IP_NULL;
}
cleanup:
ipcom_free(path);
if (fp)
ipcom_fclose(fp);
if (g)
BN_free(g);
if (p)
BN_free(p);
return dh;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_msg_kex_dh_gex_request_old
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_msg_kex_dh_gex_request_old(Ipssh_conn* ssh_conn)
{
Ip_u32 min;
Ip_u32 n;
Ip_u32 max;
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
if (ipssh_buffer_get_uint(ssh_conn->recv_plain_buf, &n))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request_old :: Failed to unpack KEX_DH_GEX_REQUEST message");
return IPCOM_ERR_FAILED;
}
IPCOM_LOG1(DEBUG, "ipssh_msg_kex_dh_gex_request_old :: n: %d", n);
if (n < IPSSH_DH_GEX_MIN || n > IPSSH_DH_GEX_MAX)
{
IPCOM_LOG1(ERR, "ipssh_msg_kex_dh_gex_request_old :: n value: %d", n);
return IPCOM_ERR_FAILED;
}
if (ipssh_msg2list_int((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), n, 5))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request_old :: ipssh_msg2list_int() failed");
return IPCOM_ERR_FAILED;
}
min = IP_MAX (n/2, IPSSH_DH_GEX_MIN);
max = IP_MIN (n*2, IPSSH_DH_GEX_MAX);
if (ssh_conn->dh_data->dh)
DH_free(ssh_conn->dh_data->dh);
ssh_conn->dh_data->dh = ipssh_create_dh_group_gex(min, n, max);
if(!ssh_conn->dh_data->dh)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request_old :: ipssh_create_dh_group_gex() failed");
return IPCOM_ERR_FAILED;
}
/* Reduce the size of the DH private key for large DH groups. It is unnecessarily big by
* default, which increases the connection time */
if (ipssh_dh_priv_key_set_length(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request_old :: ipssh_dh_priv_key_set_length() failed");
return IPCOM_ERR_FAILED;
}
/* Generate random number y and create f = g^y mod p */
if(!DH_generate_key(ssh_conn->dh_data->dh))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request_old :: DH_generate_key() failed");
return IPCOM_ERR_FAILED;
}
ssh_conn->dh_gex_old = IP_TRUE;
return ipssh_send_msg_kex_dh_gex_group(ssh_conn);
}
/*
*===========================================================================
* ipssh_msg_kex_dh_gex_request
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_msg_kex_dh_gex_request(Ipssh_conn* ssh_conn)
{
Ip_u32 min;
Ip_u32 n;
Ip_u32 max;
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
if (ipssh_buffer_get_uint(ssh_conn->recv_plain_buf, &min) ||
ipssh_buffer_get_uint(ssh_conn->recv_plain_buf, &n) ||
ipssh_buffer_get_uint(ssh_conn->recv_plain_buf, &max))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request :: Failed to unpack KEX_DH_GEX_REQUEST message");
return IPCOM_ERR_FAILED;
}
IPCOM_LOG3(DEBUG, "ipssh_msg_kex_dh_gex_request :: min: %d, n: %d, max: %d",
min, n, max);
if (min < IPSSH_DH_GEX_MIN || max > IPSSH_DH_GEX_MAX)
{
IPCOM_LOG2(ERR, "ipssh_msg_kex_dh_gex_request :: illegal min/max values: (%d/%d)",
min, max);
return IPCOM_ERR_FAILED;
}
if (min > n || max < n)
{
IPCOM_LOG2(ERR, "ipssh_msg_kex_dh_gex_request :: illegal min/max values: (%d/%d)",
min, max);
return IPCOM_ERR_FAILED;
}
if(ipssh_msg2list_int((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), min, 5) ||
ipssh_msg2list_int((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), n, 6) ||
ipssh_msg2list_int((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), max, 7))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request :: ipssh_msg2list_int() failed");
return IPCOM_ERR_FAILED;
}
if (ssh_conn->dh_data->dh)
DH_free(ssh_conn->dh_data->dh);
ssh_conn->dh_data->dh = ipssh_create_dh_group_gex(min, n, max);
if(!ssh_conn->dh_data->dh)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request :: ipssh_create_dh_group_gex() failed");
return IPCOM_ERR_FAILED;
}
/* Reduce the size of the DH private key for large DH groups. It is unnecessarily big by
* default, which increases the connection time */
if (ipssh_dh_priv_key_set_length(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request :: ipssh_dh_priv_key_set_length() failed");
return IPCOM_ERR_FAILED;
}
/* Generate random number y and create f = g^y mod p */
if(!DH_generate_key(ssh_conn->dh_data->dh))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_request :: DH_generate_key() failed");
return IPCOM_ERR_FAILED;
}
return ipssh_send_msg_kex_dh_gex_group(ssh_conn);
}
/*
*===========================================================================
* ipssh_msg_kex_dh_gex_init
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_msg_kex_dh_gex_init(Ipssh_conn* ssh_conn)
{
Ip_s32 len;
Ip_u8* e_ptr;
#ifdef IP_ASSERT
int secr_len;
#endif
IPCOM_LOG0(DEBUG, "ipssh_msg_kex_dh_gex_init ::");
/* Get e from KEY_DH_GEX_INIT message */
if (ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6)
|| ipssh_buffer_get_int(ssh_conn->recv_plain_buf, &len))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_init :: Failed to unpack e length");
return IPCOM_ERR_FAILED;
}
if (len == 0 || len != (Ip_s32)ipcom_buffer_len(ssh_conn->recv_plain_buf))
{
IPCOM_LOG1(ERR, "ipssh_msg_kex_dh_gex_init :: Invalid length of e: %d", len);
return IPCOM_ERR_FAILED;
}
e_ptr = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf);
if (ssh_conn->dh_data->e)
BN_free(ssh_conn->dh_data->e);
ssh_conn->dh_data->e = BN_bin2bn(e_ptr, len, IP_NULL);
if(!ssh_conn->dh_data->e)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_init :: BN_bin2bn() failed for e");
return IPCOM_ERR_FAILED;
}
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, len);
if(ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), /* Store e for later hash calculation */
IPSSH_MPINT,
e_ptr,
len,
ssh_conn->dh_gex_old? 8:10))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_init :: ipssh_msg2list() failed");
return IPCOM_ERR_FAILED;
}
/* Calculate the shared secret */
ssh_conn->secr_len = DH_size(ssh_conn->dh_data->dh);
#ifdef IP_ASSERT
secr_len = ssh_conn->secr_len;
#endif
if (ssh_conn->shared_secret)
ipcom_free(ssh_conn->shared_secret); /* Re-keying: free old shared secret */
ssh_conn->shared_secret = ipcom_malloc(ssh_conn->secr_len+1);
if(!ssh_conn->shared_secret) {
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_init :: out of memory");
return IPCOM_ERR_FAILED;
}
ssh_conn->secr_len = DH_compute_key(ssh_conn->shared_secret, ssh_conn->dh_data->e, ssh_conn->dh_data->dh);
if(ssh_conn->secr_len < 0)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_init :: DH_compute_key() failed");
return IPCOM_ERR_FAILED;
}
ip_assert(ssh_conn->secr_len <= secr_len);
/* If the shared secret is a negative number, we must add a zero byte */
if (ssh_conn->shared_secret[0] & 0x80)
{
ipcom_memmove(ssh_conn->shared_secret+1, ssh_conn->shared_secret, ssh_conn->secr_len);
ssh_conn->shared_secret[0] = 0;
ssh_conn->secr_len++;
}
if(ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), /* Store shared secret (K) for later hash calculation */
IPSSH_MPINT,
ssh_conn->shared_secret,
ssh_conn->secr_len,
ssh_conn->dh_gex_old? 10:12))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_dh_gex_init :: ipssh_msg2list() failed");
return IPCOM_ERR_FAILED;
}
return ipssh_send_msg_kex_dh_gex_reply(ssh_conn);
}
/*
*===========================================================================
* ipssh_send_msg_kex_dh_gex_group
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_send_msg_kex_dh_gex_group(Ipssh_conn* ssh_conn)
{
Ipcom_buffer* pkt = IP_NULL;
Ip_err rc = IPCOM_ERR_FAILED;
Ip_size_t p_pos;
Ip_size_t g_pos;
Ip_s32 len;
pkt = ipssh_buffer_new_v2_pkt(1024, IPSSH_MSG_KEX_DH_GEX_GROUP);
if(!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kex_dh_gex_group :: out of memory");
goto cleanup;
}
p_pos = ipcom_buffer_len(pkt);
len = ipssh_buffer_put_bn(pkt, ssh_conn->dh_data->dh->p);
if (len < 0)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kex_dh_gex_group :: failed to generate KEX_DH_GEX_GROUP msg");
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
(Ip_u8*)IPSSH_GET_MPINT_VALUE(ipcom_buffer_ptr2pos(pkt, p_pos)),
ipcom_buffer_len(pkt) - p_pos - 4,
ssh_conn->dh_gex_old? 6:8))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_reply :: ipssh_msg2list() failed for g");
goto cleanup;
}
g_pos = ipcom_buffer_len(pkt);
len = ipssh_buffer_put_bn(pkt, ssh_conn->dh_data->dh->g);
if (len < 0)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kex_dh_gex_group :: failed to generate KEX_DH_GEX_GROUP msg");
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
(Ip_u8*)IPSSH_GET_MPINT_VALUE(ipcom_buffer_ptr2pos(pkt, g_pos)),
ipcom_buffer_len(pkt) - g_pos - 4,
ssh_conn->dh_gex_old? 7:9))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_reply :: ipssh_msg2list() failed for g");
goto cleanup;
}
if (ipssh_send_pkt(ssh_conn, pkt, IP_FALSE) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kex_dh_gex_group :: failed to send KEX_DH_GEX_GROUP msg");
goto cleanup;
}
rc = IPCOM_SUCCESS;
cleanup:
if (pkt)
ipcom_buffer_free(pkt);
return rc;
}
/*
*===========================================================================
* ipssh_send_msg_kex_dh_gex_reply
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_send_msg_kex_dh_gex_reply(Ipssh_conn* ssh_conn)
{
Ip_size_t len;
Ip_s32 len2;
Ip_size_t f_pos;
Ip_size_t host_key_pos;
Ipcom_buffer* pkt;
IPCOM_LOG0(DEBUG, "ipssh_send_kex_dh_gex_reply()");
pkt = ipssh_buffer_new_v2_pkt(4096, IPSSH_MSG_KEX_DH_GEX_REPLY);
if(!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: out of memory");
return IPCOM_ERR_FAILED;
}
/* Add server key */
len = ipcom_buffer_len(pkt);
host_key_pos = ipcom_buffer_len(pkt);
switch (ssh_conn->conn_prop_pending.srv_host_key_alg[0])
{
case IPSSH_DSA_ID:
if(ipssh_buffer_put_dsa_key(pkt, ssh_conn->srv_dsa_key))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_buffer_put_dsa_key() failed");
goto failed;
}
break;
#ifdef IPSSH_USE_RSA
case IPSSH_RSA_ID:
if(ipssh_buffer_put_rsa_key(pkt, ssh_conn->srv_rsa_key))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_buffer_put_rsa_key() failed");
goto failed;
}
break;
#endif
default:
IP_PANIC();
goto failed;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_RAW,
(Ip_u8*)ipcom_buffer_ptr2pos(pkt, host_key_pos),
ipcom_buffer_len(pkt) - len,
4))
{
IPCOM_LOG1(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_msg2list() failed for %s host key",
(ssh_conn->conn_prop_pending.srv_host_key_alg[0] == IPSSH_DSA_ID ? "DSA": "RSA"));
goto failed;
}
/* Add f */
f_pos = ipcom_buffer_len(pkt);
len2 = ipssh_buffer_put_bn(pkt, ssh_conn->dh_data->dh->pub_key);
if (len2 < 0)
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_buffer_put_bn() failed");
goto failed;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
(Ip_u8*)IPSSH_GET_MPINT_VALUE(ipcom_buffer_ptr2pos(pkt, f_pos)),
ipcom_buffer_len(pkt) - f_pos - 4,
ssh_conn->dh_gex_old? 9:11))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_msg2list() failed for f");
goto failed;
}
/* Calculate hash */
if (ssh_conn->hash)
ipcom_free(ssh_conn->hash);
if (ipssh_calc_hash((Ipssh_msg_list*)&(ssh_conn->handshake_msgs), ssh_conn->hash_func,
ssh_conn->dh_gex_old? 11:13, &(ssh_conn->hash), &(ssh_conn->hash_len)))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_calc_hash() failed");
goto failed;
}
if (ssh_conn->sess_id_len == 0)
{
/* The session ID is only updated in the inital key exchange */
ssh_conn->sess_id_len = ssh_conn->hash_len;
ssh_conn->sess_id = ipcom_malloc(ssh_conn->hash_len);
if(!ssh_conn->sess_id)
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: out of memory");
goto failed;
}
ipcom_memcpy(ssh_conn->sess_id, ssh_conn->hash, ssh_conn->sess_id_len);
}
/* Sign hash with server key */
switch (ssh_conn->conn_prop_pending.srv_host_key_alg[0])
{
case IPSSH_DSA_ID:
if(ipssh_dss_sign(ssh_conn, ssh_conn->hash, ssh_conn->hash_len, pkt))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_dss_sign() failed");
goto failed;
}
break;
#ifdef IPSSH_USE_RSA
case IPSSH_RSA_ID:
if(ipssh_rsa_sign(ssh_conn, ssh_conn->hash, ssh_conn->hash_len, pkt))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_rsa_sign() failed");
goto failed;
}
break;
#endif
default:
IP_PANIC();
goto failed;
}
if(ipssh_send_pkt(ssh_conn, pkt, IP_TRUE))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_send_pkt() failed");
return IPCOM_ERR_FAILED;
}
if(ipssh_compute_keys(ssh_conn))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_compute_keys() failed");
return IPCOM_ERR_FAILED;
}
if(ipssh_send_new_key_msg(ssh_conn))
{
IPCOM_LOG0(ERR, "ipssh_send_kex_dh_gex_reply :: ipssh_send_new_key() failed");
return IPCOM_ERR_FAILED;
}
ssh_conn->conn_state = IPSSH_CONN_STATE_SRV_NEW_KEY;
return IPCOM_SUCCESS;
failed:
ipcom_buffer_free(pkt);
return IPCOM_ERR_FAILED;
}
#else
int ipssh_keyex_dh_gex_srv_empty_file;
#endif /* IPSSH_USE_DH_GROUP_EX */
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,659 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_keyex_rsa.c,v $ $Revision: 1.4.12.3 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_keyex_rsa.c,v $
* $Author: jli7 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger.boden@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include "ipssh_config.h"
#ifdef IPSSH_USE_KEYEX_RSA
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_syslog.h>
#include <ipcom_err.h>
#include <ipcrypto.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include "ipssh.h"
#include "ipssh_h.h"
#include "ipssh_buffer.h"
#include "ipssh_transport.h"
#include "ipssh_keyex_dh.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_send_msg_kexrsa_pubkey(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_msg_kexrsa_done(Ipssh_conn* ssh_conn);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC int
ipssh_kexrsa_get_hash_size(Ipssh_conn* ssh_conn)
{
switch(ssh_conn->conn_prop_pending.kex_alg[0])
{
case IPSSH_KEYEX_RSA1024_SHA1_ID:
return SHA_DIGEST_LENGTH;
case IPSSH_KEYEX_RSA2048_SHA256_ID:
return SHA256_DIGEST_LENGTH;
default:
IP_PANIC();
return 0;
}
}
/*
*===========================================================================
* ipssh_send_msg_kexrsa_secret
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_send_msg_kexrsa_secret(Ipssh_conn* ssh_conn, RSA* transient_key)
{
Ip_err rc = IPCOM_ERR_FAILED;
int encr_k_len;
int len;
Ip_u8* encr_k = IP_NULL;
Ip_u8* oaep_padded_shared_secret = IP_NULL;
Ip_u8* mpint_shared_secret = IP_NULL;
Ipcom_buffer* pkt = IP_NULL;
/* Generate random integer, K in rfc 4432, also known as shared secret */
ssh_conn->secr_len = RSA_size(transient_key) - 2*ipssh_kexrsa_get_hash_size(ssh_conn) - 7;
ssh_conn->shared_secret = ipcom_malloc(RSA_size(transient_key));
if (!ssh_conn->shared_secret)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_secret :: out of memory");
return IPCOM_ERR_NO_MEMORY;
}
if (!RAND_bytes(ssh_conn->shared_secret, ssh_conn->secr_len))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_secret :: failed to get random bytes");
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
ssh_conn->shared_secret,
ssh_conn->secr_len,
7))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_secret :: failed to add K to hash list");
goto cleanup;
}
encr_k_len = RSA_size(transient_key);
encr_k = ipcom_malloc(encr_k_len);
oaep_padded_shared_secret = ipcom_malloc(encr_k_len);
mpint_shared_secret = ipcom_malloc(ssh_conn->secr_len+4);
if (!encr_k || !oaep_padded_shared_secret || !mpint_shared_secret)
goto cleanup;
IP_SET_HTONL(mpint_shared_secret, ssh_conn->secr_len);
ipcom_memcpy(mpint_shared_secret+4, ssh_conn->shared_secret, ssh_conn->secr_len);
ipcrypto_rsa_oaep_encode(ssh_conn->hash_func(), mpint_shared_secret, ssh_conn->secr_len+4, oaep_padded_shared_secret, encr_k_len);
len = RSA_public_encrypt(encr_k_len, oaep_padded_shared_secret, encr_k, transient_key, RSA_NO_PADDING);
if (len < 0)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_secret :: failed to encrypt K");
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_STR,
encr_k,
len,
6))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_secret :: failed to add encrypted K to hash list");
goto cleanup;
}
pkt = ipssh_buffer_new_v2_pkt(encr_k_len+64, IPSSH_MSG_KEX_RSA_SECRET);
if (!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_secret :: failed to allocate pkt");
goto cleanup;
}
(void)ipssh_buffer_put_sshbuf(pkt, encr_k, encr_k_len);
rc = ipssh_send_pkt(ssh_conn, pkt, IP_FALSE);
cleanup:
if (encr_k)
ipcom_free(encr_k);
if (oaep_padded_shared_secret)
ipcom_free(oaep_padded_shared_secret);
if (mpint_shared_secret)
ipcom_free(mpint_shared_secret);
if(pkt)
ipcom_buffer_free(pkt);
return rc;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err
ipssh_msg_kexrsa_done(Ipssh_conn* ssh_conn)
{
char* sig_type = IP_NULL;
Ip_u8* signature = IP_NULL;
Ip_u32 sign_len;
Ip_err rc = IPCOM_ERR_FAILED;
if(ipssh_calc_hash((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
ssh_conn->hash_func,
8,
&(ssh_conn->hash),
&(ssh_conn->hash_len)))
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_done :: ipssh_calc_hash() failed");
goto cleanup;
}
if(ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6)) /* Skip headers */
goto cleanup;
/* Process signature */
if(ipcom_buffer_consume(ssh_conn->recv_plain_buf, 4)) /* Skip blob len field */
goto cleanup;
sig_type=ipssh_buffer_get_sshstr(ssh_conn->recv_plain_buf);
signature=ipssh_buffer_get_sshbuf(ssh_conn->recv_plain_buf, &sign_len);
if(!sig_type || !signature)
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_done :: failed to unpack signature");
goto cleanup;
}
/* Verify signature */
if(ipssh_verify_signature(ssh_conn->data.clt.srv_pub_key, ssh_conn->hash, ssh_conn->hash_len, sig_type, signature, sign_len) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_done :: ipssh_verify_signature() failed");
goto cleanup;
}
if(ssh_conn->sess_id_len == 0)
{
ssh_conn->sess_id = ipcom_malloc(ssh_conn->hash_len);
if(!ssh_conn->sess_id)
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_done :: out of memory");
goto cleanup;
}
ssh_conn->sess_id_len = ssh_conn->hash_len;
ipcom_memcpy(ssh_conn->sess_id, ssh_conn->hash, ssh_conn->sess_id_len);
}
rc = IPCOM_SUCCESS;
cleanup:
if (sig_type)
ipcom_free(sig_type);
if (signature)
ipcom_free(signature);
return rc;
}
/*
*===========================================================================
* ipssh_msg_kexrsa_pubkey
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_msg_kexrsa_pubkey(Ipssh_conn* ssh_conn)
{
Ip_err rc = IPCOM_ERR_FAILED;
EVP_PKEY* transient_key = IP_NULL;
Ip_u8* srv_key_ptr;
Ip_u8* transient_key_ptr;
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
srv_key_ptr = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf);
ssh_conn->data.clt.srv_pub_key = ipssh_buffer_get_pub_key(ssh_conn->recv_plain_buf);
if (!ssh_conn->data.clt.srv_pub_key)
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_pubkey :: failed to unpack srv key");
return IPCOM_ERR_FAILED;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_RAW,
srv_key_ptr,
ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf) - srv_key_ptr,
4))
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_pubkey :: failed to add host key to hash list");
goto cleanup;
}
transient_key_ptr = ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf);
transient_key = ipssh_buffer_get_pub_key(ssh_conn->recv_plain_buf);
if (!transient_key)
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_pubkey :: failed to unpack transient key");
goto cleanup;
}
if (transient_key->type != NID_rsaEncryption)
{
IPCOM_LOG1(ERR, "ipssh_msg_kexrsa_pubkey :: transient key not an RSA key: key type=%d",
transient_key->type);
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_RAW,
transient_key_ptr,
ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf) - transient_key_ptr,
5))
{
IPCOM_LOG0(ERR, "ipssh_msg_kexrsa_pubkey :: failed to add transient key to hash list");
goto cleanup;
}
rc = ipssh_send_msg_kexrsa_secret(ssh_conn, transient_key->pkey.rsa);
cleanup:
if (transient_key)
EVP_PKEY_free(transient_key);
return rc;
}
/*
*===========================================================================
* ipssh_send_msg_kexrsa_pubkey
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_send_msg_kexrsa_pubkey(Ipssh_conn* ssh_conn)
{
Ipcom_buffer* pkt;
Ip_err rc = IPCOM_ERR_FAILED;
Ip_size_t srv_key_pos;
Ip_size_t transient_key_pos;
pkt = ipssh_buffer_new_v2_pkt(1024, IPSSH_MSG_KEX_RSA_PUBKEY);
if (!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_pubkey :: out of memory");
return IPCOM_ERR_FAILED;
}
srv_key_pos = ipcom_buffer_end_pos(pkt);
switch(ssh_conn->conn_prop_pending.srv_host_key_alg[0])
{
case IPSSH_DSA_ID:
if (ipssh_buffer_put_dsa_key(pkt, ssh_conn->srv_dsa_key))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_pubkey :: failed to add srv dsa key to pkt");
goto cleanup;
}
break;
case IPSSH_RSA_ID:
if (ipssh_buffer_put_rsa_key(pkt, ssh_conn->srv_rsa_key))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_pubkey :: failed to add srv rsa key to pkt");
goto cleanup;
}
break;
default:
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_pubkey :: unknown srv host key");
IP_PANIC();
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_RAW,
(Ip_u8*)ipcom_buffer_ptr2pos(pkt, srv_key_pos),
ipcom_buffer_end_pos(pkt) - srv_key_pos,
4))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_pubkey :: failed to add host key to hash list");
goto cleanup;
}
transient_key_pos = ipcom_buffer_end_pos(pkt);
if (ipssh_buffer_put_rsa_key(pkt, ssh_conn->srv_rsa_keyex_key))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_pubkey :: out of memory");
goto cleanup;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_RAW,
(Ip_u8*)ipcom_buffer_ptr2pos(pkt, transient_key_pos),
ipcom_buffer_end_pos(pkt) - transient_key_pos,
5))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_pubkey :: failed to add transient key to hash list");
goto cleanup;
}
rc = ipssh_send_pkt(ssh_conn, pkt, IP_FALSE);
ssh_conn->conn_state = IPSSH_CONN_STATE_SRV_KEX_RSA;
cleanup:
ipcom_buffer_free(pkt);
return rc;
}
/*
*===========================================================================
* ipssh_send_msg_kexrsa_done
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_send_msg_kexrsa_done(Ipssh_conn* ssh_conn)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipcom_buffer* pkt = IP_NULL;
if(ipssh_calc_hash((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
ssh_conn->hash_func,
8,
&(ssh_conn->hash),
&(ssh_conn->hash_len)))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_done :: ipssh_calc_hash() failed");
goto failed;
}
if(ssh_conn->sess_id_len == 0)
{
ssh_conn->sess_id = ipcom_malloc(ssh_conn->hash_len);
if(!ssh_conn->sess_id)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_done :: out of memory");
goto failed;
}
ssh_conn->sess_id_len = ssh_conn->hash_len;
ipcom_memcpy(ssh_conn->sess_id, ssh_conn->hash, ssh_conn->sess_id_len);
}
pkt = ipssh_buffer_new_v2_pkt(2048, IPSSH_MSG_KEX_RSA_DONE);
if (!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_done :: failed to allocate pkt");
goto failed;
}
if (ipssh_sign_hash(ssh_conn, pkt) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_done :: ipssh_sign_hash() failed");
goto failed;
}
if (ipssh_send_pkt(ssh_conn, pkt, IP_FALSE) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_done :: failed to send SSH_MSG_NEW_KEY");
goto failed;
}
if(ipssh_compute_keys(ssh_conn))
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_done :: ipssh_compute_keys() failed");
goto failed;
}
if (ipssh_send_new_key_msg(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_send_msg_kexrsa_done :: failed to send SSH_MSG_NEW_KEY");
goto failed;
}
rc = IPCOM_SUCCESS;
failed:
if (pkt)
ipcom_buffer_free(pkt);
return rc;
}
/*
*===========================================================================
*
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_msg_kex_rsa_secret(Ipssh_conn* ssh_conn)
{
Ip_u8* encr_shared_secret; /* K in rfc 4432 */
int len;
Ip_u8* shared_secret = IP_NULL;
Ip_u8* oaep_padded_shared_secret = IP_NULL;
Ip_err rc = IPCOM_ERR_FAILED;
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
encr_shared_secret = ipssh_buffer_get_sshbuf(ssh_conn->recv_plain_buf, (Ip_u32*)&len);
if (!encr_shared_secret)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_rsa_secret :: failed to unpack secret");
return IPCOM_ERR_FAILED;
}
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_STR,
encr_shared_secret,
len,
6))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_rsa_secret :: failed to add encrypted K to hash list");
goto cleanup;
}
shared_secret = ipcom_malloc(RSA_size(ssh_conn->srv_rsa_keyex_key)+64);
oaep_padded_shared_secret = ipcom_malloc(RSA_size(ssh_conn->srv_rsa_keyex_key)+64);
if (!shared_secret || !oaep_padded_shared_secret)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_rsa_secret :: out of memory");
goto cleanup;
}
len = RSA_private_decrypt(len, encr_shared_secret, oaep_padded_shared_secret, ssh_conn->srv_rsa_keyex_key, RSA_NO_PADDING);
if (len < 0)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_rsa_secret :: RSA_private_decrypt failed");
goto cleanup;
}
if (ipcrypto_rsa_oaep_decode(ssh_conn->hash_func(), oaep_padded_shared_secret, len, shared_secret, (int*)&len) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_rsa_secret :: failed to oaep decode shared secret");
goto cleanup;
}
if (len < 4)
{
IPCOM_LOG1(ERR, "ipssh_msg_kex_rsa_secret :: invalid K lenght: %d", len);
goto cleanup;
}
ipcom_memmove(shared_secret, &shared_secret[4], len -4); /* Remove the length field */
len -= 4;
if (ipssh_msg2list((Ipssh_msg_list*)&(ssh_conn->handshake_msgs),
IPSSH_MPINT,
shared_secret,
len,
7))
{
IPCOM_LOG0(ERR, "ipssh_msg_kex_rsa_secret :: failed to add shared secret K to hash list");
goto cleanup;
}
ssh_conn->shared_secret = shared_secret;
shared_secret = IP_NULL;
ssh_conn->secr_len = len;
rc = ipssh_send_msg_kexrsa_done(ssh_conn);
ssh_conn->conn_state = IPSSH_CONN_STATE_SRV_NEW_KEY;
cleanup:
ipcom_free(encr_shared_secret);
if (shared_secret)
ipcom_free(shared_secret);
if (oaep_padded_shared_secret)
ipcom_free(oaep_padded_shared_secret);
return rc;
}
/*
*===========================================================================
* ipssh_do_keyex_rsa_clt
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_do_keyex_rsa_clt(Ipssh_conn* ssh_conn)
{
if (ipssh_read_v2_pkt2(ssh_conn, IPSSH_MSG_KEX_RSA_PUBKEY) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: failed to read SSH_MSG_KEY_RSA_PUBKEY");
return IPCOM_ERR_FAILED;
}
if (ipssh_msg_kexrsa_pubkey(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: failed to process SSH_MSG_KEY_RSA_PUBKEY");
return IPCOM_ERR_FAILED;
}
if (ipssh_read_v2_pkt2(ssh_conn, IPSSH_MSG_KEX_RSA_DONE) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: failed to read SSH_MSG_KEY_RSA_DONE");
return IPCOM_ERR_FAILED;
}
if (ipssh_msg_kexrsa_done(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: failed to process SSH_MSG_KEY_RSA_DONE");
return IPCOM_ERR_FAILED;
}
if(ipssh_compute_keys(ssh_conn))
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: ipssh_compute_keys() failed");
return IPCOM_ERR_FAILED;
}
if (ipssh_send_new_key_msg(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: failed to send SSH_MSG_NEW_KEY");
return IPCOM_ERR_FAILED;
}
if(ipssh_read_v2_pkt2(ssh_conn, IPSSH_MSG_NEWKEYS) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: failed to read SSH_MSG_NEW_KEY");
return IPCOM_ERR_FAILED;
}
if(ipssh_msg_new_key(ssh_conn) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_do_keyex_rsa_clt :: failed to process SSH_MSG_NEW_KEY");
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
#else
int ipssh_keyex_rsa_empty_file;
#endif /* IPSSH_USE_RSA_KEYEX */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,240 @@
/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_list.c,v $ $Revision: 1.26 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_list.c,v $
* $Author: rboden $ $Date: 2010-09-21 11:49:19 $
* $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_list.h"
#include <ipcom_clib.h>
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_syslog.h>
#include <ipcom_sock.h>
#include <ipcom_err.h>
#include <ipcom_strlib.h>
/*
****************************************************************************
* 4 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 5 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 6 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_list_str_insert_last
*===========================================================================
* Description: Inserts a string into the list. A terminating NULL is added.
*/
IP_GLOBAL Ip_err
ipssh_list_str_insert_last(Ipssh_str_list* head, const char* ptr, Ip_size_t len)
{
Ipssh_str_list* entry;
char* tmp_ptr;
entry = ipcom_malloc(sizeof(Ipssh_str_list));
tmp_ptr = ipcom_malloc(len+1);
if( !entry || !tmp_ptr )
{
IPCOM_LOG0(ERR,
"ipssh_list_insert_last :: out of memory");
if(entry)
ipcom_free(entry);
if(tmp_ptr)
ipcom_free(tmp_ptr);
return IPCOM_ERR_FAILED;
}
entry->str = tmp_ptr;
ipcom_memcpy(entry->str, ptr, len);
entry->str[len] = 0;
ipcom_list_insert_last((Ipcom_list*) head, (Ipcom_list*) entry);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_list_buf_insert_last
*===========================================================================
* Description: A buffer is added. The length is prepended to the inserted buffer
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_list_buf_insert_last(Ipcom_list* head, const char* ptr, Ip_size_t len)
{
Ipssh_str_list* entry;
char* tmp_ptr;
entry = ipcom_malloc(sizeof(Ipssh_str_list));
tmp_ptr = ipcom_malloc(len+4);
if( !entry || !tmp_ptr )
{
IPCOM_LOG0(ERR,
"ipssh_list_insert_last :: out of memory");
if(entry)
ipcom_free(entry);
if(tmp_ptr)
ipcom_free(tmp_ptr);
return IPCOM_ERR_FAILED;
}
entry->str = tmp_ptr;
*((Ip_s32*)entry->str) = (Ip_s32)len;
IP_PANIC();
ipcom_memcpy(entry->str+4, ptr, len);
ipcom_list_insert_last((Ipcom_list*) head, (Ipcom_list*) entry);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_str2list
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_str2list(Ipssh_str_list* list, const char* str, const char* delim)
{
char* buf;
char* item, *last;
buf = ipcom_malloc(ipcom_strlen(str)+1);
if(!buf)
return IPCOM_ERR_FAILED;
ipcom_strcpy(buf, str);
for( item = ipcom_strtok_r(buf, delim, &last);
item;
item = ipcom_strtok_r(IP_NULL, delim, &last) )
{
if( ipssh_list_str_insert_last(list, item, ipcom_strlen(item)) )
{
IPCOM_LOG0(DEBUG2, "ipssh_string2list :: ipssh_list_insert_last() failed");
ipcom_free(buf);
return IPCOM_ERR_FAILED;
}
}
ipcom_free(buf);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_list_free
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipssh_list_free(Ipcom_list* head)
{
Ipcom_list* entry;
for(entry = ipcom_list_first(head);
entry;
entry = ipcom_list_first(head))
{
ipcom_list_remove(entry);
ipcom_free(entry);
}
}
IP_GLOBAL void
ipssh_str_list_free(Ipssh_str_list* head)
{
Ipcom_list* entry;
for(entry = ipcom_list_first((Ipcom_list*)head);
entry;
entry = ipcom_list_first((Ipcom_list*)head))
{
Ipssh_str_list* str_entry = (Ipssh_str_list*) entry;
ipcom_list_remove((Ipcom_list*)entry);
if( str_entry->str )
ipcom_free(str_entry->str);
ipcom_free(str_entry);
}
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,84 @@
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_list.h,v $ $Revision: 1.5 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_list.h,v $
* $Author: rboden $ $Date: 2010-09-21 11:49:19 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef ipssh_list_h
#define ipssh_list_h
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_list.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct
{
Ipcom_list list;
char* str;
} Ipssh_str_list;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_EXTERN Ip_err ipssh_list_buf_insert_last(Ipcom_list* list, const char* ptr, Ip_size_t len);
IP_EXTERN Ip_err ipssh_list_str_insert_last(Ipssh_str_list* list, const char* ptr, Ip_size_t len);
IP_EXTERN Ip_err ipssh_sshstr2list(Ipssh_str_list* list, const char* str, const char* delim);
IP_EXTERN Ip_err ipssh_str2list(Ipssh_str_list* list, const char* str, const char* delim);
IP_EXTERN void ipssh_str_list_free(Ipssh_str_list* head);
IP_EXTERN void ipssh_list_free(Ipcom_list* head);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,151 @@
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_sftp.h,v $ $Revision: 1.9.48.3 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_sftp.h,v $
* $Author: jren $ $Date: 2017-12-13 02:40:08 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef ipssh_sftp_h
#define ipssh_sftp_h
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipssh_sftp_clt.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Packet types, sftp protocol */
#define IPSSH_FXP_INIT 1
#define IPSSH_FXP_VERSION 2
#define IPSSH_FXP_OPEN 3
#define IPSSH_FXP_CLOSE 4
#define IPSSH_FXP_READ 5
#define IPSSH_FXP_WRITE 6
#define IPSSH_FXP_LSTAT 7
#define IPSSH_FXP_FSTAT 8
#define IPSSH_FXP_SETSTAT 9
#define IPSSH_FXP_FSETSTAT 10
#define IPSSH_FXP_OPENDIR 11
#define IPSSH_FXP_READDIR 12
#define IPSSH_FXP_REMOVE 13
#define IPSSH_FXP_MKDIR 14
#define IPSSH_FXP_RMDIR 15
#define IPSSH_FXP_REALPATH 16
#define IPSSH_FXP_STAT 17
#define IPSSH_FXP_RENAME 18
#define IPSSH_FXP_READLINK 19
#define IPSSH_FXP_SYMLINK 20
#define IPSSH_FXP_STATUS 101
#define IPSSH_FXP_HANDLE 102
#define IPSSH_FXP_DATA 103
#define IPSSH_FXP_NAME 104
#define IPSSH_FXP_ATTRS 105
#define IPSSH_FXP_EXTENDED 200
#define IPSSH_FXP_EXTENDED_REPLY 201
/* The following values are defined by Wind River */
#define IPSSH_FXP_ACCESS 254
#define IPSSH_FXP_MAX 255
#define IPSSH_FILEXFER_ATTR_SIZE 0x00000001
#define IPSSH_FILEXFER_ATTR_UIDGID 0x00000002
#define IPSSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
#define IPSSH_FILEXFER_ATTR_ACMODTIME 0x00000008
#define IPSSH_FILEXFER_ATTR_EXTENDED 0x80000000
#define IPSSH_FX_OK 0
#define IPSSH_FX_EOF 1
#define IPSSH_FX_NO_SUCH_FILE 2
#define IPSSH_FX_PERMISSION_DENIED 3
#define IPSSH_FX_FAILURE 4
#define IPSSH_FX_BAD_MESSAGE 5
#define IPSSH_FX_NO_CONNECTION 6
#define IPSSH_FX_CONNECTION_LOST 7
#define IPSSH_FX_OP_UNSUPPORTED 8
#define IPSSH_FX_INVALID_HANDLE 9
#define IPSSH_FX_NO_SUCH_PATH 10
#define IPSSH_FX_FILE_ALREADY_EXISTS 11
#define IPSSH_FX_WRITE_PROTECT 12
#define IPSSH_FX_NO_MEDIA 13
#define IPSSH_FX_NO_SPACE_ON_FILESYSTEM 14
#define IPSSH_FX_QUOTA_EXCEEDED 15
#define IPSSH_FX_UNKNOWN_PRINCIPLE 16
#define IPSSH_FX_LOCK_CONFlICT 17
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_sftp_init(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_sftp_data_setup(Ipssh_conn* ssh_conn);
IP_GLOBAL void ipssh_sftp_data_free(Ipssh_conn* ssh_conn);
IP_GLOBAL Ipssh_pkt_handler ipssh_sftp_get_handler(Ip_s32 pkt_type);
IP_GLOBAL Ip_err ipssh_channel_data_sftp_handler(Ipssh_channel* channel, Ipcom_buffer* msg);
IP_GLOBAL void ipssh_sftp_cleanup(Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_pack_attr(Ipcom_buffer* pkt, struct Ip_stat* buf, Ip_u32 flags);
IP_GLOBAL Ip_err ipssh_unpack_attr(Ipcom_buffer* buf, Ip_u32 attr_flags, struct Ip_stat* file_attr);
IP_GLOBAL Ip_mode_t ipssh_mode_ipcom2ssh(Ip_mode_t mode);
IP_GLOBAL Ip_mode_t ipssh_mode_ssh2ipcom(Ip_mode_t mode);
IP_GLOBAL Ip_err ipssh_sftp_srv_pkt_dispatch(Ipssh_channel* channel, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_sftp_clt_pkt_dispatch(Ipssh_channel* channel, Ipcom_buffer* pkt);
IP_GLOBAL void ipssh_channel_sftp_init(Ipssh_channel* channel, int ch_type);
IP_GLOBAL Ip_err ipssh_send_fxp_msg(Ipssh_channel* channel, Ipcom_buffer* msg);
IP_GLOBAL Ip_err ipssh_send_fxp_status(Ipssh_channel* channel, Ip_u32 req_id, Ip_u32 status);
IP_GLOBAL Ip_err ipssh_sftp_subsystem_init_cb(Ipssh_channel* channel, Ip_fd* sock);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,377 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_sftp_file.c,v $ $Revision: 1.8.10.1 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_sftp_file.c,v $
* $Author: jren $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
* This file implements sftp file operations against a standard file system.
* The implementation can be used as a reference when implementing sftp file
* operations against other sources/sinks, e.g. memory.
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
#ifdef IPSSH_USE_SFTP
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipssh_h.h"
#include "ipssh.h"
#include "ipssh_sftp.h"
#include "ipssh_buffer.h"
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_buffer.h>
#include <ipcom_syslog.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_fd ipssh_sftp_file_open(const char *pathname, int omode, Ip_mode_t attrs);
IP_STATIC Ip_fd ipssh_sftp_file_close(Ip_fd fd);
IP_STATIC Ip_err ipssh_sftp_file_stat(const char* path, struct Ip_stat* buf);
IP_STATIC Ip_ssize_t ipssh_sftp_file_read(Ip_fd fd, char* data, Ip_size_t len);
IP_STATIC Ip_ssize_t ipssh_sftp_file_write(Ip_fd fd, const char* data, Ip_size_t len);
IP_STATIC Ip_off_t ipssh_sftp_file_lseek(Ip_fd fd, Ip_u64 offset, int whence);
IP_STATIC IP_DIR* ipssh_sftp_file_opendir(const char* path);
IP_STATIC int ipssh_sftp_file_closedir(IP_DIR* dirp);
IP_STATIC struct Ip_dirent* ipssh_sftp_file_readdir(IP_DIR* dirp);
IP_STATIC int ipssh_sftp_file_mkdir(const char* path, Ip_mode_t mode);
IP_STATIC int ipssh_sftp_file_rmdir(const char* path);
IP_STATIC int ipssh_sftp_file_unlink(const char* path);
IP_STATIC int ipssh_sftp_file_rename(const char* oldpath, const char* newpath);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipssh_sftp_func_cb ipssh_sftp_file_funcs =
{
"File System",
ipssh_sftp_file_open,
ipssh_sftp_file_close,
ipssh_sftp_file_stat,
ipssh_sftp_file_read,
ipssh_sftp_file_write,
ipssh_sftp_file_lseek,
ipssh_sftp_file_opendir,
ipssh_sftp_file_closedir,
ipssh_sftp_file_readdir,
ipssh_sftp_file_mkdir,
ipssh_sftp_file_rmdir,
ipssh_sftp_file_unlink,
ipssh_sftp_file_rename
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_sftp_file_open
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_fd
ipssh_sftp_file_open(const char *path, int omode, Ip_mode_t attrs)
{
/* IPCOM doesn't handle IP_O_TRUNC well, so force an unlink */
if (omode & IP_O_TRUNC)
(void)ipcom_unlink(path);
return ipcom_fileopen(path, omode, attrs);
}
/*
*===========================================================================
* ipssh_sftp_file_close
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_fd
ipssh_sftp_file_close(Ip_fd fd)
{
return ipcom_fileclose(fd);
}
/*
*===========================================================================
* ipssh_sftp_file_stat
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_sftp_file_stat(const char* path, struct Ip_stat* buf)
{
return ipcom_stat(path, buf);
}
/*
*===========================================================================
* ipssh_sftp_file_read
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_ssize_t
ipssh_sftp_file_read(Ip_fd fd, char* data, Ip_size_t len)
{
return ipcom_fileread(fd, data, len);
}
/*
*===========================================================================
* ipssh_sftp_file_write
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_ssize_t
ipssh_sftp_file_write(Ip_fd fd, const char* data, Ip_size_t len)
{
return ipcom_filewrite(fd, data, len);
}
/*
*===========================================================================
* ipssh_sftp_file_lseek
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_off_t
ipssh_sftp_file_lseek(Ip_fd fd, Ip_u64 offset, int whence)
{
Ip_off_t offset_lo;
Ip_off_t offset_hi;
offset_lo = (Ip_off_t)IP_U64_GETLO(offset);
offset_hi = (Ip_off_t)IP_U64_GETHI(offset);
ip_assert(offset_hi == 0);
return ipcom_lseek(fd, offset_lo, whence);
}
/*
*===========================================================================
* ipssh_sftp_file_opendir
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC IP_DIR*
ipssh_sftp_file_opendir(const char* path)
{
return ipcom_opendir(path);
}
/*
*===========================================================================
* ipssh_sftp_file_closedir
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_sftp_file_closedir(IP_DIR* dirp)
{
return ipcom_closedir(dirp);
}
/*
*===========================================================================
* ipssh_sftp_file_readdir
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC struct Ip_dirent*
ipssh_sftp_file_readdir(IP_DIR* dirp)
{
return ipcom_readdir(dirp);
}
/*
*===========================================================================
* ipssh_sftp_file_mkdir
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_sftp_file_mkdir(const char* path, Ip_mode_t mode)
{
return ipcom_mkdir(path, mode);
}
/*
*===========================================================================
* ipssh_sftp_file_rmdir
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_sftp_file_rmdir(const char* path)
{
return ipcom_rmdir(path);
}
/*
*===========================================================================
* ipssh_sftp_file_unlink
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_sftp_file_unlink(const char* path)
{
return ipcom_unlink(path);
}
/*
*===========================================================================
* ipssh_sftp_file_rename
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipssh_sftp_file_rename(const char* oldpath, const char* newpath)
{
return ipcom_rename(oldpath, newpath);
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_get_sftp_file_func_cb
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ipssh_sftp_func_cb*
ipssh_get_sftp_file_func_cb(void)
{
return &ipssh_sftp_file_funcs;
}
#else
int ipssh_sftp_file_empty_file;
#endif /* IPSSH_USE_SFTP */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,270 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_sock_shell.c,v $ $Revision: 1.42.10.3 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_sock_shell.c,v $
* $Author: jren $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipssh_h.h"
#include "ipssh.h"
#include "ipssh_connection.h"
#include "ipssh_buffer.h"
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_clib.h>
#include <ipcom_sock.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_sock_shell_stdout_handler
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
#define BUF_SIZE 256
IP_STATIC Ip_err
ipssh_sock_shell_stdout_handler(Ip_fd sock, Ipssh_conn_ctx *ctx, Ipssh_map_entry *map_entry)
{
Ip_ssize_t bytes_read;
Ipssh_channel* channel;
Ip_err rc = IPCOM_SUCCESS;
char *buf;
(void) map_entry;
IPCOM_LOG1(DEBUG2, "ipssh_sock_shell_stdout_handler :: sock=%d", sock);
channel = ipssh_channel_map_lookup(&ctx->ssh_conn->ch_map, sock);
if(!channel)
{
IPCOM_LOG1(ERR, "ipssh_sock_shell_stdout_handler :: ipssh_sock2channel failed for sock=%d", sock);
return IPCOM_ERR_FAILED;
}
buf = ipcom_malloc(BUF_SIZE);
if(!buf)
{
IPCOM_LOG0(ERR, "ipssh_sock_shell_stdout_handler :: out of memory");
return IPCOM_ERR_FAILED;
}
ipcom_memset(buf, 0, BUF_SIZE);
while(1)
{
if(channel->ssh_conn->ssh_version == 2 && channel->peer_win <= 2*BUF_SIZE)
{
IPCOM_LOG1(DEBUG, "ipssh_sock_shell_stdout_handler :: send_win = %d, returning to process win adj msg", channel->peer_win);
/* Wait for a channel window adjust message to arrive */
IP_FD_CLR(sock, &(ctx->read_set));
IP_BIT_SET(channel->flags, IPSSH_CH_FLAG_WAITING_FOR_WIN_ADJUST_MSG);
rc = IPCOM_SUCCESS;
break;
}
bytes_read = ipcom_socketread(sock, buf, BUF_SIZE - 1);
if(bytes_read == 0 || (bytes_read < 0 && (ipcom_errno == IP_ERRNO_ESHUTDOWN || ipcom_errno == IP_ERRNO_ECONNRESET)))
{
(void)ipssh_shell_exit2(ctx->ssh_conn, channel->data.shell.shell_fd);
IP_FD_CLR(sock, &(ctx->read_set));
ipcom_socketclose(sock);
ipcom_list_remove(&(map_entry->list));
ipcom_free(map_entry);
break;
}
if(bytes_read < 0)
{
if(ipcom_errno == IP_ERRNO_EWOULDBLOCK
#if (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) && (defined(IP_TARGET_SOFT) || defined(softOSE) || defined(IP_TARGET_SOLARIS2) || defined(IP_TARGET_LINUX) || defined(IP_TARGET_WIN32))
/* When INET=api in userconf file errno is not set properly. This is a somewhat crude work-around */
|| ipcom_errno == 0
#endif
)
break; /* All available data read, proceed */
IPCOM_LOG1(DEBUG, "ipssh_sock_shell_stdout_handler :: ipcom_socketread() failed, errno=%d", ipcom_errno);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
if(ipssh_send_shell_stdout_data2(ctx->ssh_conn, channel->data.shell.shell_fd, buf, bytes_read) != bytes_read)
{
IPCOM_LOG1(ERR, "ipssh_sock_shell_stdout_handler :: ipssh_send_shell_stdout_data() failed, errno=%d", ipcom_errno);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
}
cleanup:
if(buf)
ipcom_free(buf);
return rc;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_sock_shell_start
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_PUBLIC Ip_fd
ipssh_sock_shell_start(Ipssh_conn* ssh_conn, const char *user, Ipcom_shell_ctx* sh_ctx)
{
Ipssh_conn_ctx* ctx = ssh_conn->extra;
Ip_fd shell_fd = IP_INVALID_SOCKET;
Ip_s32 on = 1;
(void)user;
(void)sh_ctx;
if(ipcom_start_shell(&shell_fd, ssh_conn->sh_ctx) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "ipssh_sock_shell_start :: ipcom_shell_start failed, errno=%d", ipcom_errno);
goto err_out;
}
if(ipcom_socketioctl(shell_fd, IP_FIONBIO, (char*)&on))
{
IPCOM_LOG1(ERR, "ipssh_sock_shell_start :: ipcom_socketioctl(IP_FIONBIO) failed, errno=%d", ipcom_errno);
goto err_out;
}
IP_FD_SET(shell_fd, &(ctx->read_set));
if(!ipssh_store_map_entry(ctx, shell_fd, ipssh_sock_shell_stdout_handler, 0))
{
IPCOM_LOG1(ERR, "ipssh_sock_shell_start :: ipssh_store_map_entry() failed", ipcom_errno);
goto err_out;
}
return shell_fd;
err_out:
if(shell_fd != IP_INVALID_SOCKET)
ipcom_socketclose(shell_fd);
return IP_INVALID_SOCKET;
}
/*
*===========================================================================
* ipssh_sock_shell_stdin
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_PUBLIC Ip_err
ipssh_sock_shell_stdin(Ip_fd shell_fd, const char *data, int len)
{
Ip_ssize_t ret_val;
ret_val = ipcom_socketwrite(shell_fd, data, len);
if(ret_val < 0 || ret_val != len)
{
IPCOM_LOG3(ERR, "ipssh_shell_stdin_handler :: ipcom_socketwrite() failed, ret_val=%d, len=%d, errno=%d",
ret_val, len, ipcom_errno);
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,890 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_subsystem_clt.c,v $ $Revision: 1.5.12.2 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_subsystem_clt.c,v $
* $Author: svc-cmnet $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger.boden@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipssh_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_getopt.h>
#include "ipssh.h"
#include "ipssh_h.h"
#include "ipssh_channel.h"
#include "ipssh_buffer.h"
#include "ipssh_transport.h"
#include "ipssh_sftp_clt.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_subsystem_clt_send_ch_data_msg
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_subsystem_clt_send_ch_data_msg(Ipssh_channel* channel, void* buf, Ip_size_t len)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipcom_buffer* pkt;
ip_assert(channel->peer_win >= len);
pkt = ipssh_buffer_new_channel_data_pkt(len, channel);
if (!pkt)
{
ipcom_errno = IP_ERRNO_ENOMEM;
return IPCOM_ERR_NO_MEMORY;
}
if (ipcom_buffer_put(pkt, buf, len))
goto cleanup;
if (ipssh_send_channel_data_msg(channel, pkt))
goto cleanup;
rc = IPCOM_SUCCESS;
cleanup:
if (pkt)
ipcom_buffer_free(pkt);
return rc;
}
/*
*===========================================================================
* ipssh_send_channel_subsystem_req
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_send_channel_subsystem_req(Ipssh_conn* ssh_conn, Ipssh_channel* channel, const char* subsystem)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipcom_buffer* pkt;
pkt = ipssh_buffer_new_v2_pkt(128, IPSSH_MSG_CHANNEL_REQUEST);
if(!pkt)
{
IPCOM_LOG0(ERR, "ipssh_send_channel_subsystem_req :: out of memory");
return IPCOM_ERR_FAILED;
}
if (ipssh_buffer_put_uint(pkt, channel->peer_ch_id) ||
ipssh_buffer_put_sshstr(pkt, IPSSH_SUBSYSTEM_STR) ||
ipcom_buffer_put_char(pkt, 1) || /* want reply */
ipssh_buffer_put_sshstr(pkt, subsystem))
{
IPCOM_LOG0(ERR, "ipssh_send_channel_subsystem_req :: too small pkt");
goto cleanup;
}
rc = ipssh_send_pkt(ssh_conn, pkt, IP_FALSE);
cleanup:
ipcom_buffer_free(pkt);
return rc;
}
/*
*===========================================================================
* ipssh_subsystem_clt_ch_data_handler
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipssh_subsystem_clt_ch_data_handler(Ipssh_channel* channel, Ipcom_buffer* msg)
{
Ip_u32 ch_data_len;
Ipssh_ch_data_entry* ch_data_entry;
/* Get channel data length */
if(ipssh_buffer_get_uint(msg, &ch_data_len))
return IPCOM_ERR_FAILED;
ch_data_entry = ipcom_malloc(sizeof(Ipssh_ch_data_entry));
if (!ch_data_entry)
{
return IPCOM_ERR_NO_MEMORY;
}
ch_data_entry->msg = ipcom_buffer_new(ch_data_len);
if (!ch_data_entry->msg)
{
ipcom_free(ch_data_entry);
return IPCOM_ERR_NO_MEMORY;
}
(void)ipcom_buffer_put(ch_data_entry->msg, ipcom_buffer_start_ptr(msg), ipcom_buffer_len(msg));
ipcom_list_insert_last(&channel->ch_data_list, &ch_data_entry->list);
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
#ifdef IPTESTENGINE
IP_STATIC void
ipssh_cmd_ssh_subsystem_usage(const char* cmd_name)
{
ipcom_printf("%s, [-p port] [-u user] [-w password] [-l buf_len] [-n write_count] [-i init_write_count] [-h] -s subsystem host"IP_LF, cmd_name);
}
/*
*===========================================================================
* ipssh_ssh_subsystem_clt_bulk_transfer
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipssh_ssh_subsystem_clt_bulk_transfer(Ipssh_conn* ssh_conn, int buf_len, int write_count, int init_write_count)
{
int rc;
char* buf;
char* ref_buf;
int i;
int j;
int bytes_received = 0;
buf_len = (buf_len/26)*26;
ipcom_printf("buf_len = %d"IP_LF, buf_len);
buf = ipcom_malloc(buf_len+1);
if (!buf)
return;
ref_buf = ipcom_malloc(buf_len+1);
if (!ref_buf)
{
ipcom_free(buf);
return;
}
for (i=0; i<buf_len; i++)
ref_buf[i] = 'A' + (i%26);
ref_buf[buf_len]=0;
/* Read stdout output until the prompt is received */
while (1)
{
rc = ipssh_subsystem_clt_read(ssh_conn, buf, buf_len, 0);
if (rc <= 0)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_bulk_transfer :: failed to find prompt, errno=%d", ipcom_errno);
goto cleanup;
}
if (rc < 2)
continue;
if (buf[rc-2] == '>' && buf[rc-1] == ' ' || buf[rc-1] == '>' || rc > 7 && ipcom_strcmp(&buf[rc-7], "XunXiqX"))
break; /* prompt found */
}
/* Start the stdio_echo cmd */
ipcom_strcpy(buf, "stdio_echo\n");
if (ipssh_subsystem_clt_write(ssh_conn, buf, 11, 0) != 11)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_clt_bulk_transfer :: failed to initiate stdio_echo cmd, errno=%d", ipcom_errno);
goto cleanup;
}
ipcom_memset(buf, 0, buf_len);
while (bytes_received < 12)
{
rc = ipssh_subsystem_clt_read(ssh_conn, buf, buf_len, 0);
if (rc <= 0)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_clt_bulk_transfer :: failed to initiate stdio_echo cmd (read), errno=%d", ipcom_errno);
goto cleanup;
}
bytes_received += rc;
}
for (i=0; i<init_write_count; i++)
{
if (ipssh_subsystem_clt_write(ssh_conn, ref_buf, buf_len, 0) != buf_len)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_clt_bulk_transfer :: ipssh_subsystem_clt_write() failed, errno=%d", ipcom_errno);
goto cleanup;
}
}
bytes_received = 0;
for (i=0; i<write_count; i++)
{
if (i+init_write_count < write_count)
{
if (ipssh_subsystem_clt_write(ssh_conn, ref_buf, buf_len, 0) != buf_len)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_bulk_transfer :: ipssh_subsystem_clt_write() failed 2, errno=%d", ipcom_errno);
goto cleanup;
}
}
ipcom_memset(buf, buf_len+1, 0);
rc = ipssh_subsystem_clt_read(ssh_conn, buf, buf_len, 0);
if (rc <= 0)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_bulk_transfer :: ipssh_subsystem_clt_read() failed, errno=%d", ipcom_errno);
goto cleanup;
}
for (j=0; j<rc; j++)
{
if (buf[j] != (j+bytes_received)%26 + 'A')
{
IPCOM_LOG3(ERR, "ipssh_subsystem_clt_bulk_transfer :: incorrect data received at pos: %d, write_count: %d, init_write_count=%d",
bytes_received+j, i, init_write_count);
ipcom_printf("ipssh_subsystem_clt_bulk_transfer :: incorrect data received at pos: %d, write_count: %d, init_write_count=%d",
bytes_received+j, i, init_write_count);
goto cleanup;
}
}
bytes_received += rc;
}
cleanup:
if (buf)
ipcom_free(buf);
if (ref_buf)
ipcom_free(ref_buf);
}
/*
*===========================================================================
* ipssh_ssh_subsystem_clt_proxy
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipssh_ssh_subsystem_clt_proxy(Ipssh_conn* ssh_conn, int buf_len)
{
int rc;
char* buf;
Ip_fd_set read_set;
Ip_fd max_fd;
Ip_fd ssh_fd;
Ip_fd stdin_fd;
int num;
IP_FD_ZERO(&read_set);
stdin_fd = ipcom_fileno(ip_stdin);
ssh_fd = ipssh_conn_get_fd(ssh_conn);
max_fd = IP_MAX(stdin_fd, ssh_fd);
buf = ipcom_malloc(buf_len+1);
if (!buf)
return;
while (1)
{
IP_FD_SET(ssh_fd, &read_set);
IP_FD_SET(stdin_fd, &read_set);
num = ipcom_socketselect(max_fd + 1, &read_set, IP_NULL, IP_NULL, IP_NULL);
if (num == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_clt_proxy :: ipcom_socketselect() failed, errno=%d", ipcom_errno);
goto cleanup;
}
if (IP_FD_ISSET(ssh_fd, &read_set))
{
read_once_more:
rc = ipssh_subsystem_clt_read(ssh_conn, buf, buf_len, 0);
if (rc > 0)
{
buf[rc]=0;
ipcom_printf("%s", buf);
if (ipssh_subsystem_clt_pending_bytes(ssh_conn) > 0)
goto read_once_more;
}
else if (rc == 0)
goto cleanup;
else /* rc < 0 */
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_clt_proxy :: ipssh_subsystem_clt_read() failed, errno=%d", ipcom_errno);
ipcom_printf("ipssh_ssh_subsystem_clt_proxy :: ipssh_subsystem_clt_read() failed, errno=%d"IP_LF, ipcom_errno);
goto cleanup;
}
}
if (IP_FD_ISSET(stdin_fd, &read_set))
{
rc = ipcom_socketread(stdin_fd, buf, buf_len);
if (rc > 0)
{
if (ipssh_subsystem_clt_write(ssh_conn, buf, rc, 0) != rc)
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_clt_proxy :: ipssh_subsystem_clt_write() failed, errno=%d", ipcom_errno);
ipcom_printf("ipssh_ssh_subsystem_clt_proxy :: ipssh_subsystem_clt_write() failed, errno=%d"IP_LF, ipcom_errno);
goto cleanup;
}
}
else if (rc == 0)
goto cleanup;
else
{
IPCOM_LOG1(ERR, "ipssh_ssh_subsystem_clt_proxy :: ipcom_socketread() failed, errno=%d", ipcom_errno);
goto cleanup;
}
}
}
cleanup:
ipcom_free(buf);
}
/*
*===========================================================================
* ipssh_cmd_ssh_subsystem
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_cmd_ssh_subsystem(int argc, char** argv)
{
Ipcom_getopt opt;
int rc = IPCOM_ERR_FAILED;
char* host;
char* user = IP_NULL;
char* pw = IP_NULL;
int port = 22;
char* subsystem = IP_NULL;
Ipssh_conn* ssh_conn;
int buf_len = 512;
int write_count = 0;
int init_write_count = 0;
if(argc == 1)
{
ipssh_cmd_ssh_subsystem_usage(argv[0]);
return IPCOM_ERR_FAILED;
}
ipcom_getopt_clear_r(&opt);
while( (rc = ipcom_getopt_r(argc, argv, "hp:u:s:w:l:n:i:", &opt)) != -1)
{
switch(rc)
{
case 'p':
port = ipcom_atoi(opt.optarg);
if(port < 0 || port > 0xffff)
{
ipcom_printf("Invalid port"IP_LF);
return IPCOM_ERR_FAILED;
}
break;
/* case 'i': */
/* key_file = opt.optarg; */
/* break; */
case 'u':
user = opt.optarg;
break;
case 'w':
pw = opt.optarg;
break;
case 's':
subsystem = opt.optarg;
break;
case 'l':
buf_len = ipcom_atoi(opt.optarg);
if (buf_len < 0)
{
ipcom_printf("Illegal buf_len arg: %s"IP_LF, opt.optarg);
return IPCOM_ERR_INVALID_ARG;
}
break;
case 'n':
write_count = ipcom_atoi(opt.optarg);
if (write_count < 0)
{
ipcom_printf("Illegal write count arg: %s"IP_LF, opt.optarg);
return IPCOM_ERR_INVALID_ARG;
}
break;
case 'i':
init_write_count = ipcom_atoi(opt.optarg);
if (init_write_count < 0)
{
ipcom_printf("Illegal init write count arg: %s"IP_LF, opt.optarg);
return IPCOM_ERR_INVALID_ARG;
}
break;
case 'h':
ipssh_cmd_ssh_subsystem_usage(argv[0]);
return IPCOM_SUCCESS;
default:
ipssh_cmd_ssh_subsystem_usage(argv[0]);
return IPCOM_ERR_FAILED;
}
}
if(opt.optind == argc - 1)
host = argv[opt.optind];
else
{
ipcom_printf("No host given"IP_LF);
return IPCOM_ERR_FAILED;
}
if (!subsystem)
{
ipcom_printf("No subsystem given"IP_LF);
return IPCOM_ERR_FAILED;
}
ssh_conn = ipssh_conn_new();
if(!ssh_conn)
{
ipcom_printf("ipssh_cmd_subsystem :: out of memory"IP_LF);
return IPCOM_ERR_FAILED;
}
(void)ipssh_sftp_clt_set_userid(ssh_conn, user);
if(pw)
(void)ipssh_sftp_clt_set_pw(ssh_conn, pw);
if (ipssh_subsystem_clt_open(ssh_conn, host, port, subsystem) != IPCOM_SUCCESS)
{
ipcom_printf("Failed to establish %s subsystem connection to %s, port %d"IP_LF,
subsystem, host, port);
goto cleanup;
}
if (write_count > 0)
ipssh_ssh_subsystem_clt_bulk_transfer(ssh_conn, buf_len, write_count, init_write_count);
else
ipssh_ssh_subsystem_clt_proxy(ssh_conn, buf_len);
cleanup:
ipssh_sftp_clt_close(ssh_conn);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipssh_cmd_ssh_stdio_echo
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipssh_cmd_ssh_stdio_echo(int argc, char** argv)
{
char buf[1024];
int rc;
int laps=0;
int bytes_read=0;
(void) argc;
(void) argv;
while (1)
{
rc = ipcom_fread(buf, 1, sizeof(buf), ip_stdin);
if (rc <= 0)
return IPCOM_ERR_FAILED;
bytes_read += rc;
laps++;
ipcom_printf("stdio_echo: read %d bytes, total: %d , laps %d\n", rc, bytes_read, laps);
if (rc == 2 && buf[0] == '#' && buf[1] == '\n')
return IPCOM_SUCCESS;
if (ipcom_fwrite(buf, 1, rc, ip_stdout) <= 0)
return IPCOM_ERR_FAILED;
}
}
#endif
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipssh_subsystem_clt_open
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipssh_subsystem_clt_open(Ipssh_conn* ssh_conn,
const char* hostname,
const Ip_u16 port,
const char* subsystem)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipcom_buffer* pkt = IP_NULL;
if (!ssh_conn || !hostname || !subsystem)
return IPCOM_ERR_INVALID_ARG;
ssh_conn->mode = IPSSH_MODE_CLT;
rc = ipssh_setup_clt_transport(ssh_conn, hostname, port);
if(rc != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_subsystem_clt_open :: ipssh_setup_clt_transport() failed");
return rc;
}
ssh_conn->data.clt.channel = ipssh_channel_new(ssh_conn, 0xffffffff, ipssh_subsystem_clt_ch_data_handler);
if(!ssh_conn->data.clt.channel)
{
IPCOM_LOG0(ERR, "ipssh_subsystem_clt_open :: ipssh_channel_new failed");
return IPCOM_ERR_FAILED;
}
ssh_conn->data.clt.channel->ssh_conn = ssh_conn;
ssh_conn->data.clt.channel->type = IPSSH_CH_TYPE_SUBSYSTEM;
ipcom_list_init(&ssh_conn->data.clt.channel->ch_data_list);
pkt = ipssh_get_channel_open_pkt(ssh_conn->data.clt.channel, IPSSH_SESSION, 128);
if(!pkt)
{
IPCOM_LOG0(ERR, "ipssh_subsystem_clt_open :: ipssh_get_channel_open_pkt failed");
return IPCOM_ERR_FAILED;
}
rc = ipssh_send_pkt(ssh_conn, pkt, IP_TRUE);
if(rc != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_subsystem_clt_open :: ipssh_send_pkt failed");
return IPCOM_ERR_FAILED;
}
rc = ipssh_read_and_dispatch_v2_pkt(ssh_conn, IPSSH_MSG_CHANNEL_OPEN_CONFIRMATION);
if (rc != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_subsystem_clt_open :: ipssh_read_and_dispatch_v2_pkt2 failed for ch open conf");
return IPCOM_ERR_FAILED;
}
if(ipssh_send_channel_subsystem_req(ssh_conn, ssh_conn->data.clt.channel, subsystem) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_subsystem_clt_open :: ipssh_send_channel_request_pty_req failed");
return IPCOM_ERR_FAILED;
}
rc = ipssh_read_and_dispatch_v2_pkt(ssh_conn, IPSSH_MSG_CHANNEL_SUCCESS);
if (rc != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipssh_subsystem_clt_open :: ipssh_read_and_dispatch_v2_pkt2 failed for MSG_CHANNEL_SUCCESS");
return IPCOM_ERR_FAILED;
}
rc = IPCOM_SUCCESS;
return rc;
}
/*
*===========================================================================
* ipssh_subsystem_clt_read
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_ssize_t
ipssh_subsystem_clt_read(Ipssh_conn* ssh_conn,
char* buf,
Ip_size_t len,
int flags)
{
Ipssh_channel* channel;
Ip_u32 ch_id;
Ip_u32 msg_len;
Ip_size_t rc = 0;
Ipssh_ch_data_entry* ch_data_entry;
(void) flags;
if (!ssh_conn || !ssh_conn->data.clt.channel)
return IPCOM_ERR_INVALID_ARG;
channel = ssh_conn->data.clt.channel;
ip_assert(channel->type == IPSSH_CH_TYPE_SUBSYSTEM);
if (ipcom_list_length(&channel->ch_data_list) > 0) /* We have some left overs from previous call */
{
for (ch_data_entry = IPCOM_LIST_FIRST(&channel->ch_data_list);
ch_data_entry && len > 0;
ch_data_entry = IPCOM_LIST_FIRST(&channel->ch_data_list))
{
if (ipcom_buffer_len(ch_data_entry->msg) <= len)
{
ipcom_memcpy(buf, ipcom_buffer_start_ptr(ch_data_entry->msg), ipcom_buffer_len(ch_data_entry->msg));
len -= ipcom_buffer_len(ch_data_entry->msg);
rc += ipcom_buffer_len(ch_data_entry->msg);
buf += ipcom_buffer_len(ch_data_entry->msg);
ipcom_list_remove(&ch_data_entry->list);
ipcom_buffer_free(ch_data_entry->msg);
ipcom_free(ch_data_entry);
if (len == 0)
return rc; /* We have read the requested number of bytes */
continue;
}
ipcom_memcpy(buf, ipcom_buffer_start_ptr(ch_data_entry->msg), len);
(void)ipcom_buffer_consume(ch_data_entry->msg, len);
rc += len;
return rc;
}
return rc;
}
/* Need to read another channel data msg */
if (ipssh_read_v2_pkt2(ssh_conn, IPSSH_MSG_CHANNEL_DATA) != IPCOM_SUCCESS)
{
ipcom_errno = IP_ERRNO_EINVAL;
return -1;
}
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, 6);
if (ipssh_buffer_get_uint(ssh_conn->recv_plain_buf, &ch_id) != IPCOM_SUCCESS)
{
ipcom_errno = IP_ERRNO_EINVAL;
return -1;
}
if (ch_id != channel->my_ch_id)
{
ipcom_errno = IP_ERRNO_EINVAL;
return -1;
}
if (ipssh_buffer_get_uint(ssh_conn->recv_plain_buf, &msg_len) != IPCOM_SUCCESS)
{
ipcom_errno = IP_ERRNO_EINVAL;
return -1;
}
if(ipssh_send_channel_win_adjust_msg(channel, msg_len))
{
ipcom_errno = IP_ERRNO_EINVAL;
return -1;
}
if (msg_len <= len)
{
ipcom_memcpy(buf, ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf), msg_len);
return msg_len;
}
else /* More data in channel_data msg than the caller requests */
{
ipcom_memcpy(buf, ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf), len);
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf, len);
ch_data_entry = ipcom_malloc(sizeof(Ipssh_ch_data_entry));
if (!ch_data_entry)
{
ipcom_errno = IP_ERRNO_ENOMEM;
return -1;
}
ch_data_entry->msg = ipcom_buffer_new(ipcom_buffer_len(ssh_conn->recv_plain_buf));
if (!ch_data_entry->msg)
{
ipcom_free(ch_data_entry);
ipcom_errno = IP_ERRNO_ENOMEM;
return -1;
}
(void)ipcom_buffer_put(ch_data_entry->msg,
ipcom_buffer_start_ptr(ssh_conn->recv_plain_buf),
ipcom_buffer_len(ssh_conn->recv_plain_buf));
ipcom_list_insert_last(&channel->ch_data_list, &ch_data_entry->list);
(void)ipcom_buffer_consume(ssh_conn->recv_plain_buf,
ipcom_buffer_len(ssh_conn->recv_plain_buf));
return len;
}
}
/*
*===========================================================================
* ipssh_subsystem_clt_write
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_ssize_t
ipssh_subsystem_clt_write(Ipssh_conn* ssh_conn,
void* buf,
Ip_size_t len,
int flags)
{
Ipssh_channel* channel;
Ip_size_t org_len;
Ip_size_t tmp_len;
(void) flags;
if (!ssh_conn || !ssh_conn->data.clt.channel || ssh_conn->data.clt.channel->type != IPSSH_CH_TYPE_SUBSYSTEM)
return IPCOM_ERR_INVALID_ARG;
channel = ssh_conn->data.clt.channel;
if (channel->peer_win >= len)
{
if (ipssh_subsystem_clt_send_ch_data_msg(channel, buf, len) != IPCOM_SUCCESS)
return -1;
else
return len;
}
org_len = len;
while (len > 0)
{
if (channel->peer_win > 0)
{
tmp_len = IP_MIN(channel->peer_win, len);
if (ipssh_subsystem_clt_send_ch_data_msg(channel, buf, tmp_len) != IPCOM_SUCCESS)
return -1;
len -= tmp_len;
buf = (char*)buf + tmp_len;
}
if (len == 0)
break; /* All data sent */
/* Peer channel send window is 0, wait for a channel window adjust msg */
if (ipssh_read_and_dispatch_v2_pkt(ssh_conn, IPSSH_MSG_CHANNEL_WINDOW_ADJUST) != IPCOM_SUCCESS)
{
ipcom_errno = IP_ERRNO_EINVAL;
return -1;
}
}
return org_len;
}
/*
*===========================================================================
* ipssh_subsystem_clt_pending_bytes
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_size_t
ipssh_subsystem_clt_pending_bytes(Ipssh_conn* ssh_conn)
{
Ipssh_channel* channel;
Ip_size_t pending_bytes = 0;
Ipssh_ch_data_entry* ch_data_entry;
channel = ssh_conn->data.clt.channel;
if (!channel || ipcom_list_length(&channel->ch_data_list) == 0)
return 0;
for (ch_data_entry = IPCOM_LIST_FIRST(&channel->ch_data_list);
ch_data_entry;
ch_data_entry = IPCOM_LIST_NEXT(&ch_data_entry->list))
{
pending_bytes += ipcom_buffer_len(ch_data_entry->msg);
}
return pending_bytes;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,117 @@
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_transport.h,v $ $Revision: 1.17.10.2 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_transport.h,v $
* $Author: svc-cmnet $ $Date: 2013-03-13 07:45:44 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef ipssh_transport_h
#define ipssh_transport_h
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipssh.h"
#include "ipssh_h.h"
#include "ipssh_list.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
struct Ipssh_conn_ctx_st;
#define IPSSH_GET_PKT_LEN(pkt) ipssh_get_len(pkt)
#define IPSSH_GET_PKT_PAD_LEN(pkt) ((pkt[4]))
#define IPSSH_SET_PKT_PAD_LEN(pkt, len) ((pkt[4] = len))
#define IPSSH_GET_PKT_PAYLOAD(pkt) (&(pkt[5]))
#define IPSSH_GET_PKT_BODY(pkt) (&(pkt[6]))
#define IPSSH_GET_PKT_TYPE(pkt) (pkt[5])
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_pkt_dispatch(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_read_and_dispatch_v2_pkt(Ipssh_conn* ssh_conn, Ip_u8 expected_pkt_type);
IP_GLOBAL int ipssh_read_v2_pkt(Ipssh_conn* ssh_conn);
IP_GLOBAL int ipssh_read_v2_pkt2(Ipssh_conn* ssh_conn, Ip_u8 expected_pkt_type);
IP_GLOBAL Ip_u32 ipssh_get_len(Ip_u8* pkt);
IP_GLOBAL Ip_err ipssh_conn_v2_handler(Ip_fd sock, Ipssh_conn_ctx* ctx, Ipssh_map_entry* map_entry);
IP_GLOBAL Ip_err ipssh_send_pkt(Ipssh_conn* ssh_conn, Ipcom_buffer* buf, Ip_bool free_pkt);
IP_GLOBAL Ip_err ipssh_msg2list(Ipssh_msg_list* list, Ip_u8 type, Ip_u8* msg, Ip_size_t len, Ip_u8 pos);
IP_GLOBAL Ip_err ipssh_msg2list_int(Ipssh_msg_list* list, Ip_u32 value, Ip_u8 pos);
/* SSH packet handlers */
IP_GLOBAL Ip_err ipssh_msg_kexinit(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_kex_dh_init(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_kex_dh_gex_request_old(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_kex_dh_gex_request(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_kex_dh_gex_init(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_kex_rsa_secret(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_disconnect(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_new_key(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_service_req(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_service_accept(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_msg_ignore(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_service_request(Ipssh_conn* ssh_conn, const char* service_name);
IP_GLOBAL Ip_err ipssh_send_service_accept(Ipssh_conn* ssh_conn, const char* service_name);
IP_GLOBAL Ip_err ipssh_send_new_key_msg(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_kexinit(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_ignore_msg(Ipssh_conn* ssh_conn, const char* msg);
IP_GLOBAL Ip_err ipssh_setup_clt_transport(Ipssh_conn* ssh_conn, const char* hostname, Ip_u16 port);
IP_GLOBAL Ip_err ipssh_compute_keys(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_consume_pkt(Ipcom_buffer* buf);
IP_GLOBAL void ipssh_reset_buffers(Ipssh_conn* ssh_conn);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,86 @@
/*
******************************************************************************
* INTERPEAK HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_transport_v1.h,v $ $Revision: 1.9 $
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_transport_v1.h,v $
* $Author: rboden $ $Date: 2010-09-21 11:49:19 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef IPSSH_TRANSPORT_V1_H
#define IPSSH_TRANSPORT_V1_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_cstyle.h>
#include "ipssh_h.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef Ip_err (*Ipssh_v1_pkt_handler)(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err ipssh_send_v1_pkt(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_read_v1_pkt(Ip_fd sock, Ipssh_conn_ctx* ctx, Ipssh_map_entry* map_entry);
/* Send packet functions */
IP_GLOBAL Ip_err ipssh_send_msg_v1_public_key(Ipssh_conn* ssh_conn);
IP_GLOBAL Ip_err ipssh_send_msg_v1_no_body(Ipssh_conn* ssh_conn, Ip_u8 pkt_type);
IP_GLOBAL Ip_err ipssh_send_msg_v1_channel_open_confirmation(Ipssh_conn* ssh_conn, Ipssh_channel* channel);
IP_GLOBAL Ip_err ipssh_send_msg_v1_channel_open_failure(Ipssh_conn* ssh_conn, Ip_u32 ch_id);
IP_GLOBAL Ip_err ipssh_send_msg_v1_channel_data(Ipssh_conn* ssh_conn, Ip_u32 ch_id, Ip_u8* data, Ip_size_t len);
/* Packet handler functions */
IP_GLOBAL Ip_err ipssh_v1_msg_session_key(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_disconnect(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_ignore(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_exit_confirmation(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_max_packet_size(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_request_compression(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
IP_GLOBAL Ip_err ipssh_v1_msg_x11_request_forwarding(Ipssh_conn* ssh_conn, Ipcom_buffer* pkt);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/