]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/gadgets.cc
6 #include "ssl/gadgets.h"
7 #if HAVE_OPENSSL_X509V3_H
8 #include <openssl/x509v3.h>
12 \ingroup ServerProtocolSSLInternal
13 * Add CN to subject in request.
15 static bool addCnToRequest(Ssl::X509_REQ_Pointer
& request
, char const * cn
)
17 // not an Ssl::X509_NAME_Pointer because X509_REQ_get_subject_name()
18 // returns a pointer to the existing subject name. Nothing to clean here.
19 X509_NAME
*name
= X509_REQ_get_subject_name(request
.get());
23 // The second argument of the X509_NAME_add_entry_by_txt declared as
24 // "char *" on some OS. Use cn_name to avoid compile warnings.
25 static char cn_name
[3] = "CN";
26 if (!X509_NAME_add_entry_by_txt(name
, cn_name
, MBSTRING_ASC
, (unsigned char *)cn
, -1, -1, 0))
33 \ingroup ServerProtocolSSLInternal
34 * Make request on sign using private key and hostname.
36 static bool makeRequest(Ssl::X509_REQ_Pointer
& request
, Ssl::EVP_PKEY_Pointer
const & pkey
, char const * host
)
38 if (!X509_REQ_set_version(request
.get(), 0L))
41 if (!addCnToRequest(request
, host
))
44 if (!X509_REQ_set_pubkey(request
.get(), pkey
.get()))
49 EVP_PKEY
* Ssl::createSslPrivateKey()
51 Ssl::EVP_PKEY_Pointer
pkey(EVP_PKEY_new());
56 Ssl::RSA_Pointer
rsa(RSA_generate_key(1024, RSA_F4
, NULL
, NULL
));
61 if (!EVP_PKEY_assign_RSA(pkey
.get(), (rsa
.get())))
65 return pkey
.release();
68 X509_REQ
* Ssl::createNewX509Request(Ssl::EVP_PKEY_Pointer
const & pkey
, const char * hostname
)
70 Ssl::X509_REQ_Pointer
request(X509_REQ_new());
75 if (!makeRequest(request
, pkey
, hostname
))
77 return request
.release();
81 \ingroup ServerProtocolSSLInternal
82 * Set serial random serial number or set random serial number.
84 static bool setSerialNumber(ASN1_INTEGER
*ai
, BIGNUM
const* serial
)
88 Ssl::BIGNUM_Pointer
bn(BN_new());
90 bn
.reset(BN_dup(serial
));
95 if (!BN_pseudo_rand(bn
.get(), 64, 0, 0))
99 if (ai
&& !BN_to_ASN1_INTEGER(bn
.get(), ai
))
104 X509
* Ssl::signRequest(Ssl::X509_REQ_Pointer
const & request
, Ssl::X509_Pointer
const & x509
, Ssl::EVP_PKEY_Pointer
const & pkey
, ASN1_TIME
* timeNotAfter
, BIGNUM
const * serial
)
106 Ssl::X509_Pointer
cert(X509_new());
110 if (!setSerialNumber(X509_get_serialNumber(cert
.get()), serial
))
113 if (!X509_set_issuer_name(cert
.get(), x509
.get() ? X509_get_subject_name(x509
.get()) : X509_REQ_get_subject_name(request
.get())))
116 if (!X509_gmtime_adj(X509_get_notBefore(cert
.get()), (-2)*24*60*60))
120 if (!X509_set_notAfter(cert
.get(), timeNotAfter
))
122 } else if (!X509_gmtime_adj(X509_get_notAfter(cert
.get()), 60*60*24*356*3))
125 if (!X509_set_subject_name(cert
.get(), X509_REQ_get_subject_name(request
.get())))
128 Ssl::EVP_PKEY_Pointer
tmppkey(X509_REQ_get_pubkey(request
.get()));
130 if (!tmppkey
|| !X509_set_pubkey(cert
.get(), tmppkey
.get()))
133 if (!X509_sign(cert
.get(), pkey
.get(), EVP_sha1()))
136 return cert
.release();
139 bool Ssl::writeCertAndPrivateKeyToMemory(Ssl::X509_Pointer
const & cert
, Ssl::EVP_PKEY_Pointer
const & pkey
, std::string
& bufferToWrite
)
141 bufferToWrite
.clear();
144 BIO_Pointer
bio(BIO_new(BIO_s_mem()));
148 if (!PEM_write_bio_X509 (bio
.get(), cert
.get()))
151 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
155 long len
= BIO_get_mem_data(bio
.get(), &ptr
);
159 bufferToWrite
= std::string(ptr
, len
);
163 bool Ssl::writeCertAndPrivateKeyToFile(Ssl::X509_Pointer
const & cert
, Ssl::EVP_PKEY_Pointer
const & pkey
, char const * filename
)
168 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
171 if (!BIO_write_filename(bio
.get(), const_cast<char *>(filename
)))
174 if (!PEM_write_bio_X509(bio
.get(), cert
.get()))
177 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
183 bool Ssl::readCertAndPrivateKeyFromMemory(Ssl::X509_Pointer
& cert
, Ssl::EVP_PKEY_Pointer
& pkey
, char const * bufferToRead
)
185 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
186 BIO_puts(bio
.get(), bufferToRead
);
188 X509
* certPtr
= NULL
;
189 cert
.reset(PEM_read_bio_X509(bio
.get(), &certPtr
, 0, 0));
193 EVP_PKEY
* pkeyPtr
= NULL
;
194 pkey
.reset(PEM_read_bio_PrivateKey(bio
.get(), &pkeyPtr
, 0, 0));
201 bool Ssl::generateSslCertificateAndPrivateKey(char const *host
, Ssl::X509_Pointer
const & signedX509
, Ssl::EVP_PKEY_Pointer
const & signedPkey
, Ssl::X509_Pointer
& cert
, Ssl::EVP_PKEY_Pointer
& pkey
, BIGNUM
const * serial
)
203 pkey
.reset(createSslPrivateKey());
207 Ssl::X509_REQ_Pointer
request(createNewX509Request(pkey
, host
));
211 if (signedX509
.get() && signedPkey
.get())
212 cert
.reset(signRequest(request
, signedX509
, signedPkey
, X509_get_notAfter(signedX509
.get()), serial
));
214 cert
.reset(signRequest(request
, signedX509
, pkey
, NULL
, serial
));
223 \ingroup ServerProtocolSSLInternal
224 * Read certificate from file.
226 static X509
* readSslX509Certificate(char const * certFilename
)
230 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
233 if (!BIO_read_filename(bio
.get(), certFilename
))
235 X509
*certificate
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
);
239 EVP_PKEY
* Ssl::readSslPrivateKey(char const * keyFilename
, pem_password_cb
*passwd_callback
)
243 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
246 if (!BIO_read_filename(bio
.get(), keyFilename
))
248 EVP_PKEY
*pkey
= PEM_read_bio_PrivateKey(bio
.get(), NULL
, passwd_callback
, NULL
);
252 void Ssl::readCertAndPrivateKeyFromFiles(Ssl::X509_Pointer
& cert
, Ssl::EVP_PKEY_Pointer
& pkey
, char const * certFilename
, char const * keyFilename
)
254 if (keyFilename
== NULL
)
255 keyFilename
= certFilename
;
256 pkey
.reset(readSslPrivateKey(keyFilename
));
257 cert
.reset(readSslX509Certificate(certFilename
));
258 if (!pkey
|| !cert
|| !X509_check_private_key(cert
.get(), pkey
.get())) {
264 bool Ssl::sslDateIsInTheFuture(char const * date
)
269 tm
.data
= (unsigned char *)date
;
270 tm
.length
= strlen(date
);
272 return (X509_cmp_current_time(&tm
) > 0);