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