You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-31 18:30:33 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			255 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2016 MariaDB Corporation Ab
 | |
|  *
 | |
|  * Use of this software is governed by the Business Source License included
 | |
|  * in the LICENSE.TXT file and at www.mariadb.com/bsl11.
 | |
|  *
 | |
|  * Change Date: 2025-05-25
 | |
|  *
 | |
|  * On the date above, in accordance with the Business Source License, use
 | |
|  * of this software will be governed by version 2 or later of the General
 | |
|  * Public License.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * @file cspasswd.cpp  - Implementation of pasword encoding
 | |
|  *  Modified from MariaDB internal implementations
 | |
|  */
 | |
| 
 | |
| #include <cstdio>
 | |
| #include <getopt.h>
 | |
| #include <termios.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| #include <iostream>
 | |
| 
 | |
| #include "secrets.h"
 | |
| #include "mcsconfig.h"
 | |
| 
 | |
| using std::cin;
 | |
| using std::cout;
 | |
| using std::endl;
 | |
| using std::flush;
 | |
| using std::string;
 | |
| 
 | |
| struct option options[] = {{"help", no_argument, nullptr, 'h'},
 | |
|                            {"decrypt", no_argument, nullptr, 'd'},
 | |
|                            {"interactive", no_argument, nullptr, 'i'},
 | |
|                            {nullptr, 0, nullptr, 0}};
 | |
| 
 | |
| void print_usage(const char* executable, const char* directory)
 | |
| {
 | |
|   const char msg[] =
 | |
|       R"(Usage: %s [-h|--help] [-i|--interactive] [-d|--decrypt] [path] password
 | |
| Encrypt a Columnstore plaintext password using the encryption key in the key file
 | |
| '%s'. The key file may be generated using the 'cskeys'-utility.
 | |
|   -h, --help         Display this help.
 | |
|   -d, --decrypt      Decrypt an encrypted password instead.
 | |
|   -i, --interactive  - If cspasswd is reading from a pipe, it will read a line and
 | |
|                        use that as the password.
 | |
|                      - If cspasswd is connected to a terminal console, it will prompt
 | |
|                        for the password.
 | |
|                      If '-i' is specified, a single argument is assumed to be the path
 | |
|                      and two arguments is treated like an error.
 | |
|   path      The key file directory (default: '%s')
 | |
|   password  The password to encrypt or decrypt
 | |
| )";
 | |
| 
 | |
|   printf(msg, executable, SECRETS_FILENAME, directory);
 | |
| }
 | |
| 
 | |
| bool read_password(string* pPassword)
 | |
| {
 | |
|   bool rv = false;
 | |
|   string password;
 | |
| 
 | |
|   if (isatty(STDIN_FILENO))
 | |
|   {
 | |
|     struct termios tty;
 | |
|     tcgetattr(STDIN_FILENO, &tty);
 | |
| 
 | |
|     bool echo = (tty.c_lflag & ECHO);
 | |
|     if (echo)
 | |
|     {
 | |
|       tty.c_lflag &= ~ECHO;
 | |
|       tcsetattr(STDIN_FILENO, TCSANOW, &tty);
 | |
|     }
 | |
| 
 | |
|     cout << "Enter password : " << flush;
 | |
|     string s1;
 | |
|     std::getline(std::cin, s1);
 | |
|     cout << endl;
 | |
| 
 | |
|     cout << "Repeat password: " << flush;
 | |
|     string s2;
 | |
|     std::getline(std::cin, s2);
 | |
|     cout << endl;
 | |
| 
 | |
|     if (echo)
 | |
|     {
 | |
|       tty.c_lflag |= ECHO;
 | |
|       tcsetattr(STDIN_FILENO, TCSANOW, &tty);
 | |
|     }
 | |
| 
 | |
|     if (s1 == s2)
 | |
|     {
 | |
|       password = s1;
 | |
|       rv = true;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       cout << "Passwords are not identical." << endl;
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     std::getline(std::cin, password);
 | |
|     rv = true;
 | |
|   }
 | |
| 
 | |
|   if (rv)
 | |
|   {
 | |
|     *pPassword = password;
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| int main(int argc, char** argv)
 | |
| {
 | |
|   std::ios::sync_with_stdio();
 | |
|   const string default_directory = string(MCSDATADIR);
 | |
| 
 | |
|   enum class Mode
 | |
|   {
 | |
|     ENCRYPT,
 | |
|     DECRYPT
 | |
|   };
 | |
| 
 | |
|   auto mode = Mode::ENCRYPT;
 | |
|   bool interactive = false;
 | |
| 
 | |
|   int c;
 | |
|   while ((c = getopt_long(argc, argv, "hdi", options, NULL)) != -1)
 | |
|   {
 | |
|     switch (c)
 | |
|     {
 | |
|       case 'h': print_usage(argv[0], default_directory.c_str()); return EXIT_SUCCESS;
 | |
| 
 | |
|       case 'd': mode = Mode::DECRYPT; break;
 | |
| 
 | |
|       case 'i': interactive = true; break;
 | |
| 
 | |
|       default: print_usage(argv[0], default_directory.c_str()); return EXIT_FAILURE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   string input;
 | |
|   string path = default_directory;
 | |
| 
 | |
|   switch (argc - optind)
 | |
|   {
 | |
|     case 2:
 | |
|       // Two args provided.
 | |
|       path = argv[optind];
 | |
|       if (!interactive)
 | |
|       {
 | |
|         input = argv[optind + 1];
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         print_usage(argv[0], default_directory.c_str());
 | |
|         return EXIT_FAILURE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 1:
 | |
|       // One arg provided.
 | |
|       if (!interactive)
 | |
|       {
 | |
|         input = argv[optind];
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         path = argv[optind];
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case 0:
 | |
|       if (!interactive)
 | |
|       {
 | |
|         print_usage(argv[0], default_directory.c_str());
 | |
|         return EXIT_FAILURE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default: print_usage(argv[0], default_directory.c_str()); return EXIT_FAILURE;
 | |
|   }
 | |
| 
 | |
|   if (interactive)
 | |
|   {
 | |
|     if (!read_password(&input))
 | |
|     {
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   int rval = EXIT_FAILURE;
 | |
| 
 | |
|   string filepath = path;
 | |
|   filepath.append("/").append(SECRETS_FILENAME);
 | |
| 
 | |
|   auto keydata = secrets_readkeys(filepath);
 | |
|   if (keydata.ok)
 | |
|   {
 | |
|     bool encrypting = (mode == Mode::ENCRYPT);
 | |
|     bool new_mode = keydata.iv.empty();  // false -> constant IV from file
 | |
|     if (keydata.key.empty())
 | |
|     {
 | |
|       printf("Password encryption key file '%s' not found, cannot %s password.\n", filepath.c_str(),
 | |
|              encrypting ? "encrypt" : "decrypt");
 | |
|     }
 | |
|     else if (encrypting)
 | |
|     {
 | |
|       string encrypted = new_mode ? encrypt_password(keydata.key, input)
 | |
|                                   : encrypt_password_old(keydata.key, keydata.iv, input);
 | |
|       if (!encrypted.empty())
 | |
|       {
 | |
|         printf("%s\n", encrypted.c_str());
 | |
|         rval = EXIT_SUCCESS;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         printf("Password encryption failed.\n");
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       auto is_hex = std::all_of(input.begin(), input.end(), isxdigit);
 | |
|       if (is_hex && input.length() % 2 == 0)
 | |
|       {
 | |
|         string decrypted = new_mode ? decrypt_password(keydata.key, input)
 | |
|                                     : decrypt_password_old(keydata.key, keydata.iv, input);
 | |
|         if (!decrypted.empty())
 | |
|         {
 | |
|           printf("%s\n", decrypted.c_str());
 | |
|           rval = EXIT_SUCCESS;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           printf("Password decryption failed.\n");
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         printf("Input is not a valid hex-encoded encrypted password.\n");
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     printf("Could not read encryption key file '%s'.\n", filepath.c_str());
 | |
|   }
 | |
|   return rval;
 | |
| }
 |