lifeng 9453c52364 iSulad: update Mulan v1 to Mulan v2
Signed-off-by: lifeng <lifeng68@huawei.com>
2020-04-27 09:43:55 +08:00

228 lines
6.5 KiB
C

/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
* iSulad licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: wangfengtu
* Create: 2019-6-18
* Description: provide login
********************************************************************************/
#include "login.h"
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include "utils.h"
#include "arguments.h"
#include "isula_connect.h"
#include "log.h"
const char g_cmd_login_desc[] = "Log in to a Docker registry";
const char g_cmd_login_usage[] = "login [OPTIONS] SERVER";
struct client_arguments g_cmd_login_args = {};
/*
* Login to a docker registry.
*/
int client_login(const struct client_arguments *args)
{
isula_connect_ops *ops = NULL;
struct isula_login_request request = { 0 };
struct isula_login_response *response = NULL;
client_connect_config_t config = { 0 };
int ret = 0;
response = util_common_calloc_s(sizeof(struct isula_login_response));
if (response == NULL) {
ERROR("Out of memory");
return ECOMMON;
}
// Support type oci only currently.
request.type = "oci";
request.server = args->server;
request.username = args->username;
request.password = args->password;
ops = get_connect_client_ops();
if (ops == NULL || ops->image.login == NULL) {
ERROR("Unimplemented ops");
ret = ECOMMON;
goto out;
}
config = get_connect_config(args);
ret = ops->image.login(&request, response, &config);
if (ret != 0) {
client_print_error(response->cc, response->server_errono, response->errmsg);
ret = ESERVERERROR;
goto out;
}
COMMAND_ERROR("Login Succeeded");
out:
isula_login_response_free(response);
return ret;
}
static int get_password_from_notty(struct client_arguments *args)
{
if (g_cmd_login_args.username == NULL && g_cmd_login_args.password_stdin) {
COMMAND_ERROR("Must provide --username with --password-stdin");
return -1;
}
if (g_cmd_login_args.password != NULL) {
printf("WARNING! Using --password via the CLI is insecure. Use --password-stdin.\n");
if (g_cmd_login_args.password_stdin) {
printf("--password and --password-stdin are mutually exclusive\n");
return -1;
}
}
// Try get password from notty input.
if (g_cmd_login_args.password_stdin) {
char password[LOGIN_PASSWORD_LEN + 1] = { 0 };
int n = util_input_readall(password, sizeof(password));
if (n == 0) {
COMMAND_ERROR("Error: Password Required");
return -1;
}
if (n < 0) {
COMMAND_ERROR("Get password from notty stdin failed: %s", strerror(errno));
return -1;
}
args->password = util_strdup_s(password);
(void)memset(password, 0, sizeof(password));
}
return 0;
}
static int get_auth_from_terminal(struct client_arguments *args)
{
int n;
if (args->username == NULL) {
char username[LOGIN_USERNAME_LEN + 1] = {0};
printf("Username: ");
n = util_input_echo(username, sizeof(username));
if (n == 0) {
ERROR("Error: Non-null Username Required\n");
return -1;
}
if (n < 0) {
if (errno == ENOTTY) {
COMMAND_ERROR("Error: Cannot perform an interactive login from a non TTY device");
return -1;
}
COMMAND_ERROR("Get username failed: %s", strerror(errno));
return -1;
}
args->username = util_strdup_s(username);
}
if (args->password == NULL) {
char password[LOGIN_PASSWORD_LEN + 1] = {0};
printf("Password: ");
n = util_input_noecho(password, sizeof(password));
if (n == 0) {
ERROR("Error: Password Required\n");
return -1;
}
if (n < 0) {
if (errno == ENOTTY) {
COMMAND_ERROR("Error: Cannot perform an interactive login from a non TTY device");
return -1;
}
COMMAND_ERROR("Get password failed: %s", strerror(errno));
return -1;
}
args->password = util_strdup_s(password);
(void)memset(password, 0, sizeof(password));
}
return 0;
}
static int get_auth(struct client_arguments *args)
{
// Try get password from notty input.
if (get_password_from_notty(&g_cmd_login_args)) {
return -1;
}
// Try get username and password from terminal.
if (get_auth_from_terminal(&g_cmd_login_args)) {
return -1;
}
if (args->username == NULL || args->password == NULL) {
// This should not happen.
COMMAND_ERROR("Missing username or password");
return -1;
}
return 0;
}
int cmd_login_main(int argc, const char **argv)
{
int ret = 0;
struct log_config lconf = { 0 };
int exit_code = 1; /* exit 1 if failed to login */
command_t cmd;
struct command_option options[] = {
COMMON_OPTIONS(g_cmd_login_args),
LOGIN_OPTIONS(g_cmd_login_args)
};
set_default_command_log_config(argv[0], &lconf);
if (client_arguments_init(&g_cmd_login_args)) {
COMMAND_ERROR("client arguments init failed");
exit(ECOMMON);
}
g_cmd_login_args.progname = argv[0];
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv, g_cmd_login_desc,
g_cmd_login_usage);
if (command_parse_args(&cmd, &g_cmd_login_args.argc, &g_cmd_login_args.argv)) {
exit(exit_code);
}
if (log_init(&lconf)) {
COMMAND_ERROR("login: log init failed");
exit(exit_code);
}
if (g_cmd_login_args.argc != 1) {
COMMAND_ERROR("login requires 1 argument.");
exit(exit_code);
}
g_cmd_login_args.server = g_cmd_login_args.argv[0];
ret = get_auth(&g_cmd_login_args);
if (ret != 0) {
exit(exit_code);
}
ret = client_login(&g_cmd_login_args);
if (ret != 0) {
exit(exit_code);
}
exit(EXIT_SUCCESS);
}