/*
Copyright ( c ) 2017 , 2021 , MariaDB
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 Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <mysql/plugin_auth.h>
#include <mysqld_error.h>
#include "common.h"
#if !defined (__attribute__) && !defined (__GNUC__)
#define __attribute__(A)
#endif
#define PASSWORD_LEN_BUF 44 /* base64 of 32 bytes */
#define PASSWORD_LEN 43 /* we won't store the last byte, padding '=' */
#define CRYPTO_LONGS (CRYPTO_BYTES/sizeof (long ))
#define NONCE_LONGS (NONCE_BYTES/sizeof (long ))
/************************** SERVER *************************************/
static int loaded= 0 ;
static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
{
int pkt_len;
unsigned long nonce[CRYPTO_LONGS + NONCE_LONGS];
unsigned char *pkt, *reply= (unsigned char *)nonce;
info->password_used= PASSWORD_USED_YES;
/* prepare random nonce */
if (my_random_bytes((unsigned char *)nonce, (int )sizeof (nonce)))
return CR_ERROR; // eh? OpenSSL error
/* send it */
if (vio->write_packet(vio, reply + CRYPTO_BYTES, NONCE_BYTES))
return CR_AUTH_HANDSHAKE;
/* read the signature */
if ((pkt_len= vio->read_packet(vio, &pkt)) != CRYPTO_BYTES)
return CR_AUTH_HANDSHAKE;
memcpy(reply, pkt, CRYPTO_BYTES);
if (crypto_sign_open(reply, CRYPTO_BYTES + NONCE_BYTES,
(unsigned char *)info->auth_string))
return CR_AUTH_USER_CREDENTIALS; // wrong password provided by the user
return CR_OK;
}
static int compute_password_digest(const char *pw, size_t pwlen,
char *d, size_t *dlen)
{
unsigned char pk[CRYPTO_PUBLICKEYBYTES];
if (*dlen < PASSWORD_LEN)
return 1 ;
*dlen= PASSWORD_LEN;
crypto_sign_keypair(pk, (unsigned char *)pw, pwlen);
my_base64_encode(pk, CRYPTO_PUBLICKEYBYTES, d);
return 0 ;
}
static int digest_to_binary(const char *d, size_t dlen,
unsigned char *b, size_t *blen)
{
char pw[PASSWORD_LEN_BUF];
if (*blen < CRYPTO_PUBLICKEYBYTES || dlen != PASSWORD_LEN)
{
my_printf_error(ER_PASSWD_LENGTH, "Password hash should be %d characters long" , 0 , PASSWORD_LEN);
return 1 ;
}
*blen= CRYPTO_PUBLICKEYBYTES;
memcpy(pw, d, PASSWORD_LEN);
pw[PASSWORD_LEN]= '=' ;
if (my_base64_decode(pw, PASSWORD_LEN_BUF, b, 0 , 0 ) == CRYPTO_PUBLICKEYBYTES)
return 0 ;
my_printf_error(ER_PASSWD_LENGTH, "Password hash should be base64 encoded" , 0 );
return 1 ;
}
static struct st_mysql_auth info =
{
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
"client_ed25519" ,
auth,
compute_password_digest,
digest_to_binary
};
static int init(void *p __attribute__((unused)))
{
loaded= 1 ;
return 0 ;
}
static int deinit(void *p __attribute__((unused)))
{
loaded= 0 ;
return 0 ;
}
maria_declare_plugin(ed25519)
{
MYSQL_AUTHENTICATION_PLUGIN,
&info,
"ed25519" ,
"Sergei Golubchik" ,
"Elliptic curve ED25519 based authentication" ,
PLUGIN_LICENSE_GPL,
init,
deinit,
0 x0101,
NULL,
NULL,
"1.1" ,
MariaDB_PLUGIN_MATURITY_STABLE
}
maria_declare_plugin_end;
/************************** UDF ****************************************/
MYSQL_PLUGIN_EXPORT
char *ed25519_password(UDF_INIT *initid __attribute__((unused)),
UDF_ARGS *args, char *result, unsigned long *length,
unsigned char *is_null, unsigned char *error __attribute__((unused)))
{
unsigned char pk[CRYPTO_PUBLICKEYBYTES];
if ((*is_null= !args->args[0 ]))
return NULL;
*length= PASSWORD_LEN;
crypto_sign_keypair(pk, (unsigned char *)args->args[0 ], args->lengths[0 ]);
my_base64_encode(pk, CRYPTO_PUBLICKEYBYTES, result);
return result;
}
/*
At least one of _ init / _ deinit is needed unless the server is started
with - - allow_suspicious_udfs .
*/
MYSQL_PLUGIN_EXPORT
my_bool ed25519_password_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if (args->arg_count != 1 || args->arg_type[0 ] != STRING_RESULT)
{
strcpy(message,"Wrong arguments to ed25519_password()" );
return 1 ;
}
if (!loaded)
{
/* cannot work unless the plugin is loaded, we need services. */
strcpy(message,"Authentication plugin ed25519 is not loaded" );
return 1 ;
}
initid->max_length= PASSWORD_LEN_BUF;
return 0 ;
}
Messung V0.5 in Prozent C=94 H=100 G=96
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland