diff --git a/Dockerfile b/Dockerfile index 3d084135..cfb9048e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -100,6 +100,7 @@ RUN rm -f /opt/tomee/lib/slf4j-* COPY container_files/tier-support/log4j_fix/tomeeLib/slf4j-* /opt/tomee/lib/ RUN rm -f /opt/grouper/grouperWebapp/WEB-INF/lib/slf4j-api-* COPY container_files/tier-support/log4j_fix/webinfLib/* /opt/grouper/grouperWebapp/WEB-INF/lib/ +COPY container_files/certs/* /opt/grouper/certs/ # this is to improve openshift diff --git a/container_files/certs/TestSsl.class b/container_files/certs/TestSsl.class new file mode 100644 index 00000000..6ce4c196 Binary files /dev/null and b/container_files/certs/TestSsl.class differ diff --git a/container_files/certs/TestSsl.java b/container_files/certs/TestSsl.java new file mode 100644 index 00000000..29677b7a --- /dev/null +++ b/container_files/certs/TestSsl.java @@ -0,0 +1,39 @@ +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.*; + +/** + * Establish a SSL connection to a host and port, writes a byte and + */ +public class TestSsl { + public static void main(String[] args) { + if (args.length != 2) { + System.out.println("Usage: "+TestSsl.class.getName()+" "); + System.exit(1); + } + try { + SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1])); + + SSLParameters sslparams = new SSLParameters(); + sslparams.setEndpointIdentificationAlgorithm("HTTPS"); + sslsocket.setSSLParameters(sslparams); + + InputStream in = sslsocket.getInputStream(); + OutputStream out = sslsocket.getOutputStream(); + + // Write a test byte to get a reaction :) + out.write(1); + + while (in.available() > 0) { + System.out.print(in.read()); + } + System.out.println("Successfully connected"); + + } catch (Exception exception) { + exception.printStackTrace(); + System.exit(1); + } + } +} diff --git a/container_files/certs/get_tls_cert.py b/container_files/certs/get_tls_cert.py new file mode 100644 index 00000000..f1989659 --- /dev/null +++ b/container_files/certs/get_tls_cert.py @@ -0,0 +1,122 @@ +import sys +import pprint +import struct +import socket +import ssl +from time import sleep + +# Standard "HELLO" message for TDS +prelogin_msg = bytearray([ 0x12, 0x01, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x06, 0x01, 0x00, 0x20, + 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, + 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]) + +# Prep Header function +def prep_header(data): + data_len = len(data) + prelogin_head = bytearray([ 0x12, 0x01 ]) + header_len = 8 + total_len = header_len + data_len + data_head = prelogin_head + total_len.to_bytes(2, 'big') + data_head += bytearray([ 0x00, 0x00, 0x01, 0x00]) + return data_head + data + +def read_header(data): + if len(data) != 8: + raise ValueError("prelogin header is > 8-bytes", data) + + format = ">bbhhbb" + sct = struct.Struct(format) + unpacked = sct.unpack(data) + return { "type": unpacked[0], + "status": unpacked[1], + "length": unpacked[2], + "channel": unpacked[3], + "packet": unpacked[4], + "window": unpacked[5] + } + +tdspbuf = bytearray() +def recv_tdspacket(sock): + global tdspbuf + tdspacket = tdspbuf + header = {} + + for i in range(0,5): + tdspacket += sock.recv(4096) + print("\n# get_tdspacket: {}, tdspacket len: {} ".format(i, len(tdspacket))) + if len(tdspacket) >= 8: + header = read_header(tdspacket[:8]) + print("# Header: ", header) + if len(tdspacket) >= header['length']: + tdspbuf = tdspacket[header['length']:] + print("# Remaining tdspbuf length: {}\n".format(len(tdspbuf))) + return header, tdspacket[8:header['length']] + + sleep(0.05) + +# Ensure we have a commandline +if len(sys.argv) != 3: + print("Usage: {} ".format(sys.argv[0])) + sys.exit(1) + +hostname = sys.argv[1] +port = int(sys.argv[2]) + + +# Setup SSL +if hasattr(ssl, 'PROTOCOL_TLS'): + sslProto = ssl.PROTOCOL_TLS +else: + sslProto = ssl.PROTOCOL_SSLv23 + +sslctx = ssl.SSLContext(sslProto) +sslctx.check_hostname = False +tls_in_buf = ssl.MemoryBIO() +tls_out_buf = ssl.MemoryBIO() + +# Create the SSLObj connected to the tls_in_buf and tls_out_buf +tlssock = sslctx.wrap_bio(tls_in_buf, tls_out_buf) + +# create an INET, STREAMing socket +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.setblocking(0) +s.settimeout(1) + +# Connect to the SQL Server +s.connect(( hostname, port )) + +# Send the first TDS PRELOGIN message +s.send(prelogin_msg) + +# Get the response and ignore. We will try to negotiate encryption anyway. +header, data = recv_tdspacket(s) +while header['status']==0: + header, ext_data = recv_tdspacket(s) + data += ext_data + + +print("# Starting TLS handshake loop..") +# Craft the packet +for i in range(0,5): + try: + tlssock.do_handshake() + print("# Handshake completed, dumping certificates") + peercert = ssl.DER_cert_to_PEM_cert(tlssock.getpeercert(True)) + print(peercert) + sys.exit(0) + except ssl.SSLWantReadError as err: + # TLS wants to keep shaking hands, but because we're controlling the R/W buffers it throws an exception + print("# Shaking ({}/5)".format(i)) + + tls_data = tls_out_buf.read() + s.sendall(prep_header(tls_data)) + # TDS Packets can be split over two frames, each with their own headers. + # We have to concat these for TLS to handle nego properly + header, data = recv_tdspacket(s) + while header['status']==0: + header, ext_data = recv_tdspacket(s) + data += ext_data + + tls_in_buf.write(data) + +print("# Handshake did not complete / exiting") \ No newline at end of file