KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > ui > tcp > CmpTcpCommandHandler


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13 /*
14  * This file is part of the QuickServer library
15  * Copyright (C) 2003-2005 QuickServer.org
16  *
17  * Use, modification, copying and distribution of this software is subject to
18  * the terms and conditions of the GNU Lesser General Public License.
19  * You should have received a copy of the GNU LGP License along with this
20  * library; if not, you can download a copy from <http://www.quickserver.org/>.
21  *
22  * For questions, suggestions, bug-reports, enhancement-requests etc.
23  * visit http://www.quickserver.org
24  *
25  */

26
27 package org.ejbca.ui.tcp;
28
29 import java.io.ByteArrayInputStream JavaDoc;
30 import java.io.ByteArrayOutputStream JavaDoc;
31 import java.io.DataInputStream JavaDoc;
32 import java.io.DataOutputStream JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.net.SocketTimeoutException JavaDoc;
35 import java.security.cert.CertificateEncodingException JavaDoc;
36
37 import org.apache.log4j.Logger;
38 import org.ejbca.core.model.InternalResources;
39 import org.ejbca.core.model.log.Admin;
40 import org.ejbca.core.protocol.IResponseMessage;
41 import org.ejbca.core.protocol.cmp.CmpMessageDispatcher;
42 import org.ejbca.util.Base64;
43 import org.quickserver.net.server.ClientBinaryHandler;
44 import org.quickserver.net.server.ClientEventHandler;
45 import org.quickserver.net.server.ClientHandler;
46 import org.quickserver.net.server.DataMode;
47 import org.quickserver.net.server.DataType;
48
49
50 public class CmpTcpCommandHandler implements ClientEventHandler, ClientBinaryHandler {
51     private static final Logger log = Logger.getLogger(CmpTcpCommandHandler.class.getName());
52     /** Internal localization of logs and errors */
53     private static final InternalResources intres = InternalResources.getInstance();
54     
55     public void gotConnected(ClientHandler handler)
56     throws SocketTimeoutException JavaDoc, IOException JavaDoc {
57         log.debug("CMP connection opened: "+handler.getHostAddress());
58         handler.setDataMode(DataMode.BINARY, DataType.IN);
59         handler.setDataMode(DataMode.BINARY, DataType.OUT);
60     }
61     
62     public void lostConnection(ClientHandler handler)
63     throws IOException JavaDoc {
64         log.debug("Connection lost: "+handler.getHostAddress());
65     }
66     public void closingConnection(ClientHandler handler)
67     throws IOException JavaDoc {
68         log.debug("Connection closed: "+handler.getHostAddress());
69     }
70     
71     
72     public void handleBinary(ClientHandler handler, byte command[])
73     throws SocketTimeoutException JavaDoc, IOException JavaDoc {
74         if ((command == null) || (command.length == 0)) {
75             handler.closeConnection(); // this is something fishy
76
return;
77         }
78         String JavaDoc iMsg = intres.getLocalizedMessage("cmp.receivedmsg", handler.getHostAddress());
79         log.info(iMsg);
80         if (log.isDebugEnabled()) {
81             log.debug("Got data of length "+command.length+": "+new String JavaDoc(Base64.encode(command)));
82         }
83
84         IResponseMessage resp = null;
85         boolean close = false;
86         if (command.length > 7) {
87             ByteArrayInputStream JavaDoc bai = new ByteArrayInputStream JavaDoc(command);
88             DataInputStream JavaDoc dis = new DataInputStream JavaDoc(bai);
89             // Read the length, 32 bits
90
int len = dis.readInt();
91             log.debug("Got a message claiming to be of length: " + len);
92             
93             // Read the version, 8 bits. Version should be 10 (protocol draft nr 5)
94
int ver = dis.readByte();
95             log.debug("Got a message with version: " + ver);
96             
97             // Read flags, 8 bits for version 10
98
byte flags = dis.readByte();
99             log.debug("Got a message with flags (1 means close): " + flags);
100             // Check if the client wants us to close the connection (LSB is 1 in that case according to spec)
101
if ((flags & 0xFE) == 1) {
102                 close = true;
103             }
104             
105             // Read message type, 8 bits
106
int msgType = dis.readByte();
107             log.debug("Got a message of type: " +msgType);
108             
109             // Read message
110
int msgLen = command.length - 4;
111             // They should match
112
if (len == msgLen) {
113                 if (msgLen < 5000) {
114                     byte[] msg = new byte[len];
115                     for (int i = 7; i < command.length; i++) {
116                         msg[i-7] = command[i];
117                     }
118                     // We got our message now, we can actually process it I think
119
if (log.isDebugEnabled()) {
120                         log.debug("Received a CMP message by TCP: "+new String JavaDoc(Base64.encode(msg)));
121                     }
122                     // We must use an administrator with rights to create users
123
Admin administrator = new Admin(Admin.TYPE_RA_USER, handler.getHostAddress());
124
125                     CmpMessageDispatcher dispatcher = new CmpMessageDispatcher(administrator, CmpTcpConfiguration.instance().getProperties());
126                     resp = dispatcher.dispatch(msg);
127                     if (resp == null) {
128                         // unknown error?
129
String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errornullresp");
130                         log.error(errMsg);
131                     } else {
132                         log.debug("Sending back CMP response to client.");
133                     }
134
135                 } else {
136                     String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errortcptoolongmsg", new Integer JavaDoc(msgLen));
137                     log.error(errMsg);
138                     handler.closeConnection(); // This is something malicious
139
}
140             } else {
141                 String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errortcpwronglen", new Integer JavaDoc(msgLen), new Integer JavaDoc(len));
142                 log.error(errMsg);
143                 handler.closeConnection(); // This is something malicious
144
}
145         }
146         // Send back reply
147
byte[] sendBack = null;
148         if (resp != null) {
149             sendBack = createReturnTcpMessage(resp, close);
150         } else {
151             log.debug("Not sending back anything.");
152         }
153         if (sendBack != null) {
154             log.debug("Sending "+sendBack.length+" bytes to client");
155             handler.sendClientBinary(sendBack);
156             iMsg = intres.getLocalizedMessage("cmp.sentresponsemsg", handler.getHostAddress());
157             log.info(iMsg);
158         } else {
159             close = true;
160         }
161         if (close) {
162             handler.closeConnection(); // It's time to say good bye
163
}
164     }
165     
166     private static byte[] createReturnTcpMessage(IResponseMessage resp, boolean close) throws IOException JavaDoc {
167         ByteArrayOutputStream JavaDoc bao = new ByteArrayOutputStream JavaDoc();
168         byte[] msg;
169         try {
170             msg = resp.getResponseMessage();
171         } catch (CertificateEncodingException JavaDoc e) {
172             msg = null;
173         }
174         boolean doClose = close;
175         // 5 is pkiRep, 6 is errorMsgRep, 3 is finRep
176
// errorMsgRep should only be used for TCP protocol errors, see 3.5.6 in cmp-transport-protocols
177
int msgType = 5;
178         //if (resp.getStatus() != ResponseStatus.SUCCESS) {
179
// msgType = 6;
180
//}
181
if ( (msg == null) || (msg.length == 0) ) {
182             msg = new byte[1];
183             msg[0] = 0;
184             msgType = 3;
185             doClose = true;
186         }
187         int len = msg.length;
188         DataOutputStream JavaDoc dos = new DataOutputStream JavaDoc(bao);
189         // return msg length = msg.length + 3; 1 byte version, 1 byte flags and 1 byte message type
190
dos.writeInt(len+3);
191         dos.writeByte(10);
192         int flags = (doClose == true ? 1 : 0); // 1 if we should close, 0 otherwise
193
dos.writeByte(flags);
194         dos.writeByte(msgType);
195         dos.write(msg);
196         dos.flush();
197         if (log.isDebugEnabled()) {
198             log.debug("Wrote length: "+len+3);
199             log.debug("Wrote version: 10");
200             log.debug("Wrote flags: "+flags);
201             log.debug("Wrote msgType: "+msgType);
202             log.debug("Wrote msg with length: "+msg.length);
203         }
204         return bao.toByteArray();
205     }
206         
207 }
Popular Tags