mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 09:14:17 +01:00
9e1923ca23
Before this change the unix socket auth plugin returned true only when the OS socket user id matches the MariaDB user name. The authentication string was ignored. Now if an authentication string is defined with in `unix_socket` authentication rule, then the authentication string will be used to compare with the socket's user name, and the plugin will return a positive if matching. Make the plugin to fill in the @@external_user variable. This change is similar to MySQL commit of https://github.com/mysql/mysql-server/commit/6ddbc58e. However there's one difference with above commit: - For MySQL, both Unix user matches DB user name and Unix user matches the authentication string will be allowed to connect. - For MariaDB, we only allows the Unix user matches the authentication string to connect, if the authentication string is defined. This is because allowing both Unix user names has risks and couldn't handle the case that a customer only wants to allow one single Unix user to connect which doesn't matches the DB user name. If DB user is created with multiple unix_socket options for example: `create user A identified via unix_socket as 'B' or unix_socket as 'C';` Then both Unix user of B and C are accepted. Existing MTR test of `plugins.unix_socket` is not impacted. Also add a new MTR test to verify authentication with authentication string. See the MTR test cases for supported/unsupported cases. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.
163 lines
4.2 KiB
C
163 lines
4.2 KiB
C
/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
|
|
Copyright (c) 2010, 2011, Oracle and/or its affiliates.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; version 2 of the
|
|
License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
|
|
|
/**
|
|
@file
|
|
|
|
auth_socket authentication plugin.
|
|
|
|
Authentication is successful if the connection is done via a unix socket and
|
|
the owner of the client process matches the user name that was used when
|
|
connecting to mysqld.
|
|
*/
|
|
#define _GNU_SOURCE 1 /* for struct ucred */
|
|
|
|
#include <mysql/plugin_auth.h>
|
|
#include <string.h>
|
|
#include <pwd.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
|
|
#ifdef HAVE_PEERCRED
|
|
#define level SOL_SOCKET
|
|
|
|
#elif defined HAVE_SOCKPEERCRED
|
|
#define level SOL_SOCKET
|
|
#define ucred sockpeercred
|
|
|
|
#elif defined HAVE_XUCRED
|
|
#include <sys/un.h>
|
|
#include <sys/ucred.h>
|
|
#define level 0
|
|
#define SO_PEERCRED LOCAL_PEERCRED
|
|
#define uid cr_uid
|
|
#define ucred xucred
|
|
|
|
#elif defined HAVE_UNPCBID
|
|
#include <sys/un.h>
|
|
#define level 0
|
|
#define SO_PEERCRED LOCAL_PEEREID
|
|
#define uid unp_euid
|
|
#define ucred unpcbid
|
|
|
|
#elif defined HAVE_GETPEERUCRED
|
|
#include <ucred.h>
|
|
|
|
#elif defined HAVE_PEERCRED_STRUCT
|
|
#define level SOL_SOCKET
|
|
#define SO_PEERCRED SO_PEERID
|
|
#define uid euid
|
|
#define ucred peercred_struct
|
|
|
|
#else
|
|
#error impossible
|
|
#endif
|
|
|
|
/**
|
|
perform the unix socket based authentication
|
|
|
|
This authentication callback performs a unix socket based authentication -
|
|
it gets the uid of the client process and considers the user authenticated
|
|
if it uses username of this uid. That is - if the user is already
|
|
authenticated to the OS (if she is logged in) - she can use MySQL as herself
|
|
*/
|
|
|
|
static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
|
|
{
|
|
unsigned char *pkt;
|
|
MYSQL_PLUGIN_VIO_INFO vio_info;
|
|
#ifdef HAVE_GETPEERUCRED
|
|
ucred_t *cred = NULL;
|
|
#else
|
|
struct ucred cred;
|
|
socklen_t cred_len= sizeof(cred);
|
|
#endif
|
|
struct passwd pwd_buf, *pwd;
|
|
char buf[1024];
|
|
uid_t u;
|
|
|
|
/* no user name yet ? read the client handshake packet with the user name */
|
|
if (info->user_name == 0)
|
|
{
|
|
if (vio->read_packet(vio, &pkt) < 0)
|
|
return CR_ERROR;
|
|
}
|
|
|
|
info->password_used= PASSWORD_USED_NO_MENTION;
|
|
|
|
vio->info(vio, &vio_info);
|
|
if (vio_info.protocol != MYSQL_VIO_SOCKET)
|
|
return CR_ERROR;
|
|
|
|
/* get the UID of the client process */
|
|
#ifdef HAVE_GETPEERUCRED
|
|
if (getpeerucred(vio_info.socket, &cred) != 0)
|
|
return CR_ERROR;
|
|
u = ucred_geteuid(cred);
|
|
ucred_free(cred);
|
|
#else
|
|
if (getsockopt(vio_info.socket, level, SO_PEERCRED, &cred, &cred_len))
|
|
return CR_ERROR;
|
|
|
|
if (cred_len != sizeof(cred))
|
|
return CR_ERROR;
|
|
|
|
u = cred.uid;
|
|
#endif
|
|
|
|
/* and find the socket user name for this uid */
|
|
getpwuid_r(u, &pwd_buf, buf, sizeof(buf), &pwd);
|
|
if (pwd == NULL)
|
|
return CR_ERROR;
|
|
|
|
/* fill in the external user name used */
|
|
strncpy(info->external_user, pwd->pw_name, sizeof(info->external_user) - 1);
|
|
info->external_user[sizeof(info->external_user) - 1]= '\0';
|
|
|
|
/* compare with auth_string if it's defined, otherwise compare with DB user name*/
|
|
if (info->auth_string && info->auth_string[0])
|
|
return !strcmp(pwd->pw_name, info->auth_string) ? CR_OK : CR_ERROR;
|
|
else
|
|
return !strcmp(pwd->pw_name, info->user_name) ? CR_OK : CR_ERROR;
|
|
}
|
|
|
|
static struct st_mysql_auth socket_auth_handler=
|
|
{
|
|
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
|
|
0,
|
|
socket_auth,
|
|
NULL, NULL /* no PASSWORD() */
|
|
};
|
|
|
|
maria_declare_plugin(auth_socket)
|
|
{
|
|
MYSQL_AUTHENTICATION_PLUGIN,
|
|
&socket_auth_handler,
|
|
"unix_socket",
|
|
"Sergei Golubchik",
|
|
"Unix Socket based authentication",
|
|
PLUGIN_LICENSE_GPL,
|
|
NULL,
|
|
NULL,
|
|
0x0101,
|
|
NULL,
|
|
NULL,
|
|
"1.1",
|
|
MariaDB_PLUGIN_MATURITY_STABLE
|
|
}
|
|
maria_declare_plugin_end;
|
|
|