How do I create my own wildcard certificate on Linux? - certificate

Does anyone know if it's possible to create my own wildcard certificate under Ubuntu? For instance, I want the following domains to use one certificate:
https://a.example.com
https://b.example.com
https://c.example.com

Just follow one of the many step by step instructions for creating your own certificate with OpenSSL but replace the "Common Name" www.example.com with *.example.com.
Usually you have to keep a bit more money ready to get a certificate for this.
> openssl req -new -x509 -keyout cert.pem -out cert.pem -days 365 -nodes
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:Germany
Locality Name (eg, city) []:nameOfYourCity
Organization Name (eg, company) [Internet Widgits Pty Ltd]:nameOfYourCompany
Organizational Unit Name (eg, section) []:nameOfYourDivision
Common Name (eg, YOUR name) []:*.example.com
Email Address []:webmaster#example.com
(Sorry, my favorite howto is a german text that I don't have readily available and can't find currently, thus the 'many' links)
Edit in 2017: The original answer to this question is from 2009, when the choice for certificates did not include fully automated and free options like Let's Encrypt. Nowadays (if the "domain-validated" certification level of Let's Encrypt is enough for your purpose) it's trivial to obtain individual certificates for each and every subdomain. In case you need a higher trust level than domain-validated, wildcard certificates are still an option.
Also from 2017, note the comment below, by #ha9u63ar:
According RFC 2818 sec. 3 using CN for host name identification is not recommended anymore (deprecated) Subject Alternative Name (SAN) seems to be the way to go.
My answer to this comment: I trust that nowadays any CAs that issue Wildcard certs will have a proper set of instructions. For a self-signed quick fix, I'd not worry. On the other hand, with LetsEncrypt being around these days, it's been a long time since I've created a self-signed certificate. Gee, this answer really shows its age.

Related

Why getting SSLCertVerificationError ... self signed certificate in certificate chain - from one machine but not another?

I am trying to test an API on my site. The tests work just fine from one machine, but running the code from a different machine results in the SSLCertVerificationError - which is odd because the site has an SSL cert and is NOT self signed.
Here is the core of my code:
async def device_connect(basename, start, end):
url = SERVER_URL
async with aiohttp.ClientSession() as session:
post_tasks = []
# prepare the coroutines that post
for x in range(start, end):
myDevice={'test':'this'}
post_tasks.append(do_post(session, url, myDevice))
# now execute them all at once
await asyncio.gather(*post_tasks)
async def do_post(session, url, data):
async with session.post(url, data =data) as response:
x = await response.text()
I tried (just for testing) to set 'verify=False' or trust_env=True, but I continue to get the same error. On the other computer, this code runs fine and no trust issue results.
That error text is somewhat misleading. OpenSSL, which python uses, has dozens of error codes that indicate different ways certificate validation can fail, including
X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN -- the peer's cert can't be chained to a root cert in the local truststore; the chain received from the peer includes a root cert, which is self-signed (because root certs must be self-signed), but that root is not locally trusted
Note this is not talking about the peer/leaf cert; if that is self signed and not trusted, there is a different error X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT which displays as just 'self signed certificate' without the part about 'in certificate chain'.
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY (displays in text as 'unable to get local issuer certificate') -- the received chain does not contain a self-signed root and the peer's cert can't be chained to a locally trusted root
In both these cases the important info is the peer's cert doesn't chain to a trusted root; whether the received chain includes a self-signed root is less important. It's kind of like if you go to your doctor and after examination in one case s/he tells you "you have cancer, and the weather forecast for tomorrow is a bad storm" or in another case "you have cancer, but the weather forecast for tomorrow is sunny and pleasant". While these are in fact slightly different situations, and you might conceivably want to distinguish them, you need to focus on the part about "you have cancer", not tomorrow's weather.
So, why doesn't it chain to a trusted root? There are several possibilities:
the server is sending a cert chain with a root that SHOULD be trusted, but machine F is using a truststore that does not contain it. Depending on the situation, it might be appropriate to add that root cert to the default truststore (affecting at least all python apps unless specifically coded otherwise, and often other types of programs like C/C++ and Java also) or it might be better to customize the truststore for your appplication(s) only; or it might be that F is already customized wrongly and just needs to be fixed.
the server is sending a cert chain that actually uses a bad CA, but machine W's truststore has been wrongly configured (again either as a default or customized) to trust it.
machine F is not actually getting the real server's cert chain, because its connection is 'transparently' intercepted by something. This might be something authorized by an admin of the network (like an IDS/IPS/DLP or captive portal) or machine F (like antivirus or other 'endpoint security'), or it might be something very bad like malware or a thief or spy; or it might be in a gray area like some ISPs (try to) intercept connections and insert advertisements (at least in data likely to be displayed to a person like web pages and emails, but these can't always be distinguished).
the (legit) server is sending different cert chains to F (bad) and W (good). This could be intentional, e.g. because W is on a business' internal network while F is coming in from the public net; however you describe this as 'my site' and I assume you would know if it intended to make distinctions like this. OTOH it could be accidental; one fairly common cause is that many servers today use SNI (Server Name Indication) to select among several 'certs' (really cert chains and associated keys); if F is too old it might not be sending SNI, causing the server to send a bad cert chain. Or, some servers use different configurations for IPv4 vs IPv6; F could be connecting over one of these and W the other.
To distinguish these, and determine what (if anything) to fix, you need to look at what certs are actually being received by both machines.
If you have (or can get) OpenSSL on both, do openssl s_client -connect host:port -showcerts. For OpenSSL 1.1.1 up (now common) to omit SNI add -noservername; for older versions to include SNI add -servername host. Add -4 or -6 to control the IP version, if needed. This will show subject and issuer names (s: and i:) for each received cert; if any are different, and especially the last, look at #3 or #4. If the names are the same compare the whole base64 blobs to make sure they are entirely the same (it could be a well-camoflauged attacker). If they are the same, look at #1 or #2.
Alternatively, if policy and permissions allow, get network-level traces with Wireshark or a more basic tool like tcpdump or snoop. In a development environment this is usually easy; if either or both machine(s) is production, or in a supplier, customer/client, or partner environment, maybe not. Check SNI in ClientHello, and in TLS1.2 (or lower, but nowadays lower is usually discouraged or prohibited) look at the Certificate message received; in wireshark you can drill down to any desired level of detail. If both your client(s) and server are new enough to support TLS1.3 (and you can't configure it/them to downgrade) the Certificate message is encrypted and wireshark won't be able to show you the contents unless you can get at least one of your endpoints to export the session secrets in SSLKEYLOGFILE format.

How get X509 certificate's full cert chain programatically?

Imagine I have p12 container of private key and public certificate. When I export p12 public cert to separate .cer file with Java keytool I may click to .cer file and see full cert chain. How may I get that full path programatically?
I made little investigation. I used keytool's print cert -v command and saw property AuthorityInfoAccess with subproperty
accessMethod: caIssuers
accessLocation: URIName: http://.../some.crt
I downloaded that some.crt (it was PEM cert), and again used print cert -v and again saw
accessLocation: URIName: http://.../some2.crt and repeated downloading .crt files and geting parent until reaching root .crt which hasn't such property.
I think, that I should programatically download chain as I described above and provide it to CertPathValidator as shown here.
If I really need to get chain as I described above, is there any libraries already doing this? Is there any way to do it with std lib? I didn't find bouncycastle examples and java's standart library code like
java.security.cert.Certificate[] cchain = keystore.getCertificateChain(alias);
returns one entry for certificate actually having 2 "parents".
Nitpick: you surely mean keytool -printcert (with hyphen, without space, -v not needed here).
A privatekey entry created by Java in JKS or PKCS12 usually contains the full chain, but keytool -exportcert extracts only the leaf cert.
A PKCS12 created by something else may contain the full chain or not, possibly depending on what you clicked when creating it.
If the chain is there, KeyStore.getCertificateChain returns it, and keytool -list -v (here -v matters) shows it.
If a certificate was imported, or reimported, as a trustedcert entry -- usually in JKS, PKCS12 isn't designed for lone certs -- that never contains the chain, so getCertificateChain on that entry won't work, but IIRC CertPathBuilder can build a chain combining multiple trustedcert entries in one store.
If you do need a parent (chain) cert
you don't already have, and the child specifies AIA.caIssuers, then yes using that to fetch is sensible.
I'm pretty sure there is nothing in standard Java (JRE) library that does this for you, at least so far; I don't know about BouncyCastle or anybody else.

ClickOnce VSTO solution signed with mage.exe - certificate not trusted error

I'm trying to deploy a VSTO solution, which are 2 addins for Word and for Outlook, using ClickOnce. Due to our deployment infrastructure/practices, I cannot publish it using Visual Studio, it is instead built on a build server and deployed via a deployment server.
For local development, a self-signed certificate is used. The deployment worked with this self-signed certificate (if the the self-signed certificate was installed on the machine), but now I want to add a real company certificate so that the application can be deployed to the users.
During deployment, after the configuration files are poked, they are updated and re-signed with the real certificate. However, this produces the following error during installation:
System.Security.SecurityException: Customized functionality in this application will not work because the certificate used to sign the deployment manifest for <app name> or its location is not trusted. Contact your administrator for further assistance.
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInTrustEvaluator.VerifyTrustPromptKeyInternal(ClickOnceTrustPromptKeyValue promptKeyValue, DeploymentSignatureInformation signatureInformation, String productName, TrustStatus status)
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInTrustEvaluator.VerifyTrustUsingPromptKey(Uri manifest, DeploymentSignatureInformation signatureInformation, String productName, TrustStatus status)
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInTrustEvaluator.VerifyTrustUsingPromptKey(Uri manifest, DeploymentSignatureInformation signatureInformation, String productName)
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.ProcessSHA1Manifest(ActivationContext context, DeploymentSignatureInformation signatureInformation, PermissionSet permissionsRequested, Uri manifest, ManifestSignatureInformationCollection signatures, AddInInstallationStatus installState)
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.VerifySecurity(ActivationContext context, Uri manifest, AddInInstallationStatus installState)
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.InstallAddIn()
The Zone of the assembly that failed was:
MyComputer
The only lead I have is that, after re-signing, the values in publisherIdentity element are not changed (both .vsto and .manifest), only the Signature element has values corresponding to the new certificate.
Following commands are used to sign the .vsto and .manifest files (as far as I can see from the deployment scripts):
mage.exe -Update "[path to .vsto/.manifest]"
mage.exe -Sign "[path to .vsto/.manifest]" -CertHash [certificateHash]
where [certificateHash] is the thumbprint of the real certificate and is used to look up the certificate in certificates stores. I'm told this is security measure so that the certificate file doesn't have to be distributed along with the deployment package.
After signing, the files have their Signature values changed, but the publisherIdentity still has the name and issuerKeyHash of the self-signed certificate.
I tried poking these two values prior to re-signing, but I'm don't know how to calculate the issuerKeyHash.
Any advise on how to proceed would be much appreciated!
Edit:
I was trying out other mage.exe parameters, like '-TrustLevel FullTrust' (which didn't have any effect) or '-UseManifestForTrust True' along with Name and Publisher parameters, which yielded this error message (which is different than the one mentioned above).
************** Exception Text **************
System.InvalidOperationException: You cannot specify a <useManifestForTrust> element for a ClickOnce application that specifies a custom host.
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.GetManifests(TimeSpan timeout)
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.InstallAddIn()
.
The certificate that the app is signed with isn't trusted by Windows. As a work around,
Right click on setup.exe,
Select properties then the Digital Signatures tab
Select Vellaichamy/user then click Details
Click View Certificate and Click Install Certificate.
Do not let it automatically choose where to store the sert, install the certificate in the Trusted Root Certification Authorities Store. Once the cert is installed the app should install...
Take a look at the Granting Trust to Office Solutions article which states the following:
If you sign the solution with a known and trusted certificate, the solution will automatically be installed without prompting the end user to make a trust decision. After a certificate is obtained, the certificate must be explicitly trusted by adding it to the Trusted Publishers list.
For more information, see How to: Add a Trusted Publisher to a Client Computer for ClickOnce Applications.
Also you may find the Deploying an Office Solution by Using ClickOnce article helpful.
We have found what the problem was. We used a version of mage.exe tool from Windows SDK from a folder named 7A (I don't remember the full paths, sorry). A colleague then found another folder with versions 7A, 8 and 8A. Once we took the .exe from 8A folder, the installation works as expected.
Try copying all the necessary files to the client computer then install. If you can avoid installing from the network drive you might be able to avoid this exception.

CouchDB SSL CRT to PEM files

I have tried several ways to get some PEM files to be used by CouchDB. I have generated a cert with powershell, exported it with key to a pfx and then used openssl to convert to 2 pem files and installed them in Couch. With this approach it seems to work in IE11, but it doesn't work with firefox or other browsers. Firefox produces this error:
The key does not support the requested operation. (Error code:
sec_error_invalid_key)
I've also gotten a free ssl cert from ssl.com, (they gave me three CRT files) and tried converting it using openssl, but to no avail.
I've also followed the instructions on the page from CouchDB to generate a self signed cert specifically for this purpose, but it will not load the page. (http://docs.couchdb.com/en/latest/config/http.html#config-ssl about half way down)
Has anybody had success with this? How do I get my certs into a format that will play nice with Couch and will all browsers?
UPDATE:
Now I'm getting this error
A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot.
Not sure if this is a step forward or backwards...
It seems like CouchDB versions predating 1.7 or 1.6 are not able to have intermediate certificates specified for certificate verification. Since you are writing about having received three .crt files, (s)ome of those might be required as intermediate certificate(s). CouchDB not knowing about them can be the cause of your problem.
Apparently, one way to work around this is to concatenate your certificate file along with the intermediate certificate file(s). Simply cat them together like
$ cat yours.crt theirs.crt > couchdb.crt
...and use CouchDB's certfile configuration option to point to couchdb.crt's location.
If you prefer to convert .crt to .pem first, use sth like
$ openssl openssl x509 -in yours.crt -inform der -outform pem -out yours.pem
In a new enough version, you can probably use an intermediate certificate by setting CouchDB's cacertfile option. Have a look at this for further information.

Profiles installed by MDM service are showing as "Not Verified" after upgrading the device to iOS 6

Profiles installed by MDM service are showing as "Not Verified" after upgrading the device to iOS 6. These profiles were signed by a InCommon cert issued by AddTrust before being pushed to the devices. They were showing as "Verified" before the upgrade. Any ideas what might have caused this?
I got exactly the same problem so it is probably a bug in the iOS profile system because the very same SSL certificate is trusted by the browser. Note: Our certificate is of the "*.host.org" type.
This might be an untrusted CA in the certificate chain from the cert provider you bought it from. Looks like some CAs are untrusted or missing from iOS6. I had the same problem and included the whole of the cert chain in our cert signing bundle and the issue was resolved.
Suggest you open a support case with your cert provider to see if it's a known issue or dig around to see if you can find a list of trusted CAs used in iOS6 - I couldn't find one. Synching the device to iTunes may also refresh the CA list but this didn't work for me this time.
I have exactly the same problem as your.
My chain is GeoTrust -> RapidSSL -> MyCert. I have included the full chain in my .crt, but it stills show "not verified" when I try to install the configuration profil.
I don't know how to insert the whole path.
I use an openssl command to sign my file :
openssl smime -sign -signer #{crt_path} -inkey #{private_key_path} -nodetach -outform der -in #{file_to_sign_path} -out #{file_signed_path}
My crt_path is a .crt file, including the three certs.
EDIT
I found out the problem with my openssl command. My full chain was in the #{crt_path} but was not used by the command. I added the *-certfile #{crt_path}* and things works well !
Including the intermediate cert in the pkcs7_sign call (php openssl_pkcs7_sign() in my case) revolved the problem.
Yes! Adding the entire path (-root) did the trick.
Verify that the signature created by the MDM SW actually contains the path. Since it wasn't needed before...