// disfluid, implementation of the Solid specification // Copyright (C) 2020, 2021 Vivien Kraus // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include #include #include struct DisfluidApi { SCM scm_make_client; SCM scm_get_client_id; SCM scm_get_key_pair; SCM scm_get_redirect_uri; SCM scm_make_account_full; SCM scm_get_account_subject; SCM scm_get_account_issuer; SCM scm_get_account_key_pair; SCM scm_get_account_id_token_header; SCM scm_get_account_id_token; SCM scm_get_account_access_token; SCM scm_get_account_refresh_token; }; struct user_code { DisfluidUser func; void *data; }; static void * inner_guile (void *data) { struct user_code *user = data; struct DisfluidApi api; api.scm_make_client = scm_c_public_ref ("webid-oidc client reverse-stubs", "make-client"); api.scm_get_client_id = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-client-id"); api.scm_get_key_pair = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-key-pair"); api.scm_get_redirect_uri = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-redirect-uri"); api.scm_make_account_full = scm_c_public_ref ("webid-oidc client reverse-stubs", "make-account-full"); api.scm_get_account_subject = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-account-subject"); api.scm_get_account_issuer = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-account-issuer"); api.scm_get_account_key_pair = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-account-key-pair"); api.scm_get_account_id_token_header = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-account-id-token-header"); api.scm_get_account_id_token = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-account-id-token"); api.scm_get_account_access_token = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-account-access-token"); api.scm_get_account_refresh_token = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-account-refresh-token"); return user->func (&api, user->data); } void * disfluid_api_init (DisfluidUser func, void *data) { struct user_code code; code.func = func; code.data = data; return scm_with_guile (inner_guile, &code); } struct DisfluidClient { SCM object; }; void disfluid_api_make_client (const struct DisfluidApi *api, struct DisfluidClient **client, const char *client_id, const char *redirect_uri, const char *jwk) { SCM scm_client_id = scm_from_utf8_string (client_id); SCM scm_redirect_uri = scm_from_utf8_string (redirect_uri); SCM scm_jwk = SCM_BOOL_F; if (jwk) { scm_jwk = scm_from_utf8_string (jwk); } SCM object = scm_call_3 (api->scm_make_client, scm_client_id, scm_redirect_uri, scm_jwk); scm_dynwind_begin (0); *client = scm_malloc (sizeof (struct DisfluidClient)); scm_dynwind_unwind_handler (free, *client, 0); (*client)->object = scm_gc_protect_object (object); scm_dynwind_end (); } void disfluid_client_free (struct DisfluidClient *client) { if (client) { scm_gc_unprotect_object (client->object); } free (client); } static size_t copy_scm_string (SCM string, size_t start, size_t max, char *dest) { size_t total_length = 0; scm_dynwind_begin (0); char *all_bytes = NULL; if (scm_is_true (string)) { all_bytes = scm_to_utf8_stringn (string, &total_length); scm_dynwind_free (all_bytes); } const size_t requested_length = max; const size_t available_length = total_length - start; size_t copied_length = requested_length; if (available_length < copied_length) { copied_length = available_length; } memcpy (dest, all_bytes + start, copied_length); if (copied_length < max) { dest[copied_length] = '\0'; } scm_dynwind_end (); return total_length; } size_t disfluid_client_get_id (const struct DisfluidClient *client, const struct DisfluidApi *api, size_t start, size_t max, char *id) { SCM scm_id = scm_call_1 (api->scm_get_client_id, client->object); return copy_scm_string (scm_id, start, max, id); } size_t disfluid_client_get_key_pair (const struct DisfluidClient *client, const struct DisfluidApi *api, size_t start, size_t max, char *jwk) { SCM scm_jwk = scm_call_1 (api->scm_get_key_pair, client->object); return copy_scm_string (scm_jwk, start, max, jwk); } size_t disfluid_client_get_redirect_uri (const struct DisfluidClient *client, const struct DisfluidApi *api, size_t start, size_t max, char *redirect_uri) { SCM scm_uri = scm_call_1 (api->scm_get_redirect_uri, client->object); return copy_scm_string (scm_uri, start, max, redirect_uri); } struct DisfluidAccount { SCM object; }; void disfluid_api_make_account (const struct DisfluidApi *api, struct DisfluidAccount **account, const char *subject, const char *issuer, const char *key_pair, const char *id_token_header, const char *id_token, const char *access_token, const char *refresh_token) { SCM scm_subject = scm_from_utf8_string (subject); SCM scm_issuer = scm_from_utf8_string (issuer); SCM scm_key_pair = scm_from_utf8_string (key_pair); SCM scm_id_token_header = SCM_BOOL_F; SCM scm_id_token = SCM_BOOL_F; SCM scm_access_token = SCM_BOOL_F; SCM scm_refresh_token = SCM_BOOL_F; if (id_token_header) { scm_id_token_header = scm_from_utf8_string (id_token_header); } if (id_token) { scm_id_token = scm_from_utf8_string (id_token); } if (access_token) { scm_access_token = scm_from_utf8_string (access_token); } if (refresh_token) { scm_refresh_token = scm_from_utf8_string (refresh_token); } } void disfluid_account_free (struct DisfluidAccount *account) { if (account) { scm_gc_unprotect_object (account->object); } free (account); } size_t disfluid_account_get_subject (const struct DisfluidAccount *account, const struct DisfluidApi *api, size_t start, size_t max, char *subject) { SCM scm_id = scm_call_1 (api->scm_get_account_subject, account->object); return copy_scm_string (scm_id, start, max, subject); } size_t disfluid_account_get_issuer (const struct DisfluidAccount *account, const struct DisfluidApi *api, size_t start, size_t max, char *issuer) { SCM scm_id = scm_call_1 (api->scm_get_account_issuer, account->object); return copy_scm_string (scm_id, start, max, issuer); } size_t disfluid_account_get_key_pair (const struct DisfluidAccount *account, const struct DisfluidApi *api, size_t start, size_t max, char *jwk) { SCM scm_id = scm_call_1 (api->scm_get_account_key_pair, account->object); return copy_scm_string (scm_id, start, max, jwk); } size_t disfluid_account_get_id_token_header (const struct DisfluidAccount *account, const struct DisfluidApi *api, size_t start, size_t max, char *header) { SCM scm_id = scm_call_1 (api->scm_get_account_id_token_header, account->object); return copy_scm_string (scm_id, start, max, header); } size_t disfluid_account_get_id_token (const struct DisfluidAccount *account, const struct DisfluidApi *api, size_t start, size_t max, char *token) { SCM scm_id = scm_call_1 (api->scm_get_account_id_token, account->object); return copy_scm_string (scm_id, start, max, token); } size_t disfluid_account_get_access_token (const struct DisfluidAccount *account, const struct DisfluidApi *api, size_t start, size_t max, char *token) { SCM scm_id = scm_call_1 (api->scm_get_account_access_token, account->object); return copy_scm_string (scm_id, start, max, token); } size_t disfluid_account_get_refresh_token (const struct DisfluidAccount *account, const struct DisfluidApi *api, size_t start, size_t max, char *token) { SCM scm_id = scm_call_1 (api->scm_get_account_refresh_token, account->object); return copy_scm_string (scm_id, start, max, token); }