Skip to content

Commit

Permalink
auth methode password
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Gatto <[email protected]>
  • Loading branch information
outscale-mgo committed Feb 6, 2023
1 parent 7821204 commit 6c620a7
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 60 deletions.
177 changes: 130 additions & 47 deletions lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,17 @@
#include <string.h>
#include <assert.h>
#include "curl/curl.h"
#include <time.h>
#include "osc_sdk.h"
#include "json.h"

#define AK_SIZE 20
#define SK_SIZE 40
#define TIMESTAMP_SIZE 17
#define TIME_HDR_KEY "X-Osc-Date: "
#define TIME_HDR_KEY_L (sizeof TIME_HDR_KEY)

#define CFG_FILE "/.osc/config.json"

#ifdef _WIN32

Expand Down Expand Up @@ -166,45 +172,76 @@ int osc_str_append_string(struct osc_str *osc_str, const char *str)
return 0;
}

#define LOAD_CFG_TRY(test, ...) \
if (test) fprintf(stderr, __VA_ARGS__); return -1;

#define LOAD_CFG_GET_HOME(buf) \
{ \
const char *dest = CFG_FILE; \
char *home = getenv("HOME"); \
\
LOAD_CFG_TRY(strlen(home) + sizeof CFG_FILE > sizeof buf, \
"home path too big"); \
strcpy(stpcpy(buf, home), dest); \
}


int osc_load_ak_sk_from_conf(const char *profile, char **ak, char **sk)
{
const char *dest = "/.osc/config.json";
char *home = getenv("HOME");
char buf[1024];
struct json_object *js;
struct json_object *js, *ak_js, *sk_js;

LOAD_CFG_GET_HOME(buf);
*sk = NULL;
*ak = NULL;
strcpy(stpcpy(buf, home), dest);
js = json_object_from_file(buf);
if (!js) {
fprintf(stderr, "can't open %s\n", buf);
return -1;
}
LOAD_CFG_TRY(!js, "can't open %s\n", buf);
js = json_object_object_get(js, profile);
if (!js) {
fprintf(stderr, "can't find profile '%s'\n", profile);
return -1;
}
LOAD_CFG_TRY(!js, "can't find profile %s\n", profile);
ak_js = json_object_object_get(js, "access_key");
LOAD_CFG_TRY(!ak_js, "can't find 'access_key' in profile '%s'\n", profile);
sk_js = json_object_object_get(js, "secret_key");
LOAD_CFG_TRY(!sk_js, "can't find 'secret_key' in profile '%s'\n", profile);

*ak = strdup(json_object_get_string(json_object_object_get(js, "access_key")));
*sk = strdup(json_object_get_string(json_object_object_get(js, "secret_key")));
return 0;
}

int osc_load_loging_password_from_conf(const char *profile,
char **email, char **password)
{
char buf[1024];
struct json_object *js, *login_js, *pass_js;

LOAD_CFG_GET_HOME(buf)
*password = NULL;
*email = NULL;
js = json_object_from_file(buf);
LOAD_CFG_TRY(!js, "can't open %s\n", buf);
js = json_object_object_get(js, profile);
LOAD_CFG_TRY(!js, "can't find profile '%s'\n", profile);
login_js = json_object_object_get(js, "login");
LOAD_CFG_TRY(!login_js, "can't find 'login' in profile '%s'\n", profile);
*email = strdup(json_object_get_string(login_js));

pass_js = json_object_object_get(js, "password");
if (!pass_js) {
return 0; /* is optional */
}
*password = strdup(json_object_get_string(pass_js));
return 0;
}

int osc_load_region_from_conf(const char *profile, char **region)
{
const char *dest = "/.osc/config.json";
char *home = getenv("HOME");
struct json_object *region_obj;
char buf[1024];
struct json_object *js;

strcpy(stpcpy(buf, home), dest);
LOAD_CFG_GET_HOME(buf)
js = json_object_from_file(buf);
if (!js) {
fprintf(stderr, "can't open %s\n", buf);
return -1;
}
LOAD_CFG_TRY(!js, "can't open %s\n", buf);
js = json_object_object_get(js, profile);
if (!js)
return -1;
Expand All @@ -219,18 +256,13 @@ int osc_load_region_from_conf(const char *profile, char **region)

int osc_load_cert_from_conf(const char *profile, char **cert, char **key)
{
const char *dest = "/.osc/config.json";
char *home = getenv("HOME");
struct json_object *cert_obj, *key_obj, *js;
char buf[1024];
int ret = 0;

strcpy(stpcpy(buf, home), dest);
LOAD_CFG_GET_HOME(buf)
js = json_object_from_file(buf);
if (!js) {
fprintf(stderr, "can't open %s\n", buf);
return -1;
}
LOAD_CFG_TRY(!js, "can't open %s\n", buf);
js = json_object_object_get(js, profile);
if (!js)
return 0;
Expand Down Expand Up @@ -290,34 +322,60 @@ int osc_sdk_set_useragent(struct osc_env *e, const char *str)

int osc_init_sdk(struct osc_env *e, const char *profile, unsigned int flag)
{
char ak_sk[AK_SIZE + SK_SIZE + 2];
char *ca = getenv("CURL_CA_BUNDLE");
char *endpoint;
char *env_ak = getenv("OSC_ACCESS_KEY");
char *env_sk = getenv("OSC_SECRET_KEY");
char user_agent[sizeof "osc-sdk-c/" + OSC_SDK_VERSON_L];
char *cert = getenv("OSC_X509_CLIENT_CERT");
char *sslkey = getenv("OSC_X509_CLIENT_KEY");
char *auth = getenv("OSC_AUTH_METHOD");

strcpy(stpcpy(user_agent, "osc-sdk-c/"), osc_sdk_version_str());
e->region = getenv("OSC_REGION");
e->flag = flag;
e->auth_method = flag & OSC_ENV_PASSWORD_AUTH ? OSC_PASSWORD_METHOD :
OSC_AKSK_METHOD;
endpoint = getenv("OSC_ENDPOINT_API");
osc_init_str(&e->endpoint);

if (auth && (!strcmp(auth, "password") || !strcmp(auth, "basic")))
e->auth_method = OSC_PASSWORD_METHOD;
else if (auth && strcmp(auth, "accesskey")) {
fprintf(stderr, "'%s' invalid authentication method\n", auth);
return -1;
}

if (!profile) {
profile = getenv("OSC_PROFILE");
e->ak = env_ak;
e->sk = env_sk;
if (e->auth_method == OSC_PASSWORD_METHOD) {
e->ak = getenv("OSC_LOGIN");
e->sk = getenv("OSC_PASSWORD");
} else {
e->ak = getenv("OSC_ACCESS_KEY");
e->sk = getenv("OSC_SECRET_KEY");
}
if (!profile && (!e->ak || !e->sk))
profile = "default";

}

if (profile) {
int f;

if (osc_load_ak_sk_from_conf(profile, &e->ak, &e->sk))
return -1;
e->flag |= OSC_ENV_FREE_AK_SK;
if (e->auth_method == OSC_PASSWORD_METHOD) {
if (osc_load_loging_password_from_conf(profile, &e->ak,
&e->sk) < 0)
return -1;
e->flag |= OSC_ENV_FREE_AK;
if (!e->sk)
e->sk = getenv("OSC_PASSWORD");
else
e->flag |= OSC_ENV_FREE_SK;
} else {
if (osc_load_ak_sk_from_conf(profile, &e->ak,
&e->sk) < 0)
return -1;
e->flag |= OSC_ENV_FREE_AK_SK;
}
if (!osc_load_region_from_conf(profile, &e->region))
e->flag |= OSC_ENV_FREE_REGION;
f = osc_load_cert_from_conf(profile, &e->cert, &e->sslkey);
Expand All @@ -337,20 +395,25 @@ int osc_init_sdk(struct osc_env *e, const char *profile, unsigned int flag)
osc_str_append_string(&e->endpoint, endpoint);
}

if (!e->ak || !e->sk) {
fprintf(stderr, "access key and secret key needed\n");
return -1;
}
if (e->auth_method == OSC_AKSK_METHOD) {
if (!e->ak || !e->sk) {
fprintf(stderr, "access key and secret key needed\n");
return -1;
}

if (strlen(e->ak) != AK_SIZE || strlen(e->sk) != SK_SIZE) {
fprintf(stderr, "Wrong access key or secret key size\n");
return -1;
if (strlen(e->ak) != AK_SIZE || strlen(e->sk) != SK_SIZE) {
fprintf(stderr, "Wrong access key or secret key size\n");
return -1;
}
} else if (e->auth_method == OSC_PASSWORD_METHOD) {
if (!e->ak || !e->sk) {
fprintf(stderr, "login and password needed\n");
return -1;
}
}

e->headers = NULL;
stpcpy(stpcpy(stpcpy(ak_sk, e->ak), ":"), e->sk);
e->c = curl_easy_init();
e->headers = curl_slist_append(e->headers, "Content-Type: application/json");

/* Setting HEADERS */
if (flag & OSC_VERBOSE_MODE)
Expand All @@ -361,17 +424,35 @@ int osc_init_sdk(struct osc_env *e, const char *profile, unsigned int flag)
curl_easy_setopt(e->c, CURLOPT_SSLCERT, cert);
if (sslkey)
curl_easy_setopt(e->c, CURLOPT_SSLKEY, sslkey);
curl_easy_setopt(e->c, CURLOPT_HTTPHEADER, e->headers);
curl_easy_setopt(e->c, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(e->c, CURLOPT_USERAGENT, user_agent);

/* setting CA is CURL_CA_BUNDLE is set */
if (ca)
curl_easy_setopt(e->c, CURLOPT_CAINFO, ca);

e->headers = curl_slist_append(e->headers, "Content-Type: application/json");

/* For authentification we specify the method and our acces key / secret key */
curl_easy_setopt(e->c, CURLOPT_AWS_SIGV4, "osc");
curl_easy_setopt(e->c, CURLOPT_USERPWD, ak_sk);
if (e->auth_method == OSC_AKSK_METHOD) {
curl_easy_setopt(e->c, CURLOPT_AWS_SIGV4, "osc");
} else if (e->auth_method == OSC_PASSWORD_METHOD) {
time_t clock;
struct tm tm;
char time_hdr[TIME_HDR_KEY_L + TIMESTAMP_SIZE] = TIME_HDR_KEY;

time(&clock);
if (!gmtime_r(&clock, &tm)) {
fprintf(stderr, "gmtime_r fail\n");
return -1;
}
strftime(time_hdr + TIME_HDR_KEY_L - 1,
TIMESTAMP_SIZE, "%Y%m%dT%H%M%SZ", &tm);
e->headers = curl_slist_append(e->headers, time_hdr);
}
curl_easy_setopt(e->c, CURLOPT_HTTPHEADER, e->headers);
curl_easy_setopt(e->c, CURLOPT_USERNAME, e->ak);
curl_easy_setopt(e->c, CURLOPT_PASSWORD, e->sk);

return 0;
}
Expand All @@ -381,9 +462,11 @@ void osc_deinit_sdk(struct osc_env *e)
curl_slist_free_all(e->headers);
curl_easy_cleanup(e->c);
osc_deinit_str(&e->endpoint);
if (e->flag & OSC_ENV_FREE_AK_SK) {
if (e->flag & OSC_ENV_FREE_AK) {
free(e->ak);
e->ak = NULL;
}
if (e->flag & OSC_ENV_FREE_SK) {
free(e->sk);
e->sk = NULL;
}
Expand Down
24 changes: 18 additions & 6 deletions lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,33 @@ struct osc_str {
char *buf;
};

#define OSC_ENV_FREE_AK_SK 1
#define OSC_ENV_FREE_REGION 2
#define OSC_VERBOSE_MODE 4
#define OSC_INSECURE_MODE 8
#define OSC_ENV_FREE_CERT 16
#define OSC_ENV_FREE_SSLKEY 32
#define OSC_ENV_FREE_AK 1 << 0
#define OSC_ENV_FREE_REGION 1 << 1
#define OSC_VERBOSE_MODE 1 << 2 /* curl verbose mode + print request content */
#define OSC_INSECURE_MODE 1 << 3 /* see --insecure option of curl */
#define OSC_ENV_FREE_CERT 1 << 4
#define OSC_ENV_FREE_SSLKEY 1 << 5
#define OSC_ENV_FREE_SK 1 << 6
#define OSC_ENV_PASSWORD_AUTH 1 << 7 /* force password/login usage */

#define OSC_ENV_FREE_AK_SK (OSC_ENV_FREE_AK | OSC_ENV_FREE_SK)

#define OSC_API_VERSION "____api_version____"
#define OSC_SDK_VERSION ____sdk_version____

enum osc_auth_method {
OSC_AKSK_METHOD,
OSC_PASSWORD_METHOD
};

struct osc_env {
char *ak;
char *sk;
char *region;
char *cert;
char *sslkey;
int flag;
enum osc_auth_method auth_method;
struct curl_slist *headers;
struct osc_str endpoint;
CURL *c;
Expand Down Expand Up @@ -104,6 +114,8 @@ ____args____

int osc_load_ak_sk_from_conf(const char *profile, char **ak, char **sk);
int osc_load_region_from_conf(const char *profile, char **region);
int osc_load_loging_password_from_conf(const char *profile,
char **email, char **password);

/**
* @brief parse osc config file, and store cred_path/key_path. key is optional.
Expand Down
20 changes: 13 additions & 7 deletions main_tpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ ____complex_struct_func_parser____

int main(int ac, char **av)
{
auto_osc_env struct osc_env e;
auto_osc_str struct osc_str r;
auto_osc_env struct osc_env e = {0};
auto_osc_str struct osc_str r = {0};
int color_flag = 0;
int i;
char *help_appent = getenv("COGNAC_HELP_APPEND");
Expand All @@ -91,13 +91,17 @@ int main(int ac, char **av)
program_name = av[0];
else
++program_name;


for (i = 1; i < ac; ++i) {
if (!strcmp("--verbose", av[i])) {
flag |= OSC_VERBOSE_MODE;
} else if (!strcmp("--insecure", av[i])) {
flag |= OSC_INSECURE_MODE;
} else if (!strcmp("--insecure", av[i])) {
flag |= OSC_INSECURE_MODE;
} else if (!strcmp("--raw-print", av[i])) {
flag |= OAPI_RAW_OUTPUT;
} else if (!strcmp("--auth-password", av[i])) {
flag |= OSC_ENV_PASSWORD_AUTH;
} else if (!argcmp2("--profile", av[i], '=')) {
if (av[i][sizeof("--profile") - 1] == '=') {
profile = &av[i][sizeof("--profile")];
Expand All @@ -123,6 +127,7 @@ int main(int ac, char **av)
"options:\n"
"\t--insecure \tdoesn't verify SSL certificats\n"
"\t--raw-print \tdoesn't format the output\n"
"\t--auth-password \tuse password/login instead of AK/SK\n"
"\t--verbose \tcurl backend is now verbose\n"
"\t--profile=PROFILE \tselect profile"
"\t--help [CallName]\tthis, can be used with call name, example:\n\t\t\t\t%s --help ReadVms\n"
Expand All @@ -133,7 +138,10 @@ int main(int ac, char **av)
}

for (i = 1; i < ac; ++i) {
if (!strcmp("--verbose", av[i]) || !strcmp("--insecure", av[i])) {
if (!strcmp("--verbose", av[i]) || \
!strcmp("--insecure", av[i]) || \
!strcmp("--auth-password", av[i]) || \
!strcmp("--raw-print", av[i])) {
/* Avoid Unknow Calls */
} else if (!argcmp2("--profile", av[i], '=')) {
if (!av[i][sizeof("--profile") - 1]) {
Expand All @@ -154,8 +162,6 @@ int main(int ac, char **av)
}
}
goto show_help;
} else if (!strcmp("--raw-print", av[i])) {
program_flag |= OAPI_RAW_OUTPUT;
} else if (!strcmp("--color", av[i])) {
color_flag |= JSON_C_TO_STRING_COLOR;
} else
Expand Down

0 comments on commit 6c620a7

Please sign in to comment.