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

📄 be-secure.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
 *	what we expect it to contain. */static DH  *load_dh_file(int keylength){	FILE	   *fp;	char		fnbuf[2048];	DH		   *dh = NULL;	int			codes;	/* attempt to open file.  It's not an error if it doesn't exist. */	snprintf(fnbuf, sizeof fnbuf, "%s/dh%d.pem", DataDir, keylength);	if ((fp = fopen(fnbuf, "r")) == NULL)		return NULL;/*	flock(fileno(fp), LOCK_SH); */	dh = PEM_read_DHparams(fp, NULL, NULL, NULL);/*	flock(fileno(fp), LOCK_UN); */	fclose(fp);	/* is the prime the correct size? */	if (dh != NULL && 8 * DH_size(dh) < keylength)	{		elog(LOG, "DH errors (%s): %d bits expected, %d bits found",			 fnbuf, keylength, 8 * DH_size(dh));		dh = NULL;	}	/* make sure the DH parameters are usable */	if (dh != NULL)	{		if (DH_check(dh, &codes))		{			elog(LOG, "DH_check error (%s): %s", fnbuf, SSLerrmessage());			return NULL;		}		if (codes & DH_CHECK_P_NOT_PRIME)		{			elog(LOG, "DH error (%s): p is not prime", fnbuf);			return NULL;		}		if ((codes & DH_NOT_SUITABLE_GENERATOR) &&			(codes & DH_CHECK_P_NOT_SAFE_PRIME))		{			elog(LOG,			   "DH error (%s): neither suitable generator or safe prime",				 fnbuf);			return NULL;		}	}	return dh;}/* *	Load hardcoded DH parameters. * *	To prevent problems if the DH parameters files don't even *	exist, we can load DH parameters hardcoded into this file. */static DH  *load_dh_buffer(const char *buffer, size_t len){	BIO		   *bio;	DH		   *dh = NULL;	bio = BIO_new_mem_buf((char *) buffer, len);	if (bio == NULL)		return NULL;	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);	if (dh == NULL)		ereport(DEBUG2,				(errmsg_internal("DH load buffer: %s",								 SSLerrmessage())));	BIO_free(bio);	return dh;}/* *	Generate an empheral DH key.  Because this can take a long *	time to compute, we can use precomputed parameters of the *	common key sizes. * *	Since few sites will bother to precompute these parameter *	files, we also provide a fallback to the parameters provided *	by the OpenSSL project. * *	These values can be static (once loaded or computed) since *	the OpenSSL library can efficiently generate random keys from *	the information provided. */static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength){	DH		   *r = NULL;	static DH  *dh = NULL;	static DH  *dh512 = NULL;	static DH  *dh1024 = NULL;	static DH  *dh2048 = NULL;	static DH  *dh4096 = NULL;	switch (keylength)	{		case 512:			if (dh512 == NULL)				dh512 = load_dh_file(keylength);			if (dh512 == NULL)				dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);			r = dh512;			break;		case 1024:			if (dh1024 == NULL)				dh1024 = load_dh_file(keylength);			if (dh1024 == NULL)				dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);			r = dh1024;			break;		case 2048:			if (dh2048 == NULL)				dh2048 = load_dh_file(keylength);			if (dh2048 == NULL)				dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);			r = dh2048;			break;		case 4096:			if (dh4096 == NULL)				dh4096 = load_dh_file(keylength);			if (dh4096 == NULL)				dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);			r = dh4096;			break;		default:			if (dh == NULL)				dh = load_dh_file(keylength);			r = dh;	}	/* this may take a long time, but it may be necessary... */	if (r == NULL || 8 * DH_size(r) < keylength)	{		ereport(DEBUG2,				(errmsg_internal("DH: generating parameters (%d bits)....",								 keylength)));		r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);	}	return r;}/* *	Certificate verification callback * *	This callback allows us to log intermediate problems during *	verification, but for now we'll see if the final error message *	contains enough information. * *	This callback also allows us to override the default acceptance *	criteria (e.g., accepting self-signed or expired certs), but *	for now we accept the default checks. */static intverify_cb(int ok, X509_STORE_CTX *ctx){	return ok;}/* *	This callback is used to copy SSL information messages *	into the PostgreSQL log. */static voidinfo_cb(const SSL *ssl, int type, int args){	switch (type)	{		case SSL_CB_HANDSHAKE_START:			ereport(DEBUG4,					(errmsg_internal("SSL: handshake start")));			break;		case SSL_CB_HANDSHAKE_DONE:			ereport(DEBUG4,					(errmsg_internal("SSL: handshake done")));			break;		case SSL_CB_ACCEPT_LOOP:			ereport(DEBUG4,					(errmsg_internal("SSL: accept loop")));			break;		case SSL_CB_ACCEPT_EXIT:			ereport(DEBUG4,					(errmsg_internal("SSL: accept exit (%d)", args)));			break;		case SSL_CB_CONNECT_LOOP:			ereport(DEBUG4,					(errmsg_internal("SSL: connect loop")));			break;		case SSL_CB_CONNECT_EXIT:			ereport(DEBUG4,					(errmsg_internal("SSL: connect exit (%d)", args)));			break;		case SSL_CB_READ_ALERT:			ereport(DEBUG4,					(errmsg_internal("SSL: read alert (0x%04x)", args)));			break;		case SSL_CB_WRITE_ALERT:			ereport(DEBUG4,					(errmsg_internal("SSL: write alert (0x%04x)", args)));			break;	}}/* *	Initialize global SSL context. */static intinitialize_SSL(void){	char		fnbuf[MAXPGPATH];	struct stat buf;	if (!SSL_context)	{		SSL_library_init();		SSL_load_error_strings();		SSL_context = SSL_CTX_new(SSLv23_method());		if (!SSL_context)			ereport(FATAL,					(errmsg("could not create SSL context: %s",							SSLerrmessage())));		/*		 * Load and verify certificate and private key		 */		snprintf(fnbuf, sizeof(fnbuf), "%s/server.crt", DataDir);		if (!SSL_CTX_use_certificate_file(SSL_context, fnbuf, SSL_FILETYPE_PEM))			ereport(FATAL,					(errcode(ERRCODE_CONFIG_FILE_ERROR),			  errmsg("could not load server certificate file \"%s\": %s",					 fnbuf, SSLerrmessage())));		snprintf(fnbuf, sizeof(fnbuf), "%s/server.key", DataDir);		if (stat(fnbuf, &buf) == -1)			ereport(FATAL,					(errcode_for_file_access(),				   errmsg("could not access private key file \"%s\": %m",						  fnbuf)));		if (!S_ISREG(buf.st_mode) || (buf.st_mode & (S_IRWXG | S_IRWXO)) ||			buf.st_uid != getuid())			ereport(FATAL,					(errcode(ERRCODE_CONFIG_FILE_ERROR),				  errmsg("unsafe permissions on private key file \"%s\"",						 fnbuf),					 errdetail("File must be owned by the database user and must have no permissions for \"group\" or \"other\".")));		if (!SSL_CTX_use_PrivateKey_file(SSL_context, fnbuf, SSL_FILETYPE_PEM))			ereport(FATAL,					(errmsg("could not load private key file \"%s\": %s",							fnbuf, SSLerrmessage())));		if (!SSL_CTX_check_private_key(SSL_context))			ereport(FATAL,					(errmsg("check of private key failed: %s",							SSLerrmessage())));	}	/* set up empheral DH keys */	SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);	SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);	/* setup the allowed cipher list */	if (SSL_CTX_set_cipher_list(SSL_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1)		elog(FATAL, "could not set the cipher list (no valid ciphers available)");	/* accept client certificates, but don't require them. */	snprintf(fnbuf, sizeof(fnbuf), "%s/root.crt", DataDir);	if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, CA_PATH))	{		/* Not fatal - we do not require client certificates */		ereport(LOG,				(errmsg("could not load root certificate file \"%s\": %s",						fnbuf, SSLerrmessage()),				 errdetail("Will not verify client certificates.")));		return 0;	}	SSL_CTX_set_verify(SSL_context,					   SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,					   verify_cb);	return 0;}/* *	Destroy global SSL context. */static voiddestroy_SSL(void){	if (SSL_context)	{		SSL_CTX_free(SSL_context);		SSL_context = NULL;	}}/* *	Attempt to negotiate SSL connection. */static intopen_server_SSL(Port *port){	Assert(!port->ssl);	Assert(!port->peer);	if (!(port->ssl = SSL_new(SSL_context)) ||		!SSL_set_fd(port->ssl, port->sock) ||		SSL_accept(port->ssl) <= 0)	{		ereport(COMMERROR,				(errcode(ERRCODE_PROTOCOL_VIOLATION),				 errmsg("could not initialize SSL connection: %s",						SSLerrmessage())));		close_SSL(port);		return -1;	}	port->count = 0;	/* get client certificate, if available. */	port->peer = SSL_get_peer_certificate(port->ssl);	if (port->peer == NULL)	{		strncpy(port->peer_dn, "(anonymous)", sizeof(port->peer_dn));		strncpy(port->peer_cn, "(anonymous)", sizeof(port->peer_cn));	}	else	{		X509_NAME_oneline(X509_get_subject_name(port->peer),						  port->peer_dn, sizeof(port->peer_dn));		port->peer_dn[sizeof(port->peer_dn) - 1] = '\0';		X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),				   NID_commonName, port->peer_cn, sizeof(port->peer_cn));		port->peer_cn[sizeof(port->peer_cn) - 1] = '\0';	}	ereport(DEBUG2,			(errmsg("SSL connection from \"%s\"", port->peer_cn)));	/* set up debugging/info callback */	SSL_CTX_set_info_callback(SSL_context, info_cb);	return 0;}/* *	Close SSL connection. */static voidclose_SSL(Port *port){	if (port->ssl)	{		SSL_shutdown(port->ssl);		SSL_free(port->ssl);		port->ssl = NULL;	}	if (port->peer)	{		X509_free(port->peer);		port->peer = NULL;	}}/* * Obtain reason string for last SSL error * * Some caution is needed here since ERR_reason_error_string will * return NULL if it doesn't recognize the error code.  We don't * want to return NULL ever. */static const char *SSLerrmessage(void){	unsigned long errcode;	const char *errreason;	static char errbuf[32];	errcode = ERR_get_error();	if (errcode == 0)		return "No SSL error reported";	errreason = ERR_reason_error_string(errcode);	if (errreason != NULL)		return errreason;	snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode);	return errbuf;}#endif   /* USE_SSL */

⌨️ 快捷键说明

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