diff --git a/src/file_io.h b/src/file_io.h index a8c6e033..ae31a8f0 100644 --- a/src/file_io.h +++ b/src/file_io.h @@ -5,6 +5,7 @@ char* getOidcDir() ; oidc_error_t writeOidcFile(const char* filename, const char* text) ; +oidc_error_t writeFile(const char* filepath, const char* text) ; char* readOidcFile(const char* filename) ; char* readFile(const char* path); int fileDoesExist(const char* path); diff --git a/src/http.c b/src/http.c index ea7e26ac..b694c355 100644 --- a/src/http.c +++ b/src/http.c @@ -44,7 +44,13 @@ static size_t write_callback(void *ptr, size_t size, size_t nmemb, struct string oidc_error_t CURLErrorHandling(int res, CURL* curl) { switch(res) { case CURLE_OK: - return 0; + { + long http_code = 0; + curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code); + syslog(LOG_AUTHPRIV|LOG_DEBUG, "Received status code %ld", http_code); + oidc_errno = OIDC_SUCCESS; + return OIDC_SUCCESS; + } case CURLE_URL_MALFORMAT: case CURLE_COULDNT_RESOLVE_HOST: syslog(LOG_AUTHPRIV|LOG_ALERT, "%s (%s:%d) HTTPS Request failed: %s Please check the provided URLs.\n", __func__, __FILE__, __LINE__, curl_easy_strerror(res)); @@ -65,6 +71,7 @@ oidc_error_t CURLErrorHandling(int res, CURL* curl) { default: syslog(LOG_AUTHPRIV|LOG_ALERT, "%s (%s:%d) curl_easy_perform() failed: %s\n", __func__, __FILE__, __LINE__, curl_easy_strerror(res)); curl_easy_cleanup(curl); + oidc_errno = OIDC_EERROR; return OIDC_EERROR; } } @@ -139,6 +146,29 @@ void setPostData(CURL* curl, const char* data) { curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data_len); } +/** @fn void setUrlEncodedData(CURL* curl, const char* data) + * @brief sets the data to be posted + * @param curl the curl instance + * @param data the data to be posted + */ +void setUrlEncodedData(CURL* curl, const char* data) { + long data_len = (long)strlen(data); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data_len); +} + +void setHeaders(CURL* curl, struct curl_slist* headers) { + if(headers) { + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + } +} + +void setBasicAuth(CURL* curl, const char* username, const char* password) { + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(curl, CURLOPT_USERNAME, username); + curl_easy_setopt(curl, CURLOPT_PASSWORD, password); +} + /** @fn int perform(CURL* curl) * @brief performs the https request and checks for errors * @param curl the curl instance @@ -165,7 +195,7 @@ void cleanup(CURL* curl) { * @return a pointer to the response. Has to be freed after usage. If the Https * call failed, NULL is returned. */ -char* httpsGET(const char* url, const char* cert_path) { +char* httpsGET(const char* url, struct curl_slist* headers, const char* cert_path) { syslog(LOG_AUTHPRIV|LOG_DEBUG, "Https GET to: %s",url); CURL* curl = init(); setUrl(curl, url); @@ -174,6 +204,7 @@ char* httpsGET(const char* url, const char* cert_path) { return NULL; } setSSLOpts(curl, cert_path); + setHeaders(curl, headers); if(perform(curl)!=OIDC_SUCCESS) { return NULL; } @@ -191,7 +222,7 @@ char* httpsGET(const char* url, const char* cert_path) { * @return a pointer to the response. Has to be freed after usage. If the Https * call failed, NULL is returned. */ -char* httpsPOST(const char* url, const char* data, const char* cert_path) { +char* httpsPOST(const char* url, const char* data, struct curl_slist* headers, const char* cert_path, const char* username, const char* password) { syslog(LOG_AUTHPRIV|LOG_DEBUG, "Https POST to: %s",url); CURL* curl = init(); setUrl(curl, url); @@ -202,6 +233,10 @@ char* httpsPOST(const char* url, const char* data, const char* cert_path) { } setPostData(curl, data); setSSLOpts(curl, cert_path); + setHeaders(curl, headers); + if(username && password) { + setBasicAuth(curl, username, password); + } if(perform(curl)!=OIDC_SUCCESS) { return NULL; } diff --git a/src/http.h b/src/http.h index f55a3a1a..0b09da82 100644 --- a/src/http.h +++ b/src/http.h @@ -1,7 +1,9 @@ #ifndef HTTP_H #define HTTP_H -char* httpsGET(const char* url, const char* cert_path) ; -char* httpsPOST(const char* url, const char data[], const char* cert_path) ; +#include + +char* httpsGET(const char* url, struct curl_slist *list, const char* cert_path) ; +char* httpsPOST(const char* url, const char* data, struct curl_slist* headers, const char* cert_path, const char* username, const char* password) ; #endif diff --git a/src/ipc.h b/src/ipc.h index 97926b58..7cbc0afa 100644 --- a/src/ipc.h +++ b/src/ipc.h @@ -10,11 +10,14 @@ #include "oidc_array.h" +#define RESPONSE_SUCCESS_CLIENT "{\"status\":\"success\", \"client\":%s}" +#define RESPONSE_ERROR_CLIENT_INFO "{\"status\":\"failed\", \"error\":\"%s\", \"client\":%s, \"info\":\"%s\"}" #define RESPONSE_STATUS_SUCCESS "{\"status\":\"success\"}" -#define RESPONSE_STATUS_ENDPOINT "{\"status\":\"%s\", \"token_endpoint\":\"%s\"}" -#define RESPONSE_STATUS_ENDPOINT_REFRESH "{\"status\":\"%s\", \"token_endpoint\":\"%s\", \"refresh_token\":\"%s\"}" +#define RESPONSE_STATUS_ENDPOINT "{\"status\":\"%s\", \"token_endpoint\":\"%s\", \"authorization_endpoint\":\"%s\", \"registration_endpoint\":\"%s\", \"revocation_endpoint\":\"%s\"}" +#define RESPONSE_STATUS_ENDPOINT_REFRESH "{\"status\":\"%s\", \"token_endpoint\":\"%s\", \"authorization_endpoint\":\"%s\", \"registration_endpoint\":\"%s\", \"revocation_endpoint\":\"%s\", \"refresh_token\":\"%s\"}" #define RESPONSE_STATUS_ACCESS "{\"status\":\"%s\", \"access_token\":\"%s\"}" #define RESPONSE_STATUS_PROVIDER "{\"status\":\"%s\", \"provider_list\":\"%s\"}" +#define RESPONSE_STATUS_REGISTER "{\"status\":\"%s\", \"response\":%s}" #define RESPONSE_ERROR "{\"status\":\"failure\", \"error\":\"%s\"}" #define REQUEST "{\"request\":\"%s\", %s}" diff --git a/src/json.c b/src/json.c index d07d1e60..9b1503ee 100644 --- a/src/json.c +++ b/src/json.c @@ -5,6 +5,7 @@ #include "json.h" #include "oidc_error.h" +#include "oidc_utilities.h" /** @fn char* getJSONValue(const char* json, const char* key) @@ -122,3 +123,54 @@ oidc_error_t checkParseResult(int r, jsmntok_t t) { } +char* json_addValue(char* json, const char* key, const char* value) { + if(json==NULL || key==NULL || value==NULL) { + oidc_errno = OIDC_EARGNULL; + return json; + } + const char* const fmt = "%s, \"%s\":%s}"; + int len = strlen(json); + if(json[len-1]!='}') { + oidc_errno = OIDC_EJSONADD; + return json; + } + json[len-1] = '\0'; + char* tmp = calloc(sizeof(char), snprintf(NULL, 0, fmt, json, key, value)+1); + if(tmp==NULL) { + oidc_errno = OIDC_EALLOC; + return json; + } + sprintf(tmp, fmt, json, key, value); + if(tmp[1]==',') { + tmp[1]=' '; + } + clearFreeString(json); + oidc_errno = OIDC_SUCCESS; + return tmp; +} + +char* json_addStringValue(char* json, const char* key, char* value) { + if(json==NULL || key==NULL || value==NULL) { + oidc_errno = OIDC_EARGNULL; + return json; + } + char* tmp = calloc(sizeof(char), strlen(value)+2+1); + if(tmp==NULL) { + oidc_errno = OIDC_EALLOC; + return json; + } + sprintf(tmp, "\"%s\"", value); + char* res = json_addValue(json, key, tmp); + clearFreeString(tmp); + return res; +} + +int json_hasKey(char* json, const char* key) { + char* value = getJSONValue(json, key); + if(value) { + clearFreeString(value); + return 1; + } else { + return 0; + } +} diff --git a/src/json.h b/src/json.h index 580655d8..8055c9d0 100644 --- a/src/json.h +++ b/src/json.h @@ -14,5 +14,8 @@ int getJSONValues(const char* json, struct key_value* pairs, size_t size) ; char* getValuefromTokens(jsmntok_t t[], int r, const char* key, const char* json) ; int jsoneq(const char *json, jsmntok_t *tok, const char *s) ; int checkParseResult(int r, jsmntok_t t) ; +char* json_addValue(char* json, const char* key, const char* value) ; +char* json_addStringValue(char* json, const char* key, char* value) ; +int json_hasKey(char* json, const char* key) ; #endif // OIDC_JSON_H diff --git a/src/oidc-add.c b/src/oidc-add.c index 0b73ea15..042d5600 100644 --- a/src/oidc-add.c +++ b/src/oidc-add.c @@ -9,12 +9,13 @@ #include "prompt.h" #include "ipc.h" #include "oidc_utilities.h" +#include "version.h" #define OIDC_SOCK_ENV_NAME "OIDC_SOCK" -const char *argp_program_version = "oidc-add 0.2.0"; +const char *argp_program_version = ADD_VERSION; -const char *argp_program_bug_address = ""; +const char *argp_program_bug_address = BUG_ADDRESS; /* This structure is used by main to communicate with parse_opt. */ struct arguments { diff --git a/src/oidc-agent.c b/src/oidc-agent.c index 62fd95ad..e683e22b 100644 --- a/src/oidc-agent.c +++ b/src/oidc-agent.c @@ -17,12 +17,12 @@ #include "ipc.h" #include "provider.h" #include "oidc_utilities.h" -#include "http.h" #include "oidc_error.h" +#include "version.h" -const char *argp_program_version = "oidc-agent 0.3.0"; +const char *argp_program_version = AGENT_VERSION; -const char *argp_program_bug_address = ""; +const char *argp_program_bug_address = BUG_ADDRESS; /* This structure is used by main to communicate with parse_opt. */ struct arguments { @@ -130,7 +130,7 @@ void handleGen(int sock, struct oidc_provider** loaded_p, size_t* loaded_p_count ipc_write(sock, RESPONSE_ERROR, oidc_perror()); return; } - provider_setTokenEndpoint(provider, getTokenEndpoint(provider_getConfigEndpoint(*provider), provider_getCertPath(*provider))); + getEndpoints(provider); if(!isValid(provider_getTokenEndpoint(*provider))) { ipc_write(sock, RESPONSE_ERROR, oidc_perror()); return; @@ -141,10 +141,9 @@ void handleGen(int sock, struct oidc_provider** loaded_p, size_t* loaded_p_count return; } if(isValid(provider_getRefreshToken(*provider))) { - ipc_write(sock, RESPONSE_STATUS_ENDPOINT_REFRESH, "success", provider_getTokenEndpoint(*provider), provider_getRefreshToken(*provider)); + ipc_write(sock, RESPONSE_STATUS_ENDPOINT_REFRESH, "success", provider_getTokenEndpoint(*provider), provider_getAuthorizationEndpoint(*provider), provider_getRegistrationEndpoint(*provider), provider_getRevocationEndpoint(*provider), provider_getRefreshToken(*provider)); } else { - ipc_write(sock, RESPONSE_STATUS_ENDPOINT, "success", provider_getTokenEndpoint(*provider)); - } + ipc_write(sock, RESPONSE_STATUS_ENDPOINT, "success", provider_getTokenEndpoint(*provider), provider_getAuthorizationEndpoint(*provider), provider_getRegistrationEndpoint(*provider), provider_getRevocationEndpoint(*provider)); } provider_setUsername(provider, NULL); provider_setPassword(provider, NULL); *loaded_p = removeProvider(*loaded_p, loaded_p_count, *provider); @@ -165,16 +164,21 @@ void handleAdd(int sock, struct oidc_provider** loaded_p, size_t* loaded_p_count return; } if(retrieveAccessTokenRefreshFlowOnly(provider, FORCE_NEW_TOKEN)!=OIDC_SUCCESS) { - char* newTokenEndpoint = getTokenEndpoint(provider_getConfigEndpoint(*provider), provider_getCertPath(*provider)); - if(newTokenEndpoint && strcmp(newTokenEndpoint, provider_getTokenEndpoint(*provider))!=0) { - provider_setTokenEndpoint(provider, newTokenEndpoint); - if(retrieveAccessToken(provider, FORCE_NEW_TOKEN)!=OIDC_SUCCESS) { + char* oldTokenEndpoint = calloc(sizeof(char), strlen(provider_getTokenEndpoint(*provider))+1); + strcpy(oldTokenEndpoint, provider_getTokenEndpoint(*provider)); + oidc_error_t error = oidc_errno; + getEndpoints(provider); + if(oldTokenEndpoint && provider_getTokenEndpoint(*provider) && strcmp(oldTokenEndpoint, provider_getTokenEndpoint(*provider))!=0) { + clearFreeString(oldTokenEndpoint); + if(retrieveAccessTokenRefreshFlowOnly(provider, FORCE_NEW_TOKEN)!=OIDC_SUCCESS) { freeProvider(provider); ipc_write(sock, RESPONSE_ERROR, oidc_perror()); return; } } else { + clearFreeString(oldTokenEndpoint); freeProvider(provider); + oidc_errno = error; ipc_write(sock, RESPONSE_ERROR, oidc_perror()); return; } @@ -184,7 +188,7 @@ void handleAdd(int sock, struct oidc_provider** loaded_p, size_t* loaded_p_count ipc_write(sock, RESPONSE_STATUS_SUCCESS); } -void handleRm(int sock, struct oidc_provider** loaded_p, size_t* loaded_p_count, char* provider_json) { +void handleRm(int sock, struct oidc_provider** loaded_p, size_t* loaded_p_count, char* provider_json, int revoke) { syslog(LOG_AUTHPRIV|LOG_DEBUG, "Handle Remove request"); struct oidc_provider* provider = getProviderFromJSON(provider_json); if(provider==NULL) { @@ -193,13 +197,17 @@ void handleRm(int sock, struct oidc_provider** loaded_p, size_t* loaded_p_count, } if(NULL==findProvider(*loaded_p, *loaded_p_count, *provider)) { freeProvider(provider); - ipc_write(sock, RESPONSE_ERROR, "provider not loaded"); + ipc_write(sock, RESPONSE_ERROR, revoke ? "Could not revoke token: provider not loaded" : "provider not loaded"); + return; + } + if(revoke && revokeToken(provider)!=OIDC_SUCCESS) { + freeProvider(provider); + ipc_write(sock, RESPONSE_ERROR, "Could not revoke token: %s", oidc_perror()); return; } *loaded_p = removeProvider(*loaded_p, loaded_p_count, *provider); freeProvider(provider); ipc_write(sock, RESPONSE_STATUS_SUCCESS); - } void handleToken(int sock, struct oidc_provider* loaded_p, size_t loaded_p_count, char* short_name, char* min_valid_period_str) { @@ -229,6 +237,52 @@ void handleList(int sock, struct oidc_provider* loaded_p, size_t loaded_p_count) clearFreeString(providerList); } +void handleRegister(int sock, struct oidc_provider* loaded_p, size_t loaded_p_count, char* provider_json) { + syslog(LOG_AUTHPRIV|LOG_DEBUG, "Handle Register request"); + struct oidc_provider* provider = getProviderFromJSON(provider_json); + if(provider==NULL) { + ipc_write(sock, RESPONSE_ERROR, oidc_perror()); + return; + } + if(NULL!=findProvider(loaded_p, loaded_p_count, *provider)) { + freeProvider(provider); + ipc_write(sock, RESPONSE_ERROR, "A provider with this shortname is already loaded. I will not register a new one."); + return; + } + if(getEndpoints(provider)!=OIDC_SUCCESS) { + freeProvider(provider); + ipc_write(sock, RESPONSE_ERROR, oidc_perror()); + return; + } + char* res = dynamicRegistration(provider, 1); + if(res==NULL) { + ipc_write(sock, RESPONSE_ERROR, oidc_perror()); + } else { + if(json_hasKey(res, "error")) { // first failed + char* res2 = dynamicRegistration(provider, 0); + if(res2==NULL) { //second failed complety + ipc_write(sock, RESPONSE_ERROR, oidc_perror()); + } else { + if(json_hasKey(res2, "error")) { // first and second failed + ipc_write(sock, RESPONSE_ERROR, res); //TODO sent both responses + } else { // first failed, seconds successfull, still need the grant_types. + char* error = getJSONValue(res, "error_description"); + if(error==NULL) { + error = getJSONValue(res, "error"); + } + ipc_write(sock, RESPONSE_ERROR_CLIENT_INFO, error, res2, "The client was registered with the resulting config. It is not usable for oidc-agent in that way. Please contact the provider to update the client configuration. We need additional grant_types: password, refresh_token, authorization_code"); + clearFreeString(error); + } + } + clearFreeString(res2); + } else { // first was successfull + ipc_write(sock, RESPONSE_SUCCESS_CLIENT, res); + } + } + clearFreeString(res); + freeProvider(provider); +} + int main(int argc, char** argv) { openlog("oidc-agent", LOG_CONS|LOG_PID, LOG_AUTHPRIV); setlogmask(LOG_UPTO(LOG_NOTICE)); @@ -266,7 +320,7 @@ int main(int argc, char** argv) { } } - signal(SIGSEGV, sig_handler); + // signal(SIGSEGV, sig_handler); // TODO we can move some of this stuff behind daemonize, but tmp dir has to be // created, env var printed, and socket_path some how saved to use @@ -309,11 +363,15 @@ int main(int argc, char** argv) { } else if(strcmp(pairs[0].value, "add")==0) { handleAdd(*(con->msgsock), loaded_p_addr, &loaded_p_count, pairs[3].value); } else if(strcmp(pairs[0].value, "remove")==0) { - handleRm(*(con->msgsock), loaded_p_addr, &loaded_p_count, pairs[3].value); + handleRm(*(con->msgsock), loaded_p_addr, &loaded_p_count, pairs[3].value, 0); + } else if(strcmp(pairs[0].value, "delete")==0) { + handleRm(*(con->msgsock), loaded_p_addr, &loaded_p_count, pairs[3].value, 1); } else if(strcmp(pairs[0].value, "access_token")==0) { handleToken(*(con->msgsock), *loaded_p_addr, loaded_p_count, pairs[1].value, pairs[2].value); } else if(strcmp(pairs[0].value, "provider_list")==0) { handleList(*(con->msgsock), *loaded_p_addr, loaded_p_count); + } else if(strcmp(pairs[0].value, "register")==0) { + handleRegister(*(con->msgsock), *loaded_p_addr, loaded_p_count, pairs[3].value); } else { ipc_write(*(con->msgsock), "Bad request. Unknown request type."); } @@ -325,6 +383,7 @@ int main(int argc, char** argv) { clearFreeString(pairs[1].value); clearFreeString(pairs[2].value); clearFreeString(pairs[3].value); + clearFreeString(q); } syslog(LOG_AUTHPRIV|LOG_DEBUG, "Remove con from pool"); clientcons = removeConnection(*clientcons_addr, &number_clients, con); @@ -336,24 +395,4 @@ int main(int argc, char** argv) { -/** @fn char* getTokenEndpoint(const char* configuration_endpoint) - * @brief retrieves provider config from the configuration_endpoint - * @note the configuration_endpoint has to set prior - * @param index the index identifying the provider - */ -char* getTokenEndpoint(const char* configuration_endpoint, const char* cert_file) { - char* res = httpsGET(configuration_endpoint, cert_file); - if(NULL==res) { - return NULL; - } - char* token_endpoint = getJSONValue(res, "token_endpoint"); - clearFreeString(res); - if (isValid(token_endpoint)) { - return token_endpoint; - } else { - clearFreeString(token_endpoint); - syslog(LOG_AUTHPRIV|LOG_ERR, "Could not get token_endpoint from the configuration endpoint.\nThis could be because of a network issue, but it's more likely that you misconfigured the issuer.\n"); - return NULL; - } -} diff --git a/src/oidc-gen.c b/src/oidc-gen.c index 7321a263..7180dd9c 100644 --- a/src/oidc-gen.c +++ b/src/oidc-gen.c @@ -3,7 +3,6 @@ #include #include #include -#include #include "oidc-gen.h" #include "provider.h" @@ -14,31 +13,6 @@ #include "crypt.h" #include "ipc.h" -#define CONF_ENDPOINT_SUFFIX ".well-known/openid-configuration" - -#define OIDC_SOCK_ENV_NAME "OIDC_SOCK" - -#define PROVIDER_CONFIG_FILENAME "issuer.config" - -const char *argp_program_version = "oidc-gen 0.2.1"; - -const char *argp_program_bug_address = ""; - -struct arguments { - char* args[1]; /* provider */ - int delete; - int debug; - int verbose; - char* file; -}; - -static struct argp_option options[] = { - {"delete", 'd', 0, 0, "delete configuration for the given provider", 0}, - {"debug", 'g', 0, 0, "sets the log level to DEBUG", 0}, - {"verbose", 'v', 0, 0, "enables verbose mode. The stored data will be printed.", 0}, - {"file", 'f', "FILE", 0, "specifies file with client config", 0}, - {0} -}; static error_t parse_opt (int key, char *arg, struct argp_state *state) { struct arguments *arguments = state->input; @@ -57,6 +31,12 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { case 'f': arguments->file = arg; break; + case 'r': + arguments->registering = 1; + break; + case 'o': + arguments->output = arg; + break; case ARGP_KEY_ARG: if(state->arg_num >= 1) { argp_usage(state); @@ -95,27 +75,16 @@ int main(int argc, char** argv) { arguments.debug = 0; arguments.args[0] = NULL; arguments.file = NULL; + arguments.registering = 0; + arguments.verbose = 0; + arguments.output = NULL; argp_parse (&argp, argc, argv, 0, 0, &arguments); if(arguments.debug) { setlogmask(LOG_UPTO(LOG_DEBUG)); } - if(arguments.delete) { - if(!oidcFileDoesExist(arguments.args[0])) { - fprintf(stderr, "No provider with that shortname configured\n"); - exit(EXIT_FAILURE); - } - struct oidc_provider* loaded_p = NULL; - while(NULL==loaded_p) { - encryptionPassword = promptPassword("Enter encryption Password: "); - loaded_p = decryptProvider(arguments.args[0], encryptionPassword); - } - char* json = providerToJSON(*loaded_p); - freeProvider(loaded_p); - if(removeOidcFile(arguments.args[0])==0) { - printf("Successfully deleted provider configuration.\n"); - } + if(arguments.registering) { struct connection con = {0,0,0}; if(ipc_init(&con, OIDC_SOCK_ENV_NAME, 0)!=0) { exit(EXIT_FAILURE); @@ -124,40 +93,15 @@ int main(int argc, char** argv) { printf("Could not connect to oicd\n"); exit(EXIT_FAILURE); } - ipc_write(*(con.sock), REQUEST_CONFIG, "remove", json); - clearFreeString(json); - char* res = ipc_read(*(con.sock)); - ipc_close(&con); - if(NULL==res) { - printf("An unexpected error occured. It's seems that oidc-agent has stopped.\n That's not good."); - exit(EXIT_FAILURE); - } - - struct key_value pairs[2]; - pairs[0].key = "status"; - pairs[1].key = "error"; - if(getJSONValues(res, pairs, sizeof(pairs)/sizeof(*pairs))<0) { - printf("Could not decode json: %s\n", res); - printf("This seems to be a bug. Please hand in a bug report.\n"); - clearFreeString(res); - exit(EXIT_FAILURE); - } - clearFreeString(res); - if(strcmp(pairs[0].value, "success")==0 || strcmp(pairs[1].value, "provider not loaded")==0) { - printf("The generated provider was successfully removed from oidc-agent. You don't have to run oidc-add.\n"); - clearFreeString(pairs[0].value); - exit(EXIT_SUCCESS); - } - if(pairs[1].value!=NULL) { - printf("Error: %s\n", pairs[1].value); - printf("The provider was not removed from oidc-agent. Please run oidc-add with -r to try it again.\n"); - clearFreeString(pairs[1].value); clearFreeString(pairs[0].value); - exit(EXIT_FAILURE); - } + registerClient(*(con.sock), arguments.args[0], arguments); + exit(EXIT_SUCCESS); + } + if(arguments.delete) { + handleDelete(arguments.args[0]); + exit(EXIT_SUCCESS); } - initCrypt(); if(arguments.file) { char* inputconfig = readFile(arguments.file); syslog(LOG_AUTHPRIV|LOG_DEBUG, "Read config from user provided file: %s", inputconfig); @@ -182,15 +126,18 @@ int main(int argc, char** argv) { char* res = ipc_read(*(con.sock)); ipc_close(&con); if(NULL==res) { - printf("An unexpected error occured. It's seems that oidc-agent has stopped.\n That's not good."); + printf("An unexpected error occured. It's seems that oidc-agent has stopped.\n That's not good.\n"); exit(EXIT_FAILURE); } - struct key_value pairs[4]; + struct key_value pairs[7]; pairs[0].key = "status"; pairs[1].key = "refresh_token"; pairs[2].key = "token_endpoint"; - pairs[3].key = "error"; + pairs[3].key = "authorization_endpoint"; + pairs[4].key = "registration_endpoint"; + pairs[5].key = "revocation_endpoint"; + pairs[6].key = "error"; if(getJSONValues(res, pairs, sizeof(pairs)/sizeof(*pairs))<0) { printf("Could not decode json: %s\n", res); printf("This seems to be a bug. Please hand in a bug report.\n"); @@ -198,9 +145,9 @@ int main(int argc, char** argv) { saveExit(EXIT_FAILURE); } clearFreeString(res); - if(pairs[3].value!=NULL) { - printf("Error: %s\n", pairs[3].value); - clearFreeString(pairs[3].value); clearFreeString(pairs[2].value); clearFreeString(pairs[1].value); clearFreeString(pairs[0].value); + if(pairs[6].value!=NULL) { + printf("Error: %s\n", pairs[6].value); + clearFreeString(pairs[6].value);clearFreeString(pairs[5].value); clearFreeString(pairs[4].value); clearFreeString(pairs[3].value); clearFreeString(pairs[2].value); clearFreeString(pairs[1].value); clearFreeString(pairs[0].value); saveExit(EXIT_FAILURE); } if(pairs[2].value!=NULL) { @@ -208,6 +155,21 @@ int main(int argc, char** argv) { } else { fprintf(stderr, "Error: response does not contain token_endpoint\n"); } + if(pairs[3].value!=NULL) { + provider_setAuthorizationEndpoint(provider, pairs[3].value); + } else { + fprintf(stderr, "Error: response does not contain authorization_endpoint\n"); + } + if(pairs[4].value!=NULL) { + provider_setRegistrationEndpoint(provider, pairs[4].value); + } else { + fprintf(stderr, "Error: response does not contain registration_endpoint\n"); + } + if(pairs[5].value!=NULL) { + provider_setRevocationEndpoint(provider, pairs[5].value); + } else { + fprintf(stderr, "Error: response does not contain revocation_endpoint\n"); + } if(pairs[1].value!=NULL) { provider_setRefreshToken(provider, pairs[1].value); } @@ -243,50 +205,39 @@ int main(int argc, char** argv) { } //encrypt - do { - char* input = promptPassword("Enter encrpytion password%s: ", encryptionPassword ? " [***]" : ""); - if(encryptionPassword && !isValid(input)) { // use same encrpytion password - clearFreeString(input); - break; - } else { - if(encryptionPassword) { - clearFreeString(encryptionPassword); - } - encryptionPassword = input; - } - char* confirm = promptPassword("Confirm encryption Password: "); - if(strcmp(encryptionPassword, confirm)!=0) { - printf("Encryption passwords did not match.\n"); - if(confirm) { - clearFreeString(confirm); - } - if(encryptionPassword) { - clearFreeString(encryptionPassword); - encryptionPassword = NULL; - } - continue; - } - clearFreeString(confirm); - } while(encryptionPassword==NULL); - char* toWrite = encryptProvider(json, encryptionPassword); + encryptAndWriteConfig(json, encryptionPassword, NULL, provider->name); clearFreeString(json); - if(encryptionPassword) { - clearFreeString(encryptionPassword); - } - - writeOidcFile(provider->name, toWrite); - clearFreeString(toWrite); saveExit(EXIT_SUCCESS); return EXIT_FAILURE; } +oidc_error_t encryptAndWriteConfig(const char* text, const char* suggestedPassword, const char* filepath, const char* oidc_filename) { + initCrypt(); + char* encryptionPassword = getEncryptionPassword(suggestedPassword, UINT_MAX); + if(encryptionPassword==NULL) { + return oidc_errno; + } + char* toWrite = encryptProvider(text, encryptionPassword); + clearFreeString(encryptionPassword); + if(toWrite==NULL) { + return oidc_errno; + } + if(filepath) { + writeFile(filepath, toWrite); + } else { + writeOidcFile(oidc_filename, toWrite); + } + clearFreeString(toWrite); + return OIDC_SUCCESS; +} + void promptAndSet(char* prompt_str, void (*set_callback)(struct oidc_provider*, char*), char* (*get_callback)(struct oidc_provider), int passPrompt, int optional) { char* input = NULL; do { if(passPrompt) { - input = promptPassword(prompt_str, get_callback(*provider) ? " [***]" : ""); + input = promptPassword(prompt_str, isValid(get_callback(*provider)) ? " [***]" : ""); } else { - input = prompt(prompt_str, get_callback(*provider) ? " [" : "", get_callback(*provider) ? get_callback(*provider) : "", get_callback(*provider) ? "]" : ""); + input = prompt(prompt_str, isValid(get_callback(*provider)) ? " [" : "", isValid(get_callback(*provider)) ? get_callback(*provider) : "", isValid(get_callback(*provider)) ? "]" : ""); } if(isValid(input)) { set_callback(provider, input); @@ -372,7 +323,7 @@ void promptAndSetIssuer() { struct oidc_provider* genNewProvider(const char* short_name) { if(provider==NULL) { - provider = calloc(sizeof(struct oidc_provider), 1); + provider = calloc(sizeof(struct oidc_provider), 1); } while(!isValid(provider_getName(*provider))) { if(short_name) { @@ -400,9 +351,7 @@ struct oidc_provider* genNewProvider(const char* short_name) { continue; } if(oidcFileDoesExist(provider_getName(*provider))) { - char* res = prompt("A provider with this short name is already configured. Do you want to edit the configuration? [yes/no/quit]: "); - if(strcmp(res, "yes")==0) { - clearFreeString(res); + if(getUserConfirmation("A provider with this short name is already configured. Do you want to edit the configuration?")) { struct oidc_provider* loaded_p = NULL; while(NULL==loaded_p) { encryptionPassword = promptPassword("Enter encryption Password: "); @@ -411,10 +360,7 @@ struct oidc_provider* genNewProvider(const char* short_name) { freeProvider(provider); provider = loaded_p; break; - } else if(strcmp(res, "quit")==0) { - exit(EXIT_SUCCESS); } else { - clearFreeString(res); provider_setName(provider, NULL); continue; } @@ -462,3 +408,196 @@ char* encryptProvider(const char* json, const char* password) { return write_it; } +char* getEncryptionPassword(const char* suggestedPassword, unsigned int max_pass_tries) { + char* encryptionPassword = NULL; + unsigned int i; + unsigned int max_tries = max_pass_tries==0 ? MAX_PASS_TRIES : max_pass_tries; + for(i=0; i + char* possibleCertFiles[] = { -"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. -"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL -"/etc/ssl/ca-bundle.pem", // OpenSUSE -"/etc/pki/tls/cacert.pem" // OpenELEC + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem" // OpenELEC +}; + +#define CONF_ENDPOINT_SUFFIX ".well-known/openid-configuration" + +#define OIDC_SOCK_ENV_NAME "OIDC_SOCK" + +#define PROVIDER_CONFIG_FILENAME "issuer.config" + +#define MAX_PASS_TRIES 3 + + +const char *argp_program_version = GEN_VERSION; + +const char *argp_program_bug_address = BUG_ADDRESS; + +struct arguments { + char* args[1]; /* provider */ + int delete; + int debug; + int verbose; + char* file; + int registering; + char* output; +}; + +static struct argp_option options[] = { + {"delete", 'd', 0, 0, "delete configuration for the given provider", 0}, + {"debug", 'g', 0, 0, "sets the log level to DEBUG", 0}, + {"verbose", 'v', 0, 0, "enables verbose mode. The stored data will be printed.", 0}, + {"file", 'f', "FILE", 0, "specifies file with client config", 0}, + {"register", 'r', 0, 0, "a new client will be registered", 0}, + {"output", 'o', "OUTPUT_FILE", 0, "the path where the client config will be saved", 0}, + {0} }; struct oidc_provider* genNewProvider(); char* encryptProvider(const char* json, const char* password) ; void saveExit(int exitno); +char* getEncryptionPassword(const char* suggestedPassword, unsigned int max_pass_tries) ; +oidc_error_t encryptAndWriteConfig(const char* text, const char* suggestedPassword, const char* filepath, const char* oidc_filename) ; +void handleDelete(char* short_name) ; +void deleteClient(char* short_name, char* provider_json, int revoke) ; +void registerClient(int sock, char* short_name, struct arguments arguments) ; #endif // OIDC_GEN_H diff --git a/src/oidc-token.c b/src/oidc-token.c index a6b70858..6227c7b2 100644 --- a/src/oidc-token.c +++ b/src/oidc-token.c @@ -9,11 +9,12 @@ #include "oidc-token.h" #include "api.h" #include "oidc_utilities.h" +#include "version.h" -const char *argp_program_version = "oidc-token 0.1.0"; +const char *argp_program_version = TOKEN_VERSION; -const char *argp_program_bug_address = ""; +const char *argp_program_bug_address = BUG_ADDRESS; /* This structure is used by main to communicate with parse_opt. */ struct arguments { diff --git a/src/oidc.c b/src/oidc.c index 36b87bbd..3485b69f 100644 --- a/src/oidc.c +++ b/src/oidc.c @@ -90,7 +90,7 @@ oidc_error_t refreshFlow(struct oidc_provider* p) { char* data = calloc(sizeof(char),strlen(format)-3*2+strlen(provider_getClientSecret(*p))+strlen(provider_getClientId(*p))+strlen(provider_getRefreshToken(*p))+1); sprintf(data, format, provider_getClientId(*p), provider_getClientSecret(*p), provider_getRefreshToken(*p)); syslog(LOG_AUTHPRIV|LOG_DEBUG, "Data to send: %s",data); - char* res = httpsPOST(provider_getTokenEndpoint(*p), data, provider_getCertPath(*p)); + char* res = httpsPOST(provider_getTokenEndpoint(*p), data, NULL, provider_getCertPath(*p), NULL, NULL); clearFreeString(data); if(NULL==res) { return oidc_errno; @@ -146,7 +146,7 @@ oidc_error_t passwordFlow(struct oidc_provider* p) { char* data = calloc(sizeof(char),strlen(format)-4*2+strlen(provider_getClientSecret(*p))+strlen(provider_getClientId(*p))+strlen(provider_getUsername(*p))+strlen(provider_getPassword(*p))+1); sprintf(data, format, provider_getClientId(*p), provider_getClientSecret(*p), provider_getUsername(*p), provider_getPassword(*p)); syslog(LOG_AUTHPRIV|LOG_DEBUG, "Data to send: %s",data); - char* res = httpsPOST(provider_getTokenEndpoint(*p), data, provider_getCertPath(*p)); + char* res = httpsPOST(provider_getTokenEndpoint(*p), data, NULL, provider_getCertPath(*p), NULL, NULL); clearFreeString(data); if(res==NULL) { return oidc_errno; @@ -200,3 +200,148 @@ int tokenIsValidForSeconds(struct oidc_provider p, time_t min_valid_period) { time_t expires_at = provider_getTokenExpiresAt(p); return expires_at-now>0 && expires_at-now>min_valid_period; } + +oidc_error_t revokeToken(struct oidc_provider* provider) { + syslog(LOG_AUTHPRIV|LOG_DEBUG, "Performing Token revocation flow"); + if(!isValid(provider_getRevocationEndpoint(*provider))) { + oidc_seterror("Token revocation is not supported by this provider."); + oidc_errno = OIDC_EERROR; + return oidc_errno; + } + const char* const fmt = "token_type_hint=refresh_token&token=%s"; + char* data = calloc(sizeof(char), strlen(fmt)+strlen(provider_getRefreshToken(*provider))+1); + sprintf(data, fmt, provider_getRefreshToken(*provider)); + syslog(LOG_AUTHPRIV|LOG_DEBUG, "Data to send: %s",data); + char* res = httpsPOST(provider_getRevocationEndpoint(*provider), data, NULL, provider_getCertPath(*provider), provider_getClientId(*provider), provider_getClientSecret(*provider)); + clearFreeString(data); + if(isValid(res) && json_hasKey(res, "error")) { + char* error = getJSONValue(res, "error_description"); + if(error==NULL) { + error = getJSONValue(res, "error"); + } + oidc_errno = OIDC_EOIDC; + oidc_seterror(error); + clearFreeString(error); + } + clearFreeString(res); + + syslog(LOG_AUTHPRIV|LOG_DEBUG, "errno is %d and message is %s", oidc_errno, oidc_perror()); + if(oidc_errno==OIDC_SUCCESS) { + provider_setRefreshToken(provider, NULL); + } + + return oidc_errno; +} + +char* dynamicRegistration(struct oidc_provider* provider, int useGrantType) { + syslog(LOG_AUTHPRIV|LOG_DEBUG, "Performing dynamic Registration flow"); + if(!isValid(provider_getRegistrationEndpoint(*provider))) { + oidc_seterror("Dynamic registration is not supported by this provider."); + oidc_errno = OIDC_EERROR; + return NULL; + } + char* client_name = calloc(sizeof(char), strlen(provider_getName(*provider))+strlen("oidc-agent:")+1); + sprintf(client_name, "oidc-agent:%s", provider_getName(*provider)); + + char* json = calloc(sizeof(char), 2+1); + strcpy(json, "{}"); + json = json_addStringValue(json, "application_type", "web"); + json = json_addStringValue(json, "client_name", client_name); + clearFreeString(client_name); + json = json_addStringValue(json, "response_types", "code"); + if(useGrantType) { + json = json_addValue(json, "grant_types", "[\"password\", \"refresh_token\", \"authorization_code\"]"); + } + json = json_addValue(json, "redirect_uris", "[\"http://localhost:8080\", \"http://localhost:2912\", \"http://localhost:2408\"]"); + json = json_addValue(json, "scope", "\"openid email profile offline_access\""); + + + + + struct curl_slist* headers = NULL; + headers = curl_slist_append(headers, "Content-Type: application/json"); + syslog(LOG_AUTHPRIV|LOG_DEBUG, "Data to send: %s",json); + char* res = httpsPOST(provider_getRegistrationEndpoint(*provider), json, headers, provider_getCertPath(*provider), NULL, NULL); + curl_slist_free_all(headers); + clearFreeString(json); + if(res==NULL) { + return NULL; + } + + // struct key_value pairs[4]; + // pairs[0].key = "client_id"; + // pairs[1].key = "client_secret"; + // pairs[2].key = "error"; + // pairs[3].key = "error_message"; + // if(getJSONValues(res, pairs, sizeof(pairs)/sizeof(*pairs))<0) { + // syslog(LOG_AUTHPRIV|LOG_ALERT, "Error while parsing json\n"); + // clearFreeString(res); + // return NULL; + // } + // + // if(pairs[2].value!=NULL) { + // syslog(LOG_AUTHPRIV|LOG_ALERT, "Error registering client: %s: %s", pairs[2].value, pairs[3].value ? pairs[3].value : ""); + // oidc_seterror(pairs[3].value ? pairs[3].value : pairs[2].value); + // oidc_errno = OIDC_EOIDC; + // clearFreeString(pairs[0].value); + // clearFreeString(pairs[1].value); + // clearFreeString(pairs[2].value); + // clearFreeString(pairs[3].value); + // return NULL; + // } + // clearFreeString(pairs[2].value); + // clearFreeString(pairs[3].value); + // if(pairs[0].value==NULL || pairs[1].value==NULL) { + // syslog(LOG_AUTHPRIV|LOG_ALERT, "Error registering client: Did not find client_id and client_secret"); + // oidc_seterror("Error registering client: Did not find client_id and client_secret"); + // oidc_errno = OIDC_EOIDC; + // clearFreeString(pairs[0].value); + // clearFreeString(pairs[1].value); + // return NULL; + // } + // provider_setClientId(provider, pairs[0].value); + // provider_setClientSecret(provider, pairs[1].value); + return res; +} + + +/** @fn oidc_error_t getEndpoints(struct oidc_provider* provider) + * @brief retrieves provider config from the configuration_endpoint + * @note the configuration_endpoint has to set prior + * @param provider the provider struct, will be updated with the retrieved + * endpoints + * @return a oidc_error status code + */ +oidc_error_t getEndpoints(struct oidc_provider* provider) { + char* res = httpsGET(provider_getConfigEndpoint(*provider), NULL, provider_getCertPath(*provider)); + if(NULL==res) { + return oidc_errno; + } + struct key_value pairs[4]; + pairs[0].key = "token_endpoint"; + pairs[1].key = "authorization_endpoint"; + pairs[2].key = "registration_endpoint"; + pairs[3].key = "revocation_endpoint"; + if(getJSONValues(res, pairs, sizeof(pairs)/sizeof(*pairs))<0) { + clearFreeString(res); + return oidc_errno; + } + clearFreeString(res); + + if(pairs[0].value==NULL) { + syslog(LOG_AUTHPRIV|LOG_ERR, "Could not get token_endpoint"); + clearFreeString(pairs[1].value); + clearFreeString(pairs[2].value); + clearFreeString(pairs[3].value); + oidc_seterror("Could not get token_endpoint from the configuration_endpoint. This could be because of a network issue. But it's more likely that your issuer is not correct."); + oidc_errno = OIDC_EERROR; + return oidc_errno; + } + provider_setTokenEndpoint(provider, pairs[0].value); + provider_setAuthorizationEndpoint(provider, pairs[1].value); + provider_setRegistrationEndpoint(provider, pairs[2].value); + provider_setRevocationEndpoint(provider, pairs[3].value); + return OIDC_SUCCESS; + +} + diff --git a/src/oidc.h b/src/oidc.h index 52004c0f..ccc050ee 100644 --- a/src/oidc.h +++ b/src/oidc.h @@ -15,5 +15,8 @@ oidc_error_t tryPasswordFlow(struct oidc_provider* p) ; oidc_error_t refreshFlow(struct oidc_provider* p) ; oidc_error_t passwordFlow(struct oidc_provider* p) ; int tokenIsValidForSeconds(struct oidc_provider p, time_t min_valid_period); +char* dynamicRegistration(struct oidc_provider* provider, int useGrantType) ; +oidc_error_t revokeToken(struct oidc_provider* provider) ; +oidc_error_t getEndpoints(struct oidc_provider* provider) ; #endif //OIDC_H diff --git a/src/oidc_error.h b/src/oidc_error.h index c90680bb..4b28e562 100644 --- a/src/oidc_error.h +++ b/src/oidc_error.h @@ -26,6 +26,7 @@ enum _oidc_error { OIDC_EJSONPARS = -30, OIDC_EJSONOBJ = -31, OIDC_EJSONNOFOUND = -32, + OIDC_EJSONADD = -33, OIDC_ETCS = -40, OIDC_EIN = -41, @@ -46,6 +47,8 @@ enum _oidc_error { OIDC_ESELECT = -68, OIDC_EIOCTL = -69, + OIDC_EMAXTRIES = -70, + OIDC_ENOPE = -1337, }; @@ -79,6 +82,7 @@ static inline char* oidc_perror() { case OIDC_EJSONPARS: return "could not parse json"; case OIDC_EJSONOBJ: return "is not a json object"; case OIDC_EJSONNOFOUND: return "could not find key"; + case OIDC_EJSONADD: return "The json string does not end with '}'"; case OIDC_ETCS: return "error tcsetattr"; case OIDC_EIN: return "error getline"; case OIDC_EBADCONFIG: return "bad configuration"; @@ -94,6 +98,7 @@ static inline char* oidc_perror() { case OIDC_EIOCTL: return "error ioctl"; case OIDC_EIPCDIS: return "the other party disconnected"; case OIDC_ESELECT: return "error select"; + case OIDC_EMAXTRIES: return "reached maximum number of tries"; case OIDC_ENOPE: return "Computer says NO!"; default: return "Computer says NO!"; } diff --git a/src/prompt.c b/src/prompt.c index 381a8e0d..be113f02 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -78,3 +78,16 @@ char* prompt(char* prompt_str, ...) { buf[n-1] = 0; //removing '\n' return buf; } + +int getUserConfirmation(char* prompt_str) { + char* res = prompt("%s %s", prompt_str, "[yes/no/quit]: "); + if(strcmp(res, "yes")==0) { + clearFreeString(res); + return 1; + } else if(strcmp(res, "quit")==0) { + exit(EXIT_SUCCESS); + } else { + clearFreeString(res); + return 0; + } +} diff --git a/src/prompt.h b/src/prompt.h index 2e19db40..122964a1 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -3,5 +3,6 @@ char* promptPassword(char* prompt_str, ...) ; char* prompt(char* prompt_str, ...); +int getUserConfirmation(char* prompt_str) ; #endif // PROMPT_H diff --git a/src/provider.c b/src/provider.c index 0a2688bb..16a73796 100644 --- a/src/provider.c +++ b/src/provider.c @@ -113,17 +113,20 @@ struct oidc_provider* getProviderFromJSON(char* json) { return NULL; } struct oidc_provider* p = calloc(sizeof(struct oidc_provider), 1); - struct key_value pairs[10]; + struct key_value pairs[13]; pairs[0].key = "issuer"; pairs[1].key = "name"; pairs[2].key = "client_id"; pairs[3].key = "client_secret"; pairs[4].key = "configuration_endpoint"; pairs[5].key = "token_endpoint"; - pairs[6].key = "username"; - pairs[7].key = "password"; - pairs[8].key = "refresh_token"; - pairs[9].key = "cert_path"; + pairs[6].key = "authorization_endpoint"; + pairs[7].key = "registration_endpoint"; + pairs[8].key = "revocation_endpoint"; + pairs[9].key = "username"; + pairs[10].key = "password"; + pairs[11].key = "refresh_token"; + pairs[12].key = "cert_path"; if(getJSONValues(json, pairs, sizeof(pairs)/sizeof(*pairs))>0) { provider_setIssuer(p, pairs[0].value); provider_setName(p, pairs[1].value); @@ -131,16 +134,15 @@ struct oidc_provider* getProviderFromJSON(char* json) { provider_setClientSecret(p, pairs[3].value); provider_setConfigEndpoint(p, pairs[4].value); provider_setTokenEndpoint(p, pairs[5].value); - provider_setUsername(p, pairs[6].value); - provider_setPassword(p, pairs[7].value); - provider_setRefreshToken(p, pairs[8].value); - provider_setCertPath(p, pairs[9].value); + provider_setAuthorizationEndpoint(p, pairs[6].value); + provider_setRegistrationEndpoint(p, pairs[7].value); + provider_setRevocationEndpoint(p, pairs[8].value); + provider_setUsername(p, pairs[9].value); + provider_setPassword(p, pairs[10].value); + provider_setRefreshToken(p, pairs[11].value); + provider_setCertPath(p, pairs[12].value); } - // if(provider_getIssuer(*p) && provider_getName(*p) && provider_getClientId(*p) && provider_getClientSecret(*p) && provider_getConfigEndpoint(*p) && provider_getTokenEndpoint(*p) && provider_getUsername(*p) && provider_getPassword(*p) && provider_getRefreshToken(*p) && provider_getCertPath(*p)) { - return p; - // } - // freeProvider(p); - // return NULL; + return p; } /** @fn char* providerToJSON(struct oidc_rovider p) @@ -150,12 +152,15 @@ struct oidc_provider* getProviderFromJSON(char* json) { * after usage. */ char* providerToJSON(struct oidc_provider p) { - char* fmt = "{\n\"name\":\"%s\",\n\"issuer\":\"%s\",,\n\"configuration_endpoint\":\"%s\",\n\"token_endpoint\":\"%s\",\n\"client_id\":\"%s\",\n\"client_secret\":\"%s\",\n\"username\":\"%s\",\n\"password\":\"%s\",\n\"refresh_token\":\"%s\",\n\"cert_path\":\"%s\"\n}"; + char* fmt = "{\n\"name\":\"%s\",\n\"issuer\":\"%s\",,\n\"configuration_endpoint\":\"%s\",\n\"token_endpoint\":\"%s\",\n\"authorization_endpoint\":\"%s\",\n\"registration_endpoint\":\"%s\",\n\"revocation_endpoint\":\"%s\",\n\"client_id\":\"%s\",\n\"client_secret\":\"%s\",\n\"username\":\"%s\",\n\"password\":\"%s\",\n\"refresh_token\":\"%s\",\n\"cert_path\":\"%s\"\n}"; char* p_json = calloc(sizeof(char), snprintf(NULL, 0, fmt, isValid(provider_getName(p)) ? provider_getName(p) : "", isValid(provider_getIssuer(p)) ? provider_getIssuer(p) : "", isValid(provider_getConfigEndpoint(p)) ? provider_getConfigEndpoint(p) : "", isValid(provider_getTokenEndpoint(p)) ? provider_getTokenEndpoint(p) : "", + isValid(provider_getAuthorizationEndpoint(p)) ? provider_getAuthorizationEndpoint(p) : "", + isValid(provider_getRegistrationEndpoint(p)) ? provider_getRegistrationEndpoint(p) : "", + isValid(provider_getRevocationEndpoint(p)) ? provider_getRevocationEndpoint(p) : "", isValid(provider_getClientId(p)) ? provider_getClientId(p) : "", isValid(provider_getClientSecret(p)) ? provider_getClientSecret(p) : "", isValid(provider_getUsername(p)) ? provider_getUsername(p) : "", @@ -165,15 +170,18 @@ char* providerToJSON(struct oidc_provider p) { )+1); sprintf(p_json, fmt, isValid(provider_getName(p)) ? provider_getName(p) : "", - isValid(provider_getIssuer(p)) ? provider_getIssuer(p) : "", - isValid(provider_getConfigEndpoint(p)) ? provider_getConfigEndpoint(p) : "", - isValid(provider_getTokenEndpoint(p)) ? provider_getTokenEndpoint(p) : "", - isValid(provider_getClientId(p)) ? provider_getClientId(p) : "", - isValid(provider_getClientSecret(p)) ? provider_getClientSecret(p) : "", - isValid(provider_getUsername(p)) ? provider_getUsername(p) : "", - isValid(provider_getPassword(p)) ? provider_getPassword(p) : "", - isValid(provider_getRefreshToken(p)) ? provider_getRefreshToken(p) : "", - isValid(provider_getCertPath(p)) ? provider_getCertPath(p) : "" + isValid(provider_getIssuer(p)) ? provider_getIssuer(p) : "", + isValid(provider_getConfigEndpoint(p)) ? provider_getConfigEndpoint(p) : "", + isValid(provider_getTokenEndpoint(p)) ? provider_getTokenEndpoint(p) : "", + isValid(provider_getAuthorizationEndpoint(p)) ? provider_getAuthorizationEndpoint(p) : "", + isValid(provider_getRegistrationEndpoint(p)) ? provider_getRegistrationEndpoint(p) : "", + isValid(provider_getRevocationEndpoint(p)) ? provider_getRevocationEndpoint(p) : "", + isValid(provider_getClientId(p)) ? provider_getClientId(p) : "", + isValid(provider_getClientSecret(p)) ? provider_getClientSecret(p) : "", + isValid(provider_getUsername(p)) ? provider_getUsername(p) : "", + isValid(provider_getPassword(p)) ? provider_getPassword(p) : "", + isValid(provider_getRefreshToken(p)) ? provider_getRefreshToken(p) : "", + isValid(provider_getCertPath(p)) ? provider_getCertPath(p) : "" ); return p_json; } @@ -196,6 +204,9 @@ void freeProviderContent(struct oidc_provider* p) { provider_setIssuer(p, NULL); provider_setConfigEndpoint(p, NULL); provider_setTokenEndpoint(p, NULL); + provider_setAuthorizationEndpoint(p, NULL); + provider_setRegistrationEndpoint(p, NULL); + provider_setRevocationEndpoint(p, NULL); provider_setClientId(p, NULL); provider_setClientSecret(p, NULL); provider_setUsername(p, NULL); diff --git a/src/provider.h b/src/provider.h index 4030c5d1..ee01aacf 100644 --- a/src/provider.h +++ b/src/provider.h @@ -16,6 +16,9 @@ struct oidc_provider { char* client_secret; char* configuration_endpoint; char* token_endpoint; + char* authorization_endpoint; + char* revocation_endpoint; + char* registration_endpoint; char* username; char* password; char* refresh_token; @@ -29,6 +32,9 @@ inline static char* provider_getClientId(struct oidc_provider p) { return p.clie inline static char* provider_getClientSecret(struct oidc_provider p) { return p.client_secret; } inline static char* provider_getConfigEndpoint(struct oidc_provider p) { return p.configuration_endpoint; } inline static char* provider_getTokenEndpoint(struct oidc_provider p) { return p.token_endpoint; } +inline static char* provider_getAuthorizationEndpoint(struct oidc_provider p) { return p.authorization_endpoint; } +inline static char* provider_getRevocationEndpoint(struct oidc_provider p) { return p.revocation_endpoint; } +inline static char* provider_getRegistrationEndpoint(struct oidc_provider p) { return p.registration_endpoint; } inline static char* provider_getUsername(struct oidc_provider p) { return p.username; } inline static char* provider_getPassword(struct oidc_provider p) { return p.password; } inline static char* provider_getRefreshToken(struct oidc_provider p) { return p.refresh_token; } @@ -42,6 +48,9 @@ inline static void provider_setClientId(struct oidc_provider* p, char* client_id inline static void provider_setClientSecret(struct oidc_provider* p, char* client_secret) { clearFreeString(p->client_secret); p->client_secret=client_secret; } inline static void provider_setConfigEndpoint(struct oidc_provider* p, char* configuration_endpoint) { clearFreeString(p->configuration_endpoint); p->configuration_endpoint=configuration_endpoint; } inline static void provider_setTokenEndpoint(struct oidc_provider* p, char* token_endpoint) { clearFreeString(p->token_endpoint); p->token_endpoint=token_endpoint; } +inline static void provider_setAuthorizationEndpoint(struct oidc_provider* p, char* authorization_endpoint) { clearFreeString(p->authorization_endpoint); p->authorization_endpoint=authorization_endpoint; } +inline static void provider_setRevocationEndpoint(struct oidc_provider* p, char* revocation_endpoint) { clearFreeString(p->revocation_endpoint); p->revocation_endpoint=revocation_endpoint; } +inline static void provider_setRegistrationEndpoint(struct oidc_provider* p, char* registration_endpoint) { clearFreeString(p->registration_endpoint); p->registration_endpoint=registration_endpoint; } inline static void provider_setUsername(struct oidc_provider* p, char* username) { clearFreeString(p->username); p->username=username; } inline static void provider_setPassword(struct oidc_provider* p, char* password) { clearFreeString(p->password); p->password=password; } inline static void provider_setRefreshToken(struct oidc_provider* p, char* refresh_token) { clearFreeString(p->refresh_token); p->refresh_token=refresh_token; } diff --git a/src/version.h b/src/version.h new file mode 100644 index 00000000..f1e753b7 --- /dev/null +++ b/src/version.h @@ -0,0 +1,11 @@ +#ifndef OIDC_VERSION_H +#define OIDC_VERSION_H + +#define VERSION "0.4.0" +#define BUG_ADDRESS "" +#define AGENT_VERSION "oidc-agent " VERSION +#define GEN_VERSION "oidc-gen " VERSION +#define ADD_VERSION "oidc-add " VERSION +#define TOKEN_VERSION "oidc-token " VERSION + +#endif // OIDC_VERSION_H