aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libmysql_r/sql-common/client_async_authentication.h
blob: 2cbfdad6c209d03599e230abec75d88f0d7e6947 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License, version 2.0,
   as published by the Free Software Foundation.

   This program is also distributed with certain software (including
   but not limited to OpenSSL) that is licensed under separate terms,
   as designated in a particular file or component or in included license
   documentation.  The authors of MySQL hereby grant you an additional
   permission to link the program and your derivative works with the
   separately licensed software that they have included with MySQL.

   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, version 2.0, 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-1301  USA */

#include "mysql/plugin_auth_common.h"
#include "mysql_async.h"

#ifdef HAVE_OPENSSL
#include <openssl/ossl_typ.h>
#endif
#ifdef HAVE_WOLFSSL
#error #include <wolfssl/openssl/ssl.h>
#endif

/* this is a "superset" of MYSQL_PLUGIN_VIO, in C++ I use inheritance */
struct MCPVIO_EXT {
  int (*read_packet)(MYSQL_PLUGIN_VIO *vio, uchar **buf);
  int (*write_packet)(MYSQL_PLUGIN_VIO *vio, const uchar *pkt, int pkt_len);
  void (*info)(MYSQL_PLUGIN_VIO *vio, MYSQL_PLUGIN_VIO_INFO *info);
  net_async_status (*read_packet_nonblocking)(struct MYSQL_PLUGIN_VIO *vio,
                                              unsigned char **buf, int *result);
  net_async_status (*write_packet_nonblocking)(struct MYSQL_PLUGIN_VIO *vio,
                                               const unsigned char *pkt,
                                               int pkt_len, int *result);

  /* -= end of MYSQL_PLUGIN_VIO =- */
  MYSQL *mysql;
  auth_plugin_t *plugin; /**< what plugin we're under */
  const char *db;
  struct {
    uchar *pkt; /**< pointer into NET::buff */
    uint pkt_len;
  } cached_server_reply;
  int packets_read, packets_written; /**< counters for send/received packets */
  int mysql_change_user;             /**< if it's mysql_change_user() */
  int last_read_packet_len; /**< the length of the last *read* packet */
};

/* Our state machines have four simple return codes: */
enum mysql_state_machine_status {
  STATE_MACHINE_FAILED,      /* Completion with a failure. */
  STATE_MACHINE_CONTINUE,    /* Keep calling the state machine. */
  STATE_MACHINE_WOULD_BLOCK, /* Needs to block to continue. */
  STATE_MACHINE_DONE         /* Completion with a success. */
};

/* state machine for native password autheintication API */
enum client_auth_native_password_plugin_status {
  NATIVE_READING_PASSWORD = 1,
  NATIVE_WRITING_RESPONSE
};

enum client_auth_sha256_password_plugin_status {
  SHA256_READING_PASSWORD = 1,
  SHA256_REQUEST_PUBLIC_KEY,
  SHA256_READ_PUBLIC_KEY,
  SHA256_SEND_ENCRYPTED_PASSWORD,
  SHA256_SEND_PLAIN_PASSWORD
};

enum client_auth_caching_sha2_password_plugin_status {
  CACHING_SHA2_READING_PASSWORD = 1,
  CACHING_SHA2_WRITING_RESPONSE,
  CACHING_SHA2_CHALLENGE_RESPONSE,
  CACHING_SHA2_REQUEST_PUBLIC_KEY,
  CACHING_SHA2_READ_PUBLIC_KEY,
  CACHING_SHA2_SEND_ENCRYPTED_PASSWORD,
  CACHING_SHA2_SEND_PLAIN_PASSWORD
};

/* A state machine for authentication itself. */
struct mysql_async_auth;
typedef mysql_state_machine_status (*authsm_function)(mysql_async_auth *);

struct mysql_async_auth {
  MYSQL *mysql;
  bool non_blocking;

  char *data;
  uint data_len;
  const char *data_plugin;
  const char *db;

  const char *auth_plugin_name;
  auth_plugin_t *auth_plugin;
  MCPVIO_EXT mpvio;
  ulong pkt_length;
  int res;

  char *change_user_buff;
  int change_user_buff_len;

  int client_auth_plugin_state;
  authsm_function state_function;
};

/*
  Connection is handled with a state machine.  Each state is
  represented by a function pointer (csm_function) which returns
  a mysql_state_machine_status to indicate the state of the
  connection.
  This state machine has boundaries around network IO to allow
  reuse between blocking and non-blocking clients.
*/
struct mysql_async_connect;
typedef mysql_state_machine_status (*csm_function)(mysql_async_connect *);

/*
  define different states of an asynchronous SSL connection phase
*/
enum ssl_exchange_state {
  SSL_REQUEST = 8100,
  SSL_CONNECT = 8101,
  SSL_COMPLETE = 8102,
  SSL_NONE = 8103
};

/*
  Struct to track the state of a connection being established.  Once
  the connection is established, the context should be discarded and
  relevant values copied out of it.
*/
struct mysql_async_connect {
  /* state for the overall connection process */
  MYSQL *mysql;
  const char *host;
  const char *user;
  const char *passwd;
  const char *db;
  uint port;
  const char *unix_socket;
  ulong client_flag;
  bool non_blocking;

  ulong pkt_length;
  char *host_info;
  char buff[NAME_LEN + USERNAME_LENGTH + 100];
  int scramble_data_len;
  char *scramble_data;
  const char *scramble_plugin;
  char *scramble_buffer;
  bool scramble_buffer_allocated;

  /* context needed to establish asynchronous authentication */
  struct mysql_async_auth *auth_context;
  /* state for running init_commands */
  bool saved_reconnect;
  char **current_init_command;

  ssl_exchange_state ssl_state;
#if defined(HAVE_OPENSSL)
  SSL *ssl;
#endif
  /* state function that will be called next */
  csm_function state_function;
};