mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.5 KiB
197 lines
6.5 KiB
--- sqlite3.c 2024-03-22 19:22:47.046093173 +0100
|
|
+++ sqlite3-pass-exts.c 2024-03-22 19:24:09.557303716 +0100
|
|
@@ -26313,6 +26313,183 @@
|
|
sqlite3ResultStrAccum(context, &sRes);
|
|
}
|
|
|
|
+#define DEF_SALT_SIZE 20
|
|
+#define SHA_DIGEST_LENGTH 20
|
|
+
|
|
+/// Forward declarations
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
+
|
|
+// ctype.h
|
|
+extern int toupper (int __c) __THROW;
|
|
+
|
|
+// SHA256_crypt
|
|
+char * sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen);
|
|
+
|
|
+// OpenSSL
|
|
+unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
|
+int RAND_bytes(unsigned char *buf, int num);
|
|
+unsigned long ERR_get_error(void);
|
|
+char *ERR_error_string(unsigned long e, char *buf);
|
|
+
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
+
|
|
+int check_args_types(int argc, sqlite3_value** argv) {
|
|
+ int inv_type = sqlite3_value_type(argv[0]) != SQLITE_TEXT;
|
|
+
|
|
+ if (inv_type == 0 && argc == 2) {
|
|
+ return
|
|
+ sqlite3_value_type(argv[1]) != SQLITE_TEXT &&
|
|
+ sqlite3_value_type(argv[1]) != SQLITE_BLOB;
|
|
+ } else {
|
|
+ return inv_type;
|
|
+ }
|
|
+}
|
|
+
|
|
+int check_args_lengths(int argc, sqlite3_value** argv) {
|
|
+ int inv_size = 1;
|
|
+
|
|
+ int pass_size = sqlite3_value_bytes(argv[0]);
|
|
+ if (pass_size > 0) {
|
|
+ inv_size = 0;
|
|
+ }
|
|
+
|
|
+ if (inv_size == 0 && argc == 2) {
|
|
+ int salt_size = sqlite3_value_bytes(argv[1]);
|
|
+
|
|
+ return salt_size <= 0 || salt_size > DEF_SALT_SIZE;
|
|
+ } else {
|
|
+ return inv_size;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief SQLite3 extension function for hash generation.
|
|
+ * @details Computes a hash equivalent to the one generated by MySQL for 'mysql_native_password'.
|
|
+ * @param context SQLite3 context used for returning computation result.
|
|
+ * @param argc Number of arguments; expected to be 1.
|
|
+ * @param argv Argument list; expected to hold one argument with len > 0 of type 'SQLITE_TEXT'.
|
|
+ */
|
|
+static void mysql_native_passwordFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
|
|
+ if (argc != 1) {
|
|
+ sqlite3_result_text(context, "Invalid number of arguments", -1, SQLITE_TRANSIENT);
|
|
+ return;
|
|
+ } else {
|
|
+ if (check_args_types(argc, argv)) {
|
|
+ sqlite3_result_text(context, "Invalid argument type", -1, SQLITE_TRANSIENT);
|
|
+ return;
|
|
+ }
|
|
+ if (check_args_lengths(argc, argv)) {
|
|
+ sqlite3_result_text(context, "Invalid argument size", -1, SQLITE_TRANSIENT);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ const unsigned char* input = sqlite3_value_text(argv[0]);
|
|
+ int input_len = strlen((const char*)input);
|
|
+
|
|
+ unsigned char hash1[SHA_DIGEST_LENGTH] = { 0 };
|
|
+ unsigned char hash2[SHA_DIGEST_LENGTH] = { 0 };
|
|
+
|
|
+ SHA1(input, input_len, hash1);
|
|
+ SHA1(hash1, SHA_DIGEST_LENGTH, hash2);
|
|
+
|
|
+ char hex_hash[2 * SHA_DIGEST_LENGTH + 2];
|
|
+ unsigned int i = 0;
|
|
+
|
|
+ for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
|
|
+ sprintf(hex_hash + 2 * i + 1, "%02x", hash2[i]);
|
|
+
|
|
+ hex_hash[2 * i + 1] = toupper(hex_hash[2 * i + 1]);
|
|
+ hex_hash[2 * i + 1 + 1] = toupper(hex_hash[2 * i + 1 + 1]);
|
|
+ }
|
|
+
|
|
+ hex_hash[0] = '*';
|
|
+ hex_hash[2 * SHA_DIGEST_LENGTH + 1] = '\0';
|
|
+
|
|
+ sqlite3_result_text(context, hex_hash, -1, SQLITE_TRANSIENT);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief SQLite3 extension function for hash generation.
|
|
+ * @details Computes a hash equivalent to the one generated by MySQL for 'caching_sha2_password'.
|
|
+ * @param context SQLite3 context used for returning computation result.
|
|
+ * @param argc Number of arguments; either 1 or 2. One for random salt, two providing salt.
|
|
+ * @param argv Argument list; expected to hold either 1 or 2 arguments:
|
|
+ * 1. Password to be hashed; with len > 0 and of type 'SQLITE_TEXT'.
|
|
+ * 1. Optional salt; with (len > 0 && len <= 20) and of type ('SQLITE_TEXT' || 'SQLITE_BLOB'). If no salt is
|
|
+ * provided a randomly generated salt with length 20 will be used.
|
|
+ */
|
|
+static void caching_sha2_passwordFunc(sqlite3_context* context, int argc, sqlite3_value** argv) {
|
|
+ if (argc < 1 || argc > 2) {
|
|
+ sqlite3_result_text(context, "Invalid number of arguments", -1, SQLITE_TRANSIENT);
|
|
+ return;
|
|
+ } else {
|
|
+ if (check_args_types(argc, argv)) {
|
|
+ sqlite3_result_text(context, "Invalid argument type", -1, SQLITE_TRANSIENT);
|
|
+ return;
|
|
+ }
|
|
+ if (check_args_lengths(argc, argv)) {
|
|
+ sqlite3_result_text(context, "Invalid argument size", -1, SQLITE_TRANSIENT);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ unsigned int salt_size = DEF_SALT_SIZE;
|
|
+ const char* cpass = (const char*)sqlite3_value_text(argv[0]);
|
|
+ unsigned char salt[DEF_SALT_SIZE + 1] = { 0 };
|
|
+
|
|
+ if (argc == 2) {
|
|
+ salt_size = sqlite3_value_bytes(argv[1]);
|
|
+ const void* b_salt = sqlite3_value_blob(argv[1]);
|
|
+
|
|
+ memcpy(salt, b_salt, salt_size);
|
|
+ } else {
|
|
+ unsigned char salt_buf[DEF_SALT_SIZE + 1] = { 0 };
|
|
+
|
|
+ if (RAND_bytes(salt_buf, DEF_SALT_SIZE) != 1) {
|
|
+ const char t_msg[] = { "SALT creation failed (%lu:'%s')" };
|
|
+ char err_buf[256] = { 0 };
|
|
+ char err_msg[sizeof(err_buf)/sizeof(char) + sizeof(t_msg)/sizeof(char) + 20] = { 0 };
|
|
+
|
|
+ const unsigned long err = ERR_get_error();
|
|
+ ERR_error_string(err, err_buf);
|
|
+
|
|
+ sprintf(err_msg, t_msg, err, err_buf);
|
|
+ sqlite3_result_text(context, err_msg, -1, SQLITE_TRANSIENT);
|
|
+ return;
|
|
+ } else {
|
|
+ unsigned int i = 0;
|
|
+
|
|
+ for (i = 0; i < sizeof(salt_buf)/sizeof(unsigned char); i++) {
|
|
+ salt_buf[i] = salt_buf[i] & 0x7f;
|
|
+
|
|
+ if (salt_buf[i] == '\0' || salt_buf[i] == '$') {
|
|
+ salt_buf[i] = salt_buf[i] + 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ memcpy(salt, salt_buf, salt_size);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ #define BASE_SHA2_SALT "$5$rounds=5000$"
|
|
+ #define BASE_SHA2_HASH "$A$005$"
|
|
+
|
|
+ char sha2_buf[100] = { 0 };
|
|
+ char sha2_salt[100] = { BASE_SHA2_SALT };
|
|
+
|
|
+ strcat(sha2_salt, (const char*)salt);
|
|
+ sha256_crypt_r(cpass, sha2_salt, sha2_buf, sizeof(sha2_buf));
|
|
+
|
|
+ char sha2_hash[100] = { BASE_SHA2_HASH };
|
|
+ const char* sha256 = sha2_buf + salt_size + strlen(BASE_SHA2_SALT) + 1;
|
|
+
|
|
+ strcat(sha2_hash, (const char*)salt);
|
|
+ strcat(sha2_hash, sha256);
|
|
+
|
|
+ sqlite3_result_text(context, sha2_hash, -1, SQLITE_TRANSIENT);
|
|
+}
|
|
+
|
|
/*
|
|
** current_time()
|
|
**
|
|
@@ -133269,6 +133269,9 @@
|
|
FUNCTION(substr, 3, 0, 0, substrFunc ),
|
|
FUNCTION(substring, 2, 0, 0, substrFunc ),
|
|
FUNCTION(substring, 3, 0, 0, substrFunc ),
|
|
+ FUNCTION(mysql_native_password, 1, 0, 0, mysql_native_passwordFunc ),
|
|
+ FUNCTION(caching_sha2_password, 1, 0, 0, caching_sha2_passwordFunc ),
|
|
+ FUNCTION(caching_sha2_password, 2, 0, 0, caching_sha2_passwordFunc ),
|
|
WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
|
|
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
|
|
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
|