Re: Need help with James 3.4, smtpserver, and keystore file.

Marc Chamberlin <[email protected]>
Newsgroups gmane.comp.jakarta.james.user
Message-ID <[email protected]>
Thanks Garry for your reply, and I am sorry for the slowness of my
response, I been busy doing internet research trying to grok everything
you said in your suggestions. I think the best thing to do is to walk
you and other readers through the steps I took to create the LetsEncrypt
certificate and put it in the keystore. Then I will comment on each of
your suggestions and await for further clarification on what I should
try/do next.  I am not at all familiar with the code and inner workings
of Apache James so to me a lot of this is like trying to understand
what  is in a room by looking through a keyhole! LOL

OK, these are the steps I took -

To create the LetsEncrypt certificate I used the DNS challenge method to
create a wildcard certificate for all the domains and subdomains that I
provide email services for. This was done as follows using the certbot
command -

certbot certonly  --config-dir /etc/letsencrypt_forApacheJames
--dns-rfc2136 --dns-rfc2136-credentials
/etc/letsencrypt_forApacheJames/james/rfc2136.ini
--dns-rfc2136-propagation-seconds 10 --server
https://acme-v02.api.letsencrypt.org/directory
--preferred-challenges=dns --email [email protected] --agree-tos
-d domainname1.com -d *.domainname1.com  -d domainname2.com -d
*.domainname2.com   /etc.../

If I understand things correctly this produced 4 certificate and chain
files -

cert.pem is the certificate containing the public key for my domains.
chain.pem is the certificate for my certificate authority - LetsEncrypt
fullchain.pem is also created by certbot = cert.pem + chain.pem
privkey.pem containing the private key for my domains.

Next I created an empty keystore in the conf directory for Apache James -

cd /mail/apache-james-3.4/james-server-app-3.4.0/conf
mkdir keystore.privateFiles
cd keystore.privateFiles
keytool -genkeypair -keyalg RSA -alias emptykeystore -keystore keystore.jks

and I  migrated the keystore to PKCS12 format and deleted the
emptykeystore alias using

keytool -importkeystore -srckeystore keystore.jks -destkeystore
keystore.jks -deststoretype pkcs12
keytool -delete -alias emptykeystore -keystore keystore.jks

Next I converted the keys created by certbot into the proper format for
importing it into the keystore, using openssl to convert the keys -

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out
pkcs.p12 -name james

This creates a file called pkcs.p12 which I then import into the
keystore file -

keytool -importkeystore -deststorepass mypassword -destkeypass
mypassword -destkeystore keystore.jks -srckeystore
/etc/letsencrypt_forApacheJames/live/mydomain.com-0001/pkcs.p12
-srcstoretype PKCS12 -srcstorepass mypassword -alias james

I left out a few details like sensitive info, cd'ing to various
different directories and setting up a link to the keystore file. The
passwords are simple alphanumeric character strings. I will intersperse
the rest of my reply in-between your comments -

On 1/3/20 2:12 PM, Garry Hurley wrote:
> Okay. One thing I noticed before. The key took command will hash the password with the appropriate algorithm and use it to access the keystone file. James code is not guaranteed to use the appropriate hashing algorithm. Try the following:
I am not sure what you mean and are referring to as the hashing
algorithm though I do know what hashing is. In the steps I showed you,
that I took to create the keystore, I see parameters that specify
encryption algorithms but nothing that specifies a hashing algorithm.
> 1 sift through the code, find the hashing algorithm used by James and hard code the hashed key in the configuration file. 
Oh boy, I am not set up to build James from source and suspect that will
be a steep learning curve. I will table this option for the moment and
consider it if option 2 doesn't work.
> 2, find out which hashing algorithm is used to encrypt the key and specify it in the configuration file
This sounds promising except I don't know what hashing algorithm was
used in creating the keys. I suspect you are referring to the encryption
algorithm? (I know nothing about how the encryption is actually done,
but could imagine that it is based on a hash of some kind. I believe
that I am using the RSA encryption algorithm but check me on that... 
Also I don't know how to specify the "hashing algorithm" in the
configuration files so an example would be very helpful.
> 3, create a new key store WITHOUT a password and use that one instead. 
This sounds dangerous and I will try this approach also if all else
fails... But yeah it sounds like another path I could follow...
> For ease of use, #3 is the clear winner. For maximum security, #1 would be preferred.   I am almost certain you will find it is due to a hashing algorithm or, alternatively, a character in the password that is expressly probibited in an XML file (like an ampersand or greater/less than sign for example). 
The password is only composed of lower case letters and numbers. No
punctuation characters are used.

I don't know if this is applicable but in my internet searches looking
for discussions about the same or similar error messages that I am
seeing, I am seeing some references to problems with the tools from
BouncyCastle.  Here are a couple of links, perhaps you or some other
guru could check these out and see if I am perhaps experiencing the same
or similar issue as these folks are talking about -

https://stackoverflow.com/questions/53542198/adding-bouncycastle-provider-breaks-keystore-load

https://github.com/bcgit/bc-java/issues/586

This is above my pay grade to understand so again many thanks and I
appreciate yours and any other help offered...    Marc...

>
> Sent from my iPhone
>
>> On Dec 28, 2019, at 9:35 PM, Marc Chamberlin <[email protected]> wrote:
>>
>> Hello again,  It appears that I have managed to make a bit of progress
>> on my own since my original post. For some odd reason I got past the
>> FileNotFound exception by changing (adding) execute permission to the
>> directory containing the keystore file. So now it is set as follows -
>>
>> quasar:/mail/apache-james-3.4/james-server-app-3.4.0/conf # ll -d
>> keystore.privateFiles
>> drwxrwxrwx 2 james mail 4096 Dec 27 22:11 keystore.privateFiles
>>
>> It is a puzzler (at least to me) why adding execute permissions would
>> allow James to find my Keystore file. But I immediately hit another
>> snag, James is not correctly applying the password to access the
>> keystore file and throwing another exception. The smtpserver.xml is
>> configured as follows -
>>
>>      <tls socketTLS="false" startTLS="true">
>>       
>> <keystore>file:/mail/apache-james-3.4/james-server-app-3.4.0/conf/keystore</keystore>
>>        <secret>mypassword</secret>
>>       
>> <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
>>        <algorithm>SunX509</algorithm>
>>      </tls>
>>
>> To test the keystore file I executed the following command and it worked
>> fine -
>>
>> quasar:/mail/apache-james-3.4/james-server-app-3.4.0/conf # keytool
>> -list -v -keystore
>> /mail/apache-james-3.4/james-server-app-3.4.0/conf/keystore -storetype
>> PKCS12 -storepass mypassword
>>
>> The exception and stack walkback I am getting from James is shown
>> below.  I am continuing to Google for answers but no joy so far...
>> Anyone here got any ideas? Thanks again in advance...     Marc.
>>
>> ----
>>
>> INFO   | jvm 1    | 2019/12/28 17:13:27 | WARN  17:13:26,963 |
>> org.apache.james.container.spring.context.JamesServerApplicationContext
>> | Exception encountered during context initialization - cancelling
>> refresh attempt:
>> org.springframework.beans.factory.BeanCreationException: Error creating
>> bean with name 'smtpserver': Invocation of init method failed; nested
>> exception is java.io.IOException: keystore password was incorrect
>> INFO   | jvm 1    | 2019/12/28 17:13:27 | INFO  17:13:26,964 |
>> org.apache.james.mailetcontainer.impl.JamesMailSpooler | start dispose() ...
>> INFO   | jvm 1    | 2019/12/28 17:13:27 | INFO  17:13:26,964 |
>> org.apache.james.mailetcontainer.impl.JamesMailSpooler | thread shutdown
>> completed.
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |
>> INFO   | jvm 1    | 2019/12/28 17:13:27 | WrapperSimpleApp: Encountered
>> an error running main:
>> org.springframework.beans.factory.BeanCreationException: Error creating
>> bean with name 'smtpserver': Invocation of init method failed; nested
>> exception is java.io.IOException: keystore password was incorrect
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |
>> org.springframework.beans.factory.BeanCreationException: Error creating
>> bean with name 'smtpserver': Invocation of init method failed; nested
>> exception is java.io.IOException: keystore password was incorrect
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:396)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1507)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:638)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:942)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.apache.james.container.spring.context.JamesServerApplicationContext.<init>(JamesServerApplicationContext.java:40)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.apache.james.app.spring.JamesAppSpringMain.init(JamesAppSpringMain.java:56)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.apache.james.app.spring.JamesAppSpringMain.main(JamesAppSpringMain.java:42)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> java.lang.reflect.Method.invoke(Method.java:498)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.tanukisoftware.wrapper.WrapperSimpleApp.run(WrapperSimpleApp.java:240)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> java.lang.Thread.run(Thread.java:748)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 | Caused by:
>> java.io.IOException: keystore password was incorrect
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2059)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:238)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> java.security.KeyStore.load(KeyStore.java:1445)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.apache.james.protocols.lib.netty.AbstractConfigurableAsyncServer.buildSSLContext(AbstractConfigurableAsyncServer.java:405)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.apache.james.protocols.lib.netty.AbstractConfigurableAsyncServer.init(AbstractConfigurableAsyncServer.java:263)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.apache.james.protocols.lib.netty.AbstractServerFactory.init(AbstractServerFactory.java:57)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> java.lang.reflect.Method.invoke(Method.java:498)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:344)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:295)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       at
>> org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:130)
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       ... 22 more
>> INFO   | jvm 1    | 2019/12/28 17:13:27 | Caused by:
>> java.security.UnrecoverableKeyException: failed to decrypt safe contents
>> entry: java.lang.IllegalStateException: password has been cleared
>> INFO   | jvm 1    | 2019/12/28 17:13:27 |       ... 36 more
>>
>> -- 
>>
>>  --...  ...--  .----.  ...    -..  .    .--  .-  --...  .--.  -..-  .--     --  .-  .-.  -.-. 
>>
>>
>> *Computers: the final frontier. These are the voyages of the user Marc.
>> His mission: to explore strange new hardware. To seek out new software
>> and new applications.
>> To boldly go where no Marc has gone before!
>> *
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>

-- 

  --...  ...--  .----.  ...    -..  .    .--  .-  --...  .--.  -..-  .--     --  .-  .-.  -.-. 


*Computers: the final frontier. These are the voyages of the user Marc.
His mission: to explore strange new hardware. To seek out new software
and new applications.
To boldly go where no Marc has gone before!
*
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.