1 /* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
2    Copyright (c) 2010, 2011, Oracle and/or its affiliates.
3 
4     This program is free software; you can redistribute it and/or
5     modify it under the terms of the GNU General Public License as
6     published by the Free Software Foundation; version 2 of the
7     License.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
17 
18 /**
19   @file
20 
21   auth_socket authentication plugin.
22 
23   Authentication is successful if the connection is done via a unix socket and
24   the owner of the client process matches the user name that was used when
25   connecting to mysqld.
26 */
27 #define _GNU_SOURCE 1 /* for struct ucred */
28 
29 #include <mysql/plugin_auth.h>
30 #include <string.h>
31 #include <pwd.h>
32 #include <sys/socket.h>
33 #include <sys/types.h>
34 
35 #ifdef HAVE_PEERCRED
36 #define level SOL_SOCKET
37 
38 #elif defined HAVE_SOCKPEERCRED
39 #define level SOL_SOCKET
40 #define ucred sockpeercred
41 
42 #elif defined HAVE_XUCRED
43 #include <sys/un.h>
44 #include <sys/ucred.h>
45 #define level 0
46 #define SO_PEERCRED LOCAL_PEERCRED
47 #define uid cr_uid
48 #define ucred xucred
49 
50 #else
51 #error impossible
52 #endif
53 
54 /**
55   perform the unix socket based authentication
56 
57   This authentication callback performs a unix socket based authentication -
58   it gets the uid of the client process and considers the user authenticated
59   if it uses username of this uid. That is - if the user is already
60   authenticated to the OS (if she is logged in) - she can use MySQL as herself
61 */
62 
socket_auth(MYSQL_PLUGIN_VIO * vio,MYSQL_SERVER_AUTH_INFO * info)63 static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
64 {
65   unsigned char *pkt;
66   MYSQL_PLUGIN_VIO_INFO vio_info;
67   struct ucred cred;
68   socklen_t cred_len= sizeof(cred);
69   struct passwd pwd_buf, *pwd;
70   char buf[1024];
71 
72   /* no user name yet ? read the client handshake packet with the user name */
73   if (info->user_name == 0)
74   {
75     if (vio->read_packet(vio, &pkt) < 0)
76       return CR_ERROR;
77   }
78 
79   info->password_used= PASSWORD_USED_NO_MENTION;
80 
81   vio->info(vio, &vio_info);
82   if (vio_info.protocol != MYSQL_VIO_SOCKET)
83     return CR_ERROR;
84 
85   /* get the UID of the client process */
86   if (getsockopt(vio_info.socket, level, SO_PEERCRED, &cred, &cred_len))
87     return CR_ERROR;
88 
89   if (cred_len != sizeof(cred))
90     return CR_ERROR;
91 
92   /* and find the username for this uid */
93   getpwuid_r(cred.uid, &pwd_buf, buf, sizeof(buf), &pwd);
94   if (pwd == NULL)
95     return CR_ERROR;
96 
97   /* now it's simple as that */
98   return strcmp(pwd->pw_name, info->user_name) ? CR_ERROR : CR_OK;
99 }
100 
101 static struct st_mysql_auth socket_auth_handler=
102 {
103   MYSQL_AUTHENTICATION_INTERFACE_VERSION,
104   0,
105   socket_auth,
106   NULL, NULL /* no PASSWORD() */
107 };
108 
maria_declare_plugin(auth_socket)109 maria_declare_plugin(auth_socket)
110 {
111   MYSQL_AUTHENTICATION_PLUGIN,
112   &socket_auth_handler,
113   "unix_socket",
114   "Sergei Golubchik",
115   "Unix Socket based authentication",
116   PLUGIN_LICENSE_GPL,
117   NULL,
118   NULL,
119   0x0100,
120   NULL,
121   NULL,
122   "1.0",
123   MariaDB_PLUGIN_MATURITY_STABLE
124 }
125 maria_declare_plugin_end;
126 
127