Tools to make secret sharing easier.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

202 lines
5.3 KiB

/*
* gfsecret - Secret sharing tools
* Copyright (C) 2021 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "scheme-libcurl.h"
#include <string.h>
#include <xmem.h>
#include "scheme-module.h"
#ifdef HAVE_LIBCURL
#include <curl/curl.h>
static int
check_response(CURL *curl)
{
long http_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
return http_code == 200 || http_code == 201 ? 0 : 1;
}
struct getfile_cb_data {
unsigned char *buffer;
size_t written;
size_t allocated;
};
static size_t
write_cb(void *buffer, size_t size, size_t nmemb, void *userp)
{
struct getfile_cb_data *data = (struct getfile_cb_data *)userp;
if ( data->written + nmemb >= data->allocated ) {
size_t needed = data->written + nmemb;
data->buffer = xrealloc(data->buffer, needed);
data->allocated = needed;
}
memcpy(data->buffer + data->written, buffer, nmemb);
data->written += nmemb;
return nmemb;
}
int
gfsec_scheme_libcurl_get_file(gfsec_scheme_t scheme,
const char *authority,
const char *path,
unsigned char **buffer,
size_t *len)
{
int ret = GFSEC_SCHEME_STATUS_SUCCESS;
char *url = NULL;
CURL *curl;
struct getfile_cb_data data = { 0 };
if ( scheme != GFSEC_SCHEME_HTTP && scheme != GFSEC_SCHEME_HTTPS )
return GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME;
if ( ! (curl = curl_easy_init()) )
return GFSEC_SCHEME_STATUS_ERROR;
xasprintf(&url, "http%s://%s%s",
scheme == GFSEC_SCHEME_HTTP ? "" : "s",
authority, path);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&data);
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
if ( curl_easy_setopt(curl, CURLOPT_URL, url) != 0 )
ret = GFSEC_SCHEME_STATUS_ERROR;
if ( ret == 0 && curl_easy_perform(curl) != 0 )
ret = GFSEC_SCHEME_STATUS_ERROR;
if ( ret == 0 && check_response(curl) != 0 )
ret = GFSEC_SCHEME_STATUS_ERROR;
if ( ret == 0 ) {
*buffer = data.buffer;
*len = data.written;
}
curl_easy_cleanup(curl);
free(url);
return ret;
}
struct putfile_cb_data {
unsigned char *buffer;
size_t len;
size_t read;
};
static size_t
read_cb(char *buffer, size_t size, size_t nmemb, void *userp)
{
struct putfile_cb_data *data = (struct putfile_cb_data *)userp;
size_t len = size * nmemb;
if ( len > (data->len - data->read) )
len = data->len - data->read;
memcpy(buffer, data->buffer + data->read, len);
return len;
}
static size_t
dummy_write_cb(char *buffer, size_t size, size_t nmemb, void *userp)
{
(void) buffer;
(void) userp;
return size * nmemb;
}
int
gfsec_scheme_libcurl_put_file(gfsec_scheme_t scheme,
const char *authority,
const char *path,
unsigned char *buffer,
size_t len)
{
int ret = GFSEC_SCHEME_STATUS_SUCCESS;
char *url = NULL;
CURL *curl;
struct putfile_cb_data data = { 0 };
if ( scheme != GFSEC_SCHEME_HTTP && scheme != GFSEC_SCHEME_HTTPS )
return GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME;
if ( ! (curl = curl_easy_init()) )
return GFSEC_SCHEME_STATUS_ERROR;
xasprintf(&url, "http%s://%s%s",
scheme == GFSEC_SCHEME_HTTP ? "" : "s",
authority, path);
data.buffer = buffer;
data.len = len;
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb);
curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, dummy_write_cb);
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
if ( curl_easy_setopt(curl, CURLOPT_URL, url) != 0 )
ret = GFSEC_SCHEME_STATUS_ERROR;
if ( ret == 0 && curl_easy_setopt(curl, CURLOPT_INFILESIZE, len) != 0 )
ret = GFSEC_SCHEME_STATUS_ERROR;
if ( ret == 0 && curl_easy_perform(curl) != 0 )
ret = GFSEC_SCHEME_STATUS_ERROR;
if ( ret == 0 && check_response(curl) != 0 )
ret = GFSEC_SCHEME_STATUS_ERROR;
curl_easy_cleanup(curl);
free(url);
return ret;
}
int
gfsec_scheme_libcurl_get_supports(gfsec_supports_list_t *list)
{
(void) list;
return 0;
}
#endif /* HAVE_LIBCURL */