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 <[email protected]>
---
 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


Reply via email to