1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#!/bin/bash
# git-verify-to-tip
# -----------------
#
# Verify PGP signatures on all commits from the last signed tag
# or any arbitrary object in the repository history.
#
# This script can be installed as hooks/pre-push.
#
# Configurable parameters
# -----------------------
# We always ensure the signing key is both GOOD and VALID, which means
# that the keys you are checking against should be imported into your
# gnupghome and signed by a trusted key (e.g. your own). If you want to
# use a different GNUPG directory other than the one in your home, you
# can "export GNUPGHOME=some/path" before running this script. In addition,
# you may explicitly specify the keys to trust in the ONLYKEYS parameter below,
# e.g. if you want to make sure the signatures came from a very small subset
# of developers. Pipe-separate multiple keys, e.g.:
# ONLYKEYS="ABAF11C65A2970B130ABE3C479BE3E4300411886|647F28654894E3BD457199BE38DBBDC86092693E"
ONLYKEYS=
#
# By default, we check signatures on every commit, but if you set this to
# --merges, we will only check signatures on merges. You can also add any
# other flags accepted by git-rev-list.
REVFLAGS=
#
# When set to "" we start from the latest annotated tag we find.
# You can also list an arbitrary commit object here.
# When running as hooks/pre-push, we ignore this entirely and use the
# commit information provided by git on stdin.
STARTFROM=
#
# We can also get these parameters from the git config. E.g.:
# [verify-to-tip]
# onlykeys = ABAF11C65A2970B130ABE3C479BE3E4300411886|647F28654894E3BD457199BE38DBBDC86092693E
# revflags = --merges
# startfrom = abcdef123456
#
if [[ -z ${ONLYKEYS} ]]; then
ONLYKEYS=$(git config --get verify-to-tip.onlykeys)
fi
if [[ -z ${REVFLAGS} ]]; then
REVFLAGS=$(git config --get verify-to-tip.revflags)
fi
if [[ -z ${STARTFROM} ]]; then
STARTFROM=$(git config --get verify-to-tip.startfrom)
fi
# End configuration
function verify_raw_gpg {
# We are looking for [GNUPG:] GOODSIG and [GNUPG:] VALIDSIG
# They must be both present, or this is not a valid sig
COUNT=$(echo "${1}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
if [[ ${COUNT} -lt 2 ]]; then
return 1
fi
if [[ -z ${ONLYKEYS} ]]; then
return 0
fi
if $(echo "${1}" | grep -q -E "^\[GNUPG:\] VALIDSIG .* (${ONLYKEYS})\$"); then
return 0
fi
return 1
}
function verify_rev_range {
REVRANGE=${1}
REVFLAGS=${2}
for REV in $(git rev-list ${REVRANGE} ${REVFLAGS}); do
echo "Verifying $REV"
RAWOUT=$(git verify-commit --raw ${REV} 2>&1)
if ! verify_raw_gpg "${RAWOUT}"; then
echo "CRITICAL: ${REV} signature did NOT verify:"
echo "${RAWOUT}"
return 1
fi
done
return 0
}
# Are we running from hooks/pre-push? If so, $1 and $2 should be set.
if [[ -z "${1}${2}" ]]; then
# Not running as a pre-push hook.
if [[ -z ${STARTFROM} ]]; then
# verify the last annotated tag
STARTFROM=$(git describe --abbrev=0)
RAWOUT=$(git verify-tag --raw ${STARTFROM} 2>&1)
else
# verify the arbitrary commit provided
RAWOUT=$(git verify-commit --raw ${STARTFROM} 2>&1)
fi
echo "Verifying ${STARTFROM}"
if ! verify_raw_gpg "${RAWOUT}"; then
echo "CRITICAL: ${STARTFROM} signature did NOT verify:"
echo "${RAWOUT}"
exit 1
fi
REVRANGE="${STARTFROM}.."
if ! verify_rev_range "${REVRANGE}" "${REVFLAGS}"; then
exit 1
fi
else
# We are in a pre-push hook
Z40="0000000000000000000000000000000000000000"
while read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA; do
if [[ ${LOCAL_SHA} == ${Z40} ]]; then
# Ignore delete
continue
fi
if [[ ${REMOTE_SHA} == ${Z40} ]]; then
# New branch, examine all commits
REVRANGE=${LOCAL_SHA}
else
# Update to existing branch, examine new commits
REVRANGE="${REMOTE_SHA}..${LOCAL_SHA}"
fi
if ! verify_rev_range "${REVRANGE}" "${REVFLAGS}"; then
exit 1
fi
done
fi
echo "Verified successfully."
exit 0
|