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

📄 auth.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
				ereport(FATAL,						(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),						 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",							  hostinfo, port->user_name, port->database_name,								port->ssl ? _("SSL on") : _("SSL off"))));#else				ereport(FATAL,						(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),						 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",						   hostinfo, port->user_name, port->database_name)));#endif				break;			}		case uaKrb5:			sendAuthRequest(port, AUTH_REQ_KRB5);			status = pg_krb5_recvauth(port);			break;		case uaIdent:			/*			 * If we are doing ident on unix-domain sockets, use SCM_CREDS			 * only if it is defined and SO_PEERCRED isn't.			 */#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \	(defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \	 (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)))			if (port->raddr.addr.ss_family == AF_UNIX)			{#if defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)				/*				 * Receive credentials on next message receipt, BSD/OS,				 * NetBSD. We need to set this before the client sends the				 * next packet.				 */				int			on = 1;				if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0)					ereport(FATAL,							(errcode_for_socket_access(),					   errmsg("could not enable credential reception: %m")));#endif				sendAuthRequest(port, AUTH_REQ_SCM_CREDS);			}#endif			status = authident(port);			break;		case uaMD5:			sendAuthRequest(port, AUTH_REQ_MD5);			status = recv_and_check_password_packet(port);			break;		case uaCrypt:			sendAuthRequest(port, AUTH_REQ_CRYPT);			status = recv_and_check_password_packet(port);			break;		case uaPassword:			sendAuthRequest(port, AUTH_REQ_PASSWORD);			status = recv_and_check_password_packet(port);			break;#ifdef USE_PAM		case uaPAM:			pam_port_cludge = port;			status = CheckPAMAuth(port, port->user_name, "");			break;#endif   /* USE_PAM */		case uaTrust:			status = STATUS_OK;			break;	}	if (status == STATUS_OK)		sendAuthRequest(port, AUTH_REQ_OK);	else		auth_failed(port, status);}/* * Send an authentication request packet to the frontend. */static voidsendAuthRequest(Port *port, AuthRequest areq){	StringInfoData buf;	pq_beginmessage(&buf, 'R');	pq_sendint(&buf, (int32) areq, sizeof(int32));	/* Add the salt for encrypted passwords. */	if (areq == AUTH_REQ_MD5)		pq_sendbytes(&buf, port->md5Salt, 4);	else if (areq == AUTH_REQ_CRYPT)		pq_sendbytes(&buf, port->cryptSalt, 2);	pq_endmessage(&buf);	/*	 * Flush message so client will see it, except for AUTH_REQ_OK, which need	 * not be sent until we are ready for queries.	 */	if (areq != AUTH_REQ_OK)		pq_flush();}#ifdef USE_PAM/* * PAM conversation function */static intpam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,					 struct pam_response ** resp, void *appdata_ptr){	if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)	{		switch (msg[0]->msg_style)		{			case PAM_ERROR_MSG:				ereport(LOG,						(errmsg("error from underlying PAM layer: %s",								msg[0]->msg)));				return PAM_CONV_ERR;			default:				ereport(LOG,						(errmsg("unsupported PAM conversation %d/%s",								msg[0]->msg_style, msg[0]->msg)));				return PAM_CONV_ERR;		}	}	if (!appdata_ptr)	{		/*		 * Workaround for Solaris 2.6 where the PAM library is broken and does		 * not pass appdata_ptr to the conversation routine		 */		appdata_ptr = pam_passwd;	}	/*	 * Password wasn't passed to PAM the first time around - let's go ask the	 * client to send a password, which we then stuff into PAM.	 */	if (strlen(appdata_ptr) == 0)	{		char	   *passwd;		sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);		passwd = recv_password_packet(pam_port_cludge);		if (passwd == NULL)			return PAM_CONV_ERR;	/* client didn't want to send password */		if (strlen(passwd) == 0)		{			ereport(LOG,					(errmsg("empty password returned by client")));			return PAM_CONV_ERR;		}		appdata_ptr = passwd;	}	/*	 * Explicitly not using palloc here - PAM will free this memory in	 * pam_end()	 */	*resp = calloc(num_msg, sizeof(struct pam_response));	if (!*resp)	{		ereport(LOG,				(errcode(ERRCODE_OUT_OF_MEMORY),				 errmsg("out of memory")));		return PAM_CONV_ERR;	}	(*resp)[0].resp = strdup((char *) appdata_ptr);	(*resp)[0].resp_retcode = 0;	return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);}/* * Check authentication against PAM. */static intCheckPAMAuth(Port *port, char *user, char *password){	int			retval;	pam_handle_t *pamh = NULL;	/*	 * Apparently, Solaris 2.6 is broken, and needs ugly static variable	 * workaround	 */	pam_passwd = password;	/*	 * Set the application data portion of the conversation struct This is	 * later used inside the PAM conversation to pass the password to the	 * authentication module.	 */	pam_passw_conv.appdata_ptr = (char *) password;		/* from password above,														 * not allocated */	/* Optionally, one can set the service name in pg_hba.conf */	if (port->auth_arg && port->auth_arg[0] != '\0')		retval = pam_start(port->auth_arg, "pgsql@",						   &pam_passw_conv, &pamh);	else		retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",						   &pam_passw_conv, &pamh);	if (retval != PAM_SUCCESS)	{		ereport(LOG,				(errmsg("could not create PAM authenticator: %s",						pam_strerror(pamh, retval))));		pam_passwd = NULL;		/* Unset pam_passwd */		return STATUS_ERROR;	}	retval = pam_set_item(pamh, PAM_USER, user);	if (retval != PAM_SUCCESS)	{		ereport(LOG,				(errmsg("pam_set_item(PAM_USER) failed: %s",						pam_strerror(pamh, retval))));		pam_passwd = NULL;		/* Unset pam_passwd */		return STATUS_ERROR;	}	retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);	if (retval != PAM_SUCCESS)	{		ereport(LOG,				(errmsg("pam_set_item(PAM_CONV) failed: %s",						pam_strerror(pamh, retval))));		pam_passwd = NULL;		/* Unset pam_passwd */		return STATUS_ERROR;	}	retval = pam_authenticate(pamh, 0);	if (retval != PAM_SUCCESS)	{		ereport(LOG,				(errmsg("pam_authenticate failed: %s",						pam_strerror(pamh, retval))));		pam_passwd = NULL;		/* Unset pam_passwd */		return STATUS_ERROR;	}	retval = pam_acct_mgmt(pamh, 0);	if (retval != PAM_SUCCESS)	{		ereport(LOG,				(errmsg("pam_acct_mgmt failed: %s",						pam_strerror(pamh, retval))));		pam_passwd = NULL;		/* Unset pam_passwd */		return STATUS_ERROR;	}	retval = pam_end(pamh, retval);	if (retval != PAM_SUCCESS)	{		ereport(LOG,				(errmsg("could not release PAM authenticator: %s",						pam_strerror(pamh, retval))));	}	pam_passwd = NULL;			/* Unset pam_passwd */	return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);}#endif   /* USE_PAM *//* * Collect password response packet from frontend. * * Returns NULL if couldn't get password, else palloc'd string. */static char *recv_password_packet(Port *port){	StringInfoData buf;	if (PG_PROTOCOL_MAJOR(port->proto) >= 3)	{		/* Expect 'p' message type */		int			mtype;		mtype = pq_getbyte();		if (mtype != 'p')		{			/*			 * If the client just disconnects without offering a password,			 * don't make a log entry.  This is legal per protocol spec and in			 * fact commonly done by psql, so complaining just clutters the			 * log.			 */			if (mtype != EOF)				ereport(COMMERROR,						(errcode(ERRCODE_PROTOCOL_VIOLATION),					errmsg("expected password response, got message type %d",						   mtype)));			return NULL;		/* EOF or bad message type */		}	}	else	{		/* For pre-3.0 clients, avoid log entry if they just disconnect */		if (pq_peekbyte() == EOF)			return NULL;		/* EOF */	}	initStringInfo(&buf);	if (pq_getmessage(&buf, 1000))		/* receive password */	{		/* EOF - pq_getmessage already logged a suitable message */		pfree(buf.data);		return NULL;	}	/*	 * Apply sanity check: password packet length should agree with length of	 * contained string.  Note it is safe to use strlen here because	 * StringInfo is guaranteed to have an appended '\0'.	 */	if (strlen(buf.data) + 1 != buf.len)		ereport(COMMERROR,				(errcode(ERRCODE_PROTOCOL_VIOLATION),				 errmsg("invalid password packet size")));	/* Do not echo password to logs, for security. */	ereport(DEBUG5,			(errmsg("received password packet")));	/*	 * Return the received string.	Note we do not attempt to do any	 * character-set conversion on it; since we don't yet know the client's	 * encoding, there wouldn't be much point.	 */	return buf.data;}/* * Called when we have sent an authorization request for a password. * Get the response and check it. */static intrecv_and_check_password_packet(Port *port){	char	   *passwd;	int			result;	passwd = recv_password_packet(port);	if (passwd == NULL)		return STATUS_EOF;		/* client wouldn't send password */	result = md5_crypt_verify(port, port->user_name, passwd);	pfree(passwd);	return result;}

⌨️ 快捷键说明

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