. "$BST_LIB" # liboauth 1.0.3 (meta-oe recipes-support/liboauth) -- a C implementation of # OAuth 1.0 request signing, RFC 5849. It signs an HTTP request by building a # canonical "signature base string" from the method, the URL and the sorted, # percent-encoded parameters, and taking HMAC-SHA1 (or RSA-SHA1, or PLAINTEXT) # over it with the consumer and token secrets as the key. # # --------------------------------------------------------------------------- # WHAT SHIPS, AND WHY THAT DECIDES THE SHAPE OF THIS SUITE # # liboauth has NO command-line tool. Upstream's tests/ directory holds nine # check_PROGRAMS -- including the three self-tests this suite's expectations are # drawn from -- but they are `check_PROGRAMS`, so `make` does not build them and # `make install` does not install them. On this static-only distro ${PN} is # empty as well (no shared object is built), so the ENTIRE installed payload is # three files: /usr/include/oauth.h, /usr/lib/liboauth.a and # /usr/lib/pkgconfig/oauth.pc. # # "The three files are present" is therefore everything a shell test could say # about this port, and for a library whose failure mode is signing CORRECTLY- # SHAPED but WRONG requests, that is not coverage. BRINTOS-217 is the precedent: # oniguruma compiled and packaged perfectly on this arm and then returned # silently wrong offsets to every caller. # # So data/liboauth-probe is cross-linked with wasmcc-glibc against THE VERY # ARCHIVE THAT SHIPS (/usr/lib/liboauth.a), staged to $TMPDIR and run here. Its # source is src/liboauth_probe.c. # # --------------------------------------------------------------------------- # EVERY EXPECTED VALUE IN THE PROBE IS PUBLISHED, NOT OBSERVED # # OAuth 1.0 is specified down to the byte, so the probe does not compare against # what liboauth happens to print. It compares against the strings RFC 5849 and # OAuth Core 1.0 publish -- which is the only comparison that catches a library # that is self-consistently wrong: # # base-rfc5849-* the signature base string of RFC 5849 3.4.1.3.2, byte for # byte, built from the RFC's own example request. # sig-rfc5849-* HMAC-SHA1 over it with the specification's secrets. # sig-a52-* OAuth Core 1.0 A.5.2, reached twice: over the published # base string, and over the one liboauth builds from the # request. Both must give tR3+Ty81lMeYAr/Fid0kMTYa/WM=. # sig-rfc2202-* an HMAC-SHA1 vector that predates OAuth entirely, so the # primitive is pinned to something liboauth cannot have # defined. # rsa-* RSASSA-PKCS1-v1_5 is deterministic, so its signature is a # published constant too -- and it is the only case group # that exercises the OpenSSL half of the port. # tamper-* one character changed in a value, a nonce, a timestamp, a # token, the method, either secret, and a parameter dropped: # each must move the signature. tamper-control-untampered is # the group's control and re-asserts the reference. # # Three groups exist for PLATFORM reasons rather than for liboauth's, and are # the ones to read first on a red run: # # sig-* / rsa-* the SHA1 core is a loop-carried cursor over a 64-byte block # with rotate-and-accumulate state, and RSA runs through # OpenSSL bignums. Both are the arithmetic class a miscompile # corrupts silently rather than fatally. # split-* / ser-* oauth_split_url_parameters walks a string with pointer # arithmetic into an argv it grew by realloc, and the caller # qsorts it through a comparator function POINTER -- an # indirect call the coroutinize pass must treat # conservatively. That is the class hwjs-cc#24 broke for onig. # varargs-* oauth_catenc is liboauth's only va_list API, and varargs # across the coroutine rewrite is a standing hazard here. # # THE NATIVE CONTROL SCORED 97/97 and corrected five assertions of mine before # it did: oauth_serialize_url does NOT percent-encode (oauth_catenc does that # when the base string is assembled); oauth_serialize_url_parameters takes the # WHOLE array and skips element 0 itself, so passing &argv[1] silently loses a # parameter; and oauth_free_array clears NEITHER out-parameter despite taking # both by pointer. Those three are now pinned as cases, because each is a # footgun a consumer of this archive can hit. # # --------------------------------------------------------------------------- # WHY BUILTIN MATCHING INSTEAD OF check_out # # The probe runs ONCE and its output is read into a shell variable; every # assertion is a `case` glob against it, so there is no fork per case. On the # wasm32-hwjs runtime the forking is the cost, not the work. incd=/usr/include lib=/usr/lib/liboauth.a pc=/usr/lib/pkgconfig/oauth.pc nl=' ' # hasfile -- ok iff is a non-empty regular file. # has -- ok iff contains the literal . # hasline -- ok iff carries as a WHOLE line. # Substring matching would let oauth_sign_url2 # satisfy a lookup for oauth_sign_url. hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "absent or empty: $2"; fi; } has() { case "$3" in *"$2"*) bst_ok "$1" ;; *) bst_notok "$1" "not found: $2" ;; esac; } hasline() { case "$nl$3$nl" in *"$nl$2$nl"*) bst_ok "$1" ;; *) bst_notok "$1" "not in archive: $2" ;; esac; } # --- the shipped payload ----------------------------------------------------- hasfile liboauth/header "$incd/oauth.h" hasfile liboauth/archive "$lib" hasfile liboauth/pkgconfig "$pc" # There is deliberately no shared-object case here: shared objects are refused # distro-wide on this arm, so an absent liboauth.so is the distro's property and # not this port's, and every sibling library would assert the same thing. The # case id it would have had is left unwritten ON PURPOSE -- the verify driver # derives the suite's DECLARED id set by scanning this file for liboauth/, # so naming a case in prose that the suite never runs inflates that set and is # reported afterwards as an unexplained deficit. pctext=$(cat "$pc" 2>/dev/null) has liboauth/pc-name "Name: oauth" "$pctext" has liboauth/pc-version "Version: 1.0.3" "$pctext" has liboauth/pc-libs "-loauth" "$pctext" # oauth.pc's Requires.private is GENERATED at configure time, so this is what # the cross-configure actually concluded about this arm rather than an upstream # default -- and it is the record that liboauth found BOTH of its dependencies # here. A build that silently lost libcrypto would still produce an archive and # would still pass every case above; it would fail this one, and every rsa-* # case below it. has liboauth/pc-requires-curl "libcurl" "$pctext" has liboauth/pc-requires-crypto "libcrypto" "$pctext" # --- symbol completeness, tracked from the INSTALLED header ------------------ # Every function the installed header declares must be present in the installed # archive, so a partial compile, a visibility mistake or a header/library skew # all fail this. The list is derived from the header rather than written here, # so it survives a version bump. # # The oauth_http_* family is EXCLUDED BY CONSTRUCTION rather than to make this # pass: those entry points are compiled only when liboauth is configured with # libcurl AND are the ones this image cannot exercise anyway, and upstream marks # every one of them attribute_deprecated in the same header. They are covered by # the archive-membership case below instead, which asserts the object is there. arcsyms=$(strings -a "$lib" 2>/dev/null | grep -o 'oauth_[a-z0-9_]*' | sort -u) [ -n "$arcsyms" ] || arcsyms=$(grep -ao 'oauth_[a-z0-9_]*' "$lib" 2>/dev/null | sort -u) hdrsyms=$(grep -vE '^[[:space:]]*[*#]' "$incd/oauth.h" 2>/dev/null \ | grep -oE '\boauth_[a-z0-9_]*[[:space:]]*\(' \ | sed 's/[[:space:]]*(//' | sort -u) nsym=0 nmiss=0 missing="" for f in $hdrsyms; do case "$f" in oauth_http_*|oauth_post_*|oauth_send_*) continue ;; esac nsym=$((nsym + 1)) case "$nl$arcsyms$nl" in *"$nl$f$nl"*) ;; *) nmiss=$((nmiss + 1)); missing="$missing $f" ;; esac done if [ "$nmiss" -eq 0 ] && [ "$nsym" -gt 20 ]; then bst_ok liboauth/symbols-complete else bst_notok liboauth/symbols-complete "checked=$nsym missing=$nmiss:$missing" fi # the four translation units the archive is made of, by member name -- a # do_compile that lost one would still link for a caller that happens not to # reach it, and would fail here immediately. binutils is NOT in this image, so # `ar t` is not available: the member names sit in the ar headers as plain # ASCII and are read out of the file directly, which is the same idiom # 57-libdeflate.test uses for its symbol list. members=$(grep -ao '[a-z_]*\.o/' "$lib" 2>/dev/null | sed 's|/$||' | sort -u) hasline liboauth/member-oauth "oauth.o" "$members" hasline liboauth/member-hash "hash.o" "$members" hasline liboauth/member-xmalloc "xmalloc.o" "$members" hasline liboauth/member-oauth-http "oauth_http.o" "$members" # --- the probe --------------------------------------------------------------- # Staged to a writable path first: do_install installs data/ with mode 0644 and # the rootfs is read-only at runtime, so the payload cannot be made executable # where it sits (packager README section 4b). hasfile liboauth/probe-shipped "$BST_DATA/liboauth-probe" tmp=${TMPDIR:-/tmp} probe=$tmp/bst-liboauth-probe.$$ if cp "$BST_DATA/liboauth-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then out=$("$probe" 2>&1) has liboauth/run-started "OAU-inventory START" "$out" # percent-encoding, RFC 5849 section 3.6 has liboauth/run-esc-eq "OAU-esc-eq OK" "$out" has liboauth/run-esc-dash-eq "OAU-esc-dash-eq OK" "$out" has liboauth/run-esc-star-amp "OAU-esc-star-amp OK" "$out" has liboauth/run-esc-dollar "OAU-esc-dollar OK" "$out" has liboauth/run-esc-alnum "OAU-esc-alnum OK" "$out" has liboauth/run-esc-digits "OAU-esc-digits OK" "$out" has liboauth/run-esc-space-pct "OAU-esc-space-pct OK" "$out" has liboauth/run-esc-ampersand "OAU-esc-ampersand OK" "$out" has liboauth/run-esc-unreserved "OAU-esc-unreserved OK" "$out" has liboauth/run-esc-tilde "OAU-esc-tilde OK" "$out" has liboauth/run-esc-plus "OAU-esc-plus OK" "$out" has liboauth/run-esc-slash "OAU-esc-slash OK" "$out" has liboauth/run-esc-empty "OAU-esc-empty OK" "$out" has liboauth/run-esc-utf8-latin1 "OAU-esc-utf8-latin1 OK" "$out" has liboauth/run-esc-utf8-cjk "OAU-esc-utf8-cjk OK" "$out" has liboauth/run-esc-hex-upper "OAU-esc-hex-upper OK" "$out" has liboauth/run-unesc-roundtrip "OAU-unesc-roundtrip OK" "$out" has liboauth/run-unesc-length "OAU-unesc-length OK" "$out" has liboauth/run-unesc-utf8 "OAU-unesc-utf8 OK" "$out" has liboauth/run-unesc-lower-hex "OAU-unesc-lower-hex OK" "$out" has liboauth/run-unesc-plus-literal "OAU-unesc-plus-literal OK" "$out" has liboauth/run-esc-unesc-identity "OAU-esc-unesc-identity OK" "$out" # parameter normalisation, RFC 5849 section 3.4.1.3.2 has liboauth/run-norm-value-tiebreak "OAU-norm-value-tiebreak OK" "$out" has liboauth/run-norm-sort-by-value "OAU-norm-sort-by-value OK" "$out" has liboauth/run-norm-encoded-order "OAU-norm-encoded-order OK" "$out" has liboauth/run-norm-name-order "OAU-norm-name-order OK" "$out" has liboauth/run-norm-empty-value "OAU-norm-empty-value OK" "$out" has liboauth/run-norm-bare-name "OAU-norm-bare-name OK" "$out" # THE TICKET'S PASS CRITERION: the base string and the signature, byte-exact # against the published values has liboauth/run-base-rfc5849-post "OAU-base-rfc5849-post OK" "$out" has liboauth/run-base-rfc5849-get "OAU-base-rfc5849-get OK" "$out" has liboauth/run-base-rfc5849-len "OAU-base-rfc5849-len OK" "$out" has liboauth/run-sig-rfc5849-post "OAU-sig-rfc5849-post OK" "$out" has liboauth/run-sig-rfc5849-get "OAU-sig-rfc5849-get OK" "$out" has liboauth/run-sig-a52-published-base "OAU-sig-a52-published-base OK" "$out" has liboauth/run-base-a52 "OAU-base-a52 OK" "$out" has liboauth/run-sig-a52-built-base "OAU-sig-a52-built-base OK" "$out" has liboauth/run-base-a51-request-token "OAU-base-a51-request-token OK" "$out" has liboauth/run-sig-empty-token-secret "OAU-sig-empty-token-secret OK" "$out" has liboauth/run-sig-both-secrets "OAU-sig-both-secrets OK" "$out" has liboauth/run-sig-rfc2202-case1 "OAU-sig-rfc2202-case1 OK" "$out" has liboauth/run-sig-multiblock "OAU-sig-multiblock OK" "$out" has liboauth/run-sig-raw-embedded-nul "OAU-sig-raw-embedded-nul OK" "$out" # THE TICKET'S SECOND CRITERION: a tampered parameter must change the # signature. The control is asserted last for a reason -- a tamper group # whose reference had drifted would otherwise report a clean sweep. has liboauth/run-tamper-value "OAU-tamper-value OK" "$out" has liboauth/run-tamper-nonce "OAU-tamper-nonce OK" "$out" has liboauth/run-tamper-timestamp "OAU-tamper-timestamp OK" "$out" has liboauth/run-tamper-token "OAU-tamper-token OK" "$out" has liboauth/run-tamper-dropped-param "OAU-tamper-dropped-param OK" "$out" has liboauth/run-tamper-method "OAU-tamper-method OK" "$out" has liboauth/run-tamper-consumer-secret "OAU-tamper-consumer-secret OK" "$out" has liboauth/run-tamper-token-secret "OAU-tamper-token-secret OK" "$out" has liboauth/run-tamper-control-untampered "OAU-tamper-control-untampered OK" "$out" # the end-to-end signing entry point, in its three shapes has liboauth/run-signurl-eran "OAU-signurl-eran OK" "$out" has liboauth/run-signurl-plaintext "OAU-signurl-plaintext OK" "$out" has liboauth/run-signurl-post-url "OAU-signurl-post-url OK" "$out" has liboauth/run-signurl-post-body "OAU-signurl-post-body OK" "$out" # base64, RFC 4648 section 10 -- every signature is expressed in it has liboauth/run-b64-enc-0 "OAU-b64-enc-0 OK" "$out" has liboauth/run-b64-enc-1 "OAU-b64-enc-1 OK" "$out" has liboauth/run-b64-enc-2 "OAU-b64-enc-2 OK" "$out" has liboauth/run-b64-enc-3 "OAU-b64-enc-3 OK" "$out" has liboauth/run-b64-enc-4 "OAU-b64-enc-4 OK" "$out" has liboauth/run-b64-enc-5 "OAU-b64-enc-5 OK" "$out" has liboauth/run-b64-enc-6 "OAU-b64-enc-6 OK" "$out" has liboauth/run-b64-dec-0 "OAU-b64-dec-0 OK" "$out" has liboauth/run-b64-dec-1 "OAU-b64-dec-1 OK" "$out" has liboauth/run-b64-dec-2 "OAU-b64-dec-2 OK" "$out" has liboauth/run-b64-dec-3 "OAU-b64-dec-3 OK" "$out" has liboauth/run-b64-dec-4 "OAU-b64-dec-4 OK" "$out" has liboauth/run-b64-dec-5 "OAU-b64-dec-5 OK" "$out" has liboauth/run-b64-dec-6 "OAU-b64-dec-6 OK" "$out" has liboauth/run-b64-binary-roundtrip "OAU-b64-binary-roundtrip OK" "$out" # the request-body-hash extension has liboauth/run-bodyhash-hello "OAU-bodyhash-hello OK" "$out" has liboauth/run-bodyhash-empty "OAU-bodyhash-empty OK" "$out" has liboauth/run-bodyhash-embedded-nul "OAU-bodyhash-embedded-nul OK" "$out" # RSA-SHA1 -- the OpenSSL half of the port, sign and verify, with both # negative directions. A verifier that returned 1 for everything would pass # rsa-verify-good, which is why the two tampered cases are not optional. has liboauth/run-rsa-sign "OAU-rsa-sign OK" "$out" has liboauth/run-rsa-verify-good "OAU-rsa-verify-good OK" "$out" has liboauth/run-rsa-verify-tampered-base "OAU-rsa-verify-tampered-base OK" "$out" has liboauth/run-rsa-verify-tampered-sig "OAU-rsa-verify-tampered-sig OK" "$out" # the va_list API, the splitter/serialiser, the array helpers and the # constant-time comparator has liboauth/run-varargs-catenc3 "OAU-varargs-catenc3 OK" "$out" has liboauth/run-varargs-catenc-empty-tail "OAU-varargs-catenc-empty-tail OK" "$out" has liboauth/run-varargs-catenc1 "OAU-varargs-catenc1 OK" "$out" has liboauth/run-varargs-catenc5 "OAU-varargs-catenc5 OK" "$out" has liboauth/run-split-count "OAU-split-count OK" "$out" has liboauth/run-split-url-element "OAU-split-url-element OK" "$out" has liboauth/run-ser-sorted "OAU-ser-sorted OK" "$out" has liboauth/run-ser-parameters "OAU-ser-parameters OK" "$out" has liboauth/run-array-exists-yes "OAU-array-exists-yes OK" "$out" has liboauth/run-array-exists-no "OAU-array-exists-no OK" "$out" has liboauth/run-array-add "OAU-array-add OK" "$out" has liboauth/run-array-free-leaves-pointer "OAU-array-free-leaves-pointer OK" "$out" has liboauth/run-array-free-leaves-count "OAU-array-free-leaves-count OK" "$out" has liboauth/run-cteq-equal "OAU-cteq-equal OK" "$out" has liboauth/run-cteq-differ "OAU-cteq-differ OK" "$out" has liboauth/run-cteq-prefix "OAU-cteq-prefix OK" "$out" has liboauth/run-cteq-empty "OAU-cteq-empty OK" "$out" has liboauth/run-cteq-embedded-nul "OAU-cteq-embedded-nul OK" "$out" has liboauth/run-nonce-nonempty "OAU-nonce-nonempty OK" "$out" has liboauth/run-nonce-varies "OAU-nonce-varies OK" "$out" # The probe's own tally and its exit status. 97/97 is what the same source # scores natively against a host build of the identical release. has liboauth/run-summary "OAU-SUMMARY 97/97" "$out" check_rc liboauth/run-exit0 0 "$probe" rm -f "$probe" else bst_notok liboauth/probe-stage "cannot stage $BST_DATA/liboauth-probe" fi