MaxScale/server/core/maxpasswd.c
Markus Mäkelä 46d1187172
Backport GCC 8 fixes to 2.1
Backported the minimal set of changes required to build 2.1 with GCC
8. The format-truncation and format-overflow warnings are disabled instead
of fixed in 2.1 to remove duplication of effort that was already done in
2.2 (the commit doesn't cherry-pick cleanly).
2018-05-16 11:09:47 +03:00

200 lines
4.6 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: 2020-01-01
*
* 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 maxpasswd.c - Implementation of pasword encoding
*
* @verbatim
* Revision History
*
* Date Who Description
* 24/07/13 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#include <maxscale/cdefs.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <getopt.h>
#include <maxscale/paths.h>
#include <maxscale/log_manager.h>
#include <maxscale/random_jkiss.h>
#include <maxscale/alloc.h>
#include "internal/secrets.h"
#ifdef HAVE_GLIBC
struct option options[] =
{
{
"help",
no_argument,
NULL,
'h'
},
{ NULL, 0, NULL, 0 }
};
#endif
void print_usage(const char* executable, const char* directory)
{
printf("usage: %s [-h|--help] [path] password\n"
"\n"
"This utility creates an encrypted password using a .secrets file\n"
"that has earlier been created using maxkeys.\n"
"\n"
"-h, --help: Display this help.\n"
"\n"
"path : The directory where the .secrets file is located, or the path\n"
" of the .secrets file itself. Note that the name of the file\n"
" must be .secrets.\n"
"\n"
"If a path is not provided, the .secrets file is looked for in the\n"
"directory %s.\n",
executable, directory);
}
bool path_is_ok(const char* path)
{
// TODO: The check here is superfluous, in the sense that encryptPassword
// TODO: checks the same. However, so as not to get annoying notice output
// TODO: on success, notices are turned off and the absence of the file is
// TODO: reported as a notice. Thus, without this check maxpasswd would
// TODO: simply fail, without telling the cause.
bool rv = false;
struct stat st;
if (stat(path, &st) == 0)
{
if (S_ISDIR(st.st_mode))
{
const char TAIL[] = "/.secrets";
char file[strlen(path) + sizeof(TAIL)];
strcpy(file, path);
strcat(file, TAIL);
rv = path_is_ok(file);
}
else
{
// encryptPassword reports of any errors.
rv = true;
}
}
else
{
fprintf(stderr, "error: Could not access %s: %s.\n", path, strerror(errno));
}
return rv;
}
int main(int argc, char **argv)
{
const char* path = get_datadir();
int c;
#ifdef HAVE_GLIBC
while ((c = getopt_long(argc, argv, "h", options, NULL)) != -1)
#else
while ((c = getopt(argc, argv, "h")) != -1)
#endif
{
switch (c)
{
case 'h':
print_usage(argv[0], path);
exit(EXIT_SUCCESS);
break;
default:
print_usage(argv[0], path);
exit(EXIT_FAILURE);
break;
}
}
char* password;
switch (argc - optind)
{
case 2:
// Two args provided.
path = argv[optind];
if (!path_is_ok(path))
{
exit(EXIT_FAILURE);
}
password = argv[optind + 1];
break;
case 1:
// One arg provided.
password = argv[optind];
break;
default:
print_usage(argv[0], path);
exit(EXIT_FAILURE);
break;
}
// We'll ignore errors and steam ahead.
(void)mxs_log_init(NULL, NULL, MXS_LOG_TARGET_DEFAULT);
mxs_log_set_priority_enabled(LOG_NOTICE, false);
mxs_log_set_priority_enabled(LOG_INFO, false);
mxs_log_set_priority_enabled(LOG_DEBUG, false);
random_jkiss_init();
size_t len = strlen(password);
if (len > MXS_PASSWORD_MAXLEN)
{
fprintf(stderr,
"warning: The provided password is %lu characters long. "
"Only the first %d will be used.\n", len, MXS_PASSWORD_MAXLEN);
}
char used_password[MXS_PASSWORD_MAXLEN + 1];
strncpy(used_password, password, MXS_PASSWORD_MAXLEN);
used_password[MXS_PASSWORD_MAXLEN] = 0;
int rval = EXIT_SUCCESS;
char* enc = encrypt_password(path, used_password);
if (enc)
{
printf("%s\n", enc);
MXS_FREE(enc);
}
else
{
fprintf(stderr, "error: Failed to encode the password.\n");
rval = EXIT_FAILURE;
}
mxs_log_flush_sync();
mxs_log_finish();
return rval;
}