unofficial mirror of bug-guix@gnu.org 
 help / color / mirror / code / Atom feed
From: ludo@gnu.org (Ludovic Courtès)
To: 22883@debbugs.gnu.org
Subject: bug#22883: Authenticating a Git checkout
Date: Fri, 22 Jul 2016 10:22:15 +0200	[thread overview]
Message-ID: <87wpket748.fsf@gnu.org> (raw)
In-Reply-To: <87bn3iz1xc.fsf_-_@gnu.org> ("Ludovic \=\?utf-8\?Q\?Court\=C3\=A8s\?\= \=\?utf-8\?Q\?\=22's\?\= message of "Fri, 03 Jun 2016 18:12:47 +0200")

[-- Attachment #1: Type: text/plain, Size: 3503 bytes --]

Hi!

ludo@gnu.org (Ludovic Courtès) skribis:

> Sixth, OK, we’ll use libgit2, and write Guile bindings, maybe based on
> the CHICKEN bindings², easy!  Well no, it turns out that libgit2³ has no
> support for signed commits (the ‘signature’ abstraction there has
> nothing to do with OpenPGP signatures.)
>
> Seventh, even if it did, what would we do with the raw ASCII-armored
> OpenPGP signature?  GPG and GPGME are waaaay too high-level, so we’d
> need to implement OpenPGP (in Guile, maybe based on the OpenPGP library
> in Bigloo?)?!

This bit was too pessimistic it seems.  :-)

With the quick-hack libgit2 bindings attached, I can run this program,
which authenticates HEAD:

--8<---------------cut here---------------start------------->8---
(use-modules (guix git)
             (guix gnupg)
             (srfi srfi-11)
             (srfi srfi-26))

(let* ((repo      (open-repository "."))
       (head      (repository-head repo))
       (commit-id (reference-target head)))
  (let-values (((signature signed-data)
                (commit-signature repo commit-id)))
    (with-fluids ((%default-port-encoding "UTF-8"))
      (call-with-output-file "/tmp/s"
        (cut display signature <>))
      (call-with-output-file "/tmp/d"
        (cut display signed-data <>)))
    (pk (gnupg-verify "/tmp/s" "/tmp/d"))))
--8<---------------cut here---------------end--------------->8---

… which gives:

--8<---------------cut here---------------start------------->8---
$ ./pre-inst-env guile t.scm
gpg: Signature made Thu 21 Jul 2016 06:53:27 PM CEST using RSA key ID 3D9AEBB5
gpg: Good signature from "Ludovic Courtès <ludo@gnu.org>" [full]
gpg:                 aka "Ludovic Courtès <ludo@chbouib.org>" [full]
gpg:                 aka "Ludovic Courtès (Inria) <ludovic.courtes@inria.fr>" [full]

;;; (((unparsed-line "[GNUPG:] NEWSIG") (signature-id "5U2RqMgQpDFefFuBzsYBDsrL9xg" "2016-07-21" 1469120007) (good-signature "090B11993D9AEBB5" "Ludovic Courtès <ludo@gnu.org>") (valid-signature "3CE464558A84FDC69DB40CFB090B11993D9AEBB5" "2016-07-21" 1469120007) (unparsed-line "[GNUPG:] TRUST_FULLY")))
--8<---------------cut here---------------end--------------->8---

So I think we can go from here.  Our repo would contain a Scheme list of
authorized OpenPGP fingerprints, and we’d check whether the fingerprint
that shows up in ‘valid-signature’ above is among them (IMO this is
better than using a GnuPG keyring because GnuPG keyrings are opaque
binary blobs—we wouldn’t be able to diff subsequent revisions of the
keyring—and they contain full OpenPGP keys, including signature packets
and all that, which we don’t need/want for authorization purposes; we
may still want to store a keyring though, but simply for the purposes of
allowing gpg to check signatures.)

Since we just need to read Git objects, after all, another option would
be to avoid libgit2 and read them ourselves, which wouldn’t be hard (I’d
expect ~500 lines of code), would avoid the dependency, and be more
robust (no C!).

However, ‘guix pull’ can make good use of libgit2 to directly clone/pull
in the future, so it makes sense to have libgit2 bindings.

It Would Be Nice if the libgit2 bindings were maintained separately.  We
can start with just the features we need as (guix git), but if anyone
wants to “externalize” it and improve it, that would be more than
welcome!

Thoughts?

Thanks,
Ludo’.


[-- Attachment #2: quick hack! --]
[-- Type: text/plain, Size: 5136 bytes --]

;;; Copyright © Ludovic Courtès <ludo@gnu.org>
;;; Released under the GNU GPL version 3 or later.

(define-module (guix git)
  #:use-module (rnrs bytevectors)
  #:use-module (system foreign)
  #:use-module (ice-9 match)
  #:export (repository?
            open-repository
            reference?
            repository-head
            reference-target
            oid?
            commit-signature))

;; DRAFT!

(define libgit2
  (dynamic-link "/gnu/store/g8r0qwnzf2j17hd84cchc6cmr51sflz8-libgit2-0.24.1/lib/libgit2"))

(define (libgit2->procedure return name params)
  (pointer->procedure return (dynamic-func name libgit2) params))

(define-inlinable (libgit2->procedure* name params)
  (let ((proc (libgit2->procedure int name params)))
    (lambda args
      (let ((ret (apply proc args)))
        (unless (zero? ret)
          (throw 'git-error ret))))))

(define initialize!
  (libgit2->procedure int "git_libgit2_init" '()))

(define-syntax define-libgit2-type
  (lambda (s)
    "Define a wrapped pointer type for an opaque type of libgit2."
    (syntax-case s ()
      ((_ name)
       (let ((symbol     (syntax->datum #'name))
             (identifier (lambda (symbol)
                           (datum->syntax #'name symbol))))
         (with-syntax ((rtd    (identifier (symbol-append '< symbol '>)))
                       (pred   (identifier (symbol-append symbol '?)))
                       (wrap   (identifier (symbol-append 'pointer-> symbol)))
                       (unwrap (identifier (symbol-append symbol '->pointer))))
           #`(define-wrapped-pointer-type rtd
               pred
               wrap unwrap
               (lambda (obj port)
                 (format port "#<git-~a ~a>"
                         #,(symbol->string symbol)
                         (number->string (pointer-address (unwrap obj))
                                         16))))))))))

(define-libgit2-type repository)

(define open-repository
  (let ((proc (libgit2->procedure* "git_repository_open" '(* *))))
    (lambda (file)
      (let ((result (bytevector->pointer (make-bytevector (sizeof '*)))))
        (proc result (string->pointer file))
        (pointer->repository (dereference-pointer result))))))

(define-libgit2-type reference)

(define repository-head
  (let ((proc (libgit2->procedure* "git_repository_head" '(* *))))
    (lambda (repository)
      (let ((result (bytevector->pointer (make-bytevector (sizeof '*)))))
        (proc result (repository->pointer repository))
        (pointer->reference (dereference-pointer result))))))

(define-libgit2-type oid)

(define reference-target
  (let ((proc (libgit2->procedure '* "git_reference_target" '(*))))
    (lambda (reference)
      (pointer->oid (proc (reference->pointer reference))))))

(define-libgit2-type commit)

(define lookup-commit
  (let ((proc (libgit2->procedure* "git_commit_lookup" `(* * *))))
    (lambda (repository oid)
      (let ((result (bytevector->pointer (make-bytevector (sizeof '*)))))
        (proc result (repository->pointer repository) (oid->pointer oid))
        (pointer->commit (dereference-pointer result))))))

(define commit-raw-header
  (let ((proc (libgit2->procedure '* "git_commit_raw_header" '(*))))
    (lambda (commit)
      (pointer->string (proc (commit->pointer commit))))))

(define %buffer-struct                            ;git_buf
  (list '* size_t size_t))

(define free-buffer
  (libgit2->procedure void "git_buf_free" '(*)))

(define (buffer-content buf)
  (match (parse-c-struct buf %buffer-struct)
    ((pointer asize size)
     (pointer->bytevector pointer size))))

(define (buffer-content/string buf)
  (match (parse-c-struct buf %buffer-struct)
    ((pointer asize size)
     (pointer->string pointer size "UTF-8"))))

(define commit-signature
  (let ((proc (libgit2->procedure* "git_commit_extract_signature"
                                   '(* * * * *))))
    (lambda* (repository oid #:optional (field "gpgsig"))
      (let ((signature (make-c-struct %buffer-struct
                                      `(,%null-pointer 0 0)))
            (data      (make-c-struct %buffer-struct
                                      `(,%null-pointer 0 0))))
        (proc signature data (repository->pointer repository)
              (oid->pointer oid)
              (string->pointer field))
        (let ((signature* (buffer-content/string signature))
              (data*      (buffer-content/string data)))
          (free-buffer signature)
          (free-buffer data)
          (values signature* data*))))))


(define-libgit2-type object)

(define GIT_OBJ_ANY -2)

(define lookup-object
  (let ((proc (libgit2->procedure* "git_object_lookup" `(* * * ,int))))
    (lambda* (repository oid #:optional (type GIT_OBJ_ANY))
      (let ((result (bytevector->pointer (make-bytevector (sizeof '*)))))
        (proc result (repository->pointer repository) (oid->pointer oid)
              type)
        (pointer->object (dereference-pointer result))))))

(initialize!)

  parent reply	other threads:[~2016-07-22  8:23 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-02 18:03 bug#22883: Trustable "guix pull" Christopher Allan Webber
2016-03-02 19:26 ` Leo Famulari
2016-03-02 21:07   ` Christopher Allan Webber
2016-04-25 22:25 ` Ludovic Courtès
2016-04-26  0:13   ` Leo Famulari
2016-04-26  0:17     ` Thompson, David
2016-04-26  7:12       ` Ludovic Courtès
2016-04-30  4:43     ` Mike Gerwitz
2016-06-03 16:12       ` bug#22883: Authenticating a Git checkout Ludovic Courtès
2016-06-03 20:17         ` Leo Famulari
2016-06-04 11:04           ` Ludovic Courtès
2016-06-04  4:24         ` Mike Gerwitz
2016-06-04 11:17           ` Ludovic Courtès
2016-06-04 12:45             ` ng0
2016-06-06 12:20               ` ng0
2016-06-04 16:14             ` Mike Gerwitz
2016-06-05 20:39             ` Christopher Allan Webber
2016-06-05 21:15               ` Leo Famulari
2016-06-06  2:41               ` Mike Gerwitz
2016-06-06  7:01                 ` Ludovic Courtès
2016-07-22  8:22         ` Ludovic Courtès [this message]
2016-07-22 12:58           ` Thompson, David
2016-07-22 13:58             ` Ludovic Courtès
2017-10-24 23:30           ` Ludovic Courtès
2019-12-27 19:48             ` Ricardo Wurmus
2019-12-28 14:47               ` Ludovic Courtès
2019-12-28 16:05                 ` Ricardo Wurmus
2019-12-28 17:45                   ` Ludovic Courtès
2020-04-30 15:32                 ` Ludovic Courtès
2020-05-01 15:46                   ` Justus Winter
2020-05-01 16:50                     ` Ludovic Courtès
2020-05-01 17:04                   ` Ludovic Courtès
2020-05-19 20:23                     ` Ludovic Courtès
2020-06-01 14:07                       ` bug#22883: Channel introductions Ludovic Courtès
2020-06-02 23:45                         ` zimoun
2020-06-03  9:50                           ` Ludovic Courtès
2020-06-03 16:20                             ` zimoun
2020-06-04  9:55                               ` Ludovic Courtès
2020-05-01 17:20                   ` bug#22883: Authenticating a Git checkout Ludovic Courtès
2020-05-02 22:02                   ` Ludovic Courtès
2020-05-04  8:03                     ` Ludovic Courtès
2016-06-01 16:47   ` bug#22883: Discussion of TUF in the context of Git checkout authentication Ludovic Courtès
2016-05-15 12:40 ` bug#22883: Trustable "guix pull" fluxboks
2016-05-16 17:55   ` Thompson, David
2016-05-17 21:19   ` Ludovic Courtès
2016-06-04 16:19 ` Werner Koch
2016-06-04 22:27   ` Ludovic Courtès
2016-06-05  7:51     ` Werner Koch
2016-06-06 21:01       ` Leo Famulari
2016-06-07  8:08         ` bug#22883: gpg2 vs. gpg Ludovic Courtès
2016-06-07 11:25           ` Werner Koch
2016-06-07 12:58             ` ng0
2016-06-05  1:43   ` bug#22883: Trustable "guix pull" Mike Gerwitz
2018-08-28 19:56 ` Vagrant Cascadian
2018-09-02 16:05   ` Ludovic Courtès
2018-09-02 17:15     ` Vagrant Cascadian
2018-09-02 20:07       ` Ludovic Courtès
2019-12-20 22:11         ` bug#22883: Authenticating Git checkouts: step #1 Ludovic Courtès
     [not found]         ` <87mubmodfb.fsf_-_@gnu.org>
2019-12-21  1:33           ` zimoun
2019-12-27 12:58           ` Ludovic Courtès
     [not found]           ` <87eewqgc1v.fsf@gnu.org>
2019-12-27 20:47             ` Ricardo Wurmus
     [not found]             ` <87o8vto5rl.fsf@elephly.net>
2019-12-29  2:45               ` Vagrant Cascadian
     [not found]               ` <87a77bzw6p.fsf@yucca>
2019-12-29  7:34                 ` Efraim Flashner
2019-12-30 21:29                 ` Ludovic Courtès
2019-12-31 19:16 ` Jakub Kądziołka
2020-01-08 13:30   ` Ludovic Courtès
2020-06-02 13:49 ` bug#22883: Authenticating a Git checkout John Soo
2020-06-03  9:33   ` Ludovic Courtès
2020-06-08 21:54 ` bug#22883: [PATCH 1/9] git-authenticate: Cache takes a key parameter Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 2/9] git-authenticate: 'authenticate-commits' takes a #:keyring parameter Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 3/9] tests: Move OpenPGP helpers to (guix tests gnupg) Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 4/9] channels: 'latest-channel-instance' authenticates Git checkouts Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 5/9] channels: Make 'validate-pull' call right after clone/pull Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 6/9] .guix-channel: Add 'keyring-reference' Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 7/9] channels: Automatically add introduction for the official 'guix' channel Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 8/9] pull: Add '--disable-authentication' Ludovic Courtès
2020-06-08 21:54   ` bug#22883: [PATCH 9/9] DROP? channels: Add prehistorical authorizations to <channel-introduction> Ludovic Courtès
2020-06-08 22:04   ` bug#22883: [PATCH 1/9] git-authenticate: Cache takes a key parameter Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87wpket748.fsf@gnu.org \
    --to=ludo@gnu.org \
    --cc=22883@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).