]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/gadgets.cc
6 #include "ssl/gadgets.h"
9 \ingroup ServerProtocolSSLInternal
10 * Add CN to subject in request.
12 static bool addCnToRequest(Ssl::X509_REQ_Pointer
& request
, char const * cn
)
14 Ssl::X509_NAME_Pointer
name(X509_REQ_get_subject_name(request
.get()));
17 if (!X509_NAME_add_entry_by_txt(name
.get(), "CN", MBSTRING_ASC
, (unsigned char *)cn
, -1, -1, 0))
24 \ingroup ServerProtocolSSLInternal
25 * Make request on sign using private key and hostname.
27 static bool makeRequest(Ssl::X509_REQ_Pointer
& request
, Ssl::EVP_PKEY_Pointer
const & pkey
, char const * host
)
29 if (!X509_REQ_set_version(request
.get(), 0L))
32 if (!addCnToRequest(request
, host
))
35 if (!X509_REQ_set_pubkey(request
.get(), pkey
.get()))
40 void Ssl::BIO_free_wrapper(BIO
* bio
)
45 EVP_PKEY
* Ssl::createSslPrivateKey()
47 Ssl::EVP_PKEY_Pointer
pkey(EVP_PKEY_new());
52 Ssl::RSA_Pointer
rsa(RSA_generate_key(1024, RSA_F4
, NULL
, NULL
));
57 if (!EVP_PKEY_assign_RSA(pkey
.get(), (rsa
.get())))
61 return pkey
.release();
64 X509_REQ
* Ssl::createNewX509Request(Ssl::EVP_PKEY_Pointer
const & pkey
, const char * hostname
)
66 Ssl::X509_REQ_Pointer
request(X509_REQ_new());
71 if (!makeRequest(request
, pkey
, hostname
))
73 return request
.release();
77 \ingroup ServerProtocolSSLInternal
78 * Set serial random serial number or set random serial number.
80 static bool setSerialNumber(ASN1_INTEGER
*ai
, BIGNUM
const* serial
)
84 Ssl::BIGNUM_Pointer
bn(BN_new());
86 bn
.reset(BN_dup(serial
));
91 if (!BN_pseudo_rand(bn
.get(), 64, 0, 0))
95 if (ai
&& !BN_to_ASN1_INTEGER(bn
.get(), ai
))
100 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
)
102 Ssl::X509_Pointer
cert(X509_new());
106 if (!setSerialNumber(X509_get_serialNumber(cert
.get()), serial
))
109 if (!X509_set_issuer_name(cert
.get(), x509
.get() ? X509_get_subject_name(x509
.get()) : X509_REQ_get_subject_name(request
.get())))
112 if (!X509_gmtime_adj(X509_get_notBefore(cert
.get()), (-2)*24*60*60))
116 if (!X509_set_notAfter(cert
.get(), timeNotAfter
))
118 } else if (!X509_gmtime_adj(X509_get_notAfter(cert
.get()), 60*60*24*356*3))
121 if (!X509_set_subject_name(cert
.get(), X509_REQ_get_subject_name(request
.get())))
124 Ssl::EVP_PKEY_Pointer
tmppkey(X509_REQ_get_pubkey(request
.get()));
126 if (!tmppkey
|| !X509_set_pubkey(cert
.get(), tmppkey
.get()))
129 if (!X509_sign(cert
.get(), pkey
.get(), EVP_sha1()))
132 return cert
.release();
135 bool Ssl::writeCertAndPrivateKeyToMemory(Ssl::X509_Pointer
const & cert
, Ssl::EVP_PKEY_Pointer
const & pkey
, std::string
& bufferToWrite
)
137 bufferToWrite
.clear();
140 BIO_Pointer
bio(BIO_new(BIO_s_mem()));
144 if (!PEM_write_bio_X509 (bio
.get(), cert
.get()))
147 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
151 long len
= BIO_get_mem_data(bio
.get(), &ptr
);
155 bufferToWrite
= std::string(ptr
, len
);
159 bool Ssl::writeCertAndPrivateKeyToFile(Ssl::X509_Pointer
const & cert
, Ssl::EVP_PKEY_Pointer
const & pkey
, char const * filename
)
164 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
167 if (!BIO_write_filename(bio
.get(), const_cast<char *>(filename
)))
170 if (!PEM_write_bio_X509(bio
.get(), cert
.get()))
173 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
179 bool Ssl::readCertAndPrivateKeyFromMemory(Ssl::X509_Pointer
& cert
, Ssl::EVP_PKEY_Pointer
& pkey
, char const * bufferToRead
)
181 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
182 BIO_puts(bio
.get(), bufferToRead
);
184 X509
* certPtr
= NULL
;
185 cert
.reset(PEM_read_bio_X509(bio
.get(), &certPtr
, 0, 0));
189 EVP_PKEY
* pkeyPtr
= NULL
;
190 pkey
.reset(PEM_read_bio_PrivateKey(bio
.get(), &pkeyPtr
, 0, 0));
197 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
)
199 pkey
.reset(createSslPrivateKey());
203 Ssl::X509_REQ_Pointer
request(createNewX509Request(pkey
, host
));
207 if (signedX509
.get() && signedPkey
.get())
208 cert
.reset(signRequest(request
, signedX509
, signedPkey
, X509_get_notAfter(signedX509
.get()), serial
));
210 cert
.reset(signRequest(request
, signedX509
, pkey
, NULL
, serial
));
219 \ingroup ServerProtocolSSLInternal
220 * Read certificate from file.
222 static X509
* readSslX509Certificate(char const * certFilename
)
226 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
229 if (!BIO_read_filename(bio
.get(), certFilename
))
231 X509
*certificate
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
);
236 \ingroup ServerProtocolSSLInternal
237 * Read private key from file. Make sure that this is not encrypted file.
239 static EVP_PKEY
* readSslPrivateKey(char const * keyFilename
)
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
, NULL
, 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);