perform-download.scm 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2016, 2017, 2018, 2020 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (guix scripts perform-download)
  19. #:use-module (guix ui)
  20. #:use-module (guix scripts)
  21. #:use-module (guix derivations)
  22. #:use-module ((guix store) #:select (derivation-path? store-path?))
  23. #:use-module (guix build download)
  24. #:use-module (ice-9 match)
  25. #:export (guix-perform-download))
  26. ;; This program is a helper for the daemon's 'download' built-in builder.
  27. (define-syntax derivation-let
  28. (syntax-rules ()
  29. ((_ drv ((id name) rest ...) body ...)
  30. (let ((id (assoc-ref (derivation-builder-environment-vars drv)
  31. name)))
  32. (derivation-let drv (rest ...) body ...)))
  33. ((_ drv () body ...)
  34. (begin body ...))))
  35. (define %user-module
  36. ;; Module in which content-address mirror procedures are evaluated.
  37. (let ((module (make-fresh-user-module)))
  38. (module-use! module (resolve-interface '(guix base32)))
  39. module))
  40. (define* (perform-download drv #:optional output
  41. #:key print-build-trace?)
  42. "Perform the download described by DRV, a fixed-output derivation, to
  43. OUTPUT.
  44. Note: Unless OUTPUT is #f, we don't read the value of 'out' in DRV since the
  45. actual output is different from that when we're doing a 'bmCheck' or
  46. 'bmRepair' build."
  47. (derivation-let drv ((url "url")
  48. (output* "out")
  49. (executable "executable")
  50. (mirrors "mirrors")
  51. (content-addressed-mirrors "content-addressed-mirrors"))
  52. (unless url
  53. (leave (G_ "~a: missing URL~%") (derivation-file-name drv)))
  54. (let* ((output (or output output*))
  55. (url (call-with-input-string url read))
  56. (drv-output (assoc-ref (derivation-outputs drv) "out"))
  57. (algo (derivation-output-hash-algo drv-output))
  58. (hash (derivation-output-hash drv-output)))
  59. (unless (and algo hash)
  60. (leave (G_ "~a is not a fixed-output derivation~%")
  61. (derivation-file-name drv)))
  62. ;; We're invoked by the daemon, which gives us write access to OUTPUT.
  63. (when (url-fetch url output
  64. #:print-build-trace? print-build-trace?
  65. #:mirrors (if mirrors
  66. (call-with-input-file mirrors read)
  67. '())
  68. #:content-addressed-mirrors
  69. (if content-addressed-mirrors
  70. (call-with-input-file content-addressed-mirrors
  71. (lambda (port)
  72. (eval (read port) %user-module)))
  73. '())
  74. #:hashes `((,algo . ,hash))
  75. ;; Since DRV's output hash is known, X.509 certificate
  76. ;; validation is pointless.
  77. #:verify-certificate? #f)
  78. (when (and executable (string=? executable "1"))
  79. (chmod output #o755))))))
  80. (define (assert-low-privileges)
  81. (when (zero? (getuid))
  82. (leave (G_ "refusing to run with elevated privileges (UID ~a)~%")
  83. (getuid))))
  84. (define-command (guix-perform-download . args)
  85. (category internal)
  86. (synopsis "perform download described by fixed-output derivations")
  87. ;; This is an "out-of-band" download in that this code is executed directly
  88. ;; by the daemon and not explicitly described as an input of the derivation.
  89. ;; This allows us to sidestep bootstrapping problems, such as downloading
  90. ;; the source code of GnuTLS over HTTPS before we have built GnuTLS. See
  91. ;; <https://bugs.gnu.org/22774>.
  92. (define print-build-trace?
  93. (match (getenv "_NIX_OPTIONS")
  94. (#f #f)
  95. (str (string-contains str "print-extended-build-trace=1"))))
  96. ;; This program must be invoked by guix-daemon under an unprivileged UID to
  97. ;; prevent things downloading from 'file:///etc/shadow' or arbitrary code
  98. ;; execution via the content-addressed mirror procedures. (That means we
  99. ;; exclude users who did not pass '--build-users-group'.)
  100. (with-error-handling
  101. (match args
  102. (((? derivation-path? drv) (? store-path? output))
  103. (assert-low-privileges)
  104. (perform-download (read-derivation-from-file drv)
  105. output
  106. #:print-build-trace? print-build-trace?))
  107. (((? derivation-path? drv)) ;backward compatibility
  108. (assert-low-privileges)
  109. (perform-download (read-derivation-from-file drv)
  110. #:print-build-trace? print-build-trace?))
  111. (("--version")
  112. (show-version-and-exit))
  113. (x
  114. (leave
  115. (G_ "fixed-output derivation and output file name expected~%"))))))
  116. ;; Local Variables:
  117. ;; eval: (put 'derivation-let 'scheme-indent-function 2)
  118. ;; End:
  119. ;; perform-download.scm ends here