You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +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;
 | 
						|
}
 |