<commit_before>/*
    This file is part of libcapwap.

    libcapwap is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    libcapwap is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

*/
#include <errno.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>

#include "capwap.h"

#include "dtls_openssl.h"
#include "capwap.h"

#include "dbg.h"
#include "log.h"

#include "cw_util.h"
#include "rand.h"

#include "conn.h"
#include "sock.h"


#ifdef WITH_CW_LOG_DEBUG
static const char * ssl_version2str(int version)
{
	switch(version){
		case SSL2_VERSION:
			return "SSLv2";
		case SSL3_VERSION:
			return "SSLv3";
		case TLS1_VERSION:
			return "TLSv1";
		case DTLS1_VERSION:
			return "DTLSv1";
/*		case DTLS1_2_VERSION:
			return "DTLSv1.2"; */
	}
	return "Version unknown";
}

static void dtls_debug_cb(int write_p,int version,int type, const void * buf,size_t len, SSL * ssl, void * arg)
{
	char buffer[200];
	char * s = buffer;

	if (write_p)
		s += sprintf(s,"SSL msg out: ");
	else
		s += sprintf(s,"SSL msg in: ");

	s+=sprintf(s,"type = %d (0x%02X), %s (%08x), len = %d",type,type,ssl_version2str(version),version,(int)len);
/*	cw_dbg(DBG_DTLS_DETAIL,buffer); */
}
#endif


static void dtls_info_cb (const SSL *ssl, int where, int ret)
{
	const char *str = NULL;

	str = where & SSL_ST_CONNECT ? "connect" : where & SSL_ST_ACCEPT ? "accept" : "undefined";
	if (where & SSL_CB_LOOP)
	{
		cw_dbg (DBG_DTLS_DETAIL,"SSL state [\"%s\"]: %s", str, SSL_state_string_long (ssl));
	}
	else if (where & SSL_CB_ALERT)
	{
		cw_dbg (DBG_DTLS_DETAIL,"SSL: alert [\"%s\"]: %s : %s", where & SSL_CB_READ ? "read" : "write", \
			SSL_alert_type_string_long (ret), SSL_alert_desc_string_long (ret));
	}
}

int pem_passwd_cb(char *buf, int size, int rwflag, void *password)
{
	if (!password){
		cw_dbg(DBG_DTLS, "DTLS - No password given to decrypt privat key");
		return 0;
	}

	strncpy(buf, (char *)(password), size);
	buf[size - 1] = '\0';
	return(strlen(buf));
}

 /* Set up ephemeral RSA stuff */
 RSA *rsa_512 = NULL;
 RSA *rsa_1024 = NULL;



 RSA *tmp_rsa_callback(SSL *s, int is_export, int keylength)
 {
    RSA *rsa_tmp=NULL;

    switch (keylength) {
    case 512:
      if (rsa_512)
        rsa_tmp = rsa_512;
      else { /* generate on the fly, should not happen in this example */
    /*    rsa_tmp = RSA_generate_key(keylength,RSA_F4,NULL,NULL);*/
        rsa_512 = rsa_tmp; /* Remember for later reuse */
      }
      break;
    case 1024:
      if (rsa_1024)
        rsa_tmp=rsa_1024;
      else
        exit(0); /* should_not_happen_in_this_example(); */
      break;
    default:
      /* Generating a key on the fly is very costly, so use what is there */
      if (rsa_1024)
        rsa_tmp=rsa_1024;
      else
        rsa_tmp=rsa_512; /* Use at least a shorter key */
    }
    return(rsa_tmp);
 }





int dtls_openssl_init()
{
	int rc;
	const char * version = SSLeay_version(SSLEAY_VERSION);
	cw_dbg(DBG_INFO,"Init SSL library - %s",version);
	rc = SSL_library_init();
	ERR_clear_error();
	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();
	return rc;
}


int dtls_openssl_log_error_queue(const char *txt)
{
	char errstr[256];
	
	int e = ERR_get_error();
	if (e==0)
		return 0;

	while (e!=0){
		ERR_error_string(e,errstr);
		cw_log(LOG_ERR,"%s - %s",txt,errstr);
		e = ERR_get_error();
	}
	return 1;
}

int dtls_openssl_log_error(SSL * ssl, int rc, const char *txt)
{
	char errstr[256];
	int e;
	int en = errno; /* save errno */

	if (!ssl){
		return dtls_openssl_log_error_queue(txt);
	}


	e = SSL_get_error(ssl,rc);


	ERR_error_string(e,errstr);
	cw_log(LOG_ERR,"%s - %s","SSSSS",errstr);

	switch (e){
		case SSL_ERROR_ZERO_RETURN:
			break;
		case SSL_ERROR_SYSCALL:
			if (!dtls_openssl_log_error_queue(txt)){
				/* error queu was empty */
				if (rc<0){
					cw_log(LOG_ERR,"%s - %s",txt,strerror(en));
					return 1;
				}
				
				cw_log(LOG_ERR,"%s - EOF observed",txt);
				return 1;
			}
			

	}	<commit_msg>prints txt-parameter in error log message<commit_after>/*
    This file is part of libcapwap.

    libcapwap is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    libcapwap is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

*/
#include <errno.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>

#include "capwap.h"

#include "dtls_openssl.h"
#include "capwap.h"

#include "dbg.h"
#include "log.h"

#include "cw_util.h"
#include "rand.h"

#include "conn.h"
#include "sock.h"


#ifdef WITH_CW_LOG_DEBUG
static const char * ssl_version2str(int version)
{
	switch(version){
		case SSL2_VERSION:
			return "SSLv2";
		case SSL3_VERSION:
			return "SSLv3";
		case TLS1_VERSION:
			return "TLSv1";
		case DTLS1_VERSION:
			return "DTLSv1";
/*		case DTLS1_2_VERSION:
			return "DTLSv1.2"; */
	}
	return "Version unknown";
}

static void dtls_debug_cb(int write_p,int version,int type, const void * buf,size_t len, SSL * ssl, void * arg)
{
	char buffer[200];
	char * s = buffer;

	if (write_p)
		s += sprintf(s,"SSL msg out: ");
	else
		s += sprintf(s,"SSL msg in: ");

	s+=sprintf(s,"type = %d (0x%02X), %s (%08x), len = %d",type,type,ssl_version2str(version),version,(int)len);
/*	cw_dbg(DBG_DTLS_DETAIL,buffer); */
}
#endif


static void dtls_info_cb (const SSL *ssl, int where, int ret)
{
	const char *str = NULL;

	str = where & SSL_ST_CONNECT ? "connect" : where & SSL_ST_ACCEPT ? "accept" : "undefined";
	if (where & SSL_CB_LOOP)
	{
		cw_dbg (DBG_DTLS_DETAIL,"SSL state [\"%s\"]: %s", str, SSL_state_string_long (ssl));
	}
	else if (where & SSL_CB_ALERT)
	{
		cw_dbg (DBG_DTLS_DETAIL,"SSL: alert [\"%s\"]: %s : %s", where & SSL_CB_READ ? "read" : "write", \
			SSL_alert_type_string_long (ret), SSL_alert_desc_string_long (ret));
	}
}

int pem_passwd_cb(char *buf, int size, int rwflag, void *password)
{
	if (!password){
		cw_dbg(DBG_DTLS, "DTLS - No password given to decrypt privat key");
		return 0;
	}

	strncpy(buf, (char *)(password), size);
	buf[size - 1] = '\0';
	return(strlen(buf));
}

 /* Set up ephemeral RSA stuff */
 RSA *rsa_512 = NULL;
 RSA *rsa_1024 = NULL;



 RSA *tmp_rsa_callback(SSL *s, int is_export, int keylength)
 {
    RSA *rsa_tmp=NULL;

    switch (keylength) {
    case 512:
      if (rsa_512)
        rsa_tmp = rsa_512;
      else { /* generate on the fly, should not happen in this example */
    /*    rsa_tmp = RSA_generate_key(keylength,RSA_F4,NULL,NULL);*/
        rsa_512 = rsa_tmp; /* Remember for later reuse */
      }
      break;
    case 1024:
      if (rsa_1024)
        rsa_tmp=rsa_1024;
      else
        exit(0); /* should_not_happen_in_this_example(); */
      break;
    default:
      /* Generating a key on the fly is very costly, so use what is there */
      if (rsa_1024)
        rsa_tmp=rsa_1024;
      else
        rsa_tmp=rsa_512; /* Use at least a shorter key */
    }
    return(rsa_tmp);
 }





int dtls_openssl_init()
{
	int rc;
	const char * version = SSLeay_version(SSLEAY_VERSION);
	cw_dbg(DBG_INFO,"Init SSL library - %s",version);
	rc = SSL_library_init();
	ERR_clear_error();
	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();
	return rc;
}


int dtls_openssl_log_error_queue(const char *txt)
{
	char errstr[256];
	
	int e = ERR_get_error();
	if (e==0)
		return 0;

	while (e!=0){
		ERR_error_string(e,errstr);
		cw_log(LOG_ERR,"%s - %s",txt,errstr);
		e = ERR_get_error();
	}
	return 1;
}

int dtls_openssl_log_error(SSL * ssl, int rc, const char *txt)
{
	char errstr[256];
	int e;
	int en = errno; /* save errno */

	if (!ssl){
		return dtls_openssl_log_error_queue(txt);
	}


	e = SSL_get_error(ssl,rc);


	ERR_error_string(e,errstr);
	cw_log(LOG_ERR,"%s - %s",txt,errstr);

	switch (e){
		case SSL_ERROR_ZERO_RETURN:
			break;
		case SSL_ERROR_SYSCALL:
			if (!dtls_openssl_log_error_queue(txt)){
				/* error queu was empty */
				if (rc<0){
					cw_log(LOG_ERR,"%s - %s",txt,strerror(en));
					return 1;
				}
				
				cw_log(LOG_ERR,"%s - EOF observed",txt);
				return 1;
			}
			

	}	
{'fraction_non_alphanumeric': 0.13175450300200134, 'fraction_numerical': 0.018456748943740272, 'mean_word_length': 3.4551758296186232, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4854113', 'n_tokens_mistral': 3768, 'n_tokens_neox': 3443, 'n_words': 915}