Files
m241Neelima/components/ip_net2-6.9/ipappl/src/ipftps_tls.c
T
2026-07-30 11:19:44 +05:30

1113 lines
24 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $ipftps_tls.c$ $RCSfile: ipftps_tls.c,v $ $Revision: 1.4.12.9 $
* $Source: /home/interpeak/CVSRoot/ipappl/src/ipftps_tls.c,v $
* $Author: yli10 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Howard Xu <Hao.Xu@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipftps_config.h"
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_clib2.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#ifdef IPFTP_TLS
#include "ipftps.h"
#include <openssl/ssl.h>
#define IPFTPS_C
#include "ipftps_h.h"
#ifdef IPCOM_USE_KEY_DB
#define IPFTPS_USE_PRIVACY
IP_EXTERN Ip_err ipcom_key_db_pkey_import(const char* key_id, const EVP_PKEY* key);
IP_EXTERN EVP_PKEY* ipcom_key_db_pkey_get(const char* key_id);
#else
#warning " IPCOM_USE_KEY_DB is not defined !!"
#endif
IP_STATIC SSL_CTX *ipftps_tls_ctx = IP_NULL;
IP_GLOBAL int ipftps_tls_enbale = IP_FALSE;
typedef struct FTP_TLS
{
SSL *ctrlssl;
SSL *datassl;
Ip_bool dataflag;
Ip_bool ctrlflag;
Ip_bool ccc;
}ftp_tls;
IP_STATIC DH *get_dh512(void)
{
IP_STATIC unsigned char dh512_p[]={
0xF5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,
0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,
0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,
0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,
0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,
0xE9,0x2A,0x05,0x5F,
};
IP_STATIC unsigned char dh512_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == IP_NULL)
{
return IP_NULL;
}
dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),IP_NULL);
dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),IP_NULL);
if ((dh->p == IP_NULL) || (dh->g == IP_NULL))
{
DH_free(dh);
return IP_NULL;
}
return dh;
}
IP_STATIC DH *get_dh1024(void)
{
IP_STATIC unsigned char dh1024_p[]={
0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,
0x91,0x07,0x36,0x6B,0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,
0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,
0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,
0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,
0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,
0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,
0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,
0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,
0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,
0xA2,0x5E,0xC3,0x55,0xE9,0x2F,0x78,0xC7,
};
IP_STATIC unsigned char dh1024_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == IP_NULL)
{
return IP_NULL;
}
dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),IP_NULL);
dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),IP_NULL);
if ((dh->p == IP_NULL) || (dh->g == IP_NULL))
{
DH_free(dh);
return IP_NULL;
}
return dh;
}
IP_STATIC RSA *get_rsa(const unsigned long key_length)
{
return RSA_generate_key(key_length, RSA_F4, IP_NULL, IP_NULL);
}
IP_STATIC RSA *ipftps_cb_rsa(SSL * const ctx,
const int for_export, const int key_length)
{
(void) ctx;
if (for_export == 0 || key_length >= 1024) {
return get_rsa(1024);
}
return get_rsa(512);
}
IP_STATIC DH *ipftps_cb_dh(SSL * const ctx, const int for_export,
const int key_length)
{
(void) ctx;
if (for_export == 0 || key_length >= 1024) {
return get_dh1024();
}
return get_dh512();
}
#if 0
IP_STATIC void ipftps_tls_init_cache(void)
{
IP_STATIC const char *tls_ctx_id = "ipftps";
SSL_CTX_set_session_cache_mode(ipftps_tls_ctx, SSL_SESS_CACHE_SERVER);
SSL_CTX_set_session_id_context(ipftps_tls_ctx, (unsigned char *) tls_ctx_id,
(unsigned int) strlen(tls_ctx_id));
SSL_CTX_sess_set_cache_size(ipftps_tls_ctx, 10);
SSL_CTX_set_timeout(ipftps_tls_ctx, 60 * 60L);
}
#endif
IP_STATIC int ipftps_tls_init_diffie(void)
{
DH *dh = IP_NULL;
BIO *bio = IP_NULL;
int ret = 0;
char *file = IP_NULL;
file = ipcom_sysvar_get("ipftps.tls.cert_file", IP_NULL, 0);
if(!file)
{
ipcom_printf("ipftps_load_tls_cert: "
"failed to get ipftps.tls.cert_file sysvar\n");
return -1;
}
if ((bio = BIO_new_file(file, "r")) == IP_NULL)
{
ipcom_printf("ipftps: Can't read [%s]\n", file);
ret = -1;
goto END;
}
if ((dh = PEM_read_bio_DHparams(bio, IP_NULL, IP_NULL
#if OPENSSL_VERSION_NUMBER >= 0x00904000L
, IP_NULL
#endif
)) == IP_NULL)
{
ret = 1;
goto END;
}
if (SSL_CTX_set_tmp_dh(ipftps_tls_ctx, dh) != 1)
{
ipcom_printf("ipftps: Can't set ephemeral keys\n");
ret = -1;
}
END:
ipcom_free(file);
if (dh != IP_NULL)
{
DH_free(dh);
}
if (bio != IP_NULL)
{
BIO_free(bio);
}
if (ret != 0)
{
SSL_CTX_set_tmp_dh_callback(ipftps_tls_ctx, ipftps_cb_dh);
}
return 0;
}
/*
*===========================================================================
* ipftps_key_db_pkey_save
*===========================================================================
*
* Description:
* Save private key to Key DB.
*
* Parameters:
* ret The returned value will make sure if saving key to DB is successful.
* Returns:
* IPCOM_SUCCESS if success, IPCOM_ERR_FAILED otherwise.
*/
IP_STATIC int ipftps_key_db_pkey_save(int *ret)
{
BIO* bio = IP_NULL;
char* file = IP_NULL;
EVP_PKEY* pkey = IP_NULL;
char * pfile = IP_NULL;
file = ipcom_sysvar_get("ipftps.tls.key_file", IP_NULL, 0);
if(!file)
{
ipcom_printf("ipftps_load_tls_key : failed to get "
"ipftps.tls.key_file sysvar");
*ret = 1;
return IPCOM_ERR_FAILED;
}
pfile = file;
bio = BIO_new(BIO_s_file());
if(!bio)
goto cleanup;
if(!BIO_read_filename(bio, pfile))
goto cleanup;
pkey = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, IP_NULL);
if (pkey == IP_NULL
|| (ipcom_key_db_pkey_import("ftpsPrivateKey", pkey) == IPCOM_ERR_FAILED))
goto cleanup;
if(file)
{
ipcom_free(file);
}
if(bio)
(void)BIO_free(bio);
return IPCOM_SUCCESS;
cleanup:
if(file)
{
ipcom_free(file);
}
if(bio)
(void)BIO_free(bio);
*ret = 1;
return IPCOM_ERR_FAILED;
}
IP_STATIC int
ipftps_PEM_read_key_cb(char *buf, int num, int rwflag, void *key)
{
int i;
if (key)
{
i = ipcom_strlen(key);
i = (i > num) ? num : i;
ipcom_memcpy(buf, key, i);
*(buf+i) = 0x00;
return (i);
}
else
{
return 0;
}
}
/*
*===========================================================================
* ipftps_load_tls_key
*===========================================================================
*
* Description:
* Load private key from configuration.
*
* Parameters:
* option option description
* Returns:
* private key struct pointer if success, IP_NULL otherwise.
*/
IP_STATIC EVP_PKEY *ipftps_load_tls_key(int option)
{
BIO* bio = IP_NULL;
EVP_PKEY* ret = IP_NULL;
char* file;
char* key = IP_NULL;
char* pfile;
#ifdef IPFTPS_USE_PRIVACY
if((ipcom_sysvar_get_as_int("ipftps.tls.private.enable", 0)==1) && (ipcom_sysvar_get_as_int("ipftps.tls.enable", 0)==1))
{
if(option == 0)
{
if((ret = ipcom_key_db_pkey_get((const char *)"ftpsPrivateKey"))==IP_NULL)
{
ipcom_printf("ipftps_load_tls_key_example : failed to retrieve ");
}
return ret;
}
else
file = ipcom_sysvar_get("ipftps.tls.key_file", IP_NULL, 0);
}else
#endif
file = ipcom_sysvar_get("ipftps.tls.key_file", IP_NULL, 0);
if(!file)
{
ipcom_printf("ipftps_load_tls_key : failed to get "
"ipftps.tls.key_file sysvar");
return IP_NULL;
}
pfile = file;
bio = BIO_new(BIO_s_file());
if(!bio)
goto cleanup;
if(!BIO_read_filename(bio, pfile))
goto cleanup;
key = ipcom_sysvar_get("ipftps.tls.secret.key", IP_NULL, 0);
if(key)
ret = PEM_read_bio_PrivateKey(bio, IP_NULL, ipftps_PEM_read_key_cb, key);
else
ret = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, NULL);
cleanup:
if(file)
{
ipcom_free(file);
}
if(key)
{
ipcom_free(key);
}
if(bio)
(void)BIO_free(bio);
return ret;
}
/*
*===========================================================================
* ipftps_load_tls_cert
*===========================================================================
*
* Description:
* Load public key cert from configuration.
*
* Parameters: void
*
* Returns:
* Cert struct pointer if success, IP_NULL otherwise.
*/
IP_STATIC X509 *ipftps_load_tls_cert()
{
BIO* bio;
X509* ret = IP_NULL;
char* file;
char* pfile;
file = ipcom_sysvar_get("ipftps.tls.cert_file", IP_NULL, 0);
if(!file)
{
ipcom_printf("ipftps_load_tls_cert: "
"failed to get ipftps.tls.cert_file sysvar\n");
return IP_NULL;
}
pfile = file;
bio = BIO_new(BIO_s_file());
if(!bio)
goto cleanup;
if(!BIO_read_filename(bio, pfile) )
goto cleanup;
ret = PEM_read_bio_X509(bio, IP_NULL, IP_NULL, IP_NULL);
cleanup:
if(file)
{
ipcom_free(file);
}
if(bio)
(void)BIO_free(bio);
return ret;
}
/*
*===========================================================================
* ipftps_free_tls
*===========================================================================
*
* Description:
* Free TLS context for FTP server with TLS.
*
* Parameters: void
*
* Returns:
*/
IP_GLOBAL void ipftps_free_tls(void)
{
if (ipftps_tls_ctx != IP_NULL)
{
SSL_CTX_free(ipftps_tls_ctx);
ipftps_tls_ctx = IP_NULL;
}
return;
}
/*
*===========================================================================
* ipftps_free_tls_session
*===========================================================================
*
* Description:
* Free TLS session for FTP server.
*
* Parameters:
* session FTP server session structure.
* Returns:
*/
IP_GLOBAL void ipftps_free_tls_session(Ipftps_session *session)
{
if(session->tlsopt != IP_NULL)
{
ipcom_free(session->tlsopt);
session->tlsopt = IP_NULL;
}
return;
}
/*
*===========================================================================
* ipftps_init_tls_session
*===========================================================================
*
* Description:
* Alloc and initialize TLS session for FTP server.
*
* Parameters:
* session FTP server session structure.
* Returns:
*/
IP_GLOBAL int ipftps_init_tls_session(Ipftps_session *session)
{
ftp_tls * tls;
tls = (ftp_tls *)ipcom_malloc(sizeof(ftp_tls));
if(tls == IP_NULL)
{
return IPCOM_ERR_FAILED;
}
tls->ctrlflag = IP_FALSE;
tls->ctrlssl = IP_NULL;
tls->dataflag = IP_FALSE;
tls->datassl = IP_NULL;
tls->ccc = IP_FALSE;
session->tlsopt = (void *)tls;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipftps_init_tls
*===========================================================================
*
* Description:
* Initialize TLS context for FTP server.
*
* Parameters:
* Returns:
* IPCOM_SUCCESS if success, IPCOM_ERR_FAILED if fail.
*/
IP_GLOBAL int ipftps_init_tls(Ipftps_session *session)
{
EVP_PKEY *tls_key = IP_NULL;
X509 *tls_cert = IP_NULL;
char *strval;
int ret = 0;
int ssl_version;
if(ipftps_tls_ctx != IP_NULL)
{
/* already initialized TLS*/
return IPCOM_SUCCESS;
}
if ((strval = ipcom_sysvar_get("ipftps.tls.enable", IP_NULL, IP_NULL)) == IP_NULL)
{
/* There is no sysvar about ftp with tls, so need use common ftp */
ipftps_tls_enbale = IP_FALSE;
return IPCOM_SUCCESS;
}
ipftps_tls_enbale = ipcom_atoi(strval);
if(ipftps_tls_enbale == IP_FALSE)
{
ipcom_free(strval);
/* configuration disable ftp server with tls*/
return IPCOM_SUCCESS;
}
ipcom_free(strval);
#ifdef IPFTPS_USE_PRIVACY
if ((strval = ipcom_sysvar_get("ipftps.tls.private.enable", IP_NULL, IP_NULL)) != IP_NULL)
{
if(ipcom_atoi(strval) == IP_TRUE)
{
ipftps_key_db_pkey_save(&ret);
}
ipcom_free(strval);
}
#endif
#ifdef _WRS_CONFIG_COMPONENT_IPCRYPTO_OPENSSL_1_0_2
ssl_version = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3
| SSL_OP_NO_TLSv1 |SSL_OP_NO_TLSv1_1;
#else
ssl_version = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
#endif
ipftps_tls_ctx = SSL_CTX_new(SSLv23_server_method());
if(ipftps_tls_ctx == IP_NULL)
{
return IPCOM_ERR_FAILED;
}
SSL_CTX_set_options(ipftps_tls_ctx, SSL_OP_ALL | ssl_version);
tls_key = ipftps_load_tls_key(ret);
if(tls_key == IP_NULL)
{
goto error;
}
tls_cert = ipftps_load_tls_cert();
if(tls_cert == IP_NULL)
{
goto error;
}
if(X509_check_private_key(tls_cert, tls_key) != 1)
{
/*IPCOM_LOG0(ERR, "ipftps_init_tls: X509_check_private_key() failed");*/
goto error;
}
if(!SSL_CTX_use_PrivateKey(ipftps_tls_ctx, tls_key))
{
/*IPCOM_LOG0(ERR, "ipftps_init_tls: SSL_CTX_use_PrivateKey() failed");*/
goto error;
}
if(!SSL_CTX_use_certificate(ipftps_tls_ctx, tls_cert))
{
/*IPCOM_LOG0(ERR, "ipftps_init_tls: SSL_CTX_use_certificate() failed");*/
goto error;
}
SSL_CTX_set_tmp_rsa_callback(ipftps_tls_ctx, ipftps_cb_rsa);
if(ipftps_tls_init_diffie() == -1)
{
goto error;
}
/*ipftps_tls_init_cache();*/
if(tls_key)
EVP_PKEY_free(tls_key);
if(tls_cert)
X509_free(tls_cert);
return IPCOM_SUCCESS;
error:
SSL_CTX_free(ipftps_tls_ctx);
ipftps_tls_ctx = IP_NULL;
if(tls_key)
EVP_PKEY_free(tls_key);
if(tls_cert)
X509_free(tls_cert);
return IPCOM_ERR_FAILED;
}
/*
*===========================================================================
* ipftps_create_new_tls_csession
*===========================================================================
*
* Description:
* Create a new TLS control session for FTP server.
*
* Parameters:
* session FTP server session structure.
* Returns:
* IPCOM_SUCCESS if success, IPCOM_ERR_FAILED if fail.
*/
IP_GLOBAL int ipftps_create_new_tls_csession(Ipftps_session *session)
{
int ret1,ret2;
ftp_tls *tls;
SSL_CIPHER *cipher;
tls = (ftp_tls *)(session->tlsopt);
if(tls == IP_NULL)
{
return IPCOM_ERR_FAILED;
}
if(ipftps_tls_ctx == IP_NULL)
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_csession: ipftps_tls_ctx() is NULL");
return IPCOM_ERR_FAILED;
}
if((tls->ctrlssl = SSL_new(ipftps_tls_ctx)) == IP_NULL)
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_csession: SSL_new() Failed");
return IPCOM_ERR_FAILED;
}
if(SSL_set_fd(tls->ctrlssl, session->csock.fd) != 1)
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_csession: SSL_set_fd() Failed");
return IPCOM_ERR_FAILED;
}
SSL_set_accept_state(tls->ctrlssl);
for(;;)
{
ret1 = SSL_accept(tls->ctrlssl);
if(ret1 < 0)
{
ret2 = SSL_get_error(tls->ctrlssl,ret1);
if(ret2 == SSL_ERROR_NONE
|| ret2 == SSL_ERROR_ZERO_RETURN
|| ret2 == SSL_ERROR_WANT_READ
|| ret2 == SSL_ERROR_WANT_WRITE)
{
continue;
}
else
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_csession: SSL_accept() Failed");
ipftps_tls_shutdown(session, IPFTPS_CTRL_FLAG);
SSL_free(tls->ctrlssl);
tls->ctrlssl = IP_NULL;
goto error;
}
}
else
{
break;
}
}
if ((cipher = SSL_get_current_cipher(tls->ctrlssl)) != IP_NULL)
{
int alg_bits;
int bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
if (alg_bits < bits)
{
bits = alg_bits;
}
if (bits < 40)
{
goto error;
}
}
return IPCOM_SUCCESS;
error:
return IPCOM_ERR_FAILED;
}
/*
*===========================================================================
* ipftps_create_new_tls_dsession
*===========================================================================
*
* Description:
* Create a new TLS data session for FTP server.
*
* Parameters:
* session FTP server session structure.
* eno error number will be returned
* Returns:
* IPCOM_SUCCESS if success, IPCOM_ERR_FAILED if fail.
*/
IP_GLOBAL int ipftps_create_new_tls_dsession(Ipftps_session *session, int *eno)
{
int ret1,ret2;
ftp_tls *tls = (ftp_tls *)(session->tlsopt);
SSL_CIPHER *cipher;
if(tls == IP_NULL)
{
return IPCOM_ERR_FAILED;
}
if(tls->dataflag != IP_TRUE)
{
return IPCOM_SUCCESS;
}
if(ipftps_tls_ctx == IP_NULL)
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_dsession: ipftps_tls_ctx is NULL");
return IPCOM_ERR_FAILED;
}
if((tls->datassl = SSL_new(ipftps_tls_ctx)) == IP_NULL)
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_dsession: SSL_new() Failed");
return IPCOM_ERR_FAILED;
}
if(SSL_set_fd(tls->datassl, session->dsock.fd) != 1)
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_dsession: SSL_set_fd() Failed");
return IPCOM_ERR_FAILED;
}
SSL_set_accept_state(tls->datassl);
for(;;)
{
ret1 = SSL_accept(tls->datassl);
if(ret1 < 0)
{
ret2 = SSL_get_error(tls->datassl,ret1);
if(ret2 == SSL_ERROR_NONE
|| ret2 == SSL_ERROR_ZERO_RETURN
|| ret2 == SSL_ERROR_WANT_READ
|| ret2 == SSL_ERROR_WANT_WRITE)
{
continue;
}
else
{
IPCOM_LOG0(ERR, "ipftps_create_new_tls_dsession: SSL_accept() Failed");
ipftps_tls_shutdown(session,IPFTPS_DATA_FLAG);
SSL_free(tls->datassl);
tls->datassl = IP_NULL;
*eno = ret2;
goto error;
}
}
else
{
break;
}
}
if ((cipher = SSL_get_current_cipher(tls->datassl)) != IP_NULL)
{
int alg_bits;
int bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
if (alg_bits < bits)
{
bits = alg_bits;
}
if (bits < 40)
{
goto error;
}
}
return IPCOM_SUCCESS;
error:
return IPCOM_ERR_FAILED;
}
/*
*===========================================================================
* ipftps_tls_close_session
*===========================================================================
*
* Description:
* Close a new TLS session for FTP server.
*
* Parameters:
* session FTP server session structure.
* option IPFTPS_CTRL_FLAG for control session
* IPFTPS_DATA_FLAG for data session
* Returns:
*/
IP_GLOBAL void ipftps_tls_close_session(Ipftps_session *session, int option)
{
ftp_tls *tls = (ftp_tls *) (session->tlsopt);
if(tls == IP_NULL)
{
return;
}
switch(option)
{
case IPFTPS_CTRL_FLAG:
if(tls->ctrlssl != IP_NULL)
{
SSL_shutdown(tls->ctrlssl);
SSL_free(tls->ctrlssl);
tls->ctrlssl = IP_NULL;
}
break;
case IPFTPS_DATA_FLAG:
if(tls->datassl != IP_NULL)
{
SSL_shutdown(tls->datassl);
SSL_free(tls->datassl);
tls->datassl = IP_NULL;
}
break;
}
return;
}
/*
*===========================================================================
* ipftps_tls_send
*===========================================================================
*
* Description:
* Send a ftp packet by TLS.
*
* Parameters:
* session FTP server session structure.
* fd Socket fd
* buf Buffer will be sent
* buflen The length of buffer
* Returns:
* 1 if fail; 0 if success; 2 if don't need TLS
*/
IP_GLOBAL int ipftps_tls_send(Ipftps_session *session, Ip_fd fd,char *buf, int buflen)
{
ftp_tls *tls = (ftp_tls *)(session->tlsopt);
if(tls == IP_NULL)
{
return 2;
}
if(fd == session->dsock.fd)
{
if(tls->dataflag == IP_TRUE)
{
if(SSL_write(tls->datassl, buf, buflen) != buflen)
{
return 1;
}
return 0;
}
else
{
return 2;
}
}
if(fd == session->csock.fd)
{
if(tls->ctrlflag == IP_TRUE)
{
if(SSL_write(tls->ctrlssl, buf, buflen) != buflen)
{
return 1;
}
return 0;
}
else
{
return 2;
}
}
return 1;
}
/*
*===========================================================================
* ipftps_tls_read
*===========================================================================
*
* Description:
* Read a ftp packet by TLS.
*
* Parameters:
* session FTP server session structure.
* fd Socket fd
* buf Buffer will be for saving ftp packets
* buflen The length of buffer
* len Actual returned length
* Returns:
* 0 if success; 1 if don't need TLS
*/
IP_GLOBAL int ipftps_tls_read(Ipftps_session *session, Ip_fd fd,char *buf, int buflen, int *len)
{
ftp_tls *tls = (ftp_tls *)(session->tlsopt);
if(tls == IP_NULL)
{
return 1;
}
if(fd == session->dsock.fd)
{
if(tls->dataflag == IP_TRUE)
{
*len = SSL_read(tls->datassl, buf, buflen);
return 0;
}
else
{
return 1;
}
}
if(fd == session->csock.fd)
{
if(tls->ctrlflag == IP_TRUE)
{
*len = SSL_read(tls->ctrlssl, buf, buflen);
return 0;
}
else
{
return 1;
}
}
return 1;
}
/*
*===========================================================================
* ipftps_tls_set_flag
*===========================================================================
*
* Description:
* Set TLS flag for FTP server.
*
* Parameters:
* session FTP server session structure.
* option IPFTPS_CTRL_FLAG for TLS control session
* IPFTPS_DATA_FLAG for TLS data session
* flag IP_TRUE or IP_FALSE
* Returns:
*
*/
IP_GLOBAL void ipftps_tls_set_flag(Ipftps_session *session, int option,Ip_bool flag)
{
ftp_tls *tls = (ftp_tls *)(session->tlsopt);
if(tls == IP_NULL)
{
return;
}
if(option == IPFTPS_CTRL_FLAG)
{
tls->ctrlflag = flag;
}
if(option == IPFTPS_DATA_FLAG)
{
tls->dataflag = flag;
}
return;
}
/*
*===========================================================================
* ipftps_tls_shutdown
*===========================================================================
*
* Description:
* shut down a TLS session for FTP server.
*
* Parameters:
* session FTP server session structure.
* option IPFTPS_CTRL_FLAG for TLS control session
* IPFTPS_DATA_FLAG for TLS data session
* Returns:
*
*/
IP_GLOBAL void ipftps_tls_shutdown(Ipftps_session *session,int option)
{
ftp_tls *tls = (ftp_tls *)(session->tlsopt);
if(tls == IP_NULL)
{
return;
}
switch(option)
{
case IPFTPS_CTRL_FLAG:
if(tls->ctrlssl != IP_NULL)
{
if(SSL_shutdown(tls->ctrlssl) == 0)
{
SSL_shutdown(tls->ctrlssl);
}
tls->ctrlflag = IP_FALSE;
}
break;
case IPFTPS_DATA_FLAG:
if(tls->datassl != IP_NULL)
{
if(SSL_shutdown(tls->datassl) == 0)
{
SSL_shutdown(tls->datassl);
}
tls->dataflag = IP_FALSE;
}
break;
default:
break;
}
return;
}
IP_GLOBAL void ipftps_tls_set_ccc(Ipftps_session *session, Ip_bool flag)
{
ftp_tls *tls = (ftp_tls *)(session->tlsopt);
if(tls == IP_NULL)
{
return;
}
tls->ccc = flag;
return;
}
IP_GLOBAL Ip_bool ipftps_tls_get_ccc(Ipftps_session *session)
{
ftp_tls *tls = (ftp_tls *)(session->tlsopt);
if(tls == IP_NULL)
{
return IP_FALSE;
}
return (tls->ccc);
}
#endif