📄 tlsprotocolhandler.java
字号:
/* * Send Client hello * * First, generate some random data. */ this.clientRandom = new byte[32]; int t = (int)(System.currentTimeMillis() / 1000); this.clientRandom[0] = (byte)(t >> 24); this.clientRandom[1] = (byte)(t >> 16); this.clientRandom[2] = (byte)(t >> 8); this.clientRandom[3] = (byte)t; for (int i = 4; i < clientRandom.length; i++) { this.clientRandom[i] = (byte)random.nextInt(); } ByteArrayOutputStream os = new ByteArrayOutputStream(); TlsUtils.writeVersion(os); os.write(this.clientRandom); /* * Length of Session id */ TlsUtils.writeUint8((short)0, os); /* * Cipher suites */ TlsCipherSuiteManager.writeCipherSuites(os); /* * Compression methods, just the null method. */ byte[] compressionMethods = new byte[]{0x00}; TlsUtils.writeUint8((short)compressionMethods.length, os); os.write(compressionMethods); ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HP_CLIENT_HELLO, bos); TlsUtils.writeUint24(os.size(), bos); bos.write(os.toByteArray()); byte[] message = bos.toByteArray(); rs.writeMessage(RL_HANDSHAKE, message, 0, message.length); connection_state = CS_CLIENT_HELLO_SEND; /* * We will now read data, until we have completed the handshake. */ while (connection_state != CS_DONE) { rs.readData(); } this.tlsInputStream = new TlsInputStream(this); this.tlsOutputStream = new TlsOuputStream(this); } /** * Read data from the network. The method will return immediately, if there is * still some data left in the buffer, or block until some application * data has been read from the network. * * @param buf The buffer where the data will be copied to. * @param offset The position where the data will be placed in the buffer. * @param len The maximum number of bytes to read. * @return The number of bytes read. * @throws IOException If something goes wrong during reading data. */ protected int readApplicationData(byte[] buf, int offset, int len) throws IOException { while (applicationDataQueue.size() == 0) { /* * We need to read some data. */ if (this.failedWithError) { /* * Something went terribly wrong, we should throw an IOException */ throw new IOException(TLS_ERROR_MESSAGE); } if (this.closed) { /* * Connection has been closed, there is no more data to read. */ return -1; } try { rs.readData(); } catch (IOException e) { if (!this.closed) { this.failWithError(AL_fatal, AP_internal_error); } throw e; } catch (RuntimeException e) { if (!this.closed) { this.failWithError(AL_fatal, AP_internal_error); } throw e; } } len = Math.min(len, applicationDataQueue.size()); applicationDataQueue.read(buf, offset, len, 0); applicationDataQueue.removeData(len); return len; } /** * Send some application data to the remote system. * <p/> * The method will handle fragmentation internally. * * @param buf The buffer with the data. * @param offset The position in the buffer where the data is placed. * @param len The length of the data. * @throws IOException If something goes wrong during sending. */ protected void writeData(byte[] buf, int offset, int len) throws IOException { if (this.failedWithError) { throw new IOException(TLS_ERROR_MESSAGE); } if (this.closed) { throw new IOException("Sorry, connection has been closed, you cannot write more data"); } /* * Protect against known IV attack! * * DO NOT REMOVE THIS LINE, EXCEPT YOU KNOW EXACTLY WHAT * YOU ARE DOING HERE. */ rs.writeMessage(RL_APPLICATION_DATA, emptybuf, 0, 0); do { /* * We are only allowed to write fragments up to 2^14 bytes. */ int toWrite = Math.min(len, 1 << 14); try { rs.writeMessage(RL_APPLICATION_DATA, buf, offset, toWrite); } catch (IOException e) { if (!closed) { this.failWithError(AL_fatal, AP_internal_error); } throw e; } catch (RuntimeException e) { if (!closed) { this.failWithError(AL_fatal, AP_internal_error); } throw e; } offset += toWrite; len -= toWrite; } while (len > 0); } /** @deprecated use 'getOutputStream' instead */ public TlsOuputStream getTlsOuputStream() { return this.tlsOutputStream; } /** * @return An OutputStream which can be used to send data. */ public OutputStream getOutputStream() { return this.tlsOutputStream; } /** @deprecated use 'getInputStream' instead */ public TlsInputStream getTlsInputStream() { return this.tlsInputStream; } /** * @return An InputStream which can be used to read data. */ public InputStream getInputStream() { return this.tlsInputStream; } /** * Terminate this connection whith an alert. * <p/> * Can be used for normal closure too. * * @param alertLevel The level of the alert, an be AL_fatal or AL_warning. * @param alertDescription The exact alert message. * @throws IOException If alert was fatal. */ protected void failWithError(short alertLevel, short alertDescription) throws IOException { /* * Check if the connection is still open. */ if (!closed) { /* * Prepare the message */ byte[] error = new byte[2]; error[0] = (byte)alertLevel; error[1] = (byte)alertDescription; this.closed = true; if (alertLevel == AL_fatal) { /* * This is a fatal message. */ this.failedWithError = true; } rs.writeMessage(RL_ALERT, error, 0, 2); rs.close(); if (alertLevel == AL_fatal) { throw new IOException(TLS_ERROR_MESSAGE); } } else { throw new IOException(TLS_ERROR_MESSAGE); } } /** * Closes this connection. * * @throws IOException If something goes wrong during closing. */ public void close() throws IOException { if (!closed) { this.failWithError((short)1, (short)0); } } /** * Make sure the InputStream is now empty. Fail otherwise. * * @param is The InputStream to check. * @throws IOException If is is not empty. */ protected void assertEmpty(ByteArrayInputStream is) throws IOException { if (is.available() > 0) { this.failWithError(AL_fatal, AP_decode_error); } } protected void flush() throws IOException { rs.flush(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -