1 /*
2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #ifndef SQUID_SSL_GADGETS_H
10 #define SQUID_SSL_GADGETS_H
11
12 #include "base/HardFun.h"
13 #include "security/forward.h"
14 #include "ssl/crtd_message.h"
15
16 #if USE_OPENSSL
17 #include "compat/openssl.h"
18 #if HAVE_OPENSSL_ASN1_H
19 #include <openssl/asn1.h>
20 #endif
21 #if HAVE_OPENSSL_TXT_DB_H
22 #include <openssl/txt_db.h>
23 #endif
24 #if HAVE_OPENSSL_X509V3_H
25 #include <openssl/x509v3.h>
26 #endif
27 #endif
28 #include <string>
29
30 namespace Ssl
31 {
32 /**
33 \defgroup SslCrtdSslAPI SSL certificate generator API
34 These functions must not depend on Squid runtime code such as debug()
35 because they are used by security_file_certgen helper.
36 */
37
38 #if !defined(SQUID_SSL_SIGN_HASH_IF_NONE)
39 #define SQUID_SSL_SIGN_HASH_IF_NONE "sha256"
40 #endif
41
42 /**
43 * std::unique_ptr typedefs for common SSL objects
44 */
45 sk_dtor_wrapper(sk_X509, STACK_OF(X509) *, X509_free);
46 typedef std::unique_ptr<STACK_OF(X509), sk_X509_free_wrapper> X509_STACK_Pointer;
47
48 typedef std::unique_ptr<BIGNUM, HardFun<void, BIGNUM*, &BN_free>> BIGNUM_Pointer;
49
50 typedef std::unique_ptr<BIO, HardFun<void, BIO*, &BIO_vfree>> BIO_Pointer;
51
52 typedef std::unique_ptr<ASN1_INTEGER, HardFun<void, ASN1_INTEGER*, &ASN1_INTEGER_free>> ASN1_INT_Pointer;
53
54 typedef std::unique_ptr<ASN1_OCTET_STRING, HardFun<void, ASN1_OCTET_STRING*, &ASN1_OCTET_STRING_free>> ASN1_OCTET_STRING_Pointer;
55
56 typedef std::unique_ptr<TXT_DB, HardFun<void, TXT_DB*, &TXT_DB_free>> TXT_DB_Pointer;
57
58 typedef std::unique_ptr<X509_NAME, HardFun<void, X509_NAME*, &X509_NAME_free>> X509_NAME_Pointer;
59
60 typedef std::unique_ptr<RSA, HardFun<void, RSA*, &RSA_free>> RSA_Pointer;
61
62 typedef std::unique_ptr<X509_REQ, HardFun<void, X509_REQ*, &X509_REQ_free>> X509_REQ_Pointer;
63
64 typedef std::unique_ptr<AUTHORITY_KEYID, HardFun<void, AUTHORITY_KEYID*, &AUTHORITY_KEYID_free>> AUTHORITY_KEYID_Pointer;
65
66 sk_dtor_wrapper(sk_GENERAL_NAME, STACK_OF(GENERAL_NAME) *, GENERAL_NAME_free);
67 typedef std::unique_ptr<STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_free_wrapper> GENERAL_NAME_STACK_Pointer;
68
69 typedef std::unique_ptr<GENERAL_NAME, HardFun<void, GENERAL_NAME*, &GENERAL_NAME_free>> GENERAL_NAME_Pointer;
70
71 typedef std::unique_ptr<X509_EXTENSION, HardFun<void, X509_EXTENSION*, &X509_EXTENSION_free>> X509_EXTENSION_Pointer;
72
73 /**
74 \ingroup SslCrtdSslAPI
75 * Create 1024 bits rsa key.
76 */
77 EVP_PKEY * createSslPrivateKey();
78
79 /**
80 \ingroup SslCrtdSslAPI
81 * Write private key and SSL certificate to memory.
82 */
83 bool writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Security::PrivateKeyPointer const & pkey, std::string & bufferToWrite);
84
85 /**
86 \ingroup SslCrtdSslAPI
87 * Append SSL certificate to bufferToWrite.
88 */
89 bool appendCertToMemory(Security::CertPointer const & cert, std::string & bufferToWrite);
90
91 /**
92 \ingroup SslCrtdSslAPI
93 * Write private key and SSL certificate to memory.
94 */
95 bool readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, char const * bufferToRead);
96
97 /**
98 \ingroup SslCrtdSslAPI
99 * Read SSL certificate from memory.
100 */
101 bool readCertFromMemory(Security::CertPointer & cert, char const * bufferToRead);
102
103 /**
104 \ingroup SslCrtdSslAPI
105 * Read private key from file.
106 */
107 void ReadPrivateKeyFromFile(char const * keyFilename, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback);
108
109 /**
110 \ingroup SslCrtdSslAPI
111 * Initialize the bio with the file 'filename' openned for reading
112 */
113 bool OpenCertsFileForReading(BIO_Pointer &bio, const char *filename);
114
115 /**
116 \ingroup SslCrtdSslAPI
117 * Read a certificate from bio
118 */
119 bool ReadX509Certificate(BIO_Pointer &bio, Security::CertPointer & cert);
120
121 /**
122 \ingroup SslCrtdSslAPI
123 * Read a private key from bio
124 */
125 bool ReadPrivateKey(BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback);
126
127 /**
128 \ingroup SslCrtdSslAPI
129 * Initialize the bio with the file 'filename' openned for writting
130 */
131
132 bool OpenCertsFileForWriting(BIO_Pointer &bio, const char *filename);
133
134 /**
135 \ingroup SslCrtdSslAPI
136 * Write certificate to BIO.
137 */
138 bool WriteX509Certificate(BIO_Pointer &bio, const Security::CertPointer & cert);
139
140 /**
141 \ingroup SslCrtdSslAPI
142 * Write private key to BIO.
143 */
144 bool WritePrivateKey(BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey);
145
146 /**
147 \ingroup SslCrtdSslAPI
148 * Supported certificate signing algorithms
149 */
150 enum CertSignAlgorithm {algSignTrusted = 0, algSignUntrusted, algSignSelf, algSignEnd};
151
152 /**
153 \ingroup SslCrtdSslAPI
154 * Short names for certificate signing algorithms
155 */
156
157 extern const char *CertSignAlgorithmStr[];
158
159 /**
160 \ingroup SslCrtdSslAPI
161 * Return the short name of the signing algorithm "sg"
162 */
certSignAlgorithm(int sg)163 inline const char *certSignAlgorithm(int sg)
164 {
165 if (sg >=0 && sg < Ssl::algSignEnd)
166 return Ssl::CertSignAlgorithmStr[sg];
167
168 return NULL;
169 }
170
171 /**
172 \ingroup SslCrtdSslAPI
173 * Return the id of the signing algorithm "sg"
174 */
certSignAlgorithmId(const char * sg)175 inline CertSignAlgorithm certSignAlgorithmId(const char *sg)
176 {
177 for (int i = 0; i < algSignEnd && Ssl::CertSignAlgorithmStr[i] != NULL; i++)
178 if (strcmp(Ssl::CertSignAlgorithmStr[i], sg) == 0)
179 return (CertSignAlgorithm)i;
180
181 return algSignEnd;
182 }
183
184 /**
185 \ingroup SslCrtdSslAPI
186 * Supported certificate adaptation algorithms
187 */
188 enum CertAdaptAlgorithm {algSetValidAfter = 0, algSetValidBefore, algSetCommonName, algSetEnd};
189
190 /**
191 \ingroup SslCrtdSslAPI
192 * Short names for certificate adaptation algorithms
193 */
194 extern const char *CertAdaptAlgorithmStr[];
195
196 /**
197 \ingroup SslCrtdSslAPI
198 * Return the short name of the adaptation algorithm "alg"
199 */
sslCertAdaptAlgoritm(int alg)200 inline const char *sslCertAdaptAlgoritm(int alg)
201 {
202 if (alg >=0 && alg < Ssl::algSetEnd)
203 return Ssl::CertAdaptAlgorithmStr[alg];
204
205 return NULL;
206 }
207
208 /**
209 \ingroup SslCrtdSslAPI
210 * Simple struct to pass certificate generation parameters to generateSslCertificate function.
211 */
212 class CertificateProperties
213 {
214 public:
215 CertificateProperties();
216 Security::CertPointer mimicCert; ///< Certificate to mimic
217 Security::CertPointer signWithX509; ///< Certificate to sign the generated request
218 Security::PrivateKeyPointer signWithPkey; ///< The key of the signing certificate
219 bool setValidAfter; ///< Do not mimic "Not Valid After" field
220 bool setValidBefore; ///< Do not mimic "Not Valid Before" field
221 bool setCommonName; ///< Replace the CN field of the mimicing subject with the given
222 std::string commonName; ///< A CN to use for the generated certificate
223 CertSignAlgorithm signAlgorithm; ///< The signing algorithm to use
224 const EVP_MD *signHash; ///< The signing hash to use
225 private:
226 CertificateProperties(CertificateProperties &);
227 CertificateProperties &operator =(CertificateProperties const &);
228 };
229
230 /// \ingroup SslCrtdSslAPI
231 /// \returns certificate database key
232 std::string & OnDiskCertificateDbKey(const CertificateProperties &);
233
234 /**
235 \ingroup SslCrtdSslAPI
236 * Decide on the kind of certificate and generate a CA- or self-signed one.
237 * The generated certificate will inherite properties from certToMimic
238 * Return generated certificate and private key in resultX509 and resultPkey
239 * variables.
240 */
241 bool generateSslCertificate(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, CertificateProperties const &properties);
242
243 /**
244 \ingroup SslCrtdSslAPI
245 * Verify date. Date format it ASN1_UTCTIME. if there is out of date error,
246 * return false.
247 */
248 bool sslDateIsInTheFuture(char const * date);
249
250 /**
251 \ingroup SslCrtdSslAPI
252 * Check if the major fields of a certificates matches the properties given by
253 * a CertficateProperties object
254 \return true if the certificates matches false otherwise.
255 */
256 bool certificateMatchesProperties(X509 *peer_cert, CertificateProperties const &properties);
257
258 /**
259 \ingroup ServerProtocolSSLAPI
260 * Returns CN from the certificate, suitable for use as a host name.
261 * Uses static memory to temporary store the extracted name.
262 */
263 const char *CommonHostName(X509 *x509);
264
265 /**
266 \ingroup ServerProtocolSSLAPI
267 * Returns Organization from the certificate.
268 * Uses static memory to temporary store the extracted name.
269 */
270 const char *getOrganization(X509 *x509);
271
272 /// \ingroup ServerProtocolSSLAPI
273 /// \return whether both certificates exist and are the same (e.g., have identical ASN.1 images)
274 bool CertificatesCmp(const Security::CertPointer &cert1, const Security::CertPointer &cert2);
275
276 /// wrapper for OpenSSL X509_get0_signature() which takes care of
277 /// portability issues with older OpenSSL versions
278 const ASN1_BIT_STRING *X509_get_signature(const Security::CertPointer &);
279
280 } // namespace Ssl
281 #endif // SQUID_SSL_GADGETS_H
282
283