Skip to content
Snippets Groups Projects
oidc.c 3.73 KiB
Newer Older
/*
 * Functionalities related to OpenId Connect based authentication
 */

#include "putty.h"
#include "oidc-agent/api.h"
#include <stdio.h>

#include <curl/curl.h>
#include "cJSON.h"


accesstoken_response *get_accesstoken(char *oidc_configuration) {
    accesstoken_response *pq = snew(accesstoken_response);
    pq->accesstoken = getAccessToken3(oidc_configuration, 60, NULL, "putty-ssh-client", NULL);
    return pq;
}

struct memory {
    char *response;
    size_t size;
};

static size_t cb(void *data, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    struct memory *mem = (struct memory *)userp;

    char *ptr = realloc(mem->response, mem->size + realsize + 1);
    if(ptr == NULL)
        return 0;

    mem->response = ptr;
    memcpy(&(mem->response[mem->size]), data, realsize);
    mem->size += realsize;
    mem->response[mem->size] = 0;

    return realsize;
}

struct memory chunk;


deployed_user *deploy_user(char *hostname, char *oidc_configuration, char *oidc_motley_cue_host, int oidc_motley_cue_port) {
    deployed_user *pq = snew(deployed_user);
    // Sanity check for oidc configuration
    if (oidc_configuration == NULL) {
        pq->deployed = false;
        return pq;
    }

    CURL *curl;
    CURLcode res;
    cJSON *ssh_user;
    
    curl = curl_easy_init();
    if(curl) {
        char endpoint[1028];
        if (oidc_motley_cue_host == NULL) {
            sprintf(endpoint, "%s/user/deploy", hostname);
        } else {
            sprintf(endpoint, "%s/user/deploy", oidc_motley_cue_host);
        }
        int port;
        if (oidc_motley_cue_port != 0) {
            port = oidc_motley_cue_port;
        } else {
            port = 8080;
        }
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL, endpoint);
        curl_easy_setopt(curl, CURLOPT_PORT, port);
        curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2);
        
        struct curl_slist *headers = NULL;
        char authorization[1028];
        accesstoken_response *conf = get_accesstoken(oidc_configuration);
        sprintf(authorization, "Authorization: Bearer %s", conf->accesstoken);
        sfree(conf);

        headers = curl_slist_append(headers, authorization);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

        res = curl_easy_perform(curl);
        sfree(authorization);
        sfree(headers);

        long response_code;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
        if((res != CURLE_OK) || (response_code != 200)) {
            pq->deployed = false;
            curl_easy_cleanup(curl); 
            return pq;
        } 
        curl_easy_cleanup(curl);      
    }  
    cJSON *json = cJSON_Parse(chunk.response);
    cJSON *state = cJSON_GetObjectItem(json, "state");
    if (strcmp(state->valuestring, "deployed") != 0) {
        pq->deployed = false;
        return pq;
    }
    cJSON *credentials = cJSON_GetObjectItem(json, "credentials");
    ssh_user = cJSON_GetObjectItem(credentials, "ssh_user");
    pq->username = strdup(ssh_user->valuestring);
    pq->deployed = true;
    return pq;
}

oidc_configurations *get_loaded_oidc_configurations() {
    char *configs_str = getLoadedAccountsList();
    if (configs_str != NULL) {
        cJSON *json = cJSON_Parse(configs_str);
        oidc_configurations *ocs = new_oidc_configurations();
        for (int i = 0; i < cJSON_GetArraySize(json); i++) {
            add_oidc_configuration(ocs, cJSON_GetArrayItem(json, i)->valuestring, i);
        }
        sfree(configs_str);
        return ocs;
    } else {
        return NULL;
    }
}