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

📄 fe-secure.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
							  libpq_gettext(											"server common name \"%s\" does not resolve to %ld.%ld.%ld.%ld\n"),					 conn->peer_cn, (l >> 24) % 0x100, (l >> 16) % 0x100,							  (l >> 8) % 0x100, l % 0x100);			break;		default:			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext(											"server common name \"%s\" does not resolve to peer address\n"),							  conn->peer_cn);	}	return -1;}#endif/* *	Load precomputed DH parameters. * *	To prevent "downgrade" attacks, we perform a number of checks *	to verify that the DBA-generated DH parameters file contains *	what we expect it to contain. */static DH  *load_dh_file(int keylength){#ifdef WIN32    return NULL;#else	char		pwdbuf[BUFSIZ];	struct passwd pwdstr;	struct passwd *pwd = NULL;	FILE	   *fp;	char		fnbuf[2048];	DH		   *dh = NULL;	int			codes;	if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)		return NULL;	/* attempt to open file.  It's not an error if it doesn't exist. */	snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",			 pwd->pw_dir, 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)		dh = NULL;	/* make sure the DH parameters are usable */	if (dh != NULL)	{		if (DH_check(dh, &codes))			return NULL;		if (codes & DH_CHECK_P_NOT_PRIME)			return NULL;		if ((codes & DH_NOT_SUITABLE_GENERATOR) &&			(codes & DH_CHECK_P_NOT_SAFE_PRIME))			return NULL;	}	return dh;#endif}/* *	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);	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)		r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);	return r;}/* *	Callback used by SSL to load client cert and key. *	This callback is only called when the server wants a *	client cert. * *	Returns 1 on success, 0 on no data, -1 on error. */static intclient_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey){#ifdef WIN32   return 0;#else	char		pwdbuf[BUFSIZ];	struct passwd pwdstr;	struct passwd *pwd = NULL;	struct stat buf,				buf2;	char		fnbuf[2048];	FILE	   *fp;	PGconn	   *conn = (PGconn *) SSL_get_app_data(ssl);	int			(*cb) () = NULL;	/* how to read user password */	char		sebuf[256];	if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)	{		printfPQExpBuffer(&conn->errorMessage,					  libpq_gettext("could not get user information\n"));		return -1;	}	/* read the user certificate */	snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/postgresql.crt",			 pwd->pw_dir);	if (stat(fnbuf, &buf) == -1)		return 0;	if ((fp = fopen(fnbuf, "r")) == NULL)	{		printfPQExpBuffer(&conn->errorMessage,				  libpq_gettext("could not open certificate (%s): %s\n"),						  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));		return -1;	}	if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)	{		printfPQExpBuffer(&conn->errorMessage,				  libpq_gettext("could not read certificate (%s): %s\n"),						  fnbuf, SSLerrmessage());		fclose(fp);		return -1;	}	fclose(fp);	/* read the user key */	snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/postgresql.key",			 pwd->pw_dir);	if (stat(fnbuf, &buf) == -1)	{		printfPQExpBuffer(&conn->errorMessage,		libpq_gettext("certificate present, but not private key (%s)\n"),						  fnbuf);		X509_free(*x509);		return 0;	}	if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||		buf.st_uid != getuid())	{		printfPQExpBuffer(&conn->errorMessage,		libpq_gettext("private key (%s) has wrong permissions\n"), fnbuf);		X509_free(*x509);		return -1;	}	if ((fp = fopen(fnbuf, "r")) == NULL)	{		printfPQExpBuffer(&conn->errorMessage,			 libpq_gettext("could not open private key file (%s): %s\n"),						  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));		X509_free(*x509);		return -1;	}	if (fstat(fileno(fp), &buf2) == -1 ||		buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("private key (%s) changed during execution\n"), fnbuf);		X509_free(*x509);		return -1;	}	if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)	{		printfPQExpBuffer(&conn->errorMessage,				  libpq_gettext("could not read private key (%s): %s\n"),						  fnbuf, SSLerrmessage());		X509_free(*x509);		fclose(fp);		return -1;	}	fclose(fp);	/* verify that the cert and key go together */	if (!X509_check_private_key(*x509, *pkey))	{		printfPQExpBuffer(&conn->errorMessage,			libpq_gettext("certificate/private key mismatch (%s): %s\n"),						  fnbuf, SSLerrmessage());		X509_free(*x509);		EVP_PKEY_free(*pkey);		return -1;	}	return 1;#endif}/* *	Initialize global SSL context. */static intinitialize_SSL(PGconn *conn){#ifndef WIN32	struct stat buf;	char		pwdbuf[BUFSIZ];	struct passwd pwdstr;	struct passwd *pwd = NULL;	char		fnbuf[2048];#endif	if (!SSL_context)	{		SSL_library_init();		SSL_load_error_strings();		SSL_context = SSL_CTX_new(TLSv1_method());		if (!SSL_context)		{			printfPQExpBuffer(&conn->errorMessage,					 libpq_gettext("could not create SSL context: %s\n"),							  SSLerrmessage());			return -1;		}	}#ifndef WIN32	if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)	{		snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",				 pwd->pw_dir);		if (stat(fnbuf, &buf) == -1)		{			return 0;#ifdef NOT_USED			char		sebuf[256];			/* CLIENT CERTIFICATES NOT REQUIRED  bjm 2002-09-26 */			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("could not read root certificate list (%s): %s\n"),						 fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));			return -1;#endif		}		if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, 0))		{			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("could not read root certificate list (%s): %s\n"),							  fnbuf, SSLerrmessage());			return -1;		}	}	SSL_CTX_set_verify(SSL_context,		   SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);	SSL_CTX_set_verify_depth(SSL_context, 1);	/* 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);	/* set up mechanism to provide client certificate, if available */	SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);#endif	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 PostgresPollingStatusTypeopen_client_SSL(PGconn *conn){	int			r;	r = SSL_connect(conn->ssl);	if (r <= 0)	{		switch (SSL_get_error(conn->ssl, r))		{			case SSL_ERROR_WANT_READ:				return PGRES_POLLING_READING;			case SSL_ERROR_WANT_WRITE:				return PGRES_POLLING_WRITING;			case SSL_ERROR_SYSCALL:				{					char		sebuf[256];					if (r == -1)						printfPQExpBuffer(&conn->errorMessage,								libpq_gettext("SSL SYSCALL error: %s\n"),						SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));					else						printfPQExpBuffer(&conn->errorMessage,										  libpq_gettext("SSL SYSCALL error: EOF detected\n"));					close_SSL(conn);					return PGRES_POLLING_FAILED;				}			case SSL_ERROR_SSL:				printfPQExpBuffer(&conn->errorMessage,					  libpq_gettext("SSL error: %s\n"), SSLerrmessage());				close_SSL(conn);				return PGRES_POLLING_FAILED;			default:				printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("unrecognized SSL error code\n"));				close_SSL(conn);				return PGRES_POLLING_FAILED;		}	}	/* check the certificate chain of the server */#ifdef NOT_USED	/* CLIENT CERTIFICATES NOT REQUIRED  bjm 2002-09-26 */	/*	 * this eliminates simple man-in-the-middle attacks and simple	 * impersonations	 */	r = SSL_get_verify_result(conn->ssl);	if (r != X509_V_OK)	{		printfPQExpBuffer(&conn->errorMessage,			   libpq_gettext("certificate could not be validated: %s\n"),						  X509_verify_cert_error_string(r));		close_SSL(conn);		return PGRES_POLLING_FAILED;	}#endif	/* pull out server distinguished and common names */	conn->peer = SSL_get_peer_certificate(conn->ssl);	if (conn->peer == NULL)	{		printfPQExpBuffer(&conn->errorMessage,				libpq_gettext("certificate could not be obtained: %s\n"),						  SSLerrmessage());		close_SSL(conn);		return PGRES_POLLING_FAILED;	}	X509_NAME_oneline(X509_get_subject_name(conn->peer),					  conn->peer_dn, sizeof(conn->peer_dn));	conn->peer_dn[sizeof(conn->peer_dn) - 1] = '\0';	X509_NAME_get_text_by_NID(X509_get_subject_name(conn->peer),							  NID_commonName, conn->peer_cn, SM_USER);	conn->peer_cn[SM_USER] = '\0';	/* verify that the common name resolves to peer */#ifdef NOT_USED	/* CLIENT CERTIFICATES NOT REQUIRED  bjm 2002-09-26 */	/*	 * this is necessary to eliminate man-in-the-middle attacks and	 * impersonations where the attacker somehow learned the server's	 * private key	 */	if (verify_peer(conn) == -1)	{		close_SSL(conn);		return PGRES_POLLING_FAILED;	}#endif	/* SSL handshake is complete */	return PGRES_POLLING_OK;}/* *	Close SSL connection. */static voidclose_SSL(PGconn *conn){	if (conn->ssl)	{		SSL_shutdown(conn->ssl);		SSL_free(conn->ssl);		conn->ssl = NULL;	}	if (conn->peer)	{		X509_free(conn->peer);		conn->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;}/* *	Return pointer to SSL object. */SSL *PQgetssl(PGconn *conn){	if (!conn)		return NULL;	return conn->ssl;}#endif   /* USE_SSL */

⌨️ 快捷键说明

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