/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipftps_config.h" #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #ifdef IPFTP_TLS #include "ipftps.h" #include #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