⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 ssl_test使用openssl开发的ssl协议客户端服务器通信
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <winsock.h>
#include <windows.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define CERTF  "cert.cer"		//服务端证书
#define KEYF   "key.pem"		//服务器端私钥
#define ROOTCERTF "root.cer"	//根证书
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }

int main()
{
	int err;
	int listen_sd;//监听句柄
	int sd;
	struct sockaddr_in sa_serv;//sockaddr_in结构体,用于保存服务器端协议和端口信息
	struct sockaddr_in sa_cli;
	size_t client_len;
	SSL_CTX* ctx;	//SSL上下文句柄
	SSL*     ssl;	//SSL结构体指针
	X509*    client_cert;//X509结构体,用户保存客户端证书
	char*    str;
	char     buf [4096];
	SSL_METHOD *meth;	//SSL协议
	WSADATA     	wsaData;

	//初始化windows Socket环境。
	if (WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		exit(1);
	}
	//初始化OpenSSL环境
	SSL_load_error_strings();
	SSLeay_add_ssl_algorithms();
	//SSL协议版本,V2、V3自适应
	meth = SSLv23_server_method();
	//新建SSL上下文句柄
	ctx = SSL_CTX_new (meth);
	if (!ctx) {
		ERR_print_errors_fp(stderr);
		exit(2);
	}
	//设置服务器证书
	if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
		ERR_print_errors_fp(stderr);
		exit(3);
	}
	//设置服务器私钥
	if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
		ERR_print_errors_fp(stderr);
		exit(4);
	}
	//检查私钥和证书是否匹配
	if (!SSL_CTX_check_private_key(ctx)) {
		fprintf(stderr,"Private key does not match the certificate public key\n");
		exit(5);
	}
	//新建Socket
	listen_sd = socket (AF_INET, SOCK_STREAM, 0);  
	CHK_ERR(listen_sd, "socket");
	//初始化sa_serv,设置为TCP协议,端口为8443
	memset (&sa_serv, '\0', sizeof(sa_serv));
	sa_serv.sin_family      = AF_INET;
	sa_serv.sin_addr.s_addr = INADDR_ANY;
	sa_serv.sin_port        = htons (8443);
	//绑定端口
	err = bind(listen_sd, (struct sockaddr*) &sa_serv,
		sizeof (sa_serv));  
	CHK_ERR(err, "bind");

	//开始接收TCP链接。
	err = listen (listen_sd, 5);
	CHK_ERR(err, "listen");
	client_len = sizeof(sa_cli);
	//接受客户端TCP链接
	sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
	CHK_ERR(sd, "accept");
	closesocket (listen_sd);
	//打印客户端信息
	printf ("Connection from %lx, port %x\n",
		sa_cli.sin_addr.s_addr, sa_cli.sin_port);
	//新建SSL
	ssl = SSL_new (ctx); 
	CHK_NULL(ssl);
	//设置链接句柄到SSL结构体
	SSL_set_fd (ssl, sd);
	//接受SSL链接
	err = SSL_accept (ssl);
	CHK_SSL(err);
	//获得SSL链接用到的算法
	printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
	//获得客户端证书
	client_cert = SSL_get_peer_certificate (ssl);
	if (client_cert != NULL) {
		printf ("Client certificate:\n");
		
		str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
		CHK_NULL(str);
		printf ("\t subject: %s\n", str);
		OPENSSL_free (str);
		
		str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0);
		CHK_NULL(str);
		printf ("\t issuer: %s\n", str);
		OPENSSL_free (str);
		X509_free (client_cert);
	} else
		printf ("Client does not have certificate.\n");
	//读取客户端发送的消息
	err = SSL_read (ssl, buf, sizeof(buf) - 1);
	CHK_SSL(err);
	buf[err] = '\0';
	printf ("Got %d chars:'%s'\n", err, buf);
	//发送消息到客户端
	err = SSL_write (ssl, "I hear you.", strlen("I hear you."));  CHK_SSL(err);
	
	//清除内存
	closesocket (sd);
	SSL_free (ssl);
	SSL_CTX_free (ctx);
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -