1/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License as
5 published by the Free Software Foundation; version 2 of the
6 License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17/**
18 @file
19
20 Test driver for the mysql-test/t/plugin_auth.test
21
22 This is a set of test plugins used to test the external authentication
23 implementation.
24 See the above test file for more details.
25 This test plugin is based on the dialog plugin example.
26*/
27
28#include <my_global.h>
29#include <mysql/plugin_auth.h>
30#include <mysql/client_plugin.h>
31#include <string.h>
32#include <stdio.h>
33#include <stdlib.h>
34
35/********************* SERVER SIDE ****************************************/
36
37/**
38 dialog test plugin mimicking the ordinary auth mechanism. Used to test the auth plugin API
39*/
40static int auth_test_plugin(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
41{
42 unsigned char *pkt;
43 int pkt_len;
44
45 /* send a password question */
46 if (vio->write_packet(vio, (const unsigned char *) PASSWORD_QUESTION, 1))
47 return CR_ERROR;
48
49 /* read the answer */
50 if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
51 return CR_ERROR;
52
53 info->password_used= PASSWORD_USED_YES;
54
55 /* fail if the password is wrong */
56 if (strcmp((const char *) pkt, info->auth_string))
57 return CR_ERROR;
58
59 /* copy auth string as a destination name to check it */
60 strcpy (info->authenticated_as, info->auth_string);
61
62 /* copy something into the external user name */
63 strcpy (info->external_user, info->auth_string);
64
65 return CR_OK;
66}
67
68static struct st_mysql_auth auth_test_handler=
69{
70 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
71 "auth_test_plugin", /* requires test_plugin client's plugin */
72 auth_test_plugin
73};
74
75/**
76 dialog test plugin mimicking the ordinary auth mechanism. Used to test the clear text plugin API
77*/
78static int auth_cleartext_plugin(MYSQL_PLUGIN_VIO *vio,
79 MYSQL_SERVER_AUTH_INFO *info)
80{
81 unsigned char *pkt;
82 int pkt_len;
83
84 /* read the password */
85 if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
86 return CR_ERROR;
87
88 info->password_used= PASSWORD_USED_YES;
89
90 /* fail if the password is wrong */
91 if (strcmp((const char *) pkt, info->auth_string))
92 return CR_ERROR;
93
94 return CR_OK;
95}
96
97
98static struct st_mysql_auth auth_cleartext_handler=
99{
100 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
101 "mysql_clear_password", /* requires the clear text plugin */
102 auth_cleartext_plugin
103};
104
105mysql_declare_plugin(test_plugin)
106{
107 MYSQL_AUTHENTICATION_PLUGIN,
108 &auth_test_handler,
109 "test_plugin_server",
110 "Georgi Kodinov",
111 "plugin API test plugin",
112 PLUGIN_LICENSE_GPL,
113 NULL,
114 NULL,
115 0x0100,
116 NULL,
117 NULL,
118 NULL,
119 0,
120},
121{
122 MYSQL_AUTHENTICATION_PLUGIN,
123 &auth_cleartext_handler,
124 "cleartext_plugin_server",
125 "Georgi Kodinov",
126 "cleartext plugin API test plugin",
127 PLUGIN_LICENSE_GPL,
128 NULL,
129 NULL,
130 0x0100,
131 NULL,
132 NULL,
133 NULL,
134 0,
135}
136mysql_declare_plugin_end;
137
138
139/********************* CLIENT SIDE ***************************************/
140/*
141 client plugin used for testing the plugin API
142*/
143#include <mysql.h>
144
145/**
146 The main function of the test plugin.
147
148 Reads the prompt, check if the handshake is done and if the prompt is a
149 password request and returns the password. Otherwise return error.
150
151 @note
152 1. this plugin shows how a client authentication plugin
153 may read a MySQL protocol OK packet internally - which is important
154 where a number of packets is not known in advance.
155 2. the first byte of the prompt is special. it is not
156 shown to the user, but signals whether it is the last question
157 (prompt[0] & 1 == 1) or not last (prompt[0] & 1 == 0),
158 and whether the input is a password (not echoed).
159 3. the prompt is expected to be sent zero-terminated
160*/
161static int test_plugin_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
162{
163 unsigned char *pkt, cmd= 0;
164 int pkt_len, res;
165 char *reply;
166
167 do
168 {
169 /* read the prompt */
170 pkt_len= vio->read_packet(vio, &pkt);
171 if (pkt_len < 0)
172 return CR_ERROR;
173
174 if (pkt == 0)
175 {
176 /*
177 in mysql_change_user() the client sends the first packet, so
178 the first vio->read_packet() does nothing (pkt == 0).
179
180 We send the "password", assuming the client knows what it's doing.
181 (in other words, the dialog plugin should be only set as a default
182 authentication plugin on the client if the first question
183 asks for a password - which will be sent in clear text, by the way)
184 */
185 reply= mysql->passwd;
186 }
187 else
188 {
189 cmd= *pkt++;
190
191 /* is it MySQL protocol (0=OK or 254=need old password) packet ? */
192 if (cmd == 0 || cmd == 254)
193 return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */
194
195 /*
196 asking for a password with an empty prompt means mysql->password
197 otherwise return an error
198 */
199 if ((cmd == LAST_PASSWORD[0] || cmd == PASSWORD_QUESTION[0]) && *pkt == 0)
200 reply= mysql->passwd;
201 else
202 return CR_ERROR;
203 }
204 if (!reply)
205 return CR_ERROR;
206 /* send the reply to the server */
207 res= vio->write_packet(vio, (const unsigned char *) reply,
208 (int)strlen(reply) + 1);
209
210 if (res)
211 return CR_ERROR;
212
213 /* repeat unless it was the last question */
214 } while (cmd != LAST_QUESTION[0] && cmd != PASSWORD_QUESTION[0]);
215
216 /* the job of reading the ok/error packet is left to the server */
217 return CR_OK;
218}
219
220
221mysql_declare_client_plugin(AUTHENTICATION)
222 "auth_test_plugin",
223 "Georgi Kodinov",
224 "Dialog Client Authentication Plugin",
225 {0,1,0},
226 "GPL",
227 NULL,
228 NULL,
229 NULL,
230 NULL,
231 test_plugin_client
232mysql_end_client_plugin;
233