@voxgig/sdkgen 4.10.0 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/voxgig-sdkgen +1 -1
- package/package.json +1 -1
- package/project/.sdk/model/feature/secrets.aon +330 -0
- package/project/.sdk/model/target/c.aon +15 -2
- package/project/.sdk/model/target/cpp.aon +18 -0
- package/project/.sdk/model/target/lua.aon +17 -0
- package/project/.sdk/model/target/ocaml.aon +48 -5
- package/project/.sdk/model/target/zig.aon +30 -4
- package/project/.sdk/src/cmp/c/Config_c.ts +338 -1
- package/project/.sdk/src/cmp/c/Main_c.ts +57 -2
- package/project/.sdk/src/cmp/c/Package_c.ts +12 -2
- package/project/.sdk/src/cmp/cpp/Config_cpp.ts +324 -2
- package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +2 -0
- package/project/.sdk/src/cmp/cpp/Main_cpp.ts +62 -4
- package/project/.sdk/src/cmp/cpp/Package_cpp.ts +10 -0
- package/project/.sdk/src/cmp/lua/Config_lua.ts +88 -0
- package/project/.sdk/src/cmp/lua/Gitignore_lua.ts +4 -0
- package/project/.sdk/src/cmp/lua/Main_lua.ts +93 -3
- package/project/.sdk/src/cmp/lua/Package_lua.ts +60 -0
- package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +10 -0
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +183 -5
- package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +160 -3
- package/project/.sdk/src/cmp/ocaml/Package_ocaml.ts +25 -1
- package/project/.sdk/src/cmp/zig/Config_zig.ts +130 -9
- package/project/.sdk/src/cmp/zig/Main_zig.ts +208 -4
- package/project/.sdk/{tm/zig/build.zig → src/cmp/zig/fragment/Build.fragment.zig} +7 -0
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +25 -0
- package/project/.sdk/{tm/zig/root.zig → src/cmp/zig/fragment/Root.fragment.zig} +9 -0
- package/project/.sdk/tm/c/Makefile +58 -9
- package/project/.sdk/tm/c/core/sdk.h +10 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/capability.c +133 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/capability.h +39 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/catalog.c +83 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/catalog.h +48 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/config.c +413 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/config.h +24 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/depend.c +264 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/depend.h +29 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/env.c +220 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/env.h +19 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/export.c +97 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/export.h +19 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/graph.c +237 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/graph.h +17 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/host.c +1494 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/host.h +135 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/order.c +288 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/order.h +18 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/point.c +141 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/point.h +80 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/ref.c +170 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/ref.h +52 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/resolve.c +98 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/resolve.h +18 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/types.c +150 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/types.h +104 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/value.c +649 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/value.h +135 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/version.c +151 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/version.h +34 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/aws.c +281 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/azuresecrets.c +207 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/boru.c +164 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/clock.c +75 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/doppler.c +141 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/encode.c +144 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/gcpsecrets.c +177 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/hashicorp.c +239 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/httpjson.c +599 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/infisical.c +165 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/onepassword.c +194 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/proc.c +233 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/secretspec.c +125 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/sekretoplugins.h +125 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/sha256.c +270 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/sigv4.c +382 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/support.h +153 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/tls.c +420 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/internal.h +86 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/json.c +721 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/providers.c +813 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/sekreto.c +944 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/sekreto.h +490 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/util.c +442 -0
- package/project/.sdk/tm/c/feature/secrets.c +797 -0
- package/project/.sdk/tm/c/feature/secrets.h +46 -0
- package/project/.sdk/tm/c/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/c/tests/feature/secrets/secrets_test.c +802 -0
- package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +38 -11
- package/project/.sdk/tm/clojure/test/sdk/test/feature/secrets.clj +40 -6
- package/project/.sdk/tm/cpp/Makefile +48 -4
- package/project/.sdk/tm/cpp/feature/secrets/plugin/capability.cpp +121 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/capability.hpp +41 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/catalog.cpp +60 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/catalog.hpp +66 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/config.cpp +376 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/config.hpp +29 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/depend.cpp +230 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/depend.hpp +31 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/env.cpp +205 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/env.hpp +25 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/export.cpp +84 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/export.hpp +24 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/graph.cpp +222 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/graph.hpp +21 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/host.cpp +1200 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/host.hpp +250 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/order.cpp +250 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/order.hpp +22 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/point.cpp +110 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/point.hpp +79 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/ref.cpp +136 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/ref.hpp +60 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/resolve.cpp +82 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/resolve.hpp +25 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/types.cpp +90 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/types.hpp +65 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/value.cpp +491 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/value.hpp +120 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/version.cpp +143 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/version.hpp +36 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Aws.cpp +248 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Aws.hpp +30 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Azuresecrets.cpp +149 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Azuresecrets.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Boru.cpp +117 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Boru.hpp +27 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Crypto.cpp +180 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Crypto.hpp +52 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Doppler.cpp +87 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Doppler.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Gcpsecrets.cpp +121 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Gcpsecrets.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Hashicorp.cpp +153 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Hashicorp.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Httpjson.cpp +666 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Httpjson.hpp +160 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Infisical.cpp +123 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Infisical.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Onepassword.cpp +125 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Onepassword.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Proc.cpp +223 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Proc.hpp +47 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Secretspec.cpp +104 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Secretspec.hpp +27 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Sigv4.cpp +242 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Sigv4.hpp +58 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Tls.cpp +260 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Tls.hpp +47 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Json.cpp +476 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Json.hpp +89 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Provider.cpp +312 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Provider.hpp +263 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Providers.cpp +354 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Providers.hpp +111 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Sekreto.cpp +613 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Sekreto.hpp +227 -0
- package/project/.sdk/tm/cpp/feature/secrets.hpp +745 -0
- package/project/.sdk/tm/cpp/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/cpp/test/feature/secrets/secrets_test.cpp +808 -0
- package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +34 -8
- package/project/.sdk/tm/csharp/test/feature/secrets/SecretsFeatureTest.cs +85 -0
- package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +17 -2
- package/project/.sdk/tm/elixir/test/feature/secrets/secrets_test.exs +41 -0
- package/project/.sdk/tm/go/feature/secrets_feature.go +32 -10
- package/project/.sdk/tm/go/test/feature/secrets/secrets_feature_test.go +116 -0
- package/project/.sdk/tm/java/feature/SecretsFeature.java +33 -8
- package/project/.sdk/tm/java/test/feature/secrets/SecretsFeatureTest.java +64 -0
- package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +34 -11
- package/project/.sdk/tm/js/test/feature/secrets/Secrets.test.js +73 -0
- package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +32 -7
- package/project/.sdk/tm/kotlin/test/feature/secrets/SecretsTest.kt +69 -0
- package/project/.sdk/tm/lua/Makefile +15 -4
- package/project/.sdk/tm/lua/feature/secrets/native/sekretonet.c +806 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/capability.lua +135 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/catalog.lua +63 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/config.lua +361 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/depend.lua +232 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/env.lua +168 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/export.lua +66 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/graph.lua +194 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/host.lua +1190 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/json.lua +169 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/order.lua +207 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/point.lua +106 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/ref.lua +115 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/resolve.lua +78 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/types.lua +275 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/version.lua +131 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin.lua +76 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/addr.lua +124 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/err.lua +47 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/name.lua +315 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/aws.lua +228 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/azuresecrets.lua +137 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/boru.lua +124 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/crypto.lua +212 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/doppler.lua +89 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/gcpsecrets.lua +129 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/hashicorp.lua +154 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/httpjson.lua +248 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/infisical.lua +113 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/json.lua +449 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/net.lua +198 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/onepassword.lua +126 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/secretspec.lua +93 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/sigv4.lua +269 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/support.lua +146 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/providers.lua +346 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto.lua +479 -0
- package/project/.sdk/tm/lua/feature/secrets_feature.lua +690 -0
- package/project/.sdk/tm/lua/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/lua/test/extend_test.lua +105 -0
- package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +862 -0
- package/project/.sdk/tm/ocaml/Makefile +52 -8
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/capability.ml +106 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/catalog.ml +43 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/config.ml +349 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/defs.ml +143 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/depend.ml +217 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/env.ml +197 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/export.ml +89 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/graph.ml +227 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/host.ml +1112 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/order.ml +202 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/point.ml +138 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/ref.ml +126 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/resolve.ml +62 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/types.ml +97 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/value.ml +387 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/version.ml +139 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/aws.ml +171 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/azuresecrets.ml +116 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/boru.ml +95 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/crypto.ml +149 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/doppler.ml +61 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/gcpsecrets.ml +93 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/hashicorp.ml +120 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/http.ml +421 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/httpjson.ml +66 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/infisical.ml +85 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/onepassword.ml +112 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/runcmd.ml +97 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/secretspec.ml +68 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/sigv4.ml +259 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/tls.ml +44 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/tls_stubs.c +358 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/json.ml +376 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/provider.ml +647 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/secret.ml +299 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/sekreto.ml +347 -0
- package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +453 -0
- package/project/.sdk/tm/ocaml/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +670 -0
- package/project/.sdk/tm/perl/feature/secrets_feature.pm +33 -12
- package/project/.sdk/tm/perl/t/feature/secrets/secrets.t +47 -0
- package/project/.sdk/tm/php/feature/SecretsFeature.php +30 -6
- package/project/.sdk/tm/php/test/feature/secrets/SecretsTest.php +98 -0
- package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +28 -6
- package/project/.sdk/tm/py/test/feature/secrets/test_secrets.py +114 -0
- package/project/.sdk/tm/rb/feature/secrets_feature.rb +28 -6
- package/project/.sdk/tm/rb/test/feature/secrets/secrets_feature_test.rb +93 -0
- package/project/.sdk/tm/rust/feature/secrets.rs +33 -10
- package/project/.sdk/tm/rust/tests/feature/secrets/main.rs +96 -0
- package/project/.sdk/tm/scala/feature/SecretsFeature.scala +29 -7
- package/project/.sdk/tm/scala/sdktest/feature/secrets/SecretsTestMain.scala +71 -0
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +35 -12
- package/project/.sdk/tm/ts/test/feature/secrets/Secrets.test.ts +73 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/capability.zig +137 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/catalog.zig +90 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/config.zig +346 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/depend.zig +244 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/env.zig +201 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/export.zig +83 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/graph.zig +212 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/host.zig +1224 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/inst.zig +126 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/order.zig +228 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/plugin.zig +34 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/point.zig +166 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/ref.zig +147 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/resolve.zig +74 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/types.zig +140 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/value.zig +662 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/version.zig +139 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/aws.zig +294 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/azuresecrets.zig +222 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/boru.zig +188 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/doppler.zig +135 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/gcpsecrets.zig +170 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/hashicorp.zig +242 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/httpjson.zig +535 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/infisical.zig +167 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/onepassword.zig +202 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/secretspec.zig +160 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/sigv4.zig +336 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/addr.zig +148 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/builtins.zig +259 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/provider.zig +440 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/sekreto.zig +944 -0
- package/project/.sdk/tm/zig/feature/secrets.zig +854 -0
- package/project/.sdk/tm/zig/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/zig/test/feature/secrets/secrets_test.zig +891 -0
- package/project/sdkgen-package.json +1 -1
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
// VENDORED: @voxgig/sekreto sdk-20260908-1556-0 (cpp/plugins/Httpjson.cpp)
|
|
2
|
+
// Source: https://github.com/voxgig/sekreto @ 1267ee2e5f49566bc92695bc9eb3a60ef4924998 [tag: sdk-20260908-1556-0]
|
|
3
|
+
// License: MIT (c) voxgig - see repository LICENSE. Do not edit: resync from upstream.
|
|
4
|
+
#include "Httpjson.hpp"
|
|
5
|
+
|
|
6
|
+
#include <errno.h>
|
|
7
|
+
#include <fcntl.h>
|
|
8
|
+
#include <netdb.h>
|
|
9
|
+
#include <poll.h>
|
|
10
|
+
#include <signal.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
#include <sys/socket.h>
|
|
13
|
+
#include <sys/time.h>
|
|
14
|
+
#include <unistd.h>
|
|
15
|
+
|
|
16
|
+
#include <chrono>
|
|
17
|
+
#include <cstdlib>
|
|
18
|
+
#include <limits>
|
|
19
|
+
#include <vector>
|
|
20
|
+
|
|
21
|
+
#include "Tls.hpp"
|
|
22
|
+
|
|
23
|
+
namespace sekreto {
|
|
24
|
+
|
|
25
|
+
const int TIMEOUT = 10;
|
|
26
|
+
const size_t MAXBODY = 8 * 1024 * 1024;
|
|
27
|
+
const char* const CABUNDLE = "SEKRETO_CA_BUNDLE";
|
|
28
|
+
|
|
29
|
+
std::string bareurl(const std::string& url) {
|
|
30
|
+
size_t at = url.find('?');
|
|
31
|
+
return (std::string::npos == at) ? url : url.substr(0, at);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
namespace {
|
|
35
|
+
|
|
36
|
+
SekretoError unreachable(const std::string& url, const std::string& why) {
|
|
37
|
+
return SekretoError("sekreto: cannot reach " + bareurl(url) + ": " + why);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
std::string oserror() {
|
|
41
|
+
if (EAGAIN == errno || EWOULDBLOCK == errno) return "timed out";
|
|
42
|
+
return strerror(errno);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Stop a write to a closed peer from killing the process.
|
|
46
|
+
///
|
|
47
|
+
/// A vault that closes the connection while the request is still being
|
|
48
|
+
/// written raises SIGPIPE, whose default disposition TERMINATES - so an
|
|
49
|
+
/// application would die rather than see an error from `get()`. The
|
|
50
|
+
/// disposition is only changed if it is still the default, so an
|
|
51
|
+
/// application that has made its own arrangements keeps them.
|
|
52
|
+
void hushsigpipe() {
|
|
53
|
+
static bool done = false;
|
|
54
|
+
if (done) return;
|
|
55
|
+
done = true;
|
|
56
|
+
|
|
57
|
+
struct sigaction current;
|
|
58
|
+
if (0 != sigaction(SIGPIPE, nullptr, ¤t)) return;
|
|
59
|
+
if (SIG_DFL != current.sa_handler) return;
|
|
60
|
+
|
|
61
|
+
struct sigaction ignore;
|
|
62
|
+
memset(&ignore, 0, sizeof(ignore));
|
|
63
|
+
ignore.sa_handler = SIG_IGN;
|
|
64
|
+
sigaction(SIGPIPE, &ignore, nullptr);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// A url split into the parts a request needs.
|
|
68
|
+
struct Target {
|
|
69
|
+
/// The BARE host: what is connected to, and what the certificate is
|
|
70
|
+
/// checked against. An IPv6 literal appears here without brackets.
|
|
71
|
+
std::string host;
|
|
72
|
+
/// The authority as it goes in `Host:`. An IPv6 literal KEEPS its
|
|
73
|
+
/// brackets, because `Host: 2001:db8::1:8200` is not a valid authority
|
|
74
|
+
/// and an intermediary may reject or misroute it.
|
|
75
|
+
std::string authority;
|
|
76
|
+
int port = 0;
|
|
77
|
+
int defaultport = 0;
|
|
78
|
+
std::string path;
|
|
79
|
+
bool tls = false;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
Target split(const std::string& url) {
|
|
83
|
+
Target out;
|
|
84
|
+
std::string rest;
|
|
85
|
+
|
|
86
|
+
if (0 == url.compare(0, 8, "https://")) {
|
|
87
|
+
out.tls = true;
|
|
88
|
+
out.defaultport = 443;
|
|
89
|
+
rest = url.substr(8);
|
|
90
|
+
} else if (0 == url.compare(0, 7, "http://")) {
|
|
91
|
+
out.tls = false;
|
|
92
|
+
out.defaultport = 80;
|
|
93
|
+
rest = url.substr(7);
|
|
94
|
+
} else {
|
|
95
|
+
throw SekretoError("sekreto: not an http url: " + bareurl(url));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
std::string authority = rest;
|
|
99
|
+
out.path = "/";
|
|
100
|
+
|
|
101
|
+
size_t at = rest.find('/');
|
|
102
|
+
if (std::string::npos != at) {
|
|
103
|
+
authority = rest.substr(0, at);
|
|
104
|
+
out.path = rest.substr(at);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
out.port = out.defaultport;
|
|
108
|
+
std::string host = authority;
|
|
109
|
+
|
|
110
|
+
// A REVERSE search for the colon, so an IPv6 literal's own colons are
|
|
111
|
+
// not read as a port separator.
|
|
112
|
+
size_t colon = authority.rfind(':');
|
|
113
|
+
if (std::string::npos != colon && colon + 1 < authority.size() &&
|
|
114
|
+
']' != authority[authority.size() - 1]) {
|
|
115
|
+
host = authority.substr(0, colon);
|
|
116
|
+
out.port = std::atoi(authority.c_str() + colon + 1);
|
|
117
|
+
if (0 >= out.port || 65535 < out.port) {
|
|
118
|
+
throw SekretoError("sekreto: bad port: " + bareurl(url));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
std::string bare = host;
|
|
123
|
+
if (!bare.empty() && '[' == bare[0]) bare = bare.substr(1);
|
|
124
|
+
if (!bare.empty() && ']' == bare[bare.size() - 1]) bare = bare.substr(0, bare.size() - 1);
|
|
125
|
+
|
|
126
|
+
out.host = bare;
|
|
127
|
+
// Re-bracketed only if it really is an IPv6 literal.
|
|
128
|
+
out.authority = (std::string::npos != bare.find(':')) ? "[" + bare + "]" : bare;
|
|
129
|
+
|
|
130
|
+
return out;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// The MONOTONIC clock, for deadlines - distinct from `nowms`, which is
|
|
134
|
+
/// wall-clock and answers when a logged-in token expires. A deadline read
|
|
135
|
+
/// off the wall clock moves when the system time does.
|
|
136
|
+
long steadyms() {
|
|
137
|
+
return static_cast<long>(std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
138
|
+
std::chrono::steady_clock::now().time_since_epoch())
|
|
139
|
+
.count());
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/// Connect, under ONE deadline across every resolved address.
|
|
143
|
+
///
|
|
144
|
+
/// A name commonly resolves to several - a dual-stack host answers with
|
|
145
|
+
/// both an A and an AAAA - and giving each the full ten seconds would make
|
|
146
|
+
/// the real bound ten seconds times however many addresses the name cares
|
|
147
|
+
/// to return, which is not a bound at all when the name is the attacker's.
|
|
148
|
+
/// Each attempt gets what is left of the one deadline.
|
|
149
|
+
///
|
|
150
|
+
/// A blocking `connect` has no bound of its own: against an address that
|
|
151
|
+
/// swallows SYNs the kernel retries for a little over two minutes on
|
|
152
|
+
/// Linux. So the socket is made non-blocking and `poll` carries the
|
|
153
|
+
/// deadline.
|
|
154
|
+
int connectto(const Target& target, const std::string& url) {
|
|
155
|
+
addrinfo hints;
|
|
156
|
+
memset(&hints, 0, sizeof(hints));
|
|
157
|
+
hints.ai_family = AF_UNSPEC;
|
|
158
|
+
hints.ai_socktype = SOCK_STREAM;
|
|
159
|
+
|
|
160
|
+
char service[16];
|
|
161
|
+
snprintf(service, sizeof(service), "%d", target.port);
|
|
162
|
+
|
|
163
|
+
addrinfo* found = nullptr;
|
|
164
|
+
int code = getaddrinfo(target.host.c_str(), service, &hints, &found);
|
|
165
|
+
|
|
166
|
+
if (0 != code || nullptr == found) {
|
|
167
|
+
throw unreachable(url, gai_strerror(code));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
long deadline = steadyms() + TIMEOUT * 1000;
|
|
171
|
+
std::string last = "no address";
|
|
172
|
+
|
|
173
|
+
for (addrinfo* step = found; nullptr != step; step = step->ai_next) {
|
|
174
|
+
long left = deadline - steadyms();
|
|
175
|
+
if (0 >= left) {
|
|
176
|
+
last = "timed out";
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
int fd = socket(step->ai_family, step->ai_socktype, step->ai_protocol);
|
|
181
|
+
if (0 > fd) {
|
|
182
|
+
last = oserror();
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
int flags = fcntl(fd, F_GETFL, 0);
|
|
187
|
+
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
|
188
|
+
|
|
189
|
+
bool ok = false;
|
|
190
|
+
|
|
191
|
+
if (0 == connect(fd, step->ai_addr, step->ai_addrlen)) {
|
|
192
|
+
ok = true;
|
|
193
|
+
} else if (EINPROGRESS == errno) {
|
|
194
|
+
pollfd waiting;
|
|
195
|
+
waiting.fd = fd;
|
|
196
|
+
waiting.events = POLLOUT;
|
|
197
|
+
waiting.revents = 0;
|
|
198
|
+
|
|
199
|
+
int ready = poll(&waiting, 1, static_cast<int>(left));
|
|
200
|
+
|
|
201
|
+
if (0 < ready) {
|
|
202
|
+
int problem = 0;
|
|
203
|
+
socklen_t size = sizeof(problem);
|
|
204
|
+
if (0 == getsockopt(fd, SOL_SOCKET, SO_ERROR, &problem, &size) && 0 == problem) {
|
|
205
|
+
ok = true;
|
|
206
|
+
} else {
|
|
207
|
+
errno = problem;
|
|
208
|
+
last = 0 == problem ? "connection failed" : oserror();
|
|
209
|
+
}
|
|
210
|
+
} else if (0 == ready) {
|
|
211
|
+
last = "timed out";
|
|
212
|
+
} else {
|
|
213
|
+
last = oserror();
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
last = oserror();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (ok) {
|
|
220
|
+
fcntl(fd, F_SETFL, flags);
|
|
221
|
+
|
|
222
|
+
// A write blocks too, once the peer's receive window fills and it
|
|
223
|
+
// stops reading, so both directions are bounded.
|
|
224
|
+
timeval bound;
|
|
225
|
+
bound.tv_sec = TIMEOUT;
|
|
226
|
+
bound.tv_usec = 0;
|
|
227
|
+
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &bound, sizeof(bound));
|
|
228
|
+
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &bound, sizeof(bound));
|
|
229
|
+
|
|
230
|
+
freeaddrinfo(found);
|
|
231
|
+
return fd;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
::close(fd);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
freeaddrinfo(found);
|
|
238
|
+
throw unreachable(url, last);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
class Plainstream : public Stream {
|
|
242
|
+
public:
|
|
243
|
+
Plainstream(int fd, const std::string& url) : fd_(fd), url_(url) {}
|
|
244
|
+
|
|
245
|
+
~Plainstream() override {
|
|
246
|
+
if (0 <= fd_) ::close(fd_);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
Plainstream(const Plainstream&) = delete;
|
|
250
|
+
Plainstream& operator=(const Plainstream&) = delete;
|
|
251
|
+
|
|
252
|
+
size_t readsome(char* buf, size_t len) override {
|
|
253
|
+
while (true) {
|
|
254
|
+
ssize_t got = ::read(fd_, buf, len);
|
|
255
|
+
|
|
256
|
+
if (0 <= got) return static_cast<size_t>(got);
|
|
257
|
+
if (EINTR == errno) continue;
|
|
258
|
+
|
|
259
|
+
throw unreachable(url_, oserror());
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
void writeall(const char* buf, size_t len) override {
|
|
264
|
+
size_t sent = 0;
|
|
265
|
+
|
|
266
|
+
while (sent < len) {
|
|
267
|
+
ssize_t put = ::send(fd_, buf + sent, len - sent, MSG_NOSIGNAL);
|
|
268
|
+
|
|
269
|
+
if (0 > put) {
|
|
270
|
+
if (EINTR == errno) continue;
|
|
271
|
+
throw unreachable(url_, oserror());
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
sent += static_cast<size_t>(put);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private:
|
|
279
|
+
int fd_;
|
|
280
|
+
std::string url_;
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
/// Join a chunked body back together.
|
|
284
|
+
///
|
|
285
|
+
/// Each chunk is a hex length (any `;`-separated extensions ignored), a
|
|
286
|
+
/// CRLF, that many BYTES, and a CRLF. A zero length ends the body and any
|
|
287
|
+
/// trailer is ignored.
|
|
288
|
+
///
|
|
289
|
+
/// Bytes, not characters: a chunk length counts bytes and a boundary may
|
|
290
|
+
/// fall inside a multibyte character, so a secret with any non-ASCII
|
|
291
|
+
/// character in it would otherwise come back mangled.
|
|
292
|
+
bool dechunk(const std::string& raw, std::string& out) {
|
|
293
|
+
size_t pos = 0;
|
|
294
|
+
|
|
295
|
+
while (true) {
|
|
296
|
+
size_t at = raw.find("\r\n", pos);
|
|
297
|
+
if (std::string::npos == at) return false;
|
|
298
|
+
|
|
299
|
+
std::string header = raw.substr(pos, at - pos);
|
|
300
|
+
size_t semi = header.find(';');
|
|
301
|
+
if (std::string::npos != semi) header = header.substr(0, semi);
|
|
302
|
+
|
|
303
|
+
char* stop = nullptr;
|
|
304
|
+
long size = std::strtol(header.c_str(), &stop, 16);
|
|
305
|
+
// A length that is not hex at all is a malformed body, not a zero
|
|
306
|
+
// chunk: strtol answers 0 for both.
|
|
307
|
+
if (nullptr == stop || stop == header.c_str() || 0 > size) return false;
|
|
308
|
+
|
|
309
|
+
size_t body = at + 2;
|
|
310
|
+
|
|
311
|
+
if (0 == size) return true;
|
|
312
|
+
|
|
313
|
+
if (raw.size() < body + static_cast<size_t>(size)) return false;
|
|
314
|
+
|
|
315
|
+
out += raw.substr(body, static_cast<size_t>(size));
|
|
316
|
+
|
|
317
|
+
pos = body + static_cast<size_t>(size) + 2;
|
|
318
|
+
if (raw.size() < pos) return false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
} // namespace
|
|
323
|
+
|
|
324
|
+
std::vector<std::string> pemcerts(const std::string& text) {
|
|
325
|
+
static const std::string OPEN = "-----BEGIN CERTIFICATE-----";
|
|
326
|
+
static const std::string CLOSE = "-----END CERTIFICATE-----";
|
|
327
|
+
|
|
328
|
+
std::vector<std::string> out;
|
|
329
|
+
size_t pos = 0;
|
|
330
|
+
|
|
331
|
+
while (true) {
|
|
332
|
+
size_t start = text.find(OPEN, pos);
|
|
333
|
+
if (std::string::npos == start) break;
|
|
334
|
+
|
|
335
|
+
size_t from = start + OPEN.size();
|
|
336
|
+
size_t stop = text.find(CLOSE, from);
|
|
337
|
+
if (std::string::npos == stop) break;
|
|
338
|
+
|
|
339
|
+
std::string der;
|
|
340
|
+
if (unbase64(text.substr(from, stop - from), der)) out.push_back(der);
|
|
341
|
+
|
|
342
|
+
pos = stop + CLOSE.size();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return out;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
Response httprequest(const std::string& method, const std::string& url,
|
|
349
|
+
const Ordered& headers, const std::optional<std::string>& body) {
|
|
350
|
+
hushsigpipe();
|
|
351
|
+
|
|
352
|
+
Target target = split(url);
|
|
353
|
+
|
|
354
|
+
int fd = connectto(target, url);
|
|
355
|
+
|
|
356
|
+
std::unique_ptr<Stream> stream;
|
|
357
|
+
|
|
358
|
+
if (target.tls) {
|
|
359
|
+
// Ownership of the socket passes to the TLS stream, which closes it.
|
|
360
|
+
stream = tlsstream(fd, target.host, url);
|
|
361
|
+
} else {
|
|
362
|
+
stream.reset(new Plainstream(fd, url));
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// A default port stays implicit in `Host:`, the way a URL normalises it:
|
|
366
|
+
// a SigV4 signature covers `host`, and `Host: x:443` is not what was
|
|
367
|
+
// signed.
|
|
368
|
+
std::string hostheader = target.authority;
|
|
369
|
+
if (target.port != target.defaultport) {
|
|
370
|
+
hostheader += ":" + std::to_string(target.port);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
std::string request = method + " " + target.path + " HTTP/1.1\r\n";
|
|
374
|
+
request += "Host: " + hostheader + "\r\n";
|
|
375
|
+
request += "Accept: application/json\r\n";
|
|
376
|
+
request += "Connection: close\r\n";
|
|
377
|
+
|
|
378
|
+
for (const auto& entry : headers.pairs) {
|
|
379
|
+
request += entry.first + ": " + entry.second + "\r\n";
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (body.has_value()) {
|
|
383
|
+
request += "Content-Length: " + std::to_string(body.value().size()) + "\r\n";
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
request += "\r\n";
|
|
387
|
+
|
|
388
|
+
if (body.has_value()) request += body.value();
|
|
389
|
+
|
|
390
|
+
stream->writeall(request.data(), request.size());
|
|
391
|
+
|
|
392
|
+
// Bounded, never read-to-end: an endless body would otherwise be
|
|
393
|
+
// accumulated in memory until the read timeout, which on a loopback or
|
|
394
|
+
// datacentre link is gigabytes. One byte over the bound is enough to
|
|
395
|
+
// know it was exceeded.
|
|
396
|
+
std::string raw;
|
|
397
|
+
char buf[16384];
|
|
398
|
+
|
|
399
|
+
while (raw.size() <= MAXBODY) {
|
|
400
|
+
size_t got = stream->readsome(buf, sizeof(buf));
|
|
401
|
+
if (0 == got) break;
|
|
402
|
+
raw.append(buf, got);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// An endless body is a store that could not answer, so this is an error
|
|
406
|
+
// and never a miss - the latter would fall through to a weaker store on
|
|
407
|
+
// an attacker's cue.
|
|
408
|
+
if (MAXBODY < raw.size()) {
|
|
409
|
+
throw SekretoError("sekreto: oversized response from " + bareurl(url));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
size_t split_at = raw.find("\r\n\r\n");
|
|
413
|
+
if (std::string::npos == split_at) {
|
|
414
|
+
throw SekretoError("sekreto: malformed response from " + bareurl(url));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Headers are ASCII; the body is not necessarily, so it stays bytes
|
|
418
|
+
// until every length-counted slice has been taken.
|
|
419
|
+
std::string head = raw.substr(0, split_at);
|
|
420
|
+
std::string rawbody = raw.substr(split_at + 4);
|
|
421
|
+
|
|
422
|
+
// "HTTP/1.1 200 OK" - the second whitespace-separated field is the
|
|
423
|
+
// status.
|
|
424
|
+
size_t endline = head.find("\r\n");
|
|
425
|
+
std::string statusline = (std::string::npos == endline) ? head : head.substr(0, endline);
|
|
426
|
+
|
|
427
|
+
size_t firstspace = statusline.find(' ');
|
|
428
|
+
if (std::string::npos == firstspace) {
|
|
429
|
+
throw SekretoError("sekreto: malformed response from " + bareurl(url));
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
Response out;
|
|
433
|
+
out.status = std::atoi(statusline.c_str() + firstspace + 1);
|
|
434
|
+
|
|
435
|
+
if (0 == out.status) {
|
|
436
|
+
throw SekretoError("sekreto: malformed response from " + bareurl(url));
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// A server that does not know the body length up front sends it in
|
|
440
|
+
// chunks - which is what a vault answering from a store usually does.
|
|
441
|
+
bool chunked = false;
|
|
442
|
+
size_t pos = (std::string::npos == endline) ? head.size() : endline + 2;
|
|
443
|
+
|
|
444
|
+
while (pos < head.size()) {
|
|
445
|
+
size_t stop = head.find("\r\n", pos);
|
|
446
|
+
std::string line =
|
|
447
|
+
(std::string::npos == stop) ? head.substr(pos) : head.substr(pos, stop - pos);
|
|
448
|
+
|
|
449
|
+
size_t colon = line.find(':');
|
|
450
|
+
if (std::string::npos != colon) {
|
|
451
|
+
std::string name = asciilower(line.substr(0, colon));
|
|
452
|
+
std::string value = asciilower(line.substr(colon + 1));
|
|
453
|
+
if ("transfer-encoding" == name && std::string::npos != value.find("chunked")) {
|
|
454
|
+
chunked = true;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (std::string::npos == stop) break;
|
|
459
|
+
pos = stop + 2;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (chunked) {
|
|
463
|
+
std::string joined;
|
|
464
|
+
if (!dechunk(rawbody, joined)) {
|
|
465
|
+
throw SekretoError("sekreto: malformed response from " + bareurl(url));
|
|
466
|
+
}
|
|
467
|
+
out.body = joined;
|
|
468
|
+
} else {
|
|
469
|
+
out.body = rawbody;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return out;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
// ------------------------------------------------------------- url codecs
|
|
477
|
+
|
|
478
|
+
std::string uriescape(const std::string& text) {
|
|
479
|
+
std::string out;
|
|
480
|
+
|
|
481
|
+
for (unsigned char byte : text) {
|
|
482
|
+
bool unreserved = ('A' <= byte && 'Z' >= byte) || ('a' <= byte && 'z' >= byte) ||
|
|
483
|
+
('0' <= byte && '9' >= byte) || '-' == byte || '_' == byte ||
|
|
484
|
+
'.' == byte || '~' == byte;
|
|
485
|
+
|
|
486
|
+
if (unreserved) {
|
|
487
|
+
out.push_back(static_cast<char>(byte));
|
|
488
|
+
} else {
|
|
489
|
+
char buf[8];
|
|
490
|
+
std::snprintf(buf, sizeof(buf), "%%%02X", byte);
|
|
491
|
+
out += buf;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return out;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
std::string uridecode(const std::string& text) {
|
|
499
|
+
std::string out;
|
|
500
|
+
size_t index = 0;
|
|
501
|
+
|
|
502
|
+
while (index < text.size()) {
|
|
503
|
+
bool taken = false;
|
|
504
|
+
|
|
505
|
+
if ('%' == text[index] && index + 2 < text.size()) {
|
|
506
|
+
std::string digits = text.substr(index + 1, 2);
|
|
507
|
+
bool ok = true;
|
|
508
|
+
unsigned int code = 0;
|
|
509
|
+
|
|
510
|
+
for (char digit : digits) {
|
|
511
|
+
unsigned int val = 0;
|
|
512
|
+
if ('0' <= digit && '9' >= digit) {
|
|
513
|
+
val = static_cast<unsigned int>(digit - '0');
|
|
514
|
+
} else if ('a' <= digit && 'f' >= digit) {
|
|
515
|
+
val = static_cast<unsigned int>(digit - 'a' + 10);
|
|
516
|
+
} else if ('A' <= digit && 'F' >= digit) {
|
|
517
|
+
val = static_cast<unsigned int>(digit - 'A' + 10);
|
|
518
|
+
} else {
|
|
519
|
+
ok = false;
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
code = (code << 4) | val;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (ok) {
|
|
526
|
+
out.push_back(static_cast<char>(code));
|
|
527
|
+
index += 3;
|
|
528
|
+
taken = true;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (!taken) {
|
|
533
|
+
out.push_back(text[index]);
|
|
534
|
+
index++;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return out;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// ----------------------------------------------------------------- base64
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
namespace {
|
|
545
|
+
|
|
546
|
+
bool b64value(char ch, uint32_t& out) {
|
|
547
|
+
if ('A' <= ch && 'Z' >= ch) {
|
|
548
|
+
out = static_cast<uint32_t>(ch - 'A');
|
|
549
|
+
} else if ('a' <= ch && 'z' >= ch) {
|
|
550
|
+
out = static_cast<uint32_t>(ch - 'a' + 26);
|
|
551
|
+
} else if ('0' <= ch && '9' >= ch) {
|
|
552
|
+
out = static_cast<uint32_t>(ch - '0' + 52);
|
|
553
|
+
} else if ('+' == ch) {
|
|
554
|
+
out = 62;
|
|
555
|
+
} else if ('/' == ch) {
|
|
556
|
+
out = 63;
|
|
557
|
+
} else {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
} // namespace
|
|
565
|
+
|
|
566
|
+
bool unbase64(const std::string& text, std::string& out) {
|
|
567
|
+
std::string clean;
|
|
568
|
+
clean.reserve(text.size());
|
|
569
|
+
|
|
570
|
+
for (char ch : text) {
|
|
571
|
+
if (' ' == ch || '\n' == ch || '\r' == ch || '\t' == ch) continue;
|
|
572
|
+
clean.push_back(ch);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (0 != clean.size() % 4) return false;
|
|
576
|
+
|
|
577
|
+
size_t body = clean.size();
|
|
578
|
+
int padding = 0;
|
|
579
|
+
|
|
580
|
+
while (0 < body && '=' == clean[body - 1]) {
|
|
581
|
+
padding++;
|
|
582
|
+
body--;
|
|
583
|
+
if (2 < padding) return false;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
uint32_t accumulator = 0;
|
|
587
|
+
int bits = 0;
|
|
588
|
+
std::string decoded;
|
|
589
|
+
|
|
590
|
+
for (size_t index = 0; index < body; index++) {
|
|
591
|
+
uint32_t sextet = 0;
|
|
592
|
+
if (!b64value(clean[index], sextet)) return false;
|
|
593
|
+
|
|
594
|
+
accumulator = (accumulator << 6) | sextet;
|
|
595
|
+
bits += 6;
|
|
596
|
+
|
|
597
|
+
if (8 <= bits) {
|
|
598
|
+
bits -= 8;
|
|
599
|
+
decoded.push_back(static_cast<char>((accumulator >> bits) & 0xff));
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
out = decoded;
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
// ----------------------------------------------------------------- json
|
|
609
|
+
|
|
610
|
+
Answer fetchjson(const std::string& method, const std::string& url,
|
|
611
|
+
const Ordered& headers, const std::optional<std::string>& body) {
|
|
612
|
+
Response res = httprequest(method, url, headers, body);
|
|
613
|
+
|
|
614
|
+
Answer out;
|
|
615
|
+
out.status = res.status;
|
|
616
|
+
|
|
617
|
+
bool parsed = Json::parse(res.body, out.body);
|
|
618
|
+
|
|
619
|
+
// A success status promised JSON; a body that does not parse means the
|
|
620
|
+
// store could not answer coherently, and treating it as a miss would
|
|
621
|
+
// fall through to a weaker store. Error statuses may carry any body -
|
|
622
|
+
// they are decided on status alone.
|
|
623
|
+
if (200 == res.status && !parsed) {
|
|
624
|
+
throw SekretoError("sekreto: malformed response from " + bareurl(url));
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
return out;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
std::optional<std::string> textof(const Json& val) {
|
|
631
|
+
std::string out;
|
|
632
|
+
if (!val.text(out)) return std::nullopt;
|
|
633
|
+
return out;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// ------------------------------------------------------------ token clocks
|
|
637
|
+
|
|
638
|
+
const double NEVER = std::numeric_limits<double>::max();
|
|
639
|
+
|
|
640
|
+
double nowms() {
|
|
641
|
+
return static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
642
|
+
std::chrono::system_clock::now().time_since_epoch())
|
|
643
|
+
.count());
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
double renewtime(const Json& expires) {
|
|
647
|
+
double seconds = 0;
|
|
648
|
+
std::string text;
|
|
649
|
+
|
|
650
|
+
if (expires.asnum(seconds)) {
|
|
651
|
+
// Taken as it stands.
|
|
652
|
+
} else if (expires.asstr(text)) {
|
|
653
|
+
char* stop = nullptr;
|
|
654
|
+
seconds = std::strtod(text.c_str(), &stop);
|
|
655
|
+
if (nullptr == stop || '\0' != *stop) seconds = 0;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if (0 >= seconds) return NEVER;
|
|
659
|
+
|
|
660
|
+
double lead = seconds - 60;
|
|
661
|
+
if (1 > lead) lead = 1;
|
|
662
|
+
|
|
663
|
+
return nowms() + lead * 1000;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
} // namespace sekreto
|