diff options
| -rw-r--r-- | guix/substitutes.scm | 36 | ||||
| -rw-r--r-- | tests/substitute.scm | 35 |
2 files changed, 57 insertions, 14 deletions
diff --git a/guix/substitutes.scm b/guix/substitutes.scm index b2a79c2a48d..289a068dbf3 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2013-2021, 2023-2025 Ludovic Courtès <ludo@gnu.org> | 2 | ;;; Copyright © 2013-2021, 2023-2026 Ludovic Courtès <ludo@gnu.org> |
| 3 | ;;; Copyright © 2014 Nikita Karetnikov <nikita@karetnikov.org> | 3 | ;;; Copyright © 2014 Nikita Karetnikov <nikita@karetnikov.org> |
| 4 | ;;; Copyright © 2018 Kyle Meyer <kyle@kyleam.com> | 4 | ;;; Copyright © 2018 Kyle Meyer <kyle@kyleam.com> |
| 5 | ;;; Copyright © 2020 Christopher Baines <mail@cbaines.net> | 5 | ;;; Copyright © 2020 Christopher Baines <mail@cbaines.net> |
| @@ -230,7 +230,11 @@ it contains invalid store file names--and return the narinfo otherwise." | |||
| 230 | (dump-port port (%make-void-port "w"))) | 230 | (dump-port port (%make-void-port "w"))) |
| 231 | 231 | ||
| 232 | (define (handle-narinfo-response request response port result) | 232 | (define (handle-narinfo-response request response port result) |
| 233 | (let* ((code (response-code response)) | 233 | (let* ((hash-part (basename |
| 234 | (string-drop-right (uri-path (request-uri request)) | ||
| 235 | (string-length ".narinfo")))) | ||
| 236 | (path (hash-part->path hash-part)) | ||
| 237 | (code (response-code response)) | ||
| 234 | (len (response-content-length response)) | 238 | (len (response-content-length response)) |
| 235 | (cache (response-cache-control response)) | 239 | (cache (response-cache-control response)) |
| 236 | (ttl (and cache (assoc-ref cache 'max-age)))) | 240 | (ttl (and cache (assoc-ref cache 'max-age)))) |
| @@ -240,21 +244,18 @@ it contains invalid store file names--and return the narinfo otherwise." | |||
| 240 | ;; belong to the next response. | 244 | ;; belong to the next response. |
| 241 | (if (= code 200) ; hit | 245 | (if (= code 200) ; hit |
| 242 | (let ((narinfo (read-narinfo port url #:size len))) | 246 | (let ((narinfo (read-narinfo port url #:size len))) |
| 243 | (if narinfo | 247 | (if (and narinfo path |
| 248 | ;; Make sure we got what we asked for. | ||
| 249 | (string=? (narinfo-path narinfo) path)) | ||
| 244 | (begin | 250 | (begin |
| 245 | (cache-narinfo! url (narinfo-path narinfo) narinfo ttl) | 251 | (cache-narinfo! url (narinfo-path narinfo) narinfo ttl) |
| 246 | (cons narinfo result)) | 252 | (cons narinfo result)) |
| 247 | result)) | 253 | result)) |
| 248 | (let* ((path (uri-path (request-uri request))) | 254 | ;; Log the failing queries and indicate if it failed because the |
| 249 | (hash-part (basename | 255 | ;; narinfo is being baked. |
| 250 | (string-drop-right path 8)))) ;drop ".narinfo" | 256 | (let ((baking? (assoc-ref (response-headers response) 'x-baking))) |
| 251 | ;; Log the failing queries and indicate if it failed because the | 257 | (debug "could not fetch ~a~a ~a~a~%" |
| 252 | ;; narinfo is being baked. | 258 | url path code (if baking? " (baking)" "")) |
| 253 | (let ((baking? | ||
| 254 | (assoc-ref (response-headers response) 'x-baking))) | ||
| 255 | (debug "could not fetch ~a~a ~a~a~%" | ||
| 256 | url path code | ||
| 257 | (if baking? " (baking)" ""))) | ||
| 258 | (if len | 259 | (if len |
| 259 | (get-bytevector-n port len) | 260 | (get-bytevector-n port len) |
| 260 | (read-to-eof port)) | 261 | (read-to-eof port)) |
| @@ -288,7 +289,14 @@ it contains invalid store file names--and return the narinfo otherwise." | |||
| 288 | (files (map (compose (cut string-append base <> ".narinfo") | 289 | (files (map (compose (cut string-append base <> ".narinfo") |
| 289 | store-path-hash-part) | 290 | store-path-hash-part) |
| 290 | paths))) | 291 | paths))) |
| 291 | (filter-map (cut narinfo-from-file <> url) files))) | 292 | (filter-map (lambda (file path) |
| 293 | (let ((narinfo (narinfo-from-file file url))) | ||
| 294 | (and narinfo | ||
| 295 | ;; Make sure we got what we asked for. | ||
| 296 | (string=? (narinfo-path narinfo) path) | ||
| 297 | narinfo))) | ||
| 298 | files | ||
| 299 | paths))) | ||
| 292 | (else | 300 | (else |
| 293 | (leave (G_ "~s: unsupported server URI scheme~%") | 301 | (leave (G_ "~s: unsupported server URI scheme~%") |
| 294 | (if uri (uri-scheme uri) url))))) | 302 | (if uri (uri-scheme uri) url))))) |
diff --git a/tests/substitute.scm b/tests/substitute.scm index 8f32bfa7281..b749561347a 100644 --- a/tests/substitute.scm +++ b/tests/substitute.scm | |||
| @@ -357,6 +357,29 @@ Deriver: foo.drv") | |||
| 357 | (lambda () | 357 | (lambda () |
| 358 | (guix-substitute "--query"))))))))) | 358 | (guix-substitute "--query"))))))))) |
| 359 | 359 | ||
| 360 | (test-equal "query narinfo that returns different store path" | ||
| 361 | ;; The narinfo is valid and authorized but its 'StorePath' field points to a | ||
| 362 | ;; different store item. | ||
| 363 | "" | ||
| 364 | |||
| 365 | (let ((prefix (string-append "StorePath: " (%store-prefix) | ||
| 366 | "/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-BAR | ||
| 367 | NarHash: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | ||
| 368 | References: bar baz\n"))) | ||
| 369 | (with-narinfo (string-append prefix | ||
| 370 | "Signature: " (signature-field prefix) " | ||
| 371 | URL: example.nar | ||
| 372 | Compression: none | ||
| 373 | NarSize: 42 | ||
| 374 | Deriver: foo.drv") | ||
| 375 | (string-trim-both | ||
| 376 | (with-output-to-string | ||
| 377 | (lambda () | ||
| 378 | (with-input-from-string (string-append "have " (%store-prefix) | ||
| 379 | "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo") | ||
| 380 | (lambda () | ||
| 381 | (guix-substitute "--query"))))))))) | ||
| 382 | |||
| 360 | (test-equal "query narinfo signed with authorized key" | 383 | (test-equal "query narinfo signed with authorized key" |
| 361 | (string-append (%store-prefix) "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo") | 384 | (string-append (%store-prefix) "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo") |
| 362 | 385 | ||
| @@ -893,6 +916,18 @@ System: mips64el-linux\n"))) | |||
| 893 | (lambda () | 916 | (lambda () |
| 894 | (false-if-exception (delete-file "substitute-retrieved"))))))) | 917 | (false-if-exception (delete-file "substitute-retrieved"))))))) |
| 895 | 918 | ||
| 919 | (test-quit "substitute, narinfo does not match requested store item" | ||
| 920 | "no valid substitute" | ||
| 921 | (with-http-server `((200 ,(string-append %narinfo "Signature: " | ||
| 922 | (signature-field %narinfo)))) | ||
| 923 | (parameterize ((substitute-urls (list (%local-url)))) | ||
| 924 | ;; Narinfo is valid, signed, and authorized but requested item is | ||
| 925 | ;; /bbb…-bar and narinfo is for /aaa…-foo. | ||
| 926 | (request-substitution (string-append (%store-prefix) | ||
| 927 | "/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-bar") | ||
| 928 | "substitute-retrieved") | ||
| 929 | #f))) | ||
| 930 | |||
| 896 | (test-end "substitute") | 931 | (test-end "substitute") |
| 897 | 932 | ||
| 898 | ;;; Local Variables: | 933 | ;;; Local Variables: |
