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

📄 fe-secure.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
						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"));						SOCK_ERRNO_SET(ECONNRESET);						n = -1;					}					break;				}			case SSL_ERROR_SSL:				{					char	   *err = SSLerrmessage();					printfPQExpBuffer(&conn->errorMessage,									  libpq_gettext("SSL error: %s\n"), err);					SSLerrfree(err);				}				/* fall through */			case SSL_ERROR_ZERO_RETURN:				SOCK_ERRNO_SET(ECONNRESET);				n = -1;				break;			default:				printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("unrecognized SSL error code: %d\n"),								  err);				n = -1;				break;		}	}	else#endif	{		n = send(conn->sock, ptr, len, 0);#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)		if (n < 0 && SOCK_ERRNO == EPIPE)			got_epipe = true;#endif	}#ifndef WIN32#ifdef ENABLE_THREAD_SAFETY	pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe);#else	pqsignal(SIGPIPE, oldsighandler);#endif   /* ENABLE_THREAD_SAFETY */#endif   /* WIN32 */	return n;}/* ------------------------------------------------------------ *//*						  SSL specific code						*//* ------------------------------------------------------------ */#ifdef USE_SSL/* *	Certificate verification callback * *	This callback allows us to log intermediate problems during *	verification, but there doesn't seem to be a clean way to get *	our PGconn * structure.  So we can't log anything! * *	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;}#ifdef NOT_USED/* *	Verify that common name resolves to peer. */static intverify_peer(PGconn *conn){	struct hostent *h = NULL;	struct sockaddr addr;	struct sockaddr_in *sin;	ACCEPT_TYPE_ARG3 len;	char	  **s;	unsigned long l;	/* get the address on the other side of the socket */	len = sizeof(addr);	if (getpeername(conn->sock, &addr, &len) == -1)	{		char		sebuf[256];		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("error querying socket: %s\n"),						  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));		return -1;	}	/* weird, but legal case */	if (addr.sa_family == AF_UNIX)		return 0;	{		struct hostent hpstr;		char		buf[BUFSIZ];		int			herrno = 0;		/*		 * Currently, pqGethostbyname() is used only on platforms that don't		 * have getaddrinfo().	If you enable this function, you should		 * convert the pqGethostbyname() function call to use getaddrinfo().		 */		pqGethostbyname(conn->peer_cn, &hpstr, buf, sizeof(buf),						&h, &herrno);	}	/* what do we know about the peer's common name? */	if (h == NULL)	{		printfPQExpBuffer(&conn->errorMessage,		  libpq_gettext("could not get information about host \"%s\": %s\n"),						  conn->peer_cn, hstrerror(h_errno));		return -1;	}	/* does the address match? */	switch (addr.sa_family)	{		case AF_INET:			sin = (struct sockaddr_in *) & addr;			for (s = h->h_addr_list; *s != NULL; s++)			{				if (!memcmp(&sin->sin_addr.s_addr, *s, h->h_length))					return 0;			}			break;		default:			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("unsupported protocol\n"));			return -1;	}	/*	 * the prior test should be definitive, but in practice it sometimes	 * fails.  So we also check the aliases.	 */	for (s = h->h_aliases; *s != NULL; s++)	{		if (pg_strcasecmp(conn->peer_cn, *s) == 0)			return 0;	}	/* generate protocol-aware error message */	switch (addr.sa_family)	{		case AF_INET:			sin = (struct sockaddr_in *) & addr;			l = ntohl(sin->sin_addr.s_addr);			printfPQExpBuffer(&conn->errorMessage,							  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   /* NOT_USED *//* *	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){	char		homedir[MAXPGPATH];	char		fnbuf[MAXPGPATH];	FILE	   *fp;	DH		   *dh;	int			codes;	if (!pqGetHomeDirectory(homedir, sizeof(homedir)))		return NULL;	/* attempt to open file.  It's not an error if it doesn't exist. */	snprintf(fnbuf, sizeof(fnbuf), DHFILEPATTERN, homedir, 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;}/* *	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. * *	Must return 1 on success, 0 on no data or error. */static intclient_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey){	char		homedir[MAXPGPATH];	struct stat buf;#ifndef WIN32	struct stat buf2;#endif	char		fnbuf[MAXPGPATH];	FILE	   *fp;	PGconn	   *conn = (PGconn *) SSL_get_app_data(ssl);	int			(*cb) () = NULL;	/* how to read user password */	char		sebuf[256];	if (!pqGetHomeDirectory(homedir, sizeof(homedir)))	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("could not get user information\n"));		return 0;	}	/* read the user certificate */	snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERCERTFILE);	if ((fp = fopen(fnbuf, "r")) == NULL)	{		printfPQExpBuffer(&conn->errorMessage,			   libpq_gettext("could not open certificate file \"%s\": %s\n"),						  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));		return 0;	}	if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)	{		char	   *err = SSLerrmessage();		printfPQExpBuffer(&conn->errorMessage,			   libpq_gettext("could not read certificate file \"%s\": %s\n"),						  fnbuf, err);		SSLerrfree(err);		fclose(fp);		return 0;	}	fclose(fp);	/* read the user key */	snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERKEYFILE);	if (stat(fnbuf, &buf) == -1)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("certificate present, but not private key file \"%s\"\n"),						  fnbuf);		return 0;	}#ifndef WIN32	if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||		buf.st_uid != geteuid())	{		printfPQExpBuffer(&conn->errorMessage,			libpq_gettext("private key file \"%s\" has wrong permissions\n"),						  fnbuf);		return 0;	}#endif	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)));		return 0;	}#ifndef WIN32	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 file \"%s\" changed during execution\n"), fnbuf);		return 0;	}#endif	if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)	{		char	   *err = SSLerrmessage();		printfPQExpBuffer(&conn->errorMessage,			   libpq_gettext("could not read private key file \"%s\": %s\n"),						  fnbuf, err);		SSLerrfree(err);		fclose(fp);		return 0;	}	fclose(fp);	/* verify that the cert and key go together */	if (!X509_check_private_key(*x509, *pkey))	{		char	   *err = SSLerrmessage();		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("certificate does not match private key file \"%s\": %s\n"),						  fnbuf, err);		SSLerrfree(err);		return 0;	}	return 1;}#ifdef ENABLE_THREAD_SAFETYstatic unsigned longpq_threadidcallback(void){	/*	 * This is not starndard-compliant.  pthread_self() returns pthread_t, and

⌨️ 快捷键说明

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