1 11 package org.jivesoftware.messenger.component; 12 13 import org.dom4j.Element; 14 import org.dom4j.io.XPPPacketReader; 15 import org.jivesoftware.messenger.*; 16 import org.jivesoftware.messenger.auth.AuthFactory; 17 import org.jivesoftware.messenger.auth.UnauthorizedException; 18 import org.jivesoftware.util.LocaleUtils; 19 import org.jivesoftware.util.Log; 20 import org.xmlpull.v1.XmlPullParser; 21 import org.xmlpull.v1.XmlPullParserException; 22 import org.xmpp.component.Component; 23 import org.xmpp.component.ComponentManager; 24 import org.xmpp.packet.JID; 25 import org.xmpp.packet.Packet; 26 import org.xmpp.packet.StreamError; 27 28 import java.io.IOException ; 29 import java.io.Writer ; 30 31 36 public class ComponentSession extends Session { 37 38 private ExternalComponent component = new ExternalComponent(); 39 40 52 public static Session createSession(String serverName, XPPPacketReader reader, 53 Connection connection) throws UnauthorizedException, IOException , 54 XmlPullParserException 55 { 56 XmlPullParser xpp = reader.getXPPParser(); 57 Session session; 58 String domain = xpp.getAttributeValue("", "to"); 59 60 Log.debug("[ExComp] Starting registration of new external component for domain: " + domain); 61 62 String subdomain = domain; 64 int index = domain.indexOf(serverName); 65 if (index > -1) { 66 subdomain = domain.substring(0, index -1); 67 } 68 69 Writer writer = connection.getWriter(); 70 StringBuilder sb = new StringBuilder (); 72 sb.append("<?xml version='1.0' encoding='"); 73 sb.append(CHARSET); 74 sb.append("'?>"); 75 sb.append("<stream:stream "); 76 sb.append("xmlns:stream=\"http://etherx.jabber.org/streams\" "); 77 sb.append("xmlns=\"jabber:component:accept\" from=\""); 78 sb.append(domain); 79 sb.append("\">"); 80 81 if (domain == null) { 83 Log.debug("[ExComp] Domain not specified in stanza: " + xpp.getText()); 84 StreamError error = new StreamError(StreamError.Condition.bad_format); 86 sb.append(error.toXML()); 87 writer.write(sb.toString()); 88 writer.flush(); 89 connection.close(); 91 return null; 92 } 93 if (!ExternalComponentManager.canAccess(subdomain)) { 95 Log.debug("[ExComp] Component is not allowed to connect with subdomain: " + subdomain); 96 StreamError error = new StreamError(StreamError.Condition.host_unknown); 97 sb.append(error.toXML()); 98 writer.write(sb.toString()); 99 writer.flush(); 100 connection.close(); 102 return null; 103 } 104 String secretKey = ExternalComponentManager.getSecretForComponent(subdomain); 106 if (secretKey == null) { 107 Log.debug("[ExComp] A shared secret for the component was not found."); 108 StreamError error = new StreamError(StreamError.Condition.internal_server_error); 110 sb.append(error.toXML()); 111 writer.write(sb.toString()); 112 writer.flush(); 113 connection.close(); 115 return null; 116 } 117 if (InternalComponentManager.getInstance().getComponent(subdomain) != null) { 119 Log.debug("[ExComp] Another component is already using domain: " + domain); 120 StreamError error = new StreamError(StreamError.Condition.conflict); 123 sb.append(error.toXML()); 124 writer.write(sb.toString()); 125 writer.flush(); 126 connection.close(); 128 return null; 129 } 130 131 session = SessionManager.getInstance().createComponentSession(connection); 133 session.setAddress(new JID(null, domain , null)); 135 136 try { 137 Log.debug("[ExComp] Send stream header with ID: " + session.getStreamID() + 138 " for component with domain: " + 139 domain); 140 sb = new StringBuilder (); 142 sb.append("<?xml version='1.0' encoding='"); 143 sb.append(CHARSET); 144 sb.append("'?>"); 145 sb.append("<stream:stream "); 146 sb.append("xmlns:stream=\"http://etherx.jabber.org/streams\" "); 147 sb.append("xmlns=\"jabber:component:accept\" from=\""); 148 sb.append(domain); 149 sb.append("\" id=\""); 150 sb.append(session.getStreamID().toString()); 151 sb.append("\">"); 152 writer.write(sb.toString()); 153 writer.flush(); 154 155 Element doc = reader.parseDocument().getRootElement(); 157 String digest = "handshake".equals(doc.getName()) ? doc.getStringValue() : ""; 158 String anticipatedDigest = AuthFactory.createDigest(session.getStreamID().getID(), 159 secretKey); 160 if (!anticipatedDigest.equalsIgnoreCase(digest)) { 162 Log.debug("[ExComp] Incorrect handshake for component with domain: " + domain); 163 sb = new StringBuilder (); 166 StreamError error = new StreamError(StreamError.Condition.not_authorized); 168 sb.append(error.toXML()); 169 writer.write(sb.toString()); 170 writer.flush(); 171 connection.close(); 173 return null; 174 } 175 else { 176 session.setStatus(Session.STATUS_AUTHENTICATED); 178 writer.write("<handshake></handshake>"); 180 writer.flush(); 181 ExternalComponent component = ((ComponentSession) session).getExternalComponent(); 183 component.setSubdomain(subdomain); 184 InternalComponentManager.getInstance().addComponent(subdomain, component); 185 Log.debug("[ExComp] External component was registered SUCCESSFULLY with domain: " + 186 domain); 187 return session; 188 } 189 } 190 catch (Exception e) { 191 Log.error("An error occured while creating a ComponentSession", e); 192 connection.close(); 194 return null; 195 } 196 } 197 198 public ComponentSession(String serverName, Connection conn, StreamID id) { 199 super(serverName, conn, id); 200 } 201 202 public void process(Packet packet) throws PacketException { 203 component.processPacket(packet); 206 } 207 208 public ExternalComponent getExternalComponent() { 209 return component; 210 } 211 212 222 public class ExternalComponent implements Component { 223 224 private String name; 225 private String type; 226 private String category; 227 private String subdomain; 228 229 public void processPacket(Packet packet) { 230 if (conn != null && !conn.isClosed()) { 231 try { 232 conn.deliver(packet); 233 } 234 catch (Exception e) { 235 Log.error(LocaleUtils.getLocalizedString("admin.error"), e); 236 conn.close(); 237 } 238 } 239 } 240 241 public String getName() { 242 return name; 243 } 244 245 public String getDescription() { 246 return category + " - " + type; 247 } 248 249 public void setName(String name) { 250 this.name = name; 251 } 252 253 public String getType() { 254 return type; 255 } 256 257 public void setType(String type) { 258 this.type = type; 259 } 260 261 public String getCategory() { 262 return category; 263 } 264 265 public void setCategory(String category) { 266 this.category = category; 267 } 268 269 public String getSubdomain() { 270 return subdomain; 271 } 272 273 public void setSubdomain(String subdomain) { 274 this.subdomain = subdomain; 275 } 276 277 public void initialize(JID jid, ComponentManager componentManager) { 278 } 279 280 public void start() { 281 } 282 283 public void shutdown() { 284 } 285 } 286 } | Popular Tags |