Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  password_reuse_check.c   Sprache: C

 

/* Copyright (c) 2021, Oleksandr Byelkin and 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 St, Fifth Floor, Boston, MA 02110-1335  USA */


#include <my_global.h> // for int2store
#include <stdio.h>     // for snprintf
#include <string.h>    // for memset
#include <mysql/plugin_password_validation.h>
#include <mysqld_error.h>

#define HISTORY_DB_NAME "password_reuse_check_history"

#define SQL_BUFF_LEN 2048

#define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1))

// 0 - unlimited, otherwise number of days to check
static unsigned interval= 0;

// helping string for bin_to_hex512
static char digits[]= "0123456789ABCDEF";

/**
  Store string with length

  @param to              buffer where to put the length and string
  @param from            the string to store

  @return reference on the byte after copied string
*/


static char *store_str(char *to, const MYSQL_CONST_LEX_STRING *from)
{
  int2store(to, from->length);
  memcpy(to + 2, from->str, from->length);
  return to + 2 + from->length;
}


/**
  Convert string of 512 bits (64 bytes) to hex representation

  @param to              pointer to the result buffer
                         (should be at least 64*2 bytes)
  @param str             pointer to 512 bits (64 bytes string)
*/


static void bin_to_hex512(char *to, const unsigned char *str)
{
  const unsigned char *str_end= str + (512/8);
  for (; str != str_end; ++str)
  {
    *to++= digits[((unsigned char) *str) >> 4];
    *to++= digits[((unsigned char) *str) & 0x0F];
  }
}


/**
  Send SQL error as ER_UNKNOWN_ERROR for information

  @param mysql           Connection handler
*/


static void report_sql_error(MYSQL *mysql)
{
  my_printf_error(ER_UNKNOWN_ERROR, "password_reuse_check:[%d] %s", ME_WARNING,
                  mysql_errno(mysql), mysql_error(mysql));
}


/**
  Create the history of passwords table for this plugin.

  @param mysql           Connection handler

  @retval 1 - Error
  @retval 0 - OK
*/


static int create_table(MYSQL *mysql)
{
  if (mysql_real_query(mysql,
        // 512/8 = 64
        STRING_WITH_LEN("CREATE TABLE mysql." HISTORY_DB_NAME
                        " ( hash binary(64),"
                        " time timestamp not null default current_timestamp,"
                        " primary key (hash), index tm (time) )"
                        " ENGINE=Aria")))
  {
    report_sql_error(mysql);
    return 1;
  }
  return 0;
}


/**
  Run this query and create table if needed

  @param mysql           Connection handler
  @param query           The query to run
  @param len             length of the query text

  @retval 1 - Error
  @retval 0 - OK
*/


static int run_query_with_table_creation(MYSQL *mysql, const char *query,
                                         size_t len)
{
  if (mysql_real_query(mysql, query, (unsigned long) len))
  {
    unsigned int rc= mysql_errno(mysql);
    if (rc != ER_NO_SUCH_TABLE)
    {
      if (rc != ER_DUP_ENTRY)
      {
        report_sql_error(mysql);
      }
      else
      {
        // warning used to do not change error code
        my_printf_error(ER_NOT_VALID_PASSWORD,
                        "password_reuse_check: The password was already used",
                        ME_WARNING);
      }
      return 1;
    }
    if (create_table(mysql))
      return 1;
    if (mysql_real_query(mysql, query, (unsigned long) len))
    {
      report_sql_error(mysql);
      return 1;
    }
  }
  return 0;
}


/**
  Password validator

  @param username        User name (part of whole login name)
  @param password        Password to validate
  @param hostname        Host name (part of whole login name)

  @retval 1 - Password is not OK or an error happened
  @retval 0 - Password is OK
*/


static int validate(const MYSQL_CONST_LEX_STRING *username,
                    const MYSQL_CONST_LEX_STRING *password,
                    const MYSQL_CONST_LEX_STRING *hostname)
{
  MYSQL *mysql= NULL;
  size_t key_len= username->length + password->length + hostname->length +
                  (3 * 2 /* space for storing length of the strings */);
  size_t buff_len= (key_len > SQL_BUFF_LEN ? key_len : SQL_BUFF_LEN);
  size_t len;
  char *buff= malloc(buff_len);
  unsigned char hash[512/8];
  char escaped_hash[512/8*2 + 1];
  if (!buff)
    return 1;

  mysql= mysql_init(NULL);
  if (!mysql)
  {
    free(buff);
    return 1;
  }

  /*
    Store: username, hostname, password
    (password first to make its rewriting password in memory simplier)
  */

  store_str(store_str(store_str(buff, password), username), hostname);
  buff[key_len]= 0; // safety
  memset(hash, 0, sizeof(hash));
  my_sha512(hash, buff, key_len);
  // safety: rewrite password with zeros
  memset(buff, 0, password->length);
  if (mysql_real_connect_local(mysql) == NULL)
    goto sql_error;

  if (interval)
  {
    // trim the table
    len= snprintf(buff, buff_len,
                  "DELETE FROM mysql." HISTORY_DB_NAME
                  " WHERE time < DATE_SUB(NOW(), interval %d day)",
                  interval);
    if (run_query_with_table_creation(mysql, buff, len))
      goto sql_error;
  }

  bin_to_hex512(escaped_hash, hash);
  escaped_hash[512/8*2]= '\0';
  len= snprintf(buff, buff_len,
                "INSERT INTO mysql." HISTORY_DB_NAME "(hash) "
                "values (x'%s')",
                escaped_hash);
  if (run_query_with_table_creation(mysql, buff, len))
    goto sql_error;

  free(buff);
  mysql_close(mysql);
  return 0; // OK

sql_error:
  free(buff);
  if (mysql)
    mysql_close(mysql);
  return 1; // Error
}

static MYSQL_SYSVAR_UINT(interval, interval, PLUGIN_VAR_RQCMDARG,
  "Password history retention period in days (0 means unlimited)", NULL, NULL,
  0, 0, 365*100, 1);


static struct st_mysql_sys_var* sysvars[]= {
  MYSQL_SYSVAR(interval),
  NULL
};

static struct st_mariadb_password_validation info=
{
  MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION,
  validate
};

maria_declare_plugin(password_reuse_check)
{
  MariaDB_PASSWORD_VALIDATION_PLUGIN,
  &info,
  "password_reuse_check",
  "Oleksandr Byelkin",
  "Prevent password reuse",
  PLUGIN_LICENSE_GPL,
  NULL,
  NULL,
  0x0200,
  NULL,
  sysvars,
  "2.0",
  MariaDB_PLUGIN_MATURITY_STABLE
}
maria_declare_plugin_end;

Messung V0.5 in Prozent
C=93 H=90 G=91

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-10-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1126438
#Domains=1867298