summaryrefslogtreecommitdiff
path: root/sign-request.in
blob: b4645520e5f6e2fd45cb8ab6a045b43d70757aac (plain)
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
#!/bin/bash

key_dir='#ETCDIR#/simple-pki/keys'

if [ -r '#ETCDIR#/simple-pki/ca.conf' ]; then
  . '#ETCDIR#/simple-pki/ca.conf'
fi

cd "${0%/*}"

remove_leading_spaces() {
  sed '
    s/^ \{'"$1"'\}//
    t
    d
  '
}

tmp_dir=$(mktemp -d)
trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT

while read -r csr; do
  csr_local="${tmp_dir}/${csr##*/}"
  curl -Ss --insecure "${csr}" -o "${csr_local}"
  if ! content=$(
    openssl req -text -noout -verify -in "${csr_local}" 2>/dev/null
  ); then
    >&2 echo 'verify failed - skipping'
    rm "${csr_local}"
    continue
  fi
  content=$(
    printf '%s\n' "${content}" \
    | sed -n '
      /^Certificate Request:$/,/^\S/p
    ' \
    | remove_leading_spaces 4 \
    | sed -n '
      /^Data:$/,/^\S/p
    ' \
    | remove_leading_spaces 4
  )
  cn=$(
    printf '%s\n' "${content}" \
    | sed '
      s/^Subject: //
      t
      d
    ' \
    | tr -d ' ' \
    | tr ',' '/'
  )
  if [ -n "${cn%${ca_subject_prefix#/}/CN=*}" ]; then
    >&2 printf 'wrong subject: "%s" vs. "%s"\n' \
      "${cn}" \
      "${ca_subject_prefix#/}/CN=*"
    continue
  fi
  cn="${cn#${ca_subject_prefix#/}/CN=}"
  sans=$(
    printf '%s\n' "${content}" \
    | sed -n '
      /^Requested Extensions:$/,/^\S/ p
    ' \
    | remove_leading_spaces 4 \
    | sed -n '
      /^X\S\+ Subject Alternative Name:\s*$/,/^\S/ p
    ' \
    | remove_leading_spaces 4 \
    | sed '
      s/, /\n/g
    '
  )
  if printf '%s\n' "${sans}" | grep -vq '^\(DNS\|IP\):'; then
    >&2 echo 'invalid sans - skipping'
    rm "${csr_local}"
    continue
  fi
  sans=$(
    printf '%s\n' "${sans}" \
    | sed '
      s/^\(DNS\|IP\)://
    '
  )
  ok_sans=$(
    printf '%s\n' "${cn}" "${sans}" \
    | while read -r san; do
      if ! curl -Ss --insecure 'https://'"${san}/${csr#*//*/}" \
        | diff -q - "${csr_local}"; then
        >&2 printf 'invalid san "%s" - skipping\n' "${san}"
        rm "${csr_local}"
        break
      fi
      printf '%s\n' "${san}"
    done
  )
  if [ ! -f "${csr_local}" ]; then
    continue
  fi
  if [ "$(printf '%s\n' "${cn}" "${sans}")" != "${ok_sans}" ]; then
    >&2 echo 'some san was invalid - skipping'
    rm "${csr_local}"
    continue
  fi
  if [ ! -f "${key_dir}/${ca_name}.key" ] \
  || [ $((2*$(date +%s) + $(stat -c%Y "${key_dir}/${ca_name}.key"))) -gt $((3*$(stat -c%Y "${key_dir}/${ca_name}.key.new"))) ]; then
    key_to_use="${key_dir}/${ca_name}.key.new"
    crt_to_use="${key_dir}/${ca_name}.crt.new"
  else
    key_to_use="${key_dir}/${ca_name}.key"
    crt_to_use="${key_dir}/${ca_name}.crt"
  fi
  openssl x509 -req \
    -CAkey "${key_to_use}" \
    -CA "${crt_to_use}" \
    -CAserial "${key_dir}/${ca_name}.srl" \
    -CAcreateserial \
    -in "${csr_local}" \
    -out "${csr_local%.csr}.crt"
  rm "${csr_local}"
done

cd "${tmp_dir}"
tar -czf - *.crt