winbindd: use add_trusted_domain_from_auth
[bbaumbach/samba-autobuild/.git] / selftest / manage-ca / manage-ca.sh
1 #!/bin/bash
2 #
3
4 set -e
5 set -u
6 #set -x
7
8 umask 022
9
10 function print_usage()
11 {
12         echo "Usage:"
13         echo ""
14         echo "${0} <CNF_FILE> <CMD> [<ARG1> [<ARG2>]]"
15         echo ""
16         echo "${0} <CNF_FILE> init_ca"
17         echo "${0} <CNF_FILE> update_crl"
18         echo "${0} <CNF_FILE> publish_crl"
19         echo "${0} <CNF_FILE> create_dc <DC_DNS_NAME> <DC_OBJECTGUID_HEX>"
20         echo "${0} <CNF_FILE> revoke_dc <DC_DNS_NAME> <REVOKE_RESON>"
21         echo "${0} <CNF_FILE> create_user <USER_PRINCIPAL_NAME>"
22         echo "${0} <CNF_FILE> revoke_user <USER_PRINCIPAL_NAME> <REVOKE_RESON>"
23         echo ""
24 }
25
26 function check_arg()
27 {
28         local k="${1}"
29         local v="${2}"
30
31         test -n "${v}" || {
32                 print_usage
33                 echo "ERROR: CMD[${CMD}] argument <${k}> missing"
34                 return 1
35         }
36
37         return 0
38 }
39 CNF="${1-}"
40 test -n "${CNF}" || {
41         print_usage
42         echo "ERROR: speficy <CNF_FILE> see manage-ca.templates.d/manage-CA-example.com.cnf"
43         exit 1
44 }
45 test -e "${CNF}" || {
46         print_usage
47         echo "ERROR: CNF_FILE[${CNF}] does not exist"
48         exit 1
49 }
50 CMD="${2-}"
51 CMDARG1="${3-}"
52 CMDARG2="${4-}"
53
54 TEMPLATE_DIR="manage-ca.templates.d"
55 DEFAULT_VARS=""
56 DEFAULT_VARS="${DEFAULT_VARS} CRL_HTTP_BASE DNS_DOMAIN DEFAULT_BITS"
57 DEFAULT_VARS="${DEFAULT_VARS} DEFAULT_BITS DEFAULT_DAYS DEFAULT_CRL_DAYS"
58 DEFAULT_VARS="${DEFAULT_VARS} COUNTRY_NAME STATE_NAME LOCALITY_NAME ORGANIZATION_NAME"
59 DEFAULT_VARS="${DEFAULT_VARS} ORGANIZATIONAL_UNIT_NAME COMMON_NAME EMAIL_ADDRESS"
60
61 source "${CNF}"
62
63 DEFAULT_BITS=${DEFAULT_BITS:=8192}
64 CA_BITS=${CA_BITS:=${DEFAULT_BITS}}
65 DC_BITS=${DC_BITS:=${DEFAULT_BITS}}
66 USER_BITS=${USER_BITS:=${DEFAULT_BITS}}
67
68 CA_DAYS=${CA_DAYS:=3650}
69 CRL_DAYS=${CRL_DAYS:=30}
70 DC_DAYS=${DC_DAYS:=730}
71 USER_DAYS=${USER_DAYS:=730}
72
73 CA_DIR="CA-${DNS_DOMAIN}"
74 DEFAULT_VARS="${DEFAULT_VARS} CA_DIR"
75
76 CACERT_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.pem"
77 CACERT_CER="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.cer"
78 CACRL_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.pem"
79 CACRL_CRL="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.crl"
80 CA_SERIAL="${CA_DIR}/Private/CA-${DNS_DOMAIN}-serial.txt"
81
82 function generate_from_template()
83 {
84         local base_template="${TEMPLATE_DIR}/$1"
85         local cmd_template="${TEMPLATE_DIR}/$2"
86         local cnf_file="$3"
87         shift 3
88         local vars="$@"
89
90         test -f "${base_template}" || {
91                 echo "base_template[${base_template}] does not exists"
92                 return 1
93         }
94         test -f "${cmd_template}" || {
95                 echo "cmd_template[${cmd_template}] does not exists"
96                 return 1
97         }
98         test -e "${cnf_file}" && {
99                 echo "cnf_file[${cnf_file}] already exists"
100                 return 1
101         }
102
103         local sedargs=""
104         for k in $vars; do
105                 v=$(eval echo "\${${k}}")
106                 sedargs="${sedargs} -e 's!@@${k}@@!${v}!g'"
107         done
108
109         #echo "sedargs[${sedargs}]"
110         cat "${base_template}" "${cmd_template}" | eval sed ${sedargs} > "${cnf_file}"
111         grep '@@'  "${cnf_file}" | wc -l | grep -q '^0' || {
112                 echo "invalid context in cnf_file[${cnf_file}]"
113                 grep '@@' "${cnf_file}"
114                 return 1
115         }
116
117         return 0
118 }
119
120 case "${CMD}" in
121 init_ca)
122         test -e "${CA_DIR}" && {
123                 echo "CA with CA_DIR[${CA_DIR}] already exists"
124                 exit 1
125         }
126
127         OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
128         CA_INDEX="${CA_DIR}/Private/CA-${DNS_DOMAIN}-index.txt"
129         CA_CRLNUMBER="${CA_DIR}/Private/CA-${DNS_DOMAIN}-crlnumber.txt"
130         PRIVATEKEY="${CA_DIR}/Private/CA-${DNS_DOMAIN}-private-key.pem"
131
132         ORGANIZATIONAL_UNIT_NAME="CA Administration"
133         COMMON_NAME="CA of ${DNS_DOMAIN}"
134         EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
135
136         DEFAULT_BITS="${CA_BITS}"
137         DEFAULT_DAYS="1"
138         DEFAULT_CRL_DAYS="${CRL_DAYS}"
139
140         mkdir -p "${CA_DIR}/"{,Public}
141         umask 077
142         mkdir -p "${CA_DIR}/"{,Private,NewCerts,DCs,Users}
143         umask 022
144         touch "${CA_INDEX}"
145         echo "00" > "${CA_SERIAL}"
146         echo "00" > "${CA_CRLNUMBER}"
147
148         generate_from_template \
149                 "openssl-BASE-template.cnf" \
150                 "openssl-CA-template.cnf" \
151                 "${OPENSSLCNF}" \
152                 ${DEFAULT_VARS}
153         openssl req -new -x509 -sha256 -extensions v3_ca -days "${CA_DAYS}" -keyout "${PRIVATEKEY}" -out "${CACERT_PEM}" -config "${OPENSSLCNF}"
154         openssl x509 -in "${CACERT_PEM}" -inform PEM -out "${CACERT_CER}" -outform DER
155         echo -n "Generate CRL [ENTER] to continue"
156         read
157         openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
158         openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
159         ls -la "${CA_DIR}"/Public/CA-*
160         echo "Please run: '${0} ${CNF} publish_crl'"
161         exit 0
162         ;;
163 update_crl)
164         test -e "${CA_DIR}" || {
165                 echo "CA with CA_DIR[${CA_DIR}] does not exists"
166                 exit 1
167         }
168
169         OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
170         openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
171         openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
172         ls -la "${CACRL_PEM}" "${CACRL_CRL}"
173         echo "Please run: '${0} ${CNF} publish_crl'"
174         exit 0
175         ;;
176 publish_crl)
177         test -e "${CA_DIR}" || {
178                 echo "CA with CA_DIR[${CA_DIR}] does not exists"
179                 exit 1
180         }
181
182         echo "Upload ${CACRL_CRL} to ${CRL_SSH_BASE}/"
183         rsync -a -P "${CACRL_CRL}" "${CRL_SSH_BASE}/"
184         echo "Check ${CRL_HTTP_BASE}/CA-${DNS_DOMAIN}-crl.crl"
185         exit 0
186         ;;
187 create_dc)
188         test -e "${CA_DIR}" || {
189                 echo "CA with CA_DIR[${CA_DIR}] does not exists"
190                 exit 1
191         }
192         #
193         #
194         # ldbsearch -H ldap://DC_DNS_NAME '(dnsHostName=DC_DNS_NAME)' distinguishedName --controls=search_options:1:1 --controls=extended_dn:1:0
195         DC_DNS_NAME="${CMDARG1}"
196         check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
197         DC_OBJECTGUID_HEX=$(echo "${CMDARG2}" | tr a-z A-Z)
198         check_arg "DC_OBJECTGUID_HEX" "${DC_OBJECTGUID_HEX}"
199
200         DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
201         test -e "${DC_DIR}" && {
202                 echo "DC with DC_DIR[${DC_DIR}] already exists"
203                 exit 1
204         }
205
206         NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
207         DCFILE_BASE="DC-${DC_DNS_NAME}-S${NEXT_SERIAL}"
208         OPENSSLCNF="${DC_DIR}/${DCFILE_BASE}-openssl.cnf"
209         DCKEY_PEM="${DC_DIR}/${DCFILE_BASE}-key.pem"
210         DCKEY_PRIVATE_PEM="${DC_DIR}/${DCFILE_BASE}-private-key.pem"
211         DCKEY_PRIVATE_PEM_BASE="${DCFILE_BASE}-private-key.pem"
212         DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
213         DCREQ_PEM="${DC_DIR}/${DCFILE_BASE}-req.pem"
214         DCCERT_PEM="${DC_DIR}/${DCFILE_BASE}-cert.pem"
215         DCCERT_PEM_BASE="${DCFILE_BASE}-cert.pem"
216         DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
217         DCCERT_CER="${DC_DIR}/${DCFILE_BASE}-cert.cer"
218         DCCERT_P12="${DC_DIR}/${DCFILE_BASE}-private.p12"
219
220         ORGANIZATIONAL_UNIT_NAME="Domain Controllers"
221         COMMON_NAME="${DC_DNS_NAME}"
222         EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
223
224         DEFAULT_BITS="${DC_BITS}"
225         DEFAULT_DAYS="${DC_DAYS}"
226         DEFAULT_CRL_DAYS="${CRL_DAYS}"
227
228         umask 077
229         mkdir -p "${DC_DIR}/"
230
231         generate_from_template \
232                 "openssl-BASE-template.cnf" \
233                 "openssl-DC-template.cnf" \
234                 "${OPENSSLCNF}" \
235                 ${DEFAULT_VARS} DC_DNS_NAME DC_OBJECTGUID_HEX
236
237         openssl req -new -newkey rsa:${DC_BITS} -keyout "${DCKEY_PEM}" -out "${DCREQ_PEM}" -config "${OPENSSLCNF}"
238         openssl rsa -in "${DCKEY_PEM}" -inform PEM -out "${DCKEY_PRIVATE_PEM}" -outform PEM
239         openssl ca -config "${OPENSSLCNF}" -in "${DCREQ_PEM}" -out "${DCCERT_PEM}"
240         ln -s "${DCKEY_PRIVATE_PEM_BASE}" "${DCKEY_PRIVATE_PEM_LINK}"
241         ln -s "${DCCERT_PEM_BASE}" "${DCCERT_PEM_LINK}"
242         openssl x509 -in "${DCCERT_PEM}"  -inform PEM -out "${DCCERT_CER}" -outform DER
243         echo "Generate ${DCCERT_P12}"
244         openssl pkcs12 -in "${DCCERT_PEM}" -inkey "${DCKEY_PRIVATE_PEM}" -export -out "${DCCERT_P12}"
245         ls -la "${DC_DIR}"/*.*
246         exit 0
247         ;;
248 revoke_dc)
249         test -e "${CA_DIR}" || {
250                 echo "CA with CA_DIR[${CA_DIR}] does not exists"
251                 exit 1
252         }
253         DC_DNS_NAME="${CMDARG1}"
254         check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
255         REVOKE_REASON="${CMDARG2}"
256         check_arg "REVOKE_REASON" "${REVOKE_REASON}"
257
258         DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
259         test -e "${DC_DIR}" || {
260                 echo "DC with DC_DIR[${DC_DIR}] does not exists"
261                 exit 1
262         }
263
264         OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
265         DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
266         DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
267
268         REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
269         REVOKE_DC_DIR="${DC_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
270
271         openssl ca -config "${OPENSSLCNF}" -revoke "${DCCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
272
273         mv "${DCKEY_PRIVATE_PEM_LINK}" "${DCKEY_PRIVATE_PEM_LINK}.revoked"
274         mv "${DCCERT_PEM_LINK}" "${DCCERT_PEM_LINK}.revoked"
275         mv "${DC_DIR}" "${REVOKE_DC_DIR}"
276         echo "${REVOKE_DC_DIR}"
277
278         openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
279         openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
280         ls -la "${CACRL_PEM}" "${CACRL_CRL}"
281         echo "Please run: '${0} ${CNF} publish_crl'"
282         exit 0
283         ;;
284 create_user)
285         test -e "${CA_DIR}" || {
286                 echo "CA with CA_DIR[${CA_DIR}] does not exists"
287                 exit 1
288         }
289         USER_PRINCIPAL_NAME="${CMDARG1}"
290         check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
291
292         USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
293         test -e "${USER_DIR}" && {
294                 echo "USER with USER_DIR[${USER_DIR}] already exists"
295                 exit 1
296         }
297
298         NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
299         USERFILE_BASE="USER-${USER_PRINCIPAL_NAME}-S${NEXT_SERIAL}"
300         OPENSSLCNF="${USER_DIR}/${USERFILE_BASE}-openssl.cnf"
301         USERKEY_PEM="${USER_DIR}/${USERFILE_BASE}-key.pem"
302         USERKEY_PRIVATE_PEM="${USER_DIR}/${USERFILE_BASE}-private-key.pem"
303         USERKEY_PRIVATE_PEM_BASE="${USERFILE_BASE}-private-key.pem"
304         USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
305         USERREQ_PEM="${USER_DIR}/${USERFILE_BASE}-req.pem"
306         USERCERT_PEM="${USER_DIR}/${USERFILE_BASE}-cert.pem"
307         USERCERT_PEM_BASE="${USERFILE_BASE}-cert.pem"
308         USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
309         USERCERT_CER="${USER_DIR}/${USERFILE_BASE}-cert.cer"
310         USERCERT_P12="${USER_DIR}/${USERFILE_BASE}-private.p12"
311
312         ORGANIZATIONAL_UNIT_NAME="Users"
313         COMMON_NAME="${USER_PRINCIPAL_NAME}"
314         EMAIL_ADDRESS="${USER_PRINCIPAL_NAME}"
315
316         DEFAULT_BITS="${USER_BITS}"
317         DEFAULT_DAYS="${USER_DAYS}"
318         DEFAULT_CRL_DAYS="${CRL_DAYS}"
319
320         umask 077
321         mkdir -p "${USER_DIR}/"
322
323         generate_from_template \
324                 "openssl-BASE-template.cnf" \
325                 "openssl-USER-template.cnf" \
326                 "${OPENSSLCNF}" \
327                 ${DEFAULT_VARS} USER_PRINCIPAL_NAME
328
329         openssl req -new -newkey rsa:${USER_BITS} -keyout "${USERKEY_PEM}" -out "${USERREQ_PEM}" -config "${OPENSSLCNF}"
330         openssl rsa -in "${USERKEY_PEM}" -inform PEM -out "${USERKEY_PRIVATE_PEM}" -outform PEM
331         openssl ca -config "${OPENSSLCNF}" -in "${USERREQ_PEM}" -out "${USERCERT_PEM}"
332         ln -s "${USERKEY_PRIVATE_PEM_BASE}" "${USERKEY_PRIVATE_PEM_LINK}"
333         ln -s "${USERCERT_PEM_BASE}" "${USERCERT_PEM_LINK}"
334         openssl x509 -in "${USERCERT_PEM}"  -inform PEM -out "${USERCERT_CER}" -outform DER
335         echo "Generate ${USERCERT_P12}"
336         openssl pkcs12 -in "${USERCERT_PEM}" -inkey "${USERKEY_PRIVATE_PEM}" -export -out "${USERCERT_P12}"
337         ls -la "${USER_DIR}"/*.*
338         exit 0
339         ;;
340 revoke_user)
341         test -e "${CA_DIR}" || {
342                 echo "CA with CA_DIR[${CA_DIR}] does not exists"
343                 exit 1
344         }
345         USER_PRINCIPAL_NAME="${CMDARG1}"
346         check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
347         REVOKE_REASON="${CMDARG2}"
348         check_arg "REVOKE_REASON" "${REVOKE_REASON}"
349
350         USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
351         test -e "${USER_DIR}" || {
352                 echo "USER with USER_DIR[${USER_DIR}] does not exists"
353                 exit 1
354         }
355
356         OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
357         USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
358         USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
359
360         REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
361         REVOKE_USER_DIR="${USER_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
362
363         openssl ca -config "${OPENSSLCNF}" -revoke "${USERCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
364
365         mv "${USERKEY_PRIVATE_PEM_LINK}" "${USERKEY_PRIVATE_PEM_LINK}.revoked"
366         mv "${USERCERT_PEM_LINK}" "${USERCERT_PEM_LINK}.revoked"
367         mv "${USER_DIR}" "${REVOKE_USER_DIR}.revoked"
368         echo "${REVOKE_USER_DIR}"
369
370         openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
371         openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
372         ls -la "${CACRL_PEM}" "${CACRL_CRL}"
373         echo "Please run: '${0} ${CNF} publish_crl'"
374         exit 0
375         ;;
376 usage)
377         print_usage
378         exit 1
379         ;;
380 *)
381         print_usage
382         echo "ERROR: CMD[${CMD}] - unknown"
383         exit 1
384         ;;
385 esac
386
387 exit 1