perform-download.scm 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2016, 2017, 2018 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 derivations)
  21. #:use-module ((guix store) #:select (derivation-path? store-path?))
  22. #:use-module (guix build download)
  23. #:use-module (ice-9 match)
  24. #:export (guix-perform-download))
  25. ;; This program is a helper for the daemon's 'download' built-in builder.
  26. (define-syntax derivation-let
  27. (syntax-rules ()
  28. ((_ drv ((id name) rest ...) body ...)
  29. (let ((id (assoc-ref (derivation-builder-environment-vars drv)
  30. name)))
  31. (derivation-let drv (rest ...) body ...)))
  32. ((_ drv () body ...)
  33. (begin body ...))))
  34. (define %user-module
  35. ;; Module in which content-address mirror procedures are evaluated.
  36. (let ((module (make-fresh-user-module)))
  37. (module-use! module (resolve-interface '(guix base32)))
  38. module))
  39. (define* (perform-download drv #:optional output
  40. #:key print-build-trace?)
  41. "Perform the download described by DRV, a fixed-output derivation, to
  42. OUTPUT.
  43. Note: Unless OUTPUT is #f, we don't read the value of 'out' in DRV since the
  44. actual output is different from that when we're doing a 'bmCheck' or
  45. 'bmRepair' build."
  46. (derivation-let drv ((url "url")
  47. (output* "out")
  48. (executable "executable")
  49. (mirrors "mirrors")
  50. (content-addressed-mirrors "content-addressed-mirrors"))
  51. (unless url
  52. (leave (G_ "~a: missing URL~%") (derivation-file-name drv)))
  53. (let* ((output (or output output*))
  54. (url (call-with-input-string url read))
  55. (drv-output (assoc-ref (derivation-outputs drv) "out"))
  56. (algo (derivation-output-hash-algo drv-output))
  57. (hash (derivation-output-hash drv-output)))
  58. (unless (and algo hash)
  59. (leave (G_ "~a is not a fixed-output derivation~%")
  60. (derivation-file-name drv)))
  61. ;; We're invoked by the daemon, which gives us write access to OUTPUT.
  62. (when (url-fetch url output
  63. #:print-build-trace? print-build-trace?
  64. #:mirrors (if mirrors
  65. (call-with-input-file mirrors read)
  66. '())
  67. #:content-addressed-mirrors
  68. (if content-addressed-mirrors
  69. (call-with-input-file content-addressed-mirrors
  70. (lambda (port)
  71. (eval (read port) %user-module)))
  72. '())
  73. #:hashes `((,algo . ,hash))
  74. ;; Since DRV's output hash is known, X.509 certificate
  75. ;; validation is pointless.
  76. #:verify-certificate? #f)
  77. (when (and executable (string=? executable "1"))
  78. (chmod output #o755))))))
  79. (define (assert-low-privileges)
  80. (when (zero? (getuid))
  81. (leave (G_ "refusing to run with elevated privileges (UID ~a)~%")
  82. (getuid))))
  83. (define (guix-perform-download . args)
  84. "Perform the download described by the given fixed-output derivation.
  85. This is an \"out-of-band\" download in that this code is executed directly by
  86. the daemon and not explicitly described as an input of the derivation. This
  87. allows us to sidestep bootstrapping problems, such downloading the source code
  88. of GnuTLS over HTTPS, before we have built GnuTLS. See
  89. <http://bugs.gnu.org/22774>."
  90. (define print-build-trace?
  91. (match (getenv "_NIX_OPTIONS")
  92. (#f #f)
  93. (str (string-contains str "print-extended-build-trace=1"))))
  94. ;; This program must be invoked by guix-daemon under an unprivileged UID to
  95. ;; prevent things downloading from 'file:///etc/shadow' or arbitrary code
  96. ;; execution via the content-addressed mirror procedures. (That means we
  97. ;; exclude users who did not pass '--build-users-group'.)
  98. (with-error-handling
  99. (match args
  100. (((? derivation-path? drv) (? store-path? output))
  101. (assert-low-privileges)
  102. (perform-download (read-derivation-from-file drv)
  103. output
  104. #:print-build-trace? print-build-trace?))
  105. (((? derivation-path? drv)) ;backward compatibility
  106. (assert-low-privileges)
  107. (perform-download (read-derivation-from-file drv)
  108. #:print-build-trace? print-build-trace?))
  109. (("--version")
  110. (show-version-and-exit))
  111. (x
  112. (leave
  113. (G_ "fixed-output derivation and output file name expected~%"))))))
  114. ;; Local Variables:
  115. ;; eval: (put 'derivation-let 'scheme-indent-function 2)
  116. ;; End:
  117. ;; perform-download.scm ends here