[PATCH 2/2] erofs-utils: lib: oci: allow HTTP connections to registry
Yifan Zhao
zhaoyifan28 at huawei.com
Sun Nov 30 21:42:57 AEDT 2025
Currently, the URL used to send requests to the registry is hardcoded
with "https://". This patch introduces an optional insecure option for
`--oci`, enabling registry access via the HTTP protocol.
Also, this patch refactors the deeply nested logic in the `--oci`
argument parsing.
Signed-off-by: Yifan Zhao <zhaoyifan28 at huawei.com>
---
lib/liberofs_oci.h | 3 ++
lib/remotes/oci.c | 40 +++++++++++--------
mkfs/main.c | 97 ++++++++++++++++++++--------------------------
3 files changed, 70 insertions(+), 70 deletions(-)
diff --git a/lib/liberofs_oci.h b/lib/liberofs_oci.h
index 5298f18..9e0571f 100644
--- a/lib/liberofs_oci.h
+++ b/lib/liberofs_oci.h
@@ -23,6 +23,7 @@ struct erofs_importer;
* @password: password for authentication (optional)
* @blob_digest: specific blob digest to extract (NULL for all layers)
* @layer_index: specific layer index to extract (negative for all layers)
+ * @insecure: use HTTP for registry communication (optional)
*
* Configuration structure for OCI image parameters including registry
* location, image identification, platform specification, and authentication
@@ -37,6 +38,7 @@ struct ocierofs_config {
int layer_index;
char *tarindex_path;
char *zinfo_path;
+ bool insecure;
};
struct ocierofs_layer_info {
@@ -57,6 +59,7 @@ struct ocierofs_ctx {
struct ocierofs_layer_info **layers;
char *blob_digest;
int layer_count;
+ const char *schema;
};
struct ocierofs_iostream {
diff --git a/lib/remotes/oci.c b/lib/remotes/oci.c
index c1d6cae..d5afd6a 100644
--- a/lib/remotes/oci.c
+++ b/lib/remotes/oci.c
@@ -496,8 +496,8 @@ static char *ocierofs_discover_auth_endpoint(struct ocierofs_ctx *ctx,
api_registry = ocierofs_get_api_registry(registry);
- if (asprintf(&test_url, "https://%s/v2/%s/manifests/nonexistent",
- api_registry, repository) < 0)
+ if (asprintf(&test_url, "%s%s/v2/%s/manifests/nonexistent",
+ ctx->schema, api_registry, repository) < 0)
return NULL;
curl_easy_reset(ctx->curl);
@@ -528,9 +528,9 @@ static char *ocierofs_get_auth_token(struct ocierofs_ctx *ctx, const char *regis
const char *password)
{
static const char * const auth_patterns[] = {
- "https://%s/v2/auth",
- "https://auth.%s/token",
- "https://%s/token",
+ "%s%s/v2/auth",
+ "%sauth.%s/token",
+ "%s%s/token",
NULL,
};
char *auth_header = NULL;
@@ -561,8 +561,8 @@ static char *ocierofs_get_auth_token(struct ocierofs_ctx *ctx, const char *regis
api_registry = ocierofs_get_api_registry(registry);
- if (asprintf(&test_url, "https://%s/v2/%s/manifests/nonexistent",
- api_registry, repository) >= 0) {
+ if (asprintf(&test_url, "%s%s/v2/%s/manifests/nonexistent",
+ ctx->schema, api_registry, repository) >= 0) {
curl_easy_reset(ctx->curl);
ocierofs_curl_setup_common_options(ctx->curl);
@@ -598,7 +598,7 @@ static char *ocierofs_get_auth_token(struct ocierofs_ctx *ctx, const char *regis
for (i = 0; auth_patterns[i]; i++) {
char *auth_url;
- if (asprintf(&auth_url, auth_patterns[i], registry) < 0)
+ if (asprintf(&auth_url, auth_patterns[i], ctx->schema, registry) < 0)
continue;
auth_header = ocierofs_get_auth_token_with_url(ctx, auth_url,
@@ -629,8 +629,8 @@ static char *ocierofs_get_manifest_digest(struct ocierofs_ctx *ctx,
int ret = 0, len, i;
api_registry = ocierofs_get_api_registry(registry);
- if (asprintf(&req.url, "https://%s/v2/%s/manifests/%s",
- api_registry, repository, tag) < 0)
+ if (asprintf(&req.url, "%s%s/v2/%s/manifests/%s",
+ ctx->schema, api_registry, repository, tag) < 0)
return ERR_PTR(-ENOMEM);
if (auth_header && strstr(auth_header, "Bearer"))
@@ -749,8 +749,8 @@ static int ocierofs_fetch_layers_info(struct ocierofs_ctx *ctx)
ctx->layer_count = 0;
api_registry = ocierofs_get_api_registry(registry);
- if (asprintf(&req.url, "https://%s/v2/%s/manifests/%s",
- api_registry, repository, digest) < 0)
+ if (asprintf(&req.url, "%s%s/v2/%s/manifests/%s",
+ ctx->schema, api_registry, repository, digest) < 0)
return -ENOMEM;
if (auth_header && strstr(auth_header, "Bearer"))
@@ -1124,10 +1124,18 @@ static int ocierofs_init(struct ocierofs_ctx *ctx, const struct ocierofs_config
if (!ctx->registry || !ctx->tag || !ctx->platform)
return -ENOMEM;
+ ctx->schema = config->insecure ? "http://" : "https://";
+
ret = ocierofs_parse_ref(ctx, config->image_ref);
if (ret)
return ret;
+ if (config->insecure && (!strcmp(ctx->registry, DOCKER_API_REGISTRY) ||
+ !strcmp(ctx->registry, DOCKER_REGISTRY))) {
+ erofs_err("Insecure connection to Docker registry is not allowed");
+ return -EINVAL;
+ }
+
ret = ocierofs_prepare_layers(ctx, config);
if (ret)
return ret;
@@ -1152,8 +1160,8 @@ static int ocierofs_download_blob_to_fd(struct ocierofs_ctx *ctx,
};
api_registry = ocierofs_get_api_registry(ctx->registry);
- if (asprintf(&req.url, "https://%s/v2/%s/blobs/%s",
- api_registry, ctx->repository, digest) == -1)
+ if (asprintf(&req.url, "%s%s/v2/%s/blobs/%s",
+ ctx->schema, api_registry, ctx->repository, digest) == -1)
return -ENOMEM;
if (auth_header && strstr(auth_header, "Bearer"))
@@ -1344,8 +1352,8 @@ static int ocierofs_download_blob_range(struct ocierofs_ctx *ctx, off_t offset,
length = (size_t)(blob_size - offset);
api_registry = ocierofs_get_api_registry(ctx->registry);
- if (asprintf(&req.url, "https://%s/v2/%s/blobs/%s",
- api_registry, ctx->repository, digest) == -1)
+ if (asprintf(&req.url, "%s%s/v2/%s/blobs/%s",
+ ctx->schema, api_registry, ctx->repository, digest) == -1)
return -ENOMEM;
if (length)
diff --git a/mkfs/main.c b/mkfs/main.c
index 7aa8eae..5710948 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -218,11 +218,12 @@ static void usage(int argc, char **argv)
#endif
#ifdef OCIEROFS_ENABLED
" --oci=[f|i] generate a full (f) or index-only (i) image from OCI remote source\n"
- " [,=platform=X] X=platform (default: linux/amd64)\n"
+ " [,platform=X] X=platform (default: linux/amd64)\n"
" [,layer=#] #=layer index to extract (0-based; omit to extract all layers)\n"
" [,blob=Y] Y=blob digest to extract (omit to extract all layers)\n"
" [,username=Z] Z=username for authentication (optional)\n"
" [,password=W] W=password for authentication (optional)\n"
+ " [,insecure] use HTTP instead of HTTPS (optional)\n"
#endif
" --tar=X generate a full or index-only image from a tarball(-ish) source\n"
" (X = f|i|headerball; f=full mode, i=index mode,\n"
@@ -744,7 +745,7 @@ static int mkfs_parse_s3_cfg(char *cfg_str)
* Parse OCI options string containing comma-separated key=value pairs.
*
* Supported options include f|i, platform, blob|layer, username, password,
- * and zinfo.
+ * and insecure.
*
* Return: 0 on success, negative errno on failure
*/
@@ -772,67 +773,55 @@ static int mkfs_parse_oci_options(struct ocierofs_config *oci_cfg, char *options
if (q)
*q = '\0';
-
- p = strstr(opt, "platform=");
- if (p) {
+ if ((p = strstr(opt, "platform="))) {
p += strlen("platform=");
free(oci_cfg->platform);
oci_cfg->platform = strdup(p);
if (!oci_cfg->platform)
return -ENOMEM;
- } else {
- p = strstr(opt, "blob=");
- if (p) {
- p += strlen("blob=");
- free(oci_cfg->blob_digest);
+ } else if ((p = strstr(opt, "blob="))) {
+ p += strlen("blob=");
+ free(oci_cfg->blob_digest);
- if (oci_cfg->layer_index >= 0) {
- erofs_err("invalid --oci: blob and layer cannot be set together");
- return -EINVAL;
- }
+ if (oci_cfg->layer_index >= 0) {
+ erofs_err("invalid --oci: blob and layer cannot be set together");
+ return -EINVAL;
+ }
- if (!strncmp(p, "sha256:", 7)) {
- oci_cfg->blob_digest = strdup(p);
- if (!oci_cfg->blob_digest)
- return -ENOMEM;
- } else if (asprintf(&oci_cfg->blob_digest, "sha256:%s", p) < 0) {
+ if (!strncmp(p, "sha256:", 7)) {
+ oci_cfg->blob_digest = strdup(p);
+ if (!oci_cfg->blob_digest)
return -ENOMEM;
- }
- } else {
- p = strstr(opt, "layer=");
- if (p) {
- p += strlen("layer=");
- if (oci_cfg->blob_digest) {
- erofs_err("invalid --oci: layer and blob cannot be set together");
- return -EINVAL;
- }
- idx = strtol(p, NULL, 10);
- if (idx < 0)
- return -EINVAL;
- oci_cfg->layer_index = (int)idx;
- } else {
- p = strstr(opt, "username=");
- if (p) {
- p += strlen("username=");
- free(oci_cfg->username);
- oci_cfg->username = strdup(p);
- if (!oci_cfg->username)
- return -ENOMEM;
- } else {
- p = strstr(opt, "password=");
- if (p) {
- p += strlen("password=");
- free(oci_cfg->password);
- oci_cfg->password = strdup(p);
- if (!oci_cfg->password)
- return -ENOMEM;
- } else {
- erofs_err("mkfs: invalid --oci value %s", opt);
- return -EINVAL;
- }
- }
- }
+ } else if (asprintf(&oci_cfg->blob_digest, "sha256:%s", p) < 0) {
+ return -ENOMEM;
}
+ } else if ((p = strstr(opt, "layer="))) {
+ p += strlen("layer=");
+ if (oci_cfg->blob_digest) {
+ erofs_err("invalid --oci: layer and blob cannot be set together");
+ return -EINVAL;
+ }
+ idx = strtol(p, NULL, 10);
+ if (idx < 0)
+ return -EINVAL;
+ oci_cfg->layer_index = (int)idx;
+ } else if ((p = strstr(opt, "username="))) {
+ p += strlen("username=");
+ free(oci_cfg->username);
+ oci_cfg->username = strdup(p);
+ if (!oci_cfg->username)
+ return -ENOMEM;
+ } else if ((p = strstr(opt, "password="))) {
+ p += strlen("password=");
+ free(oci_cfg->password);
+ oci_cfg->password = strdup(p);
+ if (!oci_cfg->password)
+ return -ENOMEM;
+ } else if ((p = strstr(opt, "insecure"))) {
+ oci_cfg->insecure = true;
+ } else {
+ erofs_err("mkfs: invalid --oci value %s", opt);
+ return -EINVAL;
}
opt = q ? q + 1 : NULL;
--
2.43.0
More information about the Linux-erofs
mailing list