+Whenever an RRDP file is identified (ie. update notification URI) create a directory at '--local-repository' where all of the RRDP files (XMLs as well as 'publish' elements at those snapshot/delta files) will be created and read.
+The rsync URIs at the publish/withdraw elements, are mapped to the location <--local-repository>/<rrdp workspace>/<URI part>. Eg. if '--local-repository=/tmp/fort' and the current workspace (each TAL has its own workspace) is 'ABC', then the URI 'rsync://example.com/foo/bar.cer' will be created at '/tmp/fort/ABC/example.com/foo/bar.cer'.
-RSYNC repositories are still created at '--local-repository'.
result = false;
file = fopen(location, "rb");
if (file == NULL) {
- cb(errno, "Could not open location '%s'",
- location);
+ if (cb != NULL)
+ cb(errno, "Could not open location '%s'",
+ location);
return false;
}
if (fstat(fileno(file), &attr) == -1) {
- cb(errno, "fstat(%s) failed", location);
+ if (cb != NULL)
+ cb(errno, "fstat(%s) failed", location);
goto end;
}
end:
if (fclose(file) == -1)
- cb(errno, "fclose() failed");
+ if (cb != NULL)
+ cb(errno, "fclose() failed");
return result;
}
return hash_validate(algorithm, expected->buf, expected->size,
data->buf, data->size);
}
+
+/*
+ * Hash the @str using the specified @algorithm, setting the result at the
+ * @result buffer and its length at @result_len.
+ *
+ * Return 0 on success, any other value means error.
+ */
+int
+hash_str(char const *algorithm, char const *str, unsigned char *result,
+ unsigned int *result_len)
+{
+ unsigned char *src;
+ int error;
+
+ src = malloc(strlen(str));
+ if (src == NULL)
+ return pr_enomem();
+
+ memcpy(src, str, strlen(str));
+
+ error = hash_buffer(algorithm, src, strlen(str), result, result_len);
+
+ free(src);
+ return error;
+}
int hash_local_file(char const *, char const *, unsigned char *,
unsigned int *);
+int hash_str(char const *, char const *, unsigned char *, unsigned int *);
#endif /* SRC_HASH_H_ */
char const *ad_name, int ad_nid, int uri_flags, bool required,
int (*cb)(struct rpki_uri *, uint8_t, void *), void *arg)
{
-# define AD_METHOD (uri_flags == URI_VALID_RSYNC ? \
+# define AD_METHOD ((uri_flags & URI_VALID_RSYNC) == URI_VALID_RSYNC ? \
"RSYNC" : \
- ((uri_flags == URI_VALID_HTTPS) ? "HTTPS" : "RSYNC/HTTPS"))
+ (((uri_flags & URI_VALID_HTTPS) == URI_VALID_HTTPS) ? \
+ "HTTPS" : "RSYNC/HTTPS"))
ACCESS_DESCRIPTION *ad;
struct rpki_uri *uri;
bool found = false;
/* HTTPS RRDP */
error = handle_ad("SIA", sia, "rpkiNotify", nid_rpkiNotify(),
- URI_VALID_HTTPS, false, handle_rpkiNotify, &uris->rpkiNotify);
+ URI_VALID_HTTPS | URI_USE_RRDP_WORKSPACE, false, handle_rpkiNotify,
+ &uris->rpkiNotify);
if (error)
goto end;
* verified to comply with rfc6487#section-4.8.7
*/
static int
-force_aia_validation(struct rpki_uri *caIssuers, X509 *son, bool is_ta_child)
+force_aia_validation(struct rpki_uri *caIssuers, X509 *son)
{
X509 *parent;
struct rfc5280_name *son_name;
pr_val_debug("AIA's URI didn't matched parent URI, trying to SYNC");
- /* RSYNC is still the preferred access mechanism */
+ /* RSYNC is still the preferred access mechanism, force the sync */
do {
- error = download_files(caIssuers, false, false);
+ error = download_files(caIssuers, false, true);
if (!error)
break;
if (error == EREQFAILED) {
return error;
} while (0);
- /*
- * Consider the scenario where the TA was fetched from a distinct URI
- * (maybe an HTTPS URI), in that case keep doing the validation since
- * there's no "right" way to validate the AIA, that's where the flag
- * 'is_ta_child' comes into play.
- *
- * A possible way is to load the certificate from the cert_stack, but
- * the location itself isn't strictly the location from the AIA (the
- * solution works, but maybe it isn't right.
- */
error = certificate_load(caIssuers, &parent);
if (error)
- return !is_ta_child ? error : 0;
+ return error;
error = x509_name_decode(X509_get_subject_name(parent), "subject",
&parent_name);
* of the certificate where this Issuer is the subject (the issuer's
* immediate superior certificate)."
*
- * January 2020: this isn't a problem, all five RIRs are using one URI
- * at their TALs, that matches AIA from the first level root certificate
- * childs. Anyways, we'll try to consult the subject at IETF.
+ * As of today, this is a common scenario, since most of the TALs have
+ * an HTTPS URI.
*/
if (uri_equals(caIssuers, parent))
return 0;
/*
- * URI didn't match, try to match the immediate superior subject with
- * the current issuer. This will force an RSYNC of AIA's URI, load
- * the certificate and do the comparison.
+ * Avoid the check at direct TA childs, otherwise try to match the
+ * immediate superior subject with the current issuer. This will force
+ * an RSYNC of AIA's URI, load the certificate and do the comparison.
*/
- return force_aia_validation(caIssuers, cert,
- certstack_get_x509_num(validation_certstack(state)) == 1);
+ return certstack_get_x509_num(validation_certstack(state)) == 1 ?
+ 0 :
+ force_aia_validation(caIssuers, cert);
}
/*
return 0;
}
+/*
+ * Verify the manifest location at the local RRDP workspace. If the manifest
+ * exists, then update @mft_uri so that its location be at the workspace.
+ *
+ * Don't log in case the @mft_uri doesn't exist at the RRDP workspace.
+ */
+static int
+verify_rrdp_mft_loc(struct rpki_uri **mft_uri)
+{
+ struct rpki_uri *tmp;
+ int error;
+
+ if (db_rrdp_uris_workspace_get() == NULL)
+ return -ENOENT;
+
+ tmp = NULL;
+ error = uri_create_rsync_str_rrdp(&tmp, uri_get_global(*mft_uri),
+ uri_get_global_len(*mft_uri));
+ if (error)
+ return error;
+
+ if (!valid_file_or_dir(uri_get_local(tmp), true, false, NULL)) {
+ uri_refput(tmp);
+ return -EINVAL;
+ }
+
+ uri_refput(*mft_uri);
+ *mft_uri = tmp;
+ return 0;
+}
+
+static int
+replace_rrdp_mft_uri(struct sia_uri *sia_mft)
+{
+ struct rpki_uri *tmp;
+ int error;
+
+ tmp = NULL;
+ error = uri_create_rsync_str_rrdp(&tmp,
+ uri_get_global(sia_mft->uri),
+ uri_get_global_len(sia_mft->uri));
+ if (error)
+ return error;
+
+ uri_refput(sia_mft->uri);
+ sia_mft->uri = tmp;
+
+ return 0;
+}
+
static int
exec_rrdp_method(struct sia_ca_uris *sia_uris)
{
- return rrdp_load(sia_uris->rpkiNotify.uri);
+ int error;
+
+ /* Start working on the RRDP local workspace */
+ error = db_rrdp_uris_workspace_enable();
+ if (error)
+ return error;
+
+ error = rrdp_load(sia_uris->rpkiNotify.uri);
+ if (error) {
+ db_rrdp_uris_workspace_disable();
+ return error;
+ }
+
+ /* Successfully loaded (or no updates yet), update MFT local URI */
+ error = replace_rrdp_mft_uri(&sia_uris->mft);
+ if (error) {
+ db_rrdp_uris_workspace_disable();
+ return error;
+ }
+
+ return 0;
}
static int
exec_rsync_method(struct sia_ca_uris *sia_uris)
{
+ /* Stop working on the RRDP local workspace */
+ db_rrdp_uris_workspace_disable();
return download_files(sia_uris->caRepository.uri, false, false);
}
*/
static int
use_access_method(struct sia_ca_uris *sia_uris,
- access_method_exec rsync_cb, access_method_exec rrdp_cb,
+ access_method_exec rsync_cb, access_method_exec rrdp_cb, bool new_level,
bool *retry_repo_sync)
{
access_method_exec *cb_primary;
access_method_exec *cb_secondary;
rrdp_req_status_t rrdp_req_status;
bool primary_rrdp;
+ int upd_error;
int error;
+ /*
+ * By default, RRDP has a greater priority than rsync.
+ * See "http.priority" default value.
+ */
+ primary_rrdp = true;
+ (*retry_repo_sync) = true;
+
+ /*
+ * Very specific scenario, yet possible:
+ * - Still working at the same repository level
+ * - The previous object was working on an RRDP repository
+ * - This certificate doesn't have an update notification URI
+ *
+ * Probably the object does exist at the RRDP repository, so check if
+ * that's the case. Otherwise, just keep going.
+ *
+ * The main reason, is a (possible) hole at RFC 8182. Apparently, the
+ * CA childs aren't obligated to have the same RRDP accessMethod than
+ * their parent, so there's no problem if they don't use it at all; not
+ * even if such childs (and even the grandchilds or anyone below that
+ * level) "reside" at the RRDP repository.
+ */
+ if (!new_level && db_rrdp_uris_workspace_get() != NULL &&
+ sia_uris->rpkiNotify.uri == NULL &&
+ verify_rrdp_mft_loc(&sia_uris->mft.uri) == 0) {
+ (*retry_repo_sync) = false;
+ return replace_rrdp_mft_uri(&sia_uris->mft);
+ }
+
/*
* RSYNC will always be present (at least for now, see
* rfc6487#section-4.8.8.1). If rsync is disabled, the cb will take
* care of that.
*/
- (*retry_repo_sync) = true;
- if (sia_uris->rpkiNotify.uri == NULL || !config_get_http_enabled()) {
+ if (sia_uris->rpkiNotify.uri == NULL) {
+ primary_rrdp = false;
error = rsync_cb(sia_uris);
goto verify_mft;
}
- /* RSYNC disabled, and RRDP is present, use it */
- if (!config_get_rsync_enabled()) {
- (*retry_repo_sync) = false;
- error = rrdp_cb(sia_uris);
- goto verify_mft;
- }
-
/*
* There isn't any restriction about the preferred access method of
* children CAs being the same as the parent CA.
error = db_rrdp_uris_get_request_status(
uri_get_global(sia_uris->rpkiNotify.uri), &rrdp_req_status);
if (error == 0 && rrdp_req_status == RRDP_URI_REQ_VISITED) {
+ error = db_rrdp_uris_workspace_enable();
+ if (error) {
+ db_rrdp_uris_workspace_disable();
+ return error;
+ }
(*retry_repo_sync) = false;
- return 0;
+ return replace_rrdp_mft_uri(&sia_uris->mft);
}
/* Use CA's or configured priority? */
uri_get_global(sia_uris->rpkiNotify.uri));
}
+ /* Retry if rrdp was the first option but failed */
(*retry_repo_sync) = primary_rrdp;
error = cb_secondary(sia_uris);
/* No need to remember the working repository anymore */
default:
return error;
}
+
+ /* Error and the primary access method was RRDP? Use its workspace */
+ if (error && primary_rrdp) {
+ db_rrdp_uris_workspace_enable();
+ upd_error = replace_rrdp_mft_uri(&sia_uris->mft);
+ if (upd_error)
+ return upd_error;
+ }
+
/* Look for the manifest */
return verify_mft_loc(sia_uris->mft.uri);
}
static int
set_repository_level(bool is_ta, struct validation *state,
- struct rpki_uri *cert_uri, struct sia_ca_uris *sia_uris)
+ struct rpki_uri *cert_uri, struct sia_ca_uris *sia_uris, bool *updated)
{
char *parent_server, *current_server;
size_t parent_server_len, current_server_len;
free(parent_server);
free(current_server);
+ (*updated) = update;
return 0;
}
enum cert_type type;
struct rpp *pp;
bool repo_retry;
+ bool new_level;
int error;
state = state_retrieve();
}
/* Identify if this is a new repository before fetching it */
- error = set_repository_level(IS_TA, state, cert_uri, &sia_uris);
+ new_level = false;
+ error = set_repository_level(IS_TA, state, cert_uri, &sia_uris,
+ &new_level);
if (error)
goto revert_uris;
*
* Trying to avoid this issue, download the CA repository and validate
* manifest (and its content) again.
- *
+ *
* Avoid to re-download the repo if the mft was fetched with RRDP.
*/
repo_retry = true;
error = use_access_method(&sia_uris, exec_rsync_method,
- exec_rrdp_method, &repo_retry);
+ exec_rrdp_method, new_level, &repo_retry);
if (error)
goto revert_uris;
cert = NULL; /* Ownership stolen */
- error = handle_manifest(sia_uris.mft.uri, &pp);
+ error = handle_manifest(sia_uris.mft.uri, !repo_retry, &pp);
if (error == 0 || !repo_retry)
break;
}
static int
-build_rpp(struct Manifest *mft, struct rpki_uri *mft_uri, struct rpp **pp)
+build_rpp(struct Manifest *mft, struct rpki_uri *mft_uri, bool rrdp_workspace,
+ struct rpp **pp)
{
int i;
struct FileAndHash *fah;
for (i = 0; i < mft->fileList.list.count; i++) {
fah = mft->fileList.list.array[i];
- error = uri_create_mft(&uri, mft_uri, &fah->file);
+ error = uri_create_mft(&uri, mft_uri, &fah->file,
+ rrdp_workspace);
/*
* Not handling ENOTRSYNC is fine because the manifest URL
* should have been RSYNC. Something went wrong if an RSYNC URL
/**
* Validates the manifest pointed by @uri, returns the RPP described by it in
- * @pp.
+ * @pp. If @rrdp_workspace is true, use the local RRDP repository.
*/
int
-handle_manifest(struct rpki_uri *uri, struct rpp **pp)
+handle_manifest(struct rpki_uri *uri, bool rrdp_workspace, struct rpp **pp)
{
static OID oid = OID_MANIFEST;
struct oid_arcs arcs = OID2ARCS("manifest", oid);
goto revert_sobj;
/* Initialize out parameter (@pp) */
- error = build_rpp(mft, uri, pp);
+ error = build_rpp(mft, uri, rrdp_workspace, pp);
if (error)
goto revert_manifest;
#ifndef SRC_OBJECT_MANIFEST_H_
#define SRC_OBJECT_MANIFEST_H_
+#include <stdbool.h>
#include "uri.h"
#include "rpp.h"
-int handle_manifest(struct rpki_uri *, struct rpp **);
+int handle_manifest(struct rpki_uri *, bool, struct rpp **);
#endif /* SRC_OBJECT_MANIFEST_H_ */
#include <sys/queue.h>
#include <pthread.h>
+#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
+#include "crypto/hash.h"
#include "common.h"
#include "log.h"
struct tal_elem {
char *file_name;
struct db_rrdp_uri *uris;
+ char *workspace;
bool visited;
SLIST_ENTRY(tal_elem) next;
};
/** Read/write lock, which protects @db. */
static pthread_rwlock_t lock;
+/*
+ * Creates an ID for the RRDP local workspace.
+ *
+ * The ID is generated using the hash (sha-1) of @base. The first 4 bytes of
+ * the hash are "stringified" (8 chars) and a '/' is added at the end to
+ * (later) facilitate the concatenation of the ID at --local-repository.
+ *
+ * The ID is allocated at @result.
+ */
+static int
+get_workspace_path(char const *base, char **result)
+{
+/* SHA1 produces 20 bytes */
+#define HASH_LEN 20
+/* We'll use the first 4 bytes (8 chars) */
+#define OUT_LEN 8
+ unsigned char *hash;
+ unsigned int hash_len;
+ unsigned int i;
+ char *tmp;
+ char *ptr;
+ int error;
+
+ hash = malloc(HASH_LEN * sizeof(unsigned char));
+ if (hash == NULL)
+ return pr_enomem();
+
+ hash_len = 0;
+ error = hash_str("sha1", base, hash, &hash_len);
+ if (error) {
+ free(hash);
+ return error;
+ }
+
+ /* Get the first bytes + one slash + NUL char */
+ tmp = malloc(OUT_LEN + 2);
+ if (tmp == NULL) {
+ free(hash);
+ return pr_enomem();
+ }
+
+ ptr = tmp;
+ for (i = 0; i < OUT_LEN / 2; i++) {
+ sprintf(ptr, "%02X", hash[i]);
+ ptr += 2;
+ }
+ tmp[OUT_LEN] = '/';
+ tmp[OUT_LEN + 1] = '\0';
+
+ free(hash);
+ *result = tmp;
+ return 0;
+}
+
static int
tal_elem_create(struct tal_elem **elem, char const *name)
{
tmp_uris = NULL;
error = db_rrdp_uris_create(&tmp_uris);
- if (error) {
- free(tmp);
- return error;
- }
+ if (error)
+ goto end1;
tmp->uris = tmp_uris;
tmp->visited = true;
tmp->file_name = strdup(name);
if (tmp->file_name == NULL) {
- db_rrdp_uris_destroy(tmp->uris);
- free(tmp);
- return pr_enomem();
+ error = pr_enomem();
+ goto end2;
}
+ error = get_workspace_path(name, &tmp->workspace);
+ if (error)
+ goto end3;
+
*elem = tmp;
return 0;
+end3:
+ free(tmp->file_name);
+end2:
+ db_rrdp_uris_destroy(tmp->uris);
+end1:
+ free(tmp);
+ return error;
}
static void
db_rrdp_uris_remove_all_local(elem->uris);
db_rrdp_uris_destroy(elem->uris);
free(elem->file_name);
+ free(elem->workspace);
free(elem);
}
struct tal_elem *found;
found = db_rrdp_find_tal(tal_name);
- return found != NULL ? found->uris : NULL;
+ if (found == NULL)
+ pr_crit("db_rrdp_find_tal() returned NULL, means it hasn't been initialized");
+
+ return found->uris;
+}
+
+char const *
+db_rrdp_get_workspace(char const *tal_name)
+{
+ struct tal_elem *found;
+
+ found = db_rrdp_find_tal(tal_name);
+ if (found == NULL)
+ pr_crit("db_rrdp_find_tal() returned NULL, means it hasn't been initialized");
+
+ return found->workspace;
}
/* Set all tals to non-visited */
int db_rrdp_add_tal(char const *);
void db_rrdp_rem_tal(char const *);
+
struct db_rrdp_uri *db_rrdp_get_uris(char const *);
+char const *db_rrdp_get_workspace(char const *);
void db_rrdp_reset_visited_tals(void);
void db_rrdp_rem_nonvisited_tals(void);
struct db_rrdp_uri {
struct uris_table *table;
+ char const *current_workspace;
};
static int
return 0;
}
+static int
+get_thread_rrdp_workspace(char const **result)
+{
+ struct validation *state;
+
+ state = state_retrieve();
+ if (state == NULL)
+ return pr_val_err("No state related to this thread");
+
+ *result = validation_get_rrdp_workspace(state);
+ return 0;
+}
+
int
db_rrdp_uris_create(struct db_rrdp_uri **uris)
{
return pr_enomem();
tmp->table = NULL;
+ tmp->current_workspace = NULL;
*uris = tmp;
return 0;
return 0;
}
+
+char const *
+db_rrdp_uris_workspace_get(void)
+{
+ struct db_rrdp_uri *uris;
+ int error;
+
+ uris = NULL;
+ error = get_thread_rrdp_uris(&uris);
+ if (error)
+ return NULL;
+
+ return uris->current_workspace;
+}
+
+int
+db_rrdp_uris_workspace_enable(void)
+{
+ struct db_rrdp_uri *uris;
+ int error;
+
+ uris = NULL;
+ error = get_thread_rrdp_uris(&uris);
+ if (error)
+ return error;
+
+ return get_thread_rrdp_workspace(&uris->current_workspace);
+}
+
+int
+db_rrdp_uris_workspace_disable(void)
+{
+ struct db_rrdp_uri *uris;
+ int error;
+
+ uris = NULL;
+ error = get_thread_rrdp_uris(&uris);
+ if (error)
+ return error;
+
+ uris->current_workspace = NULL;
+ return 0;
+}
int db_rrdp_uris_remove_all_local(struct db_rrdp_uri *);
+char const *db_rrdp_uris_workspace_get(void);
+int db_rrdp_uris_workspace_enable(void);
+int db_rrdp_uris_workspace_disable(void);
+
#endif /* SRC_RRDP_DB_DB_RRDP_URIS_H_ */
uri = NULL;
if (tmp->doc_data.hash_len > 0) {
/* Get the current file from the uri */
- error = uri_create_rsync_str(&uri, tmp->doc_data.uri,
+ error = uri_create_rsync_str_rrdp(&uri, tmp->doc_data.uri,
strlen(tmp->doc_data.uri));
if (error)
goto release_base64;
goto release_tmp;
/* rfc8181#section-2.2, get the file from the uri */
- error = uri_create_rsync_str(&uri, tmp->doc_data.uri,
+ error = uri_create_rsync_str_rrdp(&uri, tmp->doc_data.uri,
strlen(tmp->doc_data.uri));
if (error)
goto release_tmp;
int error;
/* rfc8181#section-2.2 must be an rsync URI */
- error = uri_create_rsync_str(&uri, location, strlen(location));
+ error = uri_create_rsync_str_rrdp(&uri, location, strlen(location));
if (error)
return error;
int error;
/* rfc8181#section-2.2 must be an rsync URI */
- error = uri_create_rsync_str(&uri, location, strlen(location));
+ error = uri_create_rsync_str_rrdp(&uri, location, strlen(location));
if (error)
return error;
head_data = &delta_head->doc_data;
pr_val_debug("Processing delta '%s'.", delta_head->doc_data.uri);
- error = uri_create_https_str(&uri, head_data->uri,
+ error = uri_create_https_str_rrdp(&uri, head_data->uri,
strlen(head_data->uri));
if (error)
return error;
args.visited_uris = visited_uris;
pr_val_debug("Processing snapshot '%s'.", parent->snapshot.uri);
- error = uri_create_https_str(&uri, parent->snapshot.uri,
+ error = uri_create_https_str_rrdp(&uri, parent->snapshot.uri,
strlen(parent->snapshot.uri));
if (error)
return error;
* Returned values if the ancestor URI of @error_uri:
* 0 - didn't had a previous request error
* EEXIST - had a previous request error
- * > 0 - nothing, just something bad happened
+ * < 0 - nothing, just something bad happened
*/
static int
ancestor_error(char const *error_uri, void *arg)
int error;
req_err_uri = NULL;
- error = uri_create_rsync_str(&req_err_uri, error_uri,
+ error = uri_create_mixed_str(&req_err_uri, error_uri,
strlen(error_uri));
switch(error) {
case 0:
break;
- case ENOTRSYNC:
- return 0;
default:
return ENSURE_NEGATIVE(error);
}
+ /* Ignore non rsync error'd URIs */
+ if (!uri_is_rsync(req_err_uri)) {
+ free(req_err_uri);
+ return 0;
+ }
+
error = is_descendant(req_err_uri, search) ? EEXIST : 0;
free(req_err_uri);
return error;
}
+/* Validate if the ancestor URI error'd */
+static int
+check_ancestor_error(struct rpki_uri *requested_uri)
+{
+ int error;
+
+ error = reqs_errors_foreach(ancestor_error, requested_uri);
+ if (error < 0)
+ return error;
+ /* Return the requests error'd code */
+ if (error == EEXIST)
+ return EREQFAILED;
+
+ return 0;
+}
+
/**
* @is_ta: Are we rsync'ing the TA?
* The TA rsync will not be recursive, and will force SYNC_STRICT
if (!force && is_already_downloaded(requested_uri, visited_uris)) {
pr_val_debug("No need to redownload '%s'.",
uri_val_get_printable(requested_uri));
- return 0;
+ return check_ancestor_error(requested_uri);
}
if (!force)
error = get_rsync_uri(requested_uri, is_ta, &rsync_uri);
else {
- /* Validate if the ancestor URI error'd */
- error = reqs_errors_foreach(ancestor_error, requested_uri);
- if (error < 0)
+ error = check_ancestor_error(requested_uri);
+ if (error)
return error;
- /* Return the requests error'd code */
- if (error == EEXIST)
- return EREQFAILED;
error = handle_strict_strategy(requested_uri, &rsync_uri);
}
pr_val_debug("Going to RSYNC '%s'.", uri_val_get_printable(rsync_uri));
- to_op_log = reqs_errors_log_uri(uri_get_global(requested_uri));
+ to_op_log = reqs_errors_log_uri(uri_get_global(rsync_uri));
error = do_rsync(rsync_uri, is_ta, to_op_log);
switch(error) {
case 0:
/* Don't store when "force" and if its already downloaded */
if (!(force && is_already_downloaded(rsync_uri, visited_uris)))
error = mark_as_downloaded(rsync_uri, visited_uris);
- reqs_errors_rem_uri(uri_get_global(requested_uri));
+ reqs_errors_rem_uri(uri_get_global(rsync_uri));
break;
case EREQFAILED:
/* All attempts failed, avoid future requests */
- error = reqs_errors_add_uri(uri_get_global(requested_uri));
+ error = reqs_errors_add_uri(uri_get_global(rsync_uri));
if (error)
break;
error = mark_as_downloaded(rsync_uri, visited_uris);
struct uri_list *rsync_visited_uris;
+ /* Local RRDP workspace path */
+ char const *rrdp_workspace;
+
/* Shallow copy of RRDP URIs and its corresponding visited uris */
struct db_rrdp_uri *rrdp_uris;
struct validation_handler *validation_handler)
{
struct validation *result;
- struct db_rrdp_uri *uris_table;
X509_VERIFY_PARAM *params;
int error;
if (error)
goto abort4;
- uris_table = db_rrdp_get_uris(tal_get_file_name(tal));
- if (uris_table == NULL)
- pr_crit("db_rrdp_get_uris() returned NULL, means it hasn't been initialized");
- result->rrdp_uris = uris_table;
+ result->rrdp_uris = db_rrdp_get_uris(tal_get_file_name(tal));
+ result->rrdp_workspace = db_rrdp_get_workspace(tal_get_file_name(tal));
result->pubkey_state = PKS_UNTESTED;
result->validation_handler = *validation_handler;
{
return state->rrdp_uris;
}
+
+char const *
+validation_get_rrdp_workspace(struct validation *state)
+{
+ return state->rrdp_workspace;
+}
validation_get_validation_handler(struct validation *);
struct db_rrdp_uri *validation_get_rrdp_uris(struct validation *);
+char const *validation_get_rrdp_workspace(struct validation *);
#endif /* SRC_STATE_H_ */
#include <errno.h>
#include <strings.h>
+#include "rrdp/db/db_rrdp_uris.h"
#include "common.h"
#include "config.h"
#include "log.h"
static char const *const PFX_HTTPS = "https://";
size_t const PFX_RSYNC_LEN = strlen(PFX_RSYNC);
size_t const PFX_HTTPS_LEN = strlen(PFX_HTTPS);
+ uint8_t l_flags;
int error;
- if (flags == URI_VALID_RSYNC) {
+ /* Exclude RSYNC RRDP flag, isn't relevant here */
+ l_flags = flags & ~URI_USE_RRDP_WORKSPACE;
+
+ if (l_flags == URI_VALID_RSYNC) {
(*type) = URI_RSYNC;
return validate_uri_begin(PFX_RSYNC, PFX_RSYNC_LEN, global,
global_len, size, ENOTRSYNC);
}
- if (flags == URI_VALID_HTTPS) {
+ if (l_flags == URI_VALID_HTTPS) {
(*type) = URI_HTTPS;
return validate_uri_begin(PFX_HTTPS, PFX_HTTPS_LEN, global,
global_len, size, ENOTHTTPS);
}
- if (flags != (URI_VALID_RSYNC & URI_VALID_HTTPS))
+ if (l_flags != (URI_VALID_RSYNC | URI_VALID_HTTPS))
pr_crit("Unknown URI flag");
/* It has both flags */
return 0;
}
+static int
+get_local_workspace(char **result, size_t *result_len)
+{
+ char const *workspace;
+ char *tmp;
+
+ workspace = db_rrdp_uris_workspace_get();
+ if (workspace == NULL) {
+ *result = NULL;
+ *result_len = 0;
+ return 0;
+ }
+
+ tmp = strdup(workspace);
+ if (tmp == NULL)
+ return pr_enomem();
+
+ *result = tmp;
+ *result_len = strlen(tmp);
+ return 0;
+}
+
/**
* Initializes @uri->local by converting @uri->global.
*
{
char const *repository;
char *local;
+ char *workspace;
size_t prefix_len;
size_t repository_len;
size_t extra_slash;
size_t offset;
+ size_t workspace_len;
enum rpki_uri_type type;
int error;
global_len -= prefix_len;
extra_slash = (repository[repository_len - 1] == '/') ? 0 : 1;
- local = malloc(repository_len + extra_slash + global_len + 1);
- if (!local)
+ workspace = NULL;
+ workspace_len = 0;
+ if ((flags & URI_USE_RRDP_WORKSPACE) != 0) {
+ error = get_local_workspace(&workspace, &workspace_len);
+ if (error)
+ return error;
+ }
+
+ local = malloc(repository_len + extra_slash + workspace_len +
+ global_len + 1);
+ if (!local) {
+ free(workspace);
return pr_enomem();
+ }
offset = 0;
strcpy(local + offset, repository);
strcpy(local + offset, "/");
offset += extra_slash;
}
+ if (workspace_len > 0) {
+ strcpy(local + offset, workspace);
+ offset += workspace_len;
+ }
strncpy(local + offset, global, global_len);
offset += global_len;
local[offset] = '\0';
+ free(workspace);
*result = local;
(*result_type) = type;
return 0;
}
int
-uri_create_rsync_str(struct rpki_uri **uri, char const *guri, size_t guri_len)
+uri_create_rsync_str_rrdp(struct rpki_uri **uri, char const *guri,
+ size_t guri_len)
{
- return uri_create(uri, URI_VALID_RSYNC, guri, guri_len);
+ return uri_create(uri, URI_VALID_RSYNC | URI_USE_RRDP_WORKSPACE, guri,
+ guri_len);
+}
+
+int
+uri_create_https_str_rrdp(struct rpki_uri **uri, char const *guri,
+ size_t guri_len)
+{
+ return uri_create(uri, URI_VALID_HTTPS | URI_USE_RRDP_WORKSPACE, guri,
+ guri_len);
}
int
-uri_create_https_str(struct rpki_uri **uri, char const *guri, size_t guri_len)
+uri_create_rsync_str(struct rpki_uri **uri, char const *guri, size_t guri_len)
{
- return uri_create(uri, URI_VALID_HTTPS, guri, guri_len);
+ return uri_create(uri, URI_VALID_RSYNC, guri, guri_len);
}
/*
int
uri_create_mixed_str(struct rpki_uri **uri, char const *guri, size_t guri_len)
{
- return uri_create(uri, URI_VALID_RSYNC & URI_VALID_HTTPS, guri,
+ return uri_create(uri, URI_VALID_RSYNC | URI_VALID_HTTPS, guri,
guri_len);
}
* Manifests URIs are a little special in that they are relative.
*/
int
-uri_create_mft(struct rpki_uri **result, struct rpki_uri *mft, IA5String_t *ia5)
+uri_create_mft(struct rpki_uri **result, struct rpki_uri *mft, IA5String_t *ia5,
+ bool use_rrdp_workspace)
{
struct rpki_uri *uri;
+ uint8_t flags;
int error;
uri = malloc(sizeof(struct rpki_uri));
return error;
}
- error = autocomplete_local(uri, URI_VALID_RSYNC);
+ flags = URI_VALID_RSYNC;
+ if (use_rrdp_workspace)
+ flags |= URI_USE_RRDP_WORKSPACE;
+
+ error = autocomplete_local(uri, flags);
if (error) {
free(uri->global);
free(uri);
#include "asn1/asn1c/IA5String.h"
/* Flags to indicate expected uri type */
-#define URI_VALID_RSYNC 0x01
-#define URI_VALID_HTTPS 0x02
+#define URI_VALID_RSYNC 0x01
+#define URI_VALID_HTTPS 0x02
+/* Work with a local workspace (eg. map rsync RRPD uri's) */
+#define URI_USE_RRDP_WORKSPACE 0x10
struct rpki_uri;
+/* Maps RSYNC URIs of RRDP to a local workspace */
+int uri_create_rsync_str_rrdp(struct rpki_uri **, char const *, size_t);
+int uri_create_https_str_rrdp(struct rpki_uri **, char const *, size_t);
+
int uri_create_rsync_str(struct rpki_uri **, char const *, size_t);
-int uri_create_https_str(struct rpki_uri **, char const *, size_t);
int uri_create_mixed_str(struct rpki_uri **, char const *, size_t);
-int uri_create_mft(struct rpki_uri **, struct rpki_uri *, IA5String_t *);
+int uri_create_mft(struct rpki_uri **, struct rpki_uri *, IA5String_t *, bool);
int uri_create_ad(struct rpki_uri **, ACCESS_DESCRIPTION *, int);
void uri_refget(struct rpki_uri *);