[PATCH 2/2] erofs-utils: lib: oci: allow HTTP connections to registry
hudsonZhu
hudson at cyzhu.com
Mon Dec 1 20:25:38 AEDT 2025
Thanks for this patch, Yifan !
It looks good to me. I have tested the patch and it works as expected.
One suggestion: it would be nice to have similar functionality in
mount.erofs as well, for consistency across the toolkit.
Reviewed-and-tested-by: Chengyu Zhu <hudsonzhu at tencent.com>
Thanks,
Chengyu
> 2025年11月30日 18:42,Yifan Zhao <zhaoyifan28 at huawei.com> 写道:
>
> 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