Who is the author of an M3 mod?

Today I needed to find who is the developer of an M3 customer modification. There is a bug in the MForms Bookmark of program M3 Customer. Connect Addresses – OIS002 which the developer modified for our customer’s needs, and I needed to report the bug to that developer. But I do not have the MAK training nor tool, so I cannot easily see the list of modifications and their authors. My colleague Shashank remind me of the following answer in M3 Server View.

  1. Go to M3 Server View (from the Grid Management Pages, or from LifeCycle Manager):
    0
  2. Find the interactive subsystem that is running the program (in my case OIS002), and select Tools:
    1
  3. Select Find Class:
    2
  4. Search for the M3 program (in my case OIS002):
    3
  5. The line with the customer class will give the file path, version, author, date, and unique ID (in my case I found the author, Rajesh):
  6. Note: Up to here, we can access this page anonymously, without being an authenticated user nor an administrator (security vulnerability anyone?)
  7. Now, if we have access to the M3 Business Engine file system, we can open the file itself and see the full list of developers; in my case the file is at:
    D:\Infor\M3BE\env\M3BE_15.1_TST\Fix\CUS\VFix\src\mvx\app\pgm\customer\OIS002.java:
    5

That’s it.

Let me know in the comments below if you have other tips. Click Like. Share this post with your colleagues. Click Follow to subscribe. And come write the next blog post with us. This is a volunteer-based community, and your participation keeps this blog going. And send some love to the other M3 blogs too. Thank you.

M3 Web Services from Infor Process Automation

In order to securely call Infor M3 Web Services (MWS) from Infor Process Automation (IPA) we need to import the Infor Grid’s certificate in IPA’s Java truststore; here is how.

MWS authentication

MWS works with SOAP over HTTP over SSL/TLS with the digital certificate of the Infor Grid.

The Infor Grid router for MWS must have Basic authentication enabled over HTTPS (secure) and have all authentication disabled over HTTP (insecure); you can check in the Infor Grid > Configuration Manager > Routers > Default Router:
1.8

MWS from IPA

In the IPA Configuration > Web Service Connection, we set the Basic authentication with the M3 user and password:
3.6

In Infor Process Designer (IPD), we use the SOAP Web Service activity node to the HTTPS URL of MWS:
3.1

Tip: un-hard-code the scheme://host:port and replace it by a variable <!_configuration.main.MWS> to define.

Problem

When we execute the process we get the following exception:

com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

That is because IPA does not know the Infor Grid certificate.

The IPA Configuration for the Web Service Connection does not have settings for an explicit truststore. Instead, IPA implicitly relies on the JVM’s truststore; let’s set it up.

Step 1. Infor Grid certificate

Get the Infor Grid certificate file. It is a signed public key that you can get for example from the main Grid Information at something like https∶//host123.local:26108/grid/info.html
3.2  

Note: Preferably get the certificate of the root CA as it usually signs the certificates for all environments (DEV, TST, PRD, etc.).

Step 2. IPA server truststore

Check the path of the IPA server’s JVM as given in the Landmark Grid > Landmark-LM Application > Configuration > Properties > Java executable:
2.5

Import the certificate into that JVM’s truststore using the Java keytool:

keytool -import -keystore lib\security\cacerts -file grid.cer

3.5

Note: I may have mixed up the keystore and the truststore in the command; to be verified.

Step 3. IPD truststore

The path to the Infor Process Designer (IPD) JVM is given by the IPDesigner.ini file:
3.7 3.8

Import the certificate into that JVM’s truststore as well.

Step 4. Test

Now execute the process. The Web Service activity node should not throw that exception anymore.

Notes

If you have a certificate purchased from a certificate authority that is already trusted by the JVM, such as VeriSign, this setup is not necessary.

That’s it. Let me know what you think in the comments below.

HTTP channels in MEC (part 6)

Here is how to securely receive messages in MEC from partners over the Internet, in this sixth part of the guide on HTTP channels for Infor M3 Enterprise Collaborator (MEC). I will illustrate two goals: how to setup an HTTPIn or HTTPSyncIn channels in MEC over SSL/TLS, and how to expose them securely over the Internet. Previously, for the HTTPIn channel, refer to part 2; for the HTTPSyncIn channel refer to part 3; and for MEC over HTTP Secure (HTTPS) refer to part 5.

Goal

The desired goal is to allow partners to securely send messages to MEC using HTTP over SSL/TLS over the Internet. Also, the idea is to design the architecture in such a way that adding new partners is easy.

Here is the simplified diagram:

Problem

Unfortunately, MEC does not provide incoming channels for HTTPS, there are no HTTPSIn or HTTPSSyncIn channels. There is a WebServiceSyncIn channel that uses WS-Security for XML over SOAP, but it is not what I am interested in. Ideally, I would prefer to use the Infor Grid which already communicates via HTTPS, but unfortunately it does not have a native connection handler for MEC. Surprisingly, most projects I have seen use FTP + PGP, but that is insecure because the FTP username and password transit in clear text, so even though the files are encrypted a man-in-the-middle could intercept the credentials and create havoc like delete files or fill the disk with junk.

Alternatively, I could develop my own HTTPS server in Java on top of a custom MEC channel; the Java Secure Socket Extension (JSSE) is a good reference guide for how to implement SSL/TLS in Java. I have two options. I could use SSLServerSocket, but it uses blocking I/O contrary to MEC that uses non-blocking I/O for scalability and performance, consequently I would have to forgo scalability and performance. Or I could use SSLEngine to have non-blocking I/O for scalability and performance, but I would have to implement the entire TLS state machine which is overkill for my needs.

Design

I will setup a public web server https∶//partners.example.com/ at my sample company.

For that, I will setup a reverse proxy with SSL termination upstream of HTTPIn or HTTPSyncIn channels. Thanks to Rickard Eklind for the tip on using Apache + mod_proxy; I will use nginx + ngx_http_proxy_module instead, as it uses non-blocking I/O similar to HTTPIn and HTTPSyncIn, and I think it is easier to setup; either combination will work. I will need to setup the proxy server on the DMZ, setup DNS records, and generate digital certificates.

If you cannot host your own server on the DMZ, or if you cannot create your own domain name partners.example.com in the DNS records, or if you cannot create your own digital certificate signed by a trusted certificate authority, you may be able to piggy back on an existing public web server in your company and simply add a new virtual directory, like https∶//www.example.com/partners/ that will forward requests to a content-based filtering router, decrypt, filter, re-encrypt and send the requests to your reverse proxy in the LAN.
Alternatively, I could have setup a dedicated secure line per partner – such as a VPN with a filter to restrict access to only a specific destination IP address and port number for MEC on the LAN – but for each new partner that would require a lot of paperwork, security clearance, and setup on both ends, which is possible, it is more sandboxed thus more desirable, but it may not be possible in some companies. And in some clouds it may be easier to setup web servers than VPNs.

Reverse proxy with SSL termination

A reverse proxy is an intermediate server that executes the client’s request to the destination server on behalf of the client without the client being aware of the presence of the proxy; this is unlike a forward proxy that we setup in a browser. In our case, MEC partners will connect to the reverse proxy as if it were MEC, and the proxy will make the requests to MEC.

SSL termination is where the SSL/TLS connection ends. In our case, the partner will initiate the connection to the reverse proxy using the proxy’s digital certificate (which is the proxy’s public key signed by a certificate authority), then the proxy will decrypt the SSL/TLS data using its private key, then the proxy will make the HTTP request in plain text to MEC, and the response will transit back in the opposite direction. The partner will need to previously have verified and added in its keystore the proxy’s certificate or one of the certificate authorities up the chain.

Here is the simplified nginx.conf:

http {
   server {
      server_name partners.example.com;
      listen 443 ssl;
      ssl_certificate cert;
      ssl_certificate_key key;
      location / {
         proxy_pass http://ecollaborator:8080/;
      }
   }
}

Here is the simplified diagram:

Note 1: This scenario assumes the servers are on the same network which is not true for the Internet. I will put the proxy in the DMZ. See the DMZ section below.
Note 2: This scenario assumes the data does not need to be encrypted on the second network segment which is not true either. I will install a second proxy on the same host as MEC. See the end-to-end encryption section below.

Multiplexing

I need to accommodate multiple partners, for example partnerA, partnerB, and partnerC.

I will use virtual hosting to economically share resources on a single server instead of having a dedicated physical server or virtual private server per partner.

Path-based

I will multiplex by URL path, for example /A, /B, and /C. I conjecture this is no less secure than doing it name-based or port-based. Also, I conjecture it is not subject to XSS attacks so long as we enforce client authentication (see the client authentication section below).

Here is the simplified nginx.conf:

location /A {
   # partnerA
}
location /B {
   # partnerB
}
location /C {
   # partnerC
}

Here is the simplified diagram:

Name-based

Alternatively, I could multiplex by domain name, for example partnerA.example.com, partnerB.example.com, and partnerC.example.com. But then for each new partner I would need a new network interface with a new public IP address – which is scarce to obtain – and update the A records of my DNS server. Or to share the same IP address I could use Server Name Indication (SNI) and update the CNAME records of my DNS server. In any case, I would have to issue a new digital certificate with an updated Subject Alternative Name (SAN) extension, or I could use one wildcard certificate but loose the possibility of Extended Validation Certificate, and anyway wildcard certificate is not considered secure per RFC6125#section-7.2. In the end, it is a maintenance nightmare, and relying on the respective teams could be a bottleneck in some companies.

Port-based

As another alternative, I could multiplex by port number, for example partner.example.com:81, partner.example.com:82, and partner.example.com:83, indeed the same digital certificate will work for any port number, but then for each new partner I would have to update the firewall rules, it is possible, but it is more maintenance, and relying on the respective teams could be a bottleneck in some companies.

De-multiplexing

Then, I need to de-multiplex the requests to tell the partners apart in MEC. I will setup as many HTTPIn or HTTPSyncIn channels in MEC as there are partners, for example HTTPSyncIn_A on port 8081, HTTPSyncIn_B on port 8082, and HTTPSyncIn_C on port 8083, and in nginx for each partner I will setup a location block with a proxy_pass directive.

Here is the simplified nginx.conf:

location /A {
   proxy_pass http://ecollaborator:8081/;
}
location /B {
   proxy_pass http://ecollaborator:8082/;
}
location /C {
   proxy_pass http://ecollaborator:8083/;
}

Here is the simplified diagram:

demux

Here are the receive channels in Partner Admin:

Receive

Authentication

I need the client to authenticate the server, and vice versa, I need the server to authentication the client.

One of the properties of SSL/TLS is authentication, using digital certificates to affirm the identity of the entities, where server authentication is mandatory, and client authentication is optional. In my case, client authentication is mandatory.

Server authentication

The server (the reverse proxy) will present its digital certificate to the client (the MEC partner), and the client will do its certificate validation to authenticate the server.

Client authentication

On the other hand, the server (ultimately it is MEC) needs to authenticate the client (the MEC partner).

I could setup peer authentication for the proxy to verify the client’s digital certificate, but I have not tested this.

Instead, I will setup HTTP Basic authentication per path in the proxy. The username and password will be encrypted over SSL/TLS so they will remain confidential.  I will separate the locations and I will forward to each respective HTTPSyncIn channel in MEC.

Here is the simplified nginx.conf:

location /A {
   auth_basic "A";
   auth_basic_user_file A.htpasswd;
   proxy_pass http://ecollaborator:8081/;
}
location /B {
   auth_basic "B";
   auth_basic_user_file B.htpasswd;
   proxy_pass http://ecollaborator:8082/;
}
location /C {
   auth_basic "C";
   auth_basic_user_file C.htpasswd;
   proxy_pass http://ecollaborator:8083/;
}

In addition to that, we could setup rules in the firewall to only allow the source IP addresses of the partners to access the reverse proxy, it is great if combined with Basic authentication, but insufficient on its own.

To setup peer authentication, I would use ssl_verify_client. According to the nginx documentation, the context for the ssl_client_certificate directive is http and server only, not location. So I would have to append the various client certificates into one file; to be verified. And then I could use the $ssl_client_cert variable to tell partners apart; to be tested.
As another alternative, we could setup client authentication in the MEC agreement using a flat file detector to detect a username and password defined in the HTTP request payload. But that has many problems: 1) It would require hard-coding the username and password in clear text in MEC (passwords should be hashed and salted or at least encrypted), 2) if we need to change the password we would have to change and re-deploy the agreement, and 3) it would put the burden of password verification on MEC which is not designed to thwart brute force attacks.

Channel detection

Now, we have to carry over the authentication to MEC because even though nginx can pass the Basic authentication header to MEC, MEC does not use it, and if we do not authenticate partners and tell them apart they risk crossing each other. For that I will use a Channel detector in the MEC agreement of each partner.

Here are the channel detectors in Partner Admin:

detection

A drawback emerges from this setup: the number of possible messages per channel is now limited to only one. If partner A wants to send two different messages 1 and 2, for example new customer order and new rental agreement, MEC is not able to process two messages in one agreement, and it cannot reuse the same receive channel in another agreement. To assist MEC, I would have to discriminate further by path in nginx, for instance /A/message1, and /A/message2, and have as many receive channels as possible messages. I can use nested location blocks (I have not tested this). Here is the simplified nginx.conf:

location /A {
   auth_basic "A";
   auth_basic_user_file A.htpasswd;
   location /message1 {
      proxy_pass http://ecollaborator:8001/;
   }
   location /message2 {
      proxy_pass http://ecollaborator:8002/;
   }
}

I am not trained in MEC Partner Admin so maybe there is a way around it.

…on the Internet

Once a web server is placed on the Internet it will get attacked, so consult with your network and security team to harden your servers. It should at least be in the DMZ between one or two firewalls:

Here is a simplified diagram:

DMZ

Take also into account: high availability, redundancy, fail over, disaster recovery, edge caching, DNS round robin, IDS, content-based firewall, restrict physical access to the servers, restrict permissions to the files, software updates, operating system support, etc.

Note: The HTTP channels in MEC will be the single point of failure in spite of all this setup. The MEC Server runs on the Infor Grid, and the Infor Grid is meant to be distributed, fault tolerant, load balanced, scalable, and redundant. However, the HTTP channels of MEC are not Grid enabled (the HTTPIn and HTTPSyncIn channels manage their port and HTTP server themselves), so they are not distributed, fault tolerant, load balanced, scalable, and redundant, they are a single point of failure. You can learn more about Infor Grid application development on my other post.

End-to-end encryption

Now we need end-to-end encryption to protect the data on the second network segment from the reverse proxy on the DMZ to MEC on the LAN. For that, I will chain two reverse proxies with SSL termination. I will simply install the second proxy on the same host as MEC. And I will issue a second pair of digital certificate and private key for the second proxy that the two proxies will use to encrypt/decrypt. That simplifies the rules of the internal firewall, and I can setup peer authentication between the proxies.

Here is the simplified diagram with the two proxies X and Y:

chain

How to add new partners

To add a new partner D:

  1. Setup a new Receive channel in Partner Admin with a new HTTPIn or HTTPSyncIn channel for example on port 8084
  2. Setup a new agreement with channel detector
  3. Test by making an HTTP request to MEC on port 8084
  4. Setup the inner proxy:
    1. Setup a new location block in nginx.conf for path /D with proxy_pass directive to port 8084 and basic authentication
    2. Setup a new htpasswd file
    3. Restart nginx
    4. Test by making an HTTPS request to the proxy
  5. Setup the outer proxy to pass requests to the inner proxy and test it (I do not have guidelines here as my actual setup for the outer proxy uses a content-based router, not nginx)
  6. Test by making an HTTPS request from the partner to https∶//partners.example.com/D

How to setup multiple environments

To setup multiple environments, such as DEV, TST, PRD, use nested location blocks in nginx.conf, for example /DEV, /TST, /PRD (I have not tested this).

Here is the simplified nginx.conf:

location /DEV {
   location /A {
      # Development partnerA
   }
   location /B {
      # Development partnerB
   }
}
location /TST {
   location /A {
      # Test partnerA
   }
   location /B {
      # Test partnerB
   }
}

Limitations

This is the first time I setup this architecture, I have not tested all the design variations, and I have not validated that my design is a good design nor that it is secure. I am currently using a similar architecture at a major customer of mine for their production environment where they have multiple data centers, high availability, redundancy, fail over, and disaster recovery. One of their technical people reviewed the solution, they approved it, and the only concerns were that this solution might be over engineered (plausible) and that the MEC channels are the single point of failure anyway (true). I conjecture the solution is good enough and secure enough for our needs. Of course I could be completely wrong and not see a major flaw. Nothing is fully secure anyway. Please let me know what you think in the comments below.

Upcoming version of MEC

Johan Löfgren, the component owner for MEC at Infor Product Development, said they are working on a native HTTPSIn channel for an upcoming version of MEC; it is not GA and the release may or may not occur. If and when that happens, you would not need to chain two proxies anymore, you would just keep one proxy in the DMZ and use proxy_pass to send the requests directly to the HTTPSIn channels in MEC.

UPDATE 2015-04-12: What is being released is SFTP, no plans for HTTPS at the moment.

Conclusion

This was one solution to setup incoming HTTP channels in MEC to securely receive messages over SSL/TLS over the Internet. MEC does not have an HTTPSIn or HTTPSSyncIn channel, and I did not want to implement my own HTTP server over SSL/TLS in Java. Instead, I chose to setup a reverse proxy with SSL termination in a DMZ, with digital certificate and private keys, with HTTP basic authentication, with a second proxy in the MEC host for end-to-end encryption. This solution has many properties: it uses standard HTTP and SSL/TLS, and it is easy to add new partners. Also, we simplified the architecture upstream such that we do not have to rely on other teams if we need to add a new partner, which can be a maintenance nightmare and bottleneck in some companies; we can simply add new partners downstream in our proxy and Partner Admin. I conjecture this solution is secure for our needs. But remember it has not been fully reviewed, and the MEC channels are the single point of failure.

Please let me know what you think in the comments below.

Related articles

HTTP channels in MEC (part 5)

Continuing the guide on how to setup HTTP channels in Infor M3 Enterprise Collaborator (MEC), I will illustrate how to setup the HTTPSOut channel for MEC to make requests using HTTP Secure (HTTPS), i.e. HTTP over SSL/TLS; I will investigate the channel’s features and drawbacks, and I will verify if it is safe to use (it is not).

Why it matters

It is important to use SSL/TLS in partner agreements that need to transfer via HTTP sensitive information such as names, addresses, bank account numbers, purchase orders, credit card numbers, financial transactions, health records, user names, passwords, etc. More generally, it is important to accelerate the adoption of cryptography.

HTTPS in brief

SSL/TLS is a security protocol that provides privacy for a client and a server to communicate over insecure networks. It is a communication layer that sits between a transport layer (usually TCP) and an application layer (for example HTTP). Secure Sockets Layer (SSL) is the original protocol and is not considered secure anymore. Transport Layer Security (TLS) is the successor and everybody should upgrade to its latest version 1.2. https is the scheme token in the URI that indicates we are using a dedicated secure channel often on port 443.

Properties

SSL/TLS provides the following properties of secure communication:

  • Confidentiality, using a cipher to encrypt the plain text and prevent eavesdropping
  • Integrity, using signed hashes to detect tampering
  • Authentication, using digital certificates to affirm the identity of the entities

It can also provide non-repudiation, using digital signatures to assert the sender cannot deny having sent the message, provided the sender’s private key is not compromised or changed.

And depending on the key agreement protocol, it can also provide perfect forward secrecy, using ephemeral key exchanges for each session, to ensure that a message cannot be compromised if another message is compromised in the future.

Handshake

During the SSL/TLS handshake, the client and server exchange digital certificates and establish cipher suite settings. The connection bootstraps with asymmetric cryptography using public and private keys (which eliminates the problems of distributing shared keys), and then switches to symmetric cryptography using a temporary shared key for the session (which is several orders of magnitude faster).

Digital certificates

A digital certificate is a public key and the owner’s identity that have been verified and digitally signed by a certificate authority (CA). Public key infrastructure (PKI) is used to create, distribute, and revoke certificates. If an entity trusts a CA, then by transitive relation it will trust that any certificate the CA issues authenticates the owner of the certificate. There can be any number of intermediate CAs in the chain of certificates, and root CAs use self-signed certificates.

The client must verify the server certificate, and optionally the server may verify the client certificate:

  • Verify the chain of trust
  • Verify the hostname in the certificate using SubjectAltNames and Common Name; this could get tricky with wildcard patterns, null characters, and international character sets
  • Verify the certificate’s activation and expiration dates
  • Verify the certificate’s revocation status using a certification revocation list (CRL) or OCSP
  • Check the X.509 certificate extensions (e.g. can this key sign new certificates?)
  • Check that the certificates of the intermediate CAs have the CA bit set in the “Basic Constraints” field

Despite all that, validating certificates is difficult, and the CA model is broken.

Test

You can test HTTP over SSL/TLS and see the chain of certificates,

with cURL:

curl http://curl.haxx.se/ca/cacert.pem > cacert.pem
curl --verbose --cacert cacert.pem https://www.example.com/

with OpenSSL:

openssl s_client -connect www.example.com:443 -showcerts
GET / HTTP/1.1
Host: www.example.com:443

Proxy

A web proxy is a program that makes requests on behalf of a client. There are different types of web proxies, for example tunneling proxies, forward proxies, and reverse proxies. And there are different implementations, for example, explicit proxies and transparent proxies. And they have different purposes, for example caching, load balancing, securing, monitoring, filtering, bypassing, and anonymizing. Proxies may require authentication.

An explicit web proxy is for example when you set your browser to use a proxy at a certain host and port number. With that proxy, the client makes an HTTP request to the proxy using the CONNECT method, then the proxy establishes a TCP connection to the destination server, and then the proxy acts as a blind tunnel that is forwarding TCP between client and server, seeing only the SSL/TLS handshake and then encrypted traffic.

You can test HTTP over SSL/TLS via an explicit proxy,

with cURL and Fiddler:

curl --verbose --cacert cacert.pem --proxy 127.0.0.1:8888 https://www.example.com/

with proxy authentication:

curl --verbose --cacert cacert.pem --proxy http://username:password@proxy:port/ https://www.example.com/

with GNU Wget and Fiddler:

export https_proxy=localhost:8888
wget --debug --https-only https://www.example.com:443/

You will see this request and response between client and proxy, then the SSL/TLS handshake, then the HTTP traffic:

CONNECT www.example.com:443 HTTP/1.1
Host: www.example.com:443
HTTP/1.1 200 Connection Established

On the other hand, a transparent proxy intercepts the traffic at the lower network level without requiring any client configuration. It acts as the SSL termination for the client, and establishes a second encryption channel with the destination server thereby being able to monitor and filter the SSL/TLS traffic in transit; in that case the client is not aware of the presence of the proxy but must trust the proxy’s certificate, and the proxy must trust the server’s certificate.

For MEC

In our case, we want MEC to communicate with partners over a secure channel with confidentiality, integrity, and authentication to protect the data being exchanged, optionally via proxy.

Problem

MEC does not provide secure channels for HTTP out of the box. For instance, there are no HTTPSIn, HTTPSOut, HTTPSSyncIn, or HTTPSSyncOut channels. There is an HTTPSOut channel, but it is only a sample in an appendix of the documentation (does that mean it is safe to use?), and it does not come out of the box in the Partner Admin, it must be added manually (although it is available in the Java library). Also, there is a WebServiceSyncIn channels that uses WS-Security specifically for XML over SOAP, but in my case I am interested in HTTPS in general, for example for flat files, I am not interested in SOAP. Ideally, I would prefer to use the Infor Grid which already communicates via HTTPS, but unfortunately it does not have a native connection handler for MEC.

None of this means MEC is insecure, it just means you have to add the security yourself.

Documentation

The useful documentation

The MEC Partner Admin Tool User Guide contains the necessary source code and some explanation for the HTTPSOut channel and user interface:
doc1 doc2doc3

The obstructing documentation

However, the documentation references HTTPS Communication, HttpServer.xml, and HTTPSOut at the same time, yet it does not clearly explain the relationship between them, so it is confusing:
doc4 doc5

I had to find the Communication Plug-in Development User Guide of an old version of MEC to find the answer. It turns out the HttpServer.xml was a file that existed in old versions of MEC to configure the web user interface. I think the sample in the documentation used that server to test the HTTPSOut channel; I do not know. Anyway, that file does not exist anymore after MEC was ported to the Infor Grid, so that chapter is irrelevant, confusing, and unrelated to HTTPSOut. We can ignore it, and Infor should remove it from the Partner Admin guide.

Java classes

The MEC Java library ec-core-x.y.z.jar includes the Java classes sample.HTTPSOut and sample.HTTPSOutPanel:
4.1

Features

Looking at the source code, the HTTPSOut channel is similar to the HTTPOut channel: they both make a POST HTTP request to a destination server, at a host, port number, and path defined in the Partner Admin, with the message sent in the request body.

HTTPSOut uses javax.net.ssl.HttpsURLConnection which in turn uses javax.net.ssl.SSLSocket to establish a secure socket with the destination server. From the HTTPSOut point of view, it just reads/writes plain HTTP to the socket, and the socket underneath takes care of the handshake and encryption/decryption.

HTTPSOut has an advantage over HTTPOut. Given the entire HTTP traffic is encrypted over SSL/TLS, we can safely set a username and password for HTTP Basic authentication, unlike with HTTPOut where we should not set a username and password because they transit in clear text (trivial Base64 decode).

Drawbacks

HTTPOut and HTTPSOut share the same drawbacks: they do not use Java NIO, and there are no proxy settings.

HTTPSOut has additional drawbacks: there are no settings for Content-type, multi-part, and keep alive, unlike HTTPOut. Worse, the response is completely ignored unlike HTTPOut where the response is at least added to the debug log.

Test

You can test the HTTPSOut class with the following code and with a message.txt file:

javac -cp log4j-1.2.17.jar;ec-core-11.4.1.0.0.jar;. Test.java
java -cp log4j-1.2.17.jar;ec-core-11.4.1.0.0.jar;. Test < message.txt
import java.util.Properties;
import sample.HTTPSOut;

public class Test {
    public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        props.setProperty(HTTPSOut.HOST, "www.example.com");
        props.setProperty(HTTPSOut.PORT, "443");
        props.setProperty(HTTPSOut.PATH, "/");
        props.setProperty(HTTPSOut.USER, "username");
        props.setProperty(HTTPSOut.PASSWORD, "*****");
        props.setProperty(HTTPSOut.TRUST_STORE, "C:\\somewhere\\keystore");
        props.setProperty(HTTPSOut.TRUST_STORE_PWD, "*****");
        HTTPSOut client = new HTTPSOut();
        client.send(System.in, null, props);
    }
}

HTTPSOut will send the following request over SSL/TLS:

POST /Hello HTTP/1.1
Content-Type: multipart/form-data; boundary=----------------------------afatudbu6sb5-875oo9dmn52fzfypuig0x1kv
Authorization: Basic: dXNlcm5hbWU6cGFzc3dvcmQ=
User-Agent: M3 Enterprise Collaborator v11.4.1.0
Cache-Control: no-cache
Pragma: no-cache
Host: www.example.com:443
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 256
------------------------------afatudbu6sb5-875oo9dmn52fzfypuig0x1kv
Content-Disposition: form-data; name="name"; filename="output.xml"
Content-Type: application/xml

Hello, World!
------------------------------afatudbu6sb5-875oo9dmn52fzfypuig0x1kv--

Activity diagram

Here is a sample activity diagram of the HTTPSOut channel:

diagram

Authentication bug

There is a bug in the HTTPSOut class regarding the HTTP Basic authentication header that will cause the server to return HTTP/1.1 401 Unauthorized, and that is easy to fix:

// incorrect
urlConn.setRequestProperty("Authorization: Basic", Base64.encode (to64, "ISO-8859-1"));
// correct
urlConn.setRequestProperty("Authorization", "Basic " + Base64.encode (to64, "ISO-8859-1"));

The bug is located in both the HTTPSOut source code in the Partner Admin guide, and in the HTTPSOut class in the JAR file. And the JAR file is located in both the Partner Admin tool and in the MEC server in the Infor Grid.

That code is only executed if you need HTTP Basic authentication (i.e. if you specify a username and password); you can ignore it otherwise.

Proxy

If you need to use a proxy, add the following code to the HTTPSOut class and recompile it:

import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;

[...]
// get the proxy properties
String proxyHost = props.getProperty(PROXY_HOST);
int proxyPort = Integer.parseInt(props.getProperty(PROXY_PORT));
String proxyUser = props.getProperty(PROXY_USER);
String proxyPassword = props.getProperty(PROXY_PASSWORD);

// connect via proxy
InetSocketAddress proxyInet = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyInet);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection(proxy);

// authenticate to proxy
Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(proxyUser, proxyPassword.toCharArray());
    }
});

//con.setRequestProperty("Proxy-Authorization", "Basic " + Base64.encode(proxyUser + ":" + proxyPassword, "ISO-8859-1")); // this did not work for me

You will need to add some if-then-else so the user can choose to use a proxy or not, and add some exception handling around parseInt.

Also, for the user interface, you will need to add a group widget, a checkbox, four labels and four text boxes to the HTTPSOutPanel class and recompile it:
test___

Security holes

Unfortunately, the HTTPSOut class does not verify the certificate and as such the connection is susceptible to man-in-the-middle attack.

For instance, it does not verify the hostname of the certificate, it just returns true for any hostname:

HostnameVerifier hv = new HostnameVerifier() {
    public boolean verify(String s, SSLSession sslSession) {
        return true;
    }
};

More so, HTTPSOut does not verify the certificate’s dates, revocation, basic constraint, extensions, etc.

Thus, HTTPSOut is not safe to use out of the box. You have to implement certificate validation yourself. That is probably why it is only a sample.

Compilation

To compile the HTTPSOut and HTTPSOutPanel classes:

  1. Recover the source code (either copy/paste it from the Partner Admin guide, or decompile the classes).
  2. Change the code as needed (e.g. fix the authentication bug, add the proxy settings, add certificate validation, etc.)
  3. Compile the source code with:
    javac -cp lib\log4j-1.2.17.jar;lib\ec-core-11.4.1.0.0.jar sample\HTTPSOut.java
    javac -cp lib\x86-3.3.0-v3346.jar;lib\log4j-1.2.17.jar;lib\ec-core-11.4.1.0.0.jar;. sample\HTTPSOutPanel.java
    4.2
  4. Replace the Java classes in both the Partner Admin tool folder and in the MEC server folder of the Infor Grid, for example:
    D:\Infor\MECTOOLS\Partner Admin\classes\sample\
    D:\Infor\LifeCycle\host\grid\M3_Development\grids\M3_Development\applications\MECSRVDEV\MecServer\lib\sample\
    4.2_ 4.2__
  5. Restart the Partner Admin and restart the MEC server in the Infor Grid.
  6. The class loader will give precedence to the classes you put in the folders over the classes in the JAR file.

1. Preparation

Before we can use HTTPSOut, we have to prepare the terrain for SSL/TLS.

As a reminder, the HTTPSOut channel is an HTTP client that will make an HTTP request to a destination HTTP server over SSL/TLS, e.g. to https://www.example.com/.

1.1. Server authentication

The short instructions to setup server authentication are:

openssl s_client -connect www.example.com:443 > example.cer
keytool.exe -import -file example.cer -keystore example.ks -storepass changeit

The long instructions are the following.

We need to setup server authentication, i.e. for HTTPSOut to affirm the identity of the server it is connecting to; it will rely on SSLSocket to verify that the server certificate is signed by a certificate authority that is stored in a trusted keystore.

Internet Explorer, Google Chrome, Fiddler and other programs that use WinINet ultimately rely on the Windows certificate manager, certmgr.msc, but Firefox and Java each use their own key management. The JRE has its default keystore at %JAVA_HOME%\lib\security\cacerts that SSLSocket uses. HTTPSOut ignores the default keystore and requires the user to specify one. To create a Java keystore we use keytool.exe and import the server’s certificate in it.

The steps are:

  1. Open a browser to the destination server over HTTPS and open the certificate:
    2.2_
  2. Inspect the certificate, any intermediate certificate authorities, and the root certificate authority, up the chain, and make sure you trust them (if your browser does not trust them it will throw a big warning sign):
    2.5 2.6
  3. Now we need Java to trust that certificate. Check if one of the certificates in the chain is already in your Java keystore. Java already comes with a list of trusted certificates in its keystore. If the destination server presents a certificate that is already trusted by one of the trusted certificates of the JRE, it will automatically be trusted by the JRE, i.e. the friends of my friends are my friends. In my case, my JVM already trusts the certificate authority DigiCert, so by chain of trust it will automatically trust the certificate presented by http://www.example.com. It may be the same case for you:
    keytool.exe -list -keystore cacerts -storepass changeit | findstr /i DigiCert
    keytool.exe -list -keystore cacerts -storepass changeit -v -alias digicerthighassuranceevrootca

    2.8

  4. If you already have the server certificate, good, just keep in mind the location of that keystore, and skip the rest of these steps; otherwise continue reading.
  5. Export the certificate to a file, e.g. example.cer:
    2.6_ 2.6__
  6. Import the certificate to a keystore, e.g. example.ks:
    keytool.exe -import -file example.cer -keystore example.ks -storepass changeit

  7. Now you have a keystore ready for HTTPSOut.

1.2. Client authentication

As for client authentication, the HTTPSOut channel does not support that, i.e. it does not have a public/private keys and a digital certificate to present to the server if the server requests it, so we have to forget about that. If the server needs to authenticate the client, we can use Basic authentication (provided we fix the authentication bug).

2. How to setup

Now let’s setup the HTTPSOut channel in MEC.

The steps will be:

  1. Setup the Send protocol
  2. Setup the Send channel configuration
  3. Setup the Agreement with detection and processes

2.1. Setup the Send protocol

  1. Open the Partner Admin tool
  2. Go to Manage > Advanced
  3. Select the Send Protocols tab
  4. Click New, and set:
    Protocol: HTTPSOut
    Send class: sample.HTTPSOut
    UI class: sample.HTTPSOutPanel
    4.3
  5. Click OK
  6. Click Close

2.2. Setup the Send channel configuration

  1. Go to Manage > Communications
  2. Select the Send tab
  3. Click New:
    4.4.1
  4. Select protocol HTTPSOut and enter the information host, port number and path to the destination server, as well as the keystore where you saved the certificate and the keystore password, and optionally set user and password for HTTP Basic authentication to the destination server (provided you corrected the authentication bug):
    4.4.2
    Note: The keystore path is relative to the JVM that runs MEC server, i.e. java.exe must be able to access the file and have read permission to it. Also, given the Infor Grid is distributed make sure the keystore file is distributed accordingly to the correct server.
  5. Optionally set the proxy settings if you added that feature to the classes (see proxy section above)
  6. Click Send test message to ensure everything is correct; if you get an error message, test the HTTPSOut class as explained in the test section above, or check the troubleshooting tips in the section below
  7. Click OK
  8. Click Close

2.3. Setup the Agreement with detection and processes

  1. In Communications > Receive, setup any incoming channel such that we can simply trigger the partner agreement for the purposes of illustration; the protocol is not important right now; for instance I have a simple DiskIn channel that has status RUNNING in my Infor Grid, and I have a partner agreement with it in a channel detection.
  2. Go the agreement > Processes, right-click select Send, and select the HTTPSOut channel:
    5.1 5.2
  3. Click OK
  4. Click Save
  5. The HTTPSOut channel is now ready to use

3. How to test

To test the HTTPSOut channel, follow the same instructions as in the test of Part 4.

4. …on the Internet

If you are doing the HTTPS requests to a server out on the Internet you should consult with your security team. I have MEC in a LAN behind a NAT, firewall, content based filter, security appliance, and transparent proxy.

5. Troubleshooting

In case HTTPSOut does not work as expected, here are some troubleshooting tips.

Check the logs

The MEC server logs are useful for troubleshooting problems. For example, in one case I got the following exception:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

error1

That means the server certificate validation failed, either because we put the incorrect server certificate in the keystore that we defined in PartnerAdmin, either because a man-in-the-middle server presented a different certificate.

Test SSL/TLS connection

Some network and security administrators setup firewalls, proxies, and gateways that interfere with SSL/TLS. In my case, I will ensure that my host can access the destination server over SSL/TLS. For that:

  1. Locate on which node is MEC server running:
    2.0.2_
  2. From that server (for example via Remote Desktop Connection), make a test connection to the destination server over SSL/TLS, for example use OpenSSL s_client:
    openssl s_client -connect www.example.com:443 -showcerts
  3. Make sure the server certificate that is presented is the correct one.

Test HttpsURLConnection

  1. Check what JVM the MEC server is using:
    2.0.3_
  2. Use that JVM to test a HttpsURLConnection; that will check if that particular JVM of that host has access to read that keystore, it will check if it can make a SSL/TLS connection to that destination server, and it will show the server certificates received:
    // javac Test.java && java -cp . Test
    
    import java.io.OutputStream;
    import java.net.URL;
    import java.security.cert.Certificate;
    import javax.net.ssl.HttpsURLConnection;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            System.setProperty("javax.net.ssl.trustStore", "D:\\java\\jre\\lib\\security\\cacerts");
            System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
            URL url = new URL("https://www.example.com/");
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            con.setDoOutput(true);
            OutputStream out = con.getOutputStream();
            Certificate[] scerts = con.getServerCertificates();
            for (Certificate scert: scerts) {
                System.out.println(scert.toString());
            }
            con.disconnect();
        }
    }
    

Test HTTPSOut

See the section at the top to test the HTTPSOut class.

Conclusion

That was an illustration of how to setup the HTTPSOut channel in MEC so that MEC can act as a client making secure HTTP requests to servers over SSL/TLS. For that, we reviewed the basics of HTTPS, we reviewed the features and drawbacks of HTTPSOut, we learned how to fix the authentication bug, how to add proxy settings, we identified security holes, we learned how to recompile the classes, how to setup the channel in PartnerAdmin, how to test, and how to troubleshoot.

HTTPSOut lacks features, it has a bug, and it has security holes; that is probably why it is just considered a sample channel that is unsafe to use in a production environment. Take it as a starting point from which you can build your own safe channel with production quality.

Hopefully, Infor will remove the deprecated documentation from the Partner Admin guide, will enhance the HTTPSOut channel from unsafe sample to safe channel with production quality, and will eventually provide a native connection handler in the Infor Grid for MEC.

In the next part of this guide, I will illustrate how to setup HTTPS for inbound messages.

(Congratulations if you made it this far! Let me know what you think in the comments below.)

Related articles

How to decrypt Smart Office’s encrypted traffic

In the PowerPoint document How to decrypt Smart Office’s encrypted traffic I describe how to intercept and decrypt the encrypted HTTPS traffic from Lawson Smart Office which sometimes cannot be captured with Fiddler, and which is unreadable in Wireshark. This technique is useful for troubleshooting Mashups, Smart Office, Personalized Scripts, IBrix, etc.

Does that demonstrate a security flaw in Smart Office? Not at all. Read the last chapter in the document.