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 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
/* Copyright (c) 2019, 2025, 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, version 2.0,
as published by the Free Software Foundation.
This program is designed to work 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 either included with
the program or referenced in the documentation.
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 */
#ifndef SQL_COMMON_CLIENT_ASYNC_AUTHENTICATION_H
#define SQL_COMMON_CLIENT_ASYNC_AUTHENTICATION_H
#define MAX_CIPHER_LENGTH 1024
#include <openssl/ossl_typ.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include "mysql/plugin_auth_common.h"
#include "mysql_async.h"
#include "mysql_com.h"
/* 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;
/** a flag indicating that pkt, pkt_len contain valid packet to be reused */
bool pkt_received;
} 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 sha2_async_auth {
unsigned char encrypted_password[MAX_CIPHER_LENGTH];
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_PKEY *public_key;
#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
RSA *public_key;
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
unsigned char scramble_pkt[SCRAMBLE_LENGTH];
int cipher_length;
};
struct mysql_async_auth {
MYSQL *mysql;
bool non_blocking;
char *data;
uint data_len;
/** set to mysql_async_connect::scramble_plugin */
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;
/** Used by caching_sha256_password plugin */
int client_auth_plugin_state;
authsm_function state_function;
uint current_factor_index;
sha2_async_auth sha2_auth;
};
/*
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;
/** The server sends the default plugin name in Protocol::HandshakeV10 */
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;
SSL *ssl;
/* state function that will be called next */
csm_function state_function;
};
#endif /* SQL_COMMON_CLIENT_ASYNC_AUTHENTICATION_H */
|