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
