123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdbool.h>
- #include <curl/curl.h>
- #include "utils.h"
- #include "keystone.h"
- #include "cJSON.h"
- #include "curl.h"
- const char *token_header = "X-Subject-Token:";
- struct cache token_cache = { { 0 }, NULL };
- size_t grep_token(void *ptr, size_t size, size_t nmemb, void *s_) {
- if(strncasecmp(ptr, token_header, strlen(token_header)) != 0) {
- return size*nmemb;
- }
- struct string *s = s_;
- size_t new_len = s->len + size*nmemb;
- s->ptr = realloc(s->ptr, new_len+1);
- if (s->ptr == NULL) {
- fprintf(stderr, "realloc() failed\n");
- exit(EXIT_FAILURE);
- }
- memcpy(s->ptr+s->len, ptr, size*nmemb);
- s->ptr[new_len] = '\0';
- s->len = new_len;
- return size*nmemb;
- return 0;
- }
- /*
- A typical keystone token request looks like this:
- {"auth": {
- "identity": {
- "methods": [
- "password"
- ],
- "password": {
- "user": {
- "domain": {
- "name": "'$OS_USER_DOMAIN_NAME'"
- },
- "name": "'$OS_USERNAME'",
- "password": "'$OS_PASSWORD'"
- }
- }
- },
- "scope": {
- "project": {
- "domain": {
- "name": "'$OS_PROJECT_DOMAIN_NAME'"
- },
- "name": "'$OS_PROJECT_NAME'",
- "id": "'$OS_PROJECT_ID'"
- }
- }
- }}
- */
- char* token_request() {
- cJSON* tok_request_obj = cJSON_CreateObject();
- cJSON* auth_obj = cJSON_CreateObject();
- cJSON_AddItemToObject(tok_request_obj, "auth", auth_obj);
- cJSON* identity_obj = cJSON_CreateObject();
- cJSON_AddItemToObject(auth_obj, "identity", identity_obj);
- cJSON* methods_arr = cJSON_AddArrayToObject(identity_obj, "methods");
- cJSON* password_method_string = cJSON_CreateString("password");
- cJSON_AddItemToArray(methods_arr, password_method_string);
- cJSON* password_obj = cJSON_CreateObject();
- cJSON_AddItemToObject(identity_obj, "password", password_obj);
- cJSON* user_obj = cJSON_CreateObject();
- cJSON_AddItemToObject(password_obj, "user", user_obj);
- cJSON* identity_domain_obj = cJSON_CreateObject();
- if(cJSON_AddStringToObject(identity_domain_obj, "name", env[OS_USER_DOMAIN_NAME].val) == NULL) {
- WHEREAMI();
- goto tidy_token_request;
- }
- cJSON_AddItemToObject(user_obj, "domain", identity_domain_obj);
- if(cJSON_AddStringToObject(user_obj, "name", env[OS_USERNAME].val) == NULL) {
- WHEREAMI();
- goto tidy_token_request;
- }
- if(cJSON_AddStringToObject(user_obj, "password", env[OS_PASSWORD].val) == NULL) {
- WHEREAMI();
- goto tidy_token_request;
- }
- cJSON* scope_obj = cJSON_CreateObject();
- cJSON_AddItemToObject(auth_obj, "scope", scope_obj);
- cJSON* proj_obj = cJSON_CreateObject();
- cJSON_AddItemToObject(scope_obj, "project", proj_obj);
- cJSON* scope_domain_obj = cJSON_CreateObject();
- if(cJSON_AddStringToObject(scope_domain_obj, "name", env[OS_PROJECT_DOMAIN_NAME].val) == NULL) {
- WHEREAMI();
- goto tidy_token_request;
- }
- cJSON_AddItemToObject(proj_obj, "domain", scope_domain_obj);
- cJSON_AddStringToObject(proj_obj, "name", env[OS_PROJECT_NAME].val);
- cJSON_AddStringToObject(proj_obj, "id", env[OS_PROJECT_ID].val);
- char *tok_request_string = cJSON_PrintUnformatted(tok_request_obj);
- tidy_token_request:
- cJSON_Delete(tok_request_obj);
- return tok_request_string;
- }
- void get_token() {
- if(token_cache.data[0] != '\0') {
- // Clear existing data
- memset(token_cache.data, 0, sizeof(token_cache));
- }
- char* token_request_data = token_request();
- if(token_request_data == NULL) {
- WHEREAMI();
- fprintf(stderr, "Error retrieving token\n");
- }
- CURLcode err = curl_global_init(CURL_GLOBAL_NOTHING);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Something went wrong initialising libcurl (error %u)\n", err);
- exit(err);
- }
- char *tok_path = "auth/tokens?nocatalog";
- char tok_url[MAX_BUF_SZ] = { 0 };
- api_url_build(tok_url, env[OS_AUTH_URL].val, tok_path);
- CURL* handle = curl_easy_init();
- if(handle == NULL) {
- WHEREAMI();
- fprintf(stderr, "Something went wrong initialising curl session.\n");
- err = 1;
- goto easy_cleanup;
- }
- char errbuf[CURL_ERROR_SIZE] = { 0 };
- err = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errbuf);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Something went wrong preparing error buffer (error %u)\n", err);
- fprintf(stderr, "Current contents of buffer:\n%s\n", errbuf);
- goto easy_cleanup;
- }
- err = curl_easy_setopt(handle, CURLOPT_URL, tok_url);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Error %u: %s\n", err, errbuf);
- goto easy_cleanup;
- }
- struct curl_slist *H = NULL;
- H = curl_slist_append(H, "Content-Type: application/json");
- if(H == NULL) {
- WHEREAMI();
- fprintf(stderr, "Something went wrong setting token request header\n");
- goto easy_cleanup;
- }
- err = curl_easy_setopt(handle, CURLOPT_HTTPHEADER, H);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Error %u: %s\n", err, errbuf);
- goto easy_cleanup;
- }
- err = curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, grep_token);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Error %u: %s\n", err, errbuf);
- goto easy_cleanup;
- }
- struct string h;
- init_string(&h);
- err = curl_easy_setopt(handle, CURLOPT_HEADERDATA, &h);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Error %u: %s\n", err, errbuf);
- goto easy_cleanup;
- }
- err = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, string_stuffer);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Error %u: %s\n", err, errbuf);
- goto easy_cleanup;
- }
- struct string s;
- init_string(&s);
- err = curl_easy_setopt(handle, CURLOPT_WRITEDATA, &s);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Error %u: %s\n", err, errbuf);
- goto easy_cleanup;
- }
- err = curl_easy_setopt(handle, CURLOPT_POSTFIELDS, token_request_data);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Something went wrong setting token request data\n");
- goto easy_cleanup;
- }
- err = curl_easy_perform(handle);
- if(err) {
- WHEREAMI();
- fprintf(stderr, "Error %u: %s\n", err, errbuf);
- goto easy_cleanup;
- }
- cJSON *resp = cJSON_Parse(s.ptr);
- cJSON *_token = cJSON_GetObjectItem(resp, "token");
- cJSON *_expiry = cJSON_GetObjectItem(_token, "expires_at");
- token_cache.expires = cJSON_GetStringValue(_expiry);
- h.ptr[h.len - 1] = '\0'; // Remove trailing '\n'
- h.ptr[h.len - 2] = '\0'; // Remove trailing '\r'
- strncpy(token_cache.data, h.ptr + strlen(token_header) + 1, 256);
- if(h.ptr != NULL) {
- free(h.ptr);
- }
- easy_cleanup:
- if(H != NULL) {
- curl_slist_free_all(H);
- }
- if(handle != NULL) {
- curl_easy_cleanup(handle);
- }
- if(s.ptr != NULL) {
- free(s.ptr);
- }
- curl_global_cleanup();
- }
- static int create(int argc, char **argv) {
- get_token();
- printf("%s\n", token_cache.data);
- return 0;
- }
- static struct command subcommands[] = {
- CMD_DEF(create),
- { NULL, NULL }
- };
- int token(int argc, char **argv) {
- common_main(argc, argv, subcommands);
- return 0;
- }
|