[PATCH 2/2] erofs-utils: lib: oci: allow HTTP connections to registry

Gao Xiang hsiangkao at linux.alibaba.com
Tue Dec 2 18:40:15 AEDT 2025


Hi Yifan,

Would you mind updating mkfs.erofs manpage too?

Thanks,
Gao Xiang

On 2025/12/1 19:15, zhaoyifan (H) wrote:
> Hi Chengyu,
> 
> Thanks for your review. I will try to deal with `mount.erofs` later.
> 
> 
> Thanks,
> 
> Yifan Zhao
> 
> 
> On 2025/12/1 17:25, hudsonZhu wrote:
>> 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