Merge "Issue #2756 implemented HTTP public key auth scheme" into development
Former-commit-id: 21d22f790f71941797a23926be5ed77c6d72353b
This commit is contained in:
commit
869909cc66
50 changed files with 3216 additions and 274 deletions
|
@ -19,7 +19,9 @@ Require-Bundle: org.eclipse.core.runtime,
|
|||
com.raytheon.uf.common.localization,
|
||||
com.raytheon.uf.viz.core,
|
||||
com.raytheon.uf.common.time,
|
||||
com.raytheon.uf.common.util
|
||||
com.raytheon.uf.common.util,
|
||||
com.raytheon.uf.common.xmpp,
|
||||
com.raytheon.uf.common.http
|
||||
Export-Package: com.raytheon.uf.viz.collaboration.comm,
|
||||
com.raytheon.uf.viz.collaboration.comm.compression,
|
||||
com.raytheon.uf.viz.collaboration.comm.identity,
|
||||
|
@ -28,6 +30,7 @@ Export-Package: com.raytheon.uf.viz.collaboration.comm,
|
|||
com.raytheon.uf.viz.collaboration.comm.identity.invite,
|
||||
com.raytheon.uf.viz.collaboration.comm.identity.roster,
|
||||
com.raytheon.uf.viz.collaboration.comm.identity.user,
|
||||
com.raytheon.uf.viz.collaboration.comm.packet,
|
||||
com.raytheon.uf.viz.collaboration.comm.provider,
|
||||
com.raytheon.uf.viz.collaboration.comm.provider.event,
|
||||
com.raytheon.uf.viz.collaboration.comm.provider.info,
|
||||
|
|
|
@ -17,15 +17,22 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.viz.collaboration.comm.provider;
|
||||
package com.raytheon.uf.viz.collaboration.comm.packet;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jivesoftware.smack.packet.PacketExtension;
|
||||
import org.jivesoftware.smack.util.Base64;
|
||||
|
||||
import com.raytheon.uf.common.serialization.SerializationUtil;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.xmpp.PacketConstants;
|
||||
import com.raytheon.uf.common.xmpp.XmlBuilder;
|
||||
import com.raytheon.uf.common.xmpp.XmlBuilder.Pair;
|
||||
import com.raytheon.uf.common.xmpp.ext.BaseExtension;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.CollaborationXmlManager;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SerializationMode;
|
||||
|
||||
/**
|
||||
* XMPP packet extension for collaboration session data
|
||||
|
@ -37,13 +44,14 @@ import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 11, 2013 2562 bclement Initial creation
|
||||
* Feb 27, 2013 2756 bclement extends BaseExtension
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class SessionPayload implements PacketExtension {
|
||||
public class SessionPayload extends BaseExtension {
|
||||
|
||||
private static final IUFStatusHandler log = UFStatus
|
||||
.getHandler(SessionPayload.class);
|
||||
|
@ -52,8 +60,6 @@ public class SessionPayload implements PacketExtension {
|
|||
Config, Command, Invitation;
|
||||
};
|
||||
|
||||
public static final String XMLNS = "urn:uf:viz:collaboration";
|
||||
|
||||
public static final String ELEMENT_NAME = "SessionData";
|
||||
|
||||
public static final String TYPE_ATTRIBUTE = "payloadtype";
|
||||
|
@ -75,6 +81,7 @@ public class SessionPayload implements PacketExtension {
|
|||
* message object
|
||||
*/
|
||||
public SessionPayload(PayloadType type, SerializationMode mode, Object data) {
|
||||
super(ELEMENT_NAME, PacketConstants.COLLAB_XMLNS);
|
||||
this.payloadType = type;
|
||||
this.mode = mode;
|
||||
this.data = data;
|
||||
|
@ -106,18 +113,16 @@ public class SessionPayload implements PacketExtension {
|
|||
*/
|
||||
public static String createXml(PayloadType type, SerializationMode mode,
|
||||
Object data) throws CollaborationException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder = new StringBuilder();
|
||||
builder.append("<").append(ELEMENT_NAME).append(" ");
|
||||
appendAttribute(builder, "xmlns", XMLNS);
|
||||
appendAttribute(builder, TYPE_ATTRIBUTE, type.name());
|
||||
appendAttribute(builder, ENCODING_ATTRIBUTE, mode.name());
|
||||
builder.append(">");
|
||||
XmlBuilder builder = new XmlBuilder();
|
||||
Pair typeAttr = new Pair(TYPE_ATTRIBUTE, type.name());
|
||||
Pair encAttr = new Pair(ENCODING_ATTRIBUTE, mode.name());
|
||||
builder.startTag(ELEMENT_NAME, PacketConstants.COLLAB_XMLNS,
|
||||
Arrays.asList(typeAttr, encAttr));
|
||||
switch (mode) {
|
||||
case THRIFT:
|
||||
try {
|
||||
byte[] arr = SerializationUtil.transformToThrift(data);
|
||||
builder.append(Base64.encodeBytes(arr));
|
||||
builder.appendText(Base64.encodeBytes(arr));
|
||||
} catch (Exception e) {
|
||||
throw new CollaborationException(
|
||||
"[THRIFT] Could not serialize object", e);
|
||||
|
@ -128,14 +133,14 @@ public class SessionPayload implements PacketExtension {
|
|||
CollaborationXmlManager jaxb = CollaborationXmlManager
|
||||
.getInstance();
|
||||
String xml = jaxb.marshalToFragment(data);
|
||||
builder.append(xml);
|
||||
builder.appendText(xml);
|
||||
} catch (Exception je) {
|
||||
throw new CollaborationException(
|
||||
"[JAXB] Could not serialize object", je);
|
||||
}
|
||||
break;
|
||||
case STRING:
|
||||
builder.append(data.toString());
|
||||
builder.appendText(data.toString());
|
||||
break;
|
||||
case NONE:
|
||||
throw new CollaborationException("Serialization of "
|
||||
|
@ -143,23 +148,10 @@ public class SessionPayload implements PacketExtension {
|
|||
case ISNULL:
|
||||
break;
|
||||
}
|
||||
builder.append("</").append(ELEMENT_NAME).append(">");
|
||||
builder.endTag(ELEMENT_NAME);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format XML attribute name/value pair and append to string builder
|
||||
*
|
||||
* @param sb
|
||||
* @param name
|
||||
* @param value
|
||||
*/
|
||||
private static void appendAttribute(StringBuilder sb, String name,
|
||||
String value) {
|
||||
sb.append(name).append("='").append(value).append("' ");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the payloadType
|
||||
*/
|
||||
|
@ -181,26 +173,6 @@ public class SessionPayload implements PacketExtension {
|
|||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.jivesoftware.smack.packet.PacketExtension#getElementName()
|
||||
*/
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT_NAME;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.jivesoftware.smack.packet.PacketExtension#getNamespace()
|
||||
*/
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return XMLNS;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -219,5 +191,4 @@ public class SessionPayload implements PacketExtension {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.viz.collaboration.comm.provider;
|
||||
package com.raytheon.uf.viz.collaboration.comm.packet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -34,8 +34,11 @@ import com.raytheon.uf.common.serialization.SerializationException;
|
|||
import com.raytheon.uf.common.serialization.SerializationUtil;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.xmpp.BaseProvider;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.CollaborationXmlManager;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SerializationMode;
|
||||
|
||||
/**
|
||||
* XMPP packet extension parsing provider for collaboration session data
|
||||
|
@ -48,6 +51,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload.PayloadTyp
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 16, 2013 2562 bclement Initial creation
|
||||
* Feb 12, 2014 2793 bclement improved error handling
|
||||
* Feb 27, 2013 2756 bclement extends BaseProvider
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -55,98 +59,86 @@ import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload.PayloadTyp
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class SessionPayloadProvider implements PacketExtensionProvider {
|
||||
public class SessionPayloadProvider extends BaseProvider<SessionPayload>
|
||||
implements PacketExtensionProvider {
|
||||
|
||||
private static final IUFStatusHandler log = UFStatus
|
||||
.getHandler(SessionPayloadProvider.class);
|
||||
|
||||
public SessionPayloadProvider() {
|
||||
super(SessionPayload.ELEMENT_NAME);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jivesoftware.smack.provider.PacketExtensionProvider#parseExtension(org.xmlpull.v1.XmlPullParser)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.jivesoftware.smack.provider.PacketExtensionProvider#parseExtension
|
||||
* (org.xmlpull.v1.XmlPullParser)
|
||||
*/
|
||||
@Override
|
||||
public PacketExtension parseExtension(XmlPullParser parser)
|
||||
throws Exception {
|
||||
return parse(parser);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.xmpp.BaseProvider#parseInternal(org.xmlpull.v1
|
||||
* .XmlPullParser)
|
||||
*/
|
||||
@Override
|
||||
protected SessionPayload parseInternal(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
try {
|
||||
return parseInternal(parser);
|
||||
String typeString = parser.getAttributeValue(null,
|
||||
SessionPayload.TYPE_ATTRIBUTE);
|
||||
String modeString = parser.getAttributeValue(null,
|
||||
SessionPayload.ENCODING_ATTRIBUTE);
|
||||
checkAttribute(SessionPayload.TYPE_ATTRIBUTE, typeString);
|
||||
checkAttribute(SessionPayload.ENCODING_ATTRIBUTE, modeString);
|
||||
|
||||
SerializationMode mode;
|
||||
try {
|
||||
mode = SerializationMode.valueOf(modeString);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new CollaborationException(
|
||||
"Unsupported payload encoding: " + modeString, e);
|
||||
}
|
||||
PayloadType t;
|
||||
try {
|
||||
t = PayloadType.valueOf(typeString);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new CollaborationException(
|
||||
"Unsupported IQ payload type: " + typeString, e);
|
||||
}
|
||||
Object data;
|
||||
switch (mode) {
|
||||
case THRIFT:
|
||||
String text = getText(parser);
|
||||
data = unmarshalThrift(text);
|
||||
break;
|
||||
case JAXB:
|
||||
data = unmarshalJaxb(parser);
|
||||
break;
|
||||
case STRING:
|
||||
data = getText(parser);
|
||||
break;
|
||||
default:
|
||||
throw new CollaborationException("Could not deserialize object");
|
||||
}
|
||||
return new SessionPayload(t, mode, data);
|
||||
} catch (CollaborationException e) {
|
||||
// collaboration exceptions are only thrown for problems with our own format
|
||||
// collaboration exceptions are only thrown for problems with our
|
||||
// own format
|
||||
log.error("Unable to parse collaboration packet", e);
|
||||
return new SessionPayload(PayloadType.Command,
|
||||
SerializationMode.ISNULL, null);
|
||||
} finally {
|
||||
// ensure that we are at the end of the packet so we don't corrupt
|
||||
// stream
|
||||
while (!atEndOfPacket(parser)) {
|
||||
parser.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parser
|
||||
* @return true if parser is at the end tag of the payload packet
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
private static boolean atEndOfPacket(XmlPullParser parser)
|
||||
throws XmlPullParserException {
|
||||
return parser.getEventType() == XmlPullParser.END_TAG
|
||||
&& parser.getName().equals(SessionPayload.ELEMENT_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse contents of packet extension from XMPP stream.
|
||||
*
|
||||
* @param parser
|
||||
* @return
|
||||
* @throws CollaborationException
|
||||
* when error occurs with collaboration format
|
||||
* @throws XmlPullParserException
|
||||
* when error occurs with XMPP stream
|
||||
* @throws IOException
|
||||
* when error occurs with XMPP stream
|
||||
*/
|
||||
private static PacketExtension parseInternal(XmlPullParser parser)
|
||||
throws CollaborationException, XmlPullParserException, IOException {
|
||||
String typeString = parser.getAttributeValue(null,
|
||||
SessionPayload.TYPE_ATTRIBUTE);
|
||||
String modeString = parser.getAttributeValue(null,
|
||||
SessionPayload.ENCODING_ATTRIBUTE);
|
||||
checkAttribute(SessionPayload.TYPE_ATTRIBUTE, typeString);
|
||||
checkAttribute(SessionPayload.ENCODING_ATTRIBUTE, modeString);
|
||||
|
||||
SerializationMode mode;
|
||||
try {
|
||||
mode = SerializationMode.valueOf(modeString);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new CollaborationException("Unsupported payload encoding: "
|
||||
+ modeString, e);
|
||||
}
|
||||
PayloadType t;
|
||||
try {
|
||||
t = PayloadType.valueOf(typeString);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new CollaborationException("Unsupported IQ payload type: "
|
||||
+ typeString, e);
|
||||
}
|
||||
Object data;
|
||||
switch (mode) {
|
||||
case THRIFT:
|
||||
String text = getText(parser);
|
||||
data = unmarshalThrift(text);
|
||||
break;
|
||||
case JAXB:
|
||||
data = unmarshalJaxb(parser);
|
||||
break;
|
||||
case STRING:
|
||||
data = getText(parser);
|
||||
break;
|
||||
default:
|
||||
throw new CollaborationException("Could not deserialize object");
|
||||
}
|
||||
return new SessionPayload(t, mode, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshal base64 encoded thrift data
|
||||
*
|
||||
|
@ -185,31 +177,6 @@ public class SessionPayloadProvider implements PacketExtensionProvider {
|
|||
return manager.unmarshalFromXPP(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any text elements under current tag
|
||||
*
|
||||
* @param parser
|
||||
* @return
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private static String getText(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
boolean done = false;
|
||||
StringBuilder payloadText = new StringBuilder();
|
||||
while (!done) {
|
||||
if (atEndOfPacket(parser)) {
|
||||
done = true;
|
||||
continue;
|
||||
} else if (parser.getEventType() == XmlPullParser.TEXT) {
|
||||
payloadText.append(parser.getText());
|
||||
}
|
||||
parser.next();
|
||||
}
|
||||
return payloadText.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that value is not null or empty
|
||||
*
|
|
@ -43,6 +43,7 @@ import com.raytheon.uf.common.serialization.jaxb.JaxbDummyObject;
|
|||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.xmpp.PullParserJaxbAdapter;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
import com.raytheon.uf.viz.core.procedures.ProcedureXmlManager;
|
||||
import com.raytheon.uf.viz.core.reflect.SubClassLocator;
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.viz.collaboration.comm.provider.session;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SignatureException;
|
||||
|
||||
import org.apache.http.message.AbstractHttpMessage;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.util.SyncPacketSend;
|
||||
|
||||
import com.raytheon.uf.common.http.auth.ClientSignatureAuth;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.xmpp.BaseProvider;
|
||||
import com.raytheon.uf.common.xmpp.iq.AuthInfo;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
|
||||
/**
|
||||
* Manages collaboration client's authentication credentials for HTTP data
|
||||
* server which are stored on the XMPP server
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 24, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ClientAuthManager {
|
||||
|
||||
private static final IUFStatusHandler log = UFStatus
|
||||
.getHandler(ClientAuthManager.class);
|
||||
|
||||
private final XMPPConnection conn;
|
||||
|
||||
public static enum State {
|
||||
PENDING, ENABLED, DISABLED, ERROR
|
||||
}
|
||||
|
||||
private State state = State.PENDING;
|
||||
|
||||
private final Object stateMonitor = new Object();
|
||||
|
||||
private ClientSignatureAuth sigAuth;
|
||||
|
||||
/**
|
||||
* @param conn
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
public ClientAuthManager(XMPPConnection conn) throws CollaborationException {
|
||||
this.conn = conn;
|
||||
if (isEnabledOnServer(conn)) {
|
||||
createAndRegisterAuth();
|
||||
} else {
|
||||
this.sigAuth = null;
|
||||
this.state = State.DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param conn
|
||||
* @return true if server supports collaboration auth feature
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
public static boolean isEnabledOnServer(XMPPConnection conn)
|
||||
throws CollaborationException {
|
||||
try {
|
||||
return BaseProvider.serverSupportsFeature(conn,
|
||||
AuthInfo.AUTH_QUERY_XMLNS);
|
||||
} catch (XMPPException e) {
|
||||
throw new CollaborationException(
|
||||
"Unable to query server for supported features", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new key pair and register key with server
|
||||
*
|
||||
* @return
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
private void createAndRegisterAuth() {
|
||||
Job job = new Job("Creating and registering collaboration credentials") {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
State authState = State.ERROR;
|
||||
try {
|
||||
ClientSignatureAuth auth = new ClientSignatureAuth();
|
||||
String encodedKey = auth.getEncodedPublicKey();
|
||||
AuthInfo packet = AuthInfo.createSetPacket(encodedKey,
|
||||
auth.getKeyAlgorithm());
|
||||
SyncPacketSend.getReply(conn, packet);
|
||||
ClientAuthManager.this.sigAuth = auth;
|
||||
authState = State.ENABLED;
|
||||
} catch (GeneralSecurityException e) {
|
||||
log.error("Problem creating public key auth", e);
|
||||
} catch (XMPPException e) {
|
||||
log.error("Problem registering public key", e);
|
||||
} finally {
|
||||
synchronized (stateMonitor) {
|
||||
ClientAuthManager.this.state = authState;
|
||||
stateMonitor.notifyAll();
|
||||
}
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
job.setPriority(Job.SHORT);
|
||||
job.setSystem(true);
|
||||
job.schedule();
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: this method will block if auth registration has not yet completed
|
||||
*
|
||||
* @return the sigAuth, null if {@link ClientAuthManager#getState()} is
|
||||
* {@link State#DISABLED}
|
||||
*/
|
||||
public ClientSignatureAuth getSigAuth() {
|
||||
if (state.equals(State.PENDING)) {
|
||||
waitForInit();
|
||||
}
|
||||
return sigAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an Auth header to the message using the credential and a signature
|
||||
* generated from the URI.
|
||||
*
|
||||
* @param msg
|
||||
* @param credential
|
||||
* @param uri
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
public void signRequest(AbstractHttpMessage msg, String credential, URI uri)
|
||||
throws CollaborationException {
|
||||
signRequest(msg, credential, uri, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an Auth header to the message using the credential and a signature
|
||||
* generated from the URI and body.
|
||||
*
|
||||
* @param msg
|
||||
* @param credential
|
||||
* @param uri
|
||||
* @param body
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
public void signRequest(AbstractHttpMessage msg, String credential,
|
||||
URI uri, byte[] body) throws CollaborationException {
|
||||
ClientSignatureAuth sigAuth = getSigAuth();
|
||||
if (state.equals(State.ENABLED)) {
|
||||
String sig;
|
||||
try {
|
||||
if (body != null) {
|
||||
sig = sigAuth.sign(uri, body);
|
||||
} else {
|
||||
sig = sigAuth.sign(uri);
|
||||
}
|
||||
} catch (SignatureException e) {
|
||||
throw new CollaborationException(
|
||||
"Problem signing HTTP message", e);
|
||||
}
|
||||
String headerValue = ClientSignatureAuth.formatAuthHeader(
|
||||
credential, sig);
|
||||
msg.addHeader(ClientSignatureAuth.HTTP_AUTH_HEADER, headerValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* waits thread until state is no longer pending auth registration
|
||||
*/
|
||||
private void waitForInit() {
|
||||
synchronized (stateMonitor) {
|
||||
if (state.equals(State.PENDING)) {
|
||||
try {
|
||||
stateMonitor.wait();
|
||||
} catch (InterruptedException e) {
|
||||
log.error("Interrupted waiting for auth", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the state of the auth registration
|
||||
*/
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
|
@ -48,6 +48,9 @@ import com.google.common.eventbus.EventBus;
|
|||
import com.google.common.net.HostAndPort;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.xmpp.PacketConstants;
|
||||
import com.raytheon.uf.common.xmpp.iq.AuthInfo;
|
||||
import com.raytheon.uf.common.xmpp.iq.AuthInfoProvider;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.IAccountManager;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.ISession;
|
||||
|
@ -59,9 +62,9 @@ import com.raytheon.uf.viz.collaboration.comm.identity.event.IVenueInvitationEve
|
|||
import com.raytheon.uf.viz.collaboration.comm.identity.event.RosterChangeType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.invite.SharedDisplayVenueInvite;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.invite.VenueInvite;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayloadProvider;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayloadProvider;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.Tools;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.event.RosterChangeEvent;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.event.ServerDisconnectEvent;
|
||||
|
@ -114,6 +117,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
|||
* Feb 13, 2014 2751 bclement better types for venueid and invitor
|
||||
* Feb 18, 2014 2793 bclement improved disconnection notification and handling
|
||||
* Feb 24, 2014 2632 mpduff Fix roster change type for presence change.
|
||||
* Feb 28, 2014 2756 bclement added authManager
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -125,9 +129,11 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
|||
public class CollaborationConnection implements IEventPublisher {
|
||||
|
||||
static {
|
||||
ProviderManager.getInstance().addExtensionProvider(
|
||||
SessionPayload.ELEMENT_NAME, SessionPayload.XMLNS,
|
||||
new SessionPayloadProvider());
|
||||
ProviderManager pm = ProviderManager.getInstance();
|
||||
pm.addExtensionProvider(SessionPayload.ELEMENT_NAME,
|
||||
PacketConstants.COLLAB_XMLNS, new SessionPayloadProvider());
|
||||
pm.addIQProvider(PacketConstants.QUERY_ELEMENT_NAME,
|
||||
AuthInfo.AUTH_QUERY_XMLNS, new AuthInfoProvider());
|
||||
}
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
|
@ -155,6 +161,8 @@ public class CollaborationConnection implements IEventPublisher {
|
|||
|
||||
private XMPPConnection connection;
|
||||
|
||||
private final ClientAuthManager authManager;
|
||||
|
||||
public static boolean COMPRESS = true;
|
||||
|
||||
static {
|
||||
|
@ -209,6 +217,8 @@ public class CollaborationConnection implements IEventPublisher {
|
|||
setupP2PComm();
|
||||
getPeerToPeerSession();
|
||||
|
||||
authManager = new ClientAuthManager(connection);
|
||||
|
||||
userPresence = initialPresence;
|
||||
if (accountManager != null && initialPresence != null) {
|
||||
accountManager.sendPresence(initialPresence);
|
||||
|
@ -632,7 +642,7 @@ public class CollaborationConnection implements IEventPublisher {
|
|||
|
||||
if (message != null) {
|
||||
SessionPayload payload = (SessionPayload) message
|
||||
.getExtension(SessionPayload.XMLNS);
|
||||
.getExtension(PacketConstants.COLLAB_XMLNS);
|
||||
if (payload != null) {
|
||||
handleCollabInvite(venueId, invitor,
|
||||
payload);
|
||||
|
@ -770,4 +780,11 @@ public class CollaborationConnection implements IEventPublisher {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the authManager
|
||||
*/
|
||||
public ClientAuthManager getAuthManager() {
|
||||
return authManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.jivesoftware.smack.packet.Packet;
|
|||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.xmpp.PacketConstants;
|
||||
import com.raytheon.uf.viz.collaboration.comm.Activator;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.ISession;
|
||||
|
@ -36,7 +37,7 @@ import com.raytheon.uf.viz.collaboration.comm.identity.event.IHttpXmppMessage;
|
|||
import com.raytheon.uf.viz.collaboration.comm.identity.event.IHttpdCollaborationConfigurationEvent;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.event.ITextMessageEvent;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.user.IUser;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.TextMessage;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.Tools;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.event.ChatMessageEvent;
|
||||
|
@ -61,6 +62,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
|
|||
* Feb 13, 2014 2751 bclement changed IQualifiedID objects to IUser
|
||||
* Feb 17, 2014 2756 bclement null check for message from field
|
||||
* moved url validation from regex to java utility
|
||||
* Feb 24, 2014 2756 bclement moved xmpp objects to new packages
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -134,7 +136,7 @@ public class PeerToPeerCommHelper implements PacketListener {
|
|||
}
|
||||
} else {
|
||||
SessionPayload payload = (SessionPayload) msg
|
||||
.getExtension(SessionPayload.XMLNS);
|
||||
.getExtension(PacketConstants.COLLAB_XMLNS);
|
||||
if (payload != null) {
|
||||
switch (payload.getPayloadType()) {
|
||||
case Command:
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
|||
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||
import org.jivesoftware.smackx.pubsub.packet.SyncPacketSend;
|
||||
|
||||
import com.raytheon.uf.common.xmpp.ext.ChangeAffiliationExtension;
|
||||
|
||||
/**
|
||||
* PubSub operations not implemented by the Smack PubSub manager. This includes
|
||||
* operations to modify ownership of a topic node.
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
**/
|
||||
package com.raytheon.uf.viz.collaboration.comm.provider.session;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
|
@ -49,14 +51,17 @@ import org.jivesoftware.smackx.pubsub.listener.ItemEventListener;
|
|||
import org.jivesoftware.smackx.pubsub.packet.SyncPacketSend;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.raytheon.uf.common.comm.HttpClient;
|
||||
import com.raytheon.uf.common.comm.HttpClient.HttpClientResponse;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.xmpp.ext.ChangeAffiliationExtension;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.ISession;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.ISharedDisplaySession;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.user.SharedDisplayRole;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.Tools;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.event.LeaderChangeEvent;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
|
||||
|
@ -82,6 +87,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
|||
* Feb 18, 2014 2751 bclement implemented room and pubsub ownership transfer
|
||||
* Feb 19, 2014 2751 bclement added isClosed()
|
||||
* Feb 24, 2014 2751 bclement added validation for change leader event
|
||||
* Feb 28, 2014 2756 bclement added cleanUpHttpStorage()
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -156,6 +162,7 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
// before cleanup?
|
||||
log.info("Deleting old topic: " + aff.getNodeId());
|
||||
try {
|
||||
cleanUpHttpStorage(aff.getNodeId());
|
||||
pubsubMgr.deleteNode(aff.getNodeId());
|
||||
} catch (XMPPException e) {
|
||||
log.error(
|
||||
|
@ -481,6 +488,7 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
topic.removeItemDeleteListener(this);
|
||||
topic.removeItemEventListener(this);
|
||||
if (hasRole(SharedDisplayRole.SESSION_LEADER)) {
|
||||
cleanUpHttpStorage(topic.getId());
|
||||
pubsubMgr.deleteNode(topic.getId());
|
||||
}
|
||||
topic = null;
|
||||
|
@ -494,6 +502,38 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete session directory on HTTP server. This should only be called if
|
||||
* this client is the owner of the topic associated with the session and
|
||||
* only after the session is closed.
|
||||
*
|
||||
* TODO this will not be needed if the xmpp server takes care of shared
|
||||
* display session lifecycle (create, transfer ownership, destroy, etc)
|
||||
*
|
||||
* @param sessionid
|
||||
*/
|
||||
private void cleanUpHttpStorage(String sessionid) {
|
||||
try {
|
||||
String userid = getAccount().getNormalizedId();
|
||||
String url = PeerToPeerCommHelper.getCollaborationHttpServer();
|
||||
url += sessionid + "/";
|
||||
URI uri = new URI(url);
|
||||
HttpDelete delete = new HttpDelete(uri);
|
||||
ClientAuthManager authManager = getConnection().getAuthManager();
|
||||
authManager.signRequest(delete, userid, uri);
|
||||
HttpClientResponse response = HttpClient.getInstance()
|
||||
.executeRequest(delete);
|
||||
if (!response.isSuccess() && !response.isNotExists()) {
|
||||
throw new CollaborationException("Session deletion failed for "
|
||||
+ uri + ": " + new String(response.data));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(
|
||||
"Problem cleaning up old HTTP storage objects for session: "
|
||||
+ sessionid, e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
|
|
@ -52,8 +52,8 @@ import com.raytheon.uf.viz.collaboration.comm.identity.event.ParticipantEventTyp
|
|||
import com.raytheon.uf.viz.collaboration.comm.identity.info.IVenue;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.invite.VenueInvite;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.user.IUser;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload;
|
||||
import com.raytheon.uf.viz.collaboration.comm.packet.SessionPayload.PayloadType;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.TextMessage;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.Tools;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.event.UserNicknameChangedEvent;
|
||||
|
|
|
@ -20,7 +20,8 @@ Require-Bundle: org.eclipse.core.runtime,
|
|||
com.raytheon.uf.common.time,
|
||||
com.raytheon.uf.common.geospatial,
|
||||
com.raytheon.uf.common.util,
|
||||
com.raytheon.viz.core
|
||||
com.raytheon.viz.core,
|
||||
com.raytheon.uf.common.http
|
||||
Export-Package: com.raytheon.uf.viz.collaboration.display,
|
||||
com.raytheon.uf.viz.collaboration.display.data,
|
||||
com.raytheon.uf.viz.collaboration.display.editor,
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.http.client.methods.HttpRequestBase;
|
|||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.protocol.HTTP;
|
||||
|
||||
import com.raytheon.uf.common.comm.HttpClient;
|
||||
import com.raytheon.uf.common.comm.HttpClient.HttpClientResponse;
|
||||
|
@ -53,6 +54,7 @@ import com.raytheon.uf.common.status.UFStatus;
|
|||
import com.raytheon.uf.viz.collaboration.comm.compression.CompressionUtil;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException;
|
||||
import com.raytheon.uf.viz.collaboration.comm.identity.ISharedDisplaySession;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.session.ClientAuthManager;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.session.PeerToPeerCommHelper;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
||||
import com.raytheon.uf.viz.remote.graphics.Dispatcher;
|
||||
|
@ -75,6 +77,8 @@ import com.raytheon.uf.viz.remote.graphics.events.ICreationEvent;
|
|||
* Feb 17, 2014 2756 bclement added xml parsing for HTTP directory listing
|
||||
* Feb 24, 2014 2751 bclement added separate paths for each provider under session id
|
||||
* Feb 25, 2014 2751 bclement fixed provider id path for webDAV
|
||||
* Feb 28, 2014 2756 bclement added auth, moved response code checks to response object
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
|
@ -90,16 +94,18 @@ public class CollaborationObjectEventStorage implements
|
|||
private static NetworkStatistics stats = com.raytheon.uf.viz.collaboration.comm.Activator
|
||||
.getDefault().getNetworkStats();
|
||||
|
||||
private static final String SLASH = "/";
|
||||
|
||||
public static IObjectEventPersistance createPersistanceObject(
|
||||
ISharedDisplaySession session, Dispatcher dispatcher)
|
||||
throws CollaborationException {
|
||||
CollaborationObjectEventStorage persistance = new CollaborationObjectEventStorage(
|
||||
session, dispatcher.getDispatcherId());
|
||||
persistance.createFolder(URI.create(persistance.sessionDataURL));
|
||||
persistance.sessionDataURL += persistance.displayId + "/";
|
||||
persistance.createFolder(URI.create(persistance.sessionDataURL));
|
||||
appendProviderIdToPath(persistance);
|
||||
persistance.createFolder(URI.create(persistance.sessionDataURL));
|
||||
persistance.sessionDataURL += persistance.displayId + SLASH;
|
||||
persistance.createFolder(URI.create(persistance.sessionDataURL));
|
||||
return persistance;
|
||||
}
|
||||
|
||||
|
@ -112,8 +118,8 @@ public class CollaborationObjectEventStorage implements
|
|||
private static void appendProviderIdToPath(
|
||||
CollaborationObjectEventStorage persistance) {
|
||||
try {
|
||||
persistance.sessionDataURL += URLEncoder.encode(persistance.providerid,
|
||||
"UTF-8") + "/";
|
||||
persistance.sessionDataURL += URLEncoder.encode(
|
||||
persistance.providerid, HTTP.UTF_8) + SLASH;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.warn("URL encoding failed, retrying with default encoding: "
|
||||
+ e.getLocalizedMessage());
|
||||
|
@ -127,8 +133,8 @@ public class CollaborationObjectEventStorage implements
|
|||
ISharedDisplaySession session, int displayId) {
|
||||
CollaborationObjectEventStorage persistance = new CollaborationObjectEventStorage(
|
||||
session, displayId);
|
||||
persistance.sessionDataURL += persistance.displayId + "/";
|
||||
appendProviderIdToPath(persistance);
|
||||
persistance.sessionDataURL += persistance.displayId + SLASH;
|
||||
return persistance;
|
||||
}
|
||||
|
||||
|
@ -148,14 +154,17 @@ public class CollaborationObjectEventStorage implements
|
|||
|
||||
private final String providerid;
|
||||
|
||||
private final ClientAuthManager authManager;
|
||||
|
||||
private CollaborationObjectEventStorage(ISharedDisplaySession session,
|
||||
int displayId) {
|
||||
this.displayId = displayId;
|
||||
this.client = HttpClient.getInstance();
|
||||
this.authManager = session.getConnection().getAuthManager();
|
||||
VenueParticipant dataProvider = session.getCurrentDataProvider();
|
||||
this.providerid = dataProvider.getUserid().getNormalizedId();
|
||||
this.sessionDataURL = PeerToPeerCommHelper.getCollaborationHttpServer();
|
||||
this.sessionDataURL += session.getSessionId() + "/";
|
||||
this.sessionDataURL += session.getSessionId() + SLASH;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -187,10 +196,9 @@ public class CollaborationObjectEventStorage implements
|
|||
|
||||
try {
|
||||
CollaborationHttpPersistedEvent wrapped = new CollaborationHttpPersistedEvent();
|
||||
String objectPath = event.getObjectId() + "/"
|
||||
String objectPath = event.getObjectId() + SLASH
|
||||
+ event.getClass().getName() + ".obj";
|
||||
String eventObjectURL = sessionDataURL + objectPath;
|
||||
HttpPut put = new HttpPut(eventObjectURL);
|
||||
|
||||
CollaborationHttpPersistedObject persistObject = new CollaborationHttpPersistedObject();
|
||||
persistObject.persistTime = System.currentTimeMillis();
|
||||
|
@ -198,9 +206,9 @@ public class CollaborationObjectEventStorage implements
|
|||
byte[] toPersist = CompressionUtil.compress(SerializationUtil
|
||||
.transformToThrift(persistObject));
|
||||
stats.log(event.getClass().getSimpleName(), toPersist.length, 0);
|
||||
put.setEntity(new ByteArrayEntity(toPersist));
|
||||
HttpPut put = createPut(eventObjectURL, toPersist);
|
||||
HttpClientResponse response = executeRequest(put);
|
||||
if (isSuccess(response.code) == false) {
|
||||
if (response.isSuccess() == false) {
|
||||
throw new CollaborationException(
|
||||
"Error uploading event object (" + event.getObjectId()
|
||||
+ ") to server @ " + eventObjectURL + " : "
|
||||
|
@ -216,6 +224,35 @@ public class CollaborationObjectEventStorage implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create http put method object. Adds auth header if needed.
|
||||
*
|
||||
* @param url
|
||||
* @param body
|
||||
* @return
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
private HttpPut createPut(String url, byte[] body) throws CollaborationException{
|
||||
URI uri = URI.create(url);
|
||||
HttpPut put = new HttpPut(uri);
|
||||
authManager.signRequest(put, providerid, uri, body);
|
||||
put.setEntity(new ByteArrayEntity(body));
|
||||
return put;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create http delete method object. Adds auth header if needed.
|
||||
*
|
||||
* @param uri
|
||||
* @return
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
private HttpDelete createDelete(URI uri) throws CollaborationException {
|
||||
HttpDelete delete = new HttpDelete(uri);
|
||||
authManager.signRequest(delete, providerid, uri);
|
||||
return delete;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -273,7 +310,7 @@ public class CollaborationObjectEventStorage implements
|
|||
String objectPath = event.getResourcePath();
|
||||
HttpGet get = new HttpGet(sessionDataURL + objectPath);
|
||||
HttpClientResponse response = executeRequest(get);
|
||||
if (isSuccess(response.code)) {
|
||||
if (response.isSuccess()) {
|
||||
try {
|
||||
CollaborationHttpPersistedObject dataObject = SerializationUtil
|
||||
.transformFromThrift(
|
||||
|
@ -286,7 +323,7 @@ public class CollaborationObjectEventStorage implements
|
|||
} catch (SerializationException e) {
|
||||
throw new CollaborationException(e);
|
||||
}
|
||||
} else if (isNotExists(response.code)) {
|
||||
} else if (response.isNotExists()) {
|
||||
// Object was deleted
|
||||
return null;
|
||||
} else {
|
||||
|
@ -310,8 +347,8 @@ public class CollaborationObjectEventStorage implements
|
|||
get.addHeader(new BasicHeader(ACCEPTS_HEADER, XML_CONTENT_TYPE + ","
|
||||
+ HTML_CONTENT_TYPE));
|
||||
HttpClientResponse response = executeRequest(get);
|
||||
if (isSuccess(response.code) == false) {
|
||||
if (isNotExists(response.code)) {
|
||||
if (response.isSuccess() == false) {
|
||||
if (response.isNotExists()) {
|
||||
return new AbstractDispatchingObjectEvent[0];
|
||||
}
|
||||
throw new CollaborationException("Error retrieving object ("
|
||||
|
@ -475,7 +512,7 @@ public class CollaborationObjectEventStorage implements
|
|||
};
|
||||
mkcol.setURI(folderPath);
|
||||
HttpClientResponse rsp = executeRequest(mkcol);
|
||||
if (isSuccess(rsp.code) == false && isDirExists(rsp.code) == false) {
|
||||
if (rsp.isSuccess() == false && isDirExists(rsp.code) == false) {
|
||||
throw new CollaborationException("Folder creation failed for "
|
||||
+ folderPath + ": " + new String(rsp.data));
|
||||
}
|
||||
|
@ -488,9 +525,9 @@ public class CollaborationObjectEventStorage implements
|
|||
* @throws CollaborationException
|
||||
*/
|
||||
private void deleteResource(URI uri) throws CollaborationException {
|
||||
HttpClientResponse rsp = executeRequest(new HttpDelete(uri));
|
||||
HttpClientResponse rsp = executeRequest(createDelete(uri));
|
||||
// If request was success or resource doesn't exist, we are good
|
||||
if (isSuccess(rsp.code) == false && isNotExists(rsp.code) == false) {
|
||||
if (rsp.isSuccess() == false && rsp.isNotExists() == false) {
|
||||
throw new CollaborationException("Folder creation failed for "
|
||||
+ uri + ": " + new String(rsp.data));
|
||||
}
|
||||
|
@ -512,22 +549,6 @@ public class CollaborationObjectEventStorage implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code
|
||||
* @return true if code is a 200 level return code
|
||||
*/
|
||||
private boolean isSuccess(int code) {
|
||||
return code >= 200 && code < 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code
|
||||
* @return true if resource does not exist on server
|
||||
*/
|
||||
private boolean isNotExists(int code) {
|
||||
return code == 404 || code == 410;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this error is related to MKCOL. MKCOL is only required for
|
||||
* DAV (pre 14.3)
|
||||
|
|
|
@ -77,8 +77,7 @@
|
|||
id="org.jivesoftware.smack"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="true"/>
|
||||
version="0.0.0"/>
|
||||
|
||||
<plugin
|
||||
id="org.eclipse.equinox.concurrent"
|
||||
|
@ -87,4 +86,18 @@
|
|||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.common.xmpp"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.common.http"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
|
|
|
@ -107,6 +107,7 @@ import com.raytheon.uf.common.util.ByteArrayOutputStreamPool.ByteArrayOutputStre
|
|||
* Feb 04, 2014 2704 njensen Better error message with bad address
|
||||
* Https authentication failures notify handler
|
||||
* Feb 17, 2014 2756 bclement added content type to response object
|
||||
* Feb 28, 2014 2756 bclement added isSuccess() and isNotExists() to response
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -126,6 +127,20 @@ public class HttpClient {
|
|||
this.data = data != null ? data : new byte[0];
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if code is a 200 level return code
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return code >= 200 && code < 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if resource does not exist on server
|
||||
*/
|
||||
public boolean isNotExists() {
|
||||
return code == 404 || code == 410;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,5 +5,8 @@ Bundle-SymbolicName: com.raytheon.uf.common.http
|
|||
Bundle-Version: 1.14.0
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Export-Package: com.raytheon.uf.common.http
|
||||
Require-Bundle: org.apache.commons.lang;bundle-version="2.3.0"
|
||||
Export-Package: com.raytheon.uf.common.http,
|
||||
com.raytheon.uf.common.http.auth
|
||||
Require-Bundle: org.apache.commons.lang,
|
||||
org.apache.http,
|
||||
org.apache.commons.codec
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.http.auth;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.utils.URIUtils;
|
||||
|
||||
/**
|
||||
* Implements signature authentication for HTTP clients
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 25, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ClientSignatureAuth extends SignatureAuthScheme {
|
||||
|
||||
private final KeyPair keypair;
|
||||
|
||||
private final Signature sig;
|
||||
|
||||
/**
|
||||
* Default constructor, creates a new keypair
|
||||
*
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public ClientSignatureAuth() throws NoSuchAlgorithmException,
|
||||
InvalidKeyException {
|
||||
this(generateKeys());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keypair
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public ClientSignatureAuth(KeyPair keypair)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException {
|
||||
this.keypair = keypair;
|
||||
this.sig = Signature.getInstance(SIG_ALG);
|
||||
this.sig.initSign(this.keypair.getPrivate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a base64 encoded signature from URI
|
||||
*
|
||||
* @param uri
|
||||
* @return
|
||||
* @throws SignatureException
|
||||
*/
|
||||
public String sign(URI uri) throws SignatureException {
|
||||
return sign(uri, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a base64 encoded signature from URI and body
|
||||
*
|
||||
* @param uri
|
||||
* @param bytes
|
||||
* @return
|
||||
* @throws SignatureException
|
||||
*/
|
||||
public String sign(URI uri, byte[] bytes) throws SignatureException {
|
||||
HttpHost host = URIUtils.extractHost(uri);
|
||||
synchronized (sig) {
|
||||
sig.update(host.toHostString().getBytes());
|
||||
sig.update(uri.getPath().getBytes());
|
||||
if (bytes != null) {
|
||||
sig.update(bytes);
|
||||
}
|
||||
return base64Encode(sig.sign());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new public/private key pair using the default algorithms
|
||||
*
|
||||
* @return
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public static final KeyPair generateKeys() throws NoSuchAlgorithmException {
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KEY_ALG);
|
||||
SecureRandom random = SecureRandom.getInstance(RANDOM_ALG);
|
||||
keyGen.initialize(KEY_SIZE, random);
|
||||
return keyGen.generateKeyPair();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the keypair
|
||||
*/
|
||||
public KeyPair getKeypair() {
|
||||
return keypair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default public key algorithm
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getKeyAlgorithm() {
|
||||
return KEY_ALG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base64 X509 encoded public key
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEncodedPublicKey() {
|
||||
PublicKey pub = keypair.getPublic();
|
||||
return base64Encode(pub.getEncoded());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.http.auth;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implements signature authentication for HTTP servers
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 25, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ServerSignatureAuth extends SignatureAuthScheme {
|
||||
|
||||
private final Map<String, KeyFactory> factoryMap = new HashMap<String, KeyFactory>();
|
||||
|
||||
/**
|
||||
* Get the KeyFactory associated with the provided algorithm, a new factory
|
||||
* is created and cached if not found
|
||||
*
|
||||
* @param keyAlg
|
||||
* @return
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public KeyFactory getFactory(String keyAlg) throws NoSuchAlgorithmException {
|
||||
KeyFactory rval;
|
||||
synchronized (factoryMap) {
|
||||
rval = factoryMap.get(keyAlg);
|
||||
if (rval == null) {
|
||||
rval = KeyFactory.getInstance(keyAlg);
|
||||
factoryMap.put(keyAlg, rval);
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a base64 X509 encoded public key using the provided algorithm.
|
||||
*
|
||||
* @param encodedKey
|
||||
* @param algorithm
|
||||
* @return
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeySpecException
|
||||
*/
|
||||
public PublicKey decodePublicKey(String encodedKey, String algorithm)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
byte[] bytes = base64Decode(encodedKey);
|
||||
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(bytes);
|
||||
KeyFactory factory = getFactory(algorithm);
|
||||
return factory.generatePublic(pubKeySpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sig
|
||||
* @param hostHeader
|
||||
* host used in request including port
|
||||
* @param path
|
||||
* path used in request
|
||||
* @return true if the signature matches the URI parts provided
|
||||
* @throws SignatureException
|
||||
*/
|
||||
public boolean verify(Signature sig, String hostHeader, String path)
|
||||
throws SignatureException {
|
||||
return verify(sig, hostHeader, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sig
|
||||
* @param hostHeader
|
||||
* host used in request including port
|
||||
* @param path
|
||||
* path used in request
|
||||
* @param bytes
|
||||
* body of request
|
||||
* @return true if the signature matches the URI parts and body provided
|
||||
* @throws SignatureException
|
||||
*/
|
||||
public boolean verify(Signature sig, String hostHeader, String path,
|
||||
byte[] bytes) throws SignatureException {
|
||||
synchronized (sig) {
|
||||
sig.update(hostHeader.getBytes());
|
||||
sig.update(path.getBytes());
|
||||
if (bytes != null) {
|
||||
sig.update(bytes);
|
||||
}
|
||||
return sig.verify(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.http.auth;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
/**
|
||||
* Base class for signature authentication scheme
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 25, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class SignatureAuthScheme {
|
||||
|
||||
protected static final String RANDOM_ALG = "SHA1PRNG";
|
||||
|
||||
protected static final int KEY_SIZE = 256;
|
||||
|
||||
protected static final String KEY_ALG = "EC";
|
||||
|
||||
protected static final String SIG_ALG = "SHA256WITHECDSA";
|
||||
|
||||
public static final String HTTP_AUTH_HEADER = "Authorization";
|
||||
|
||||
public static final String AUTH_PARAMETER_DELIM = ",";
|
||||
|
||||
public static final String CRED_FIELD_NAME = "Credential";
|
||||
|
||||
public static final String SIG_FIELD_NAME = "Signature";
|
||||
|
||||
/**
|
||||
* matches '[alorithm-name] [credentials-and-signature]'
|
||||
*/
|
||||
private static final Pattern AUTH_HEADER_PATTERN = Pattern
|
||||
.compile("^(\\S+)\\s+(\\S.+)$");
|
||||
|
||||
/**
|
||||
* matches header parameter key/value pairs '[key1]=[val1],[key2]=[val2]'
|
||||
*/
|
||||
private static final Pattern AUTH_PARAMETER_PATTERN = Pattern
|
||||
.compile("([^,=]+)=([^,=]+)");
|
||||
|
||||
/**
|
||||
* Create an Authorization header in the form
|
||||
*
|
||||
* <pre>
|
||||
* '[algorithm-name] Credential=[userid],Signature=[signature]'
|
||||
* </pre>
|
||||
*
|
||||
* Using the default signature algorithm.
|
||||
*
|
||||
* @param userid
|
||||
* @param signature
|
||||
* @return
|
||||
*/
|
||||
public static String formatAuthHeader(String userid, String signature) {
|
||||
return formatAuthHeader(new SignedCredential(userid, signature, SIG_ALG));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Authorization header in the form
|
||||
*
|
||||
* <pre>
|
||||
* '[algorithm-name] Credential=[userid],Signature=[signature]'
|
||||
* </pre>
|
||||
*
|
||||
* @param sc
|
||||
* @return
|
||||
*/
|
||||
public static String formatAuthHeader(SignedCredential sc) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(sc.getAlgorithm()).append(" ");
|
||||
builder.append(CRED_FIELD_NAME).append("=");
|
||||
builder.append(sc.getUserid()).append(AUTH_PARAMETER_DELIM);
|
||||
builder.append(SIG_FIELD_NAME).append("=");
|
||||
builder.append(sc.getSignature());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an Authorization header in the form
|
||||
*
|
||||
* <pre>
|
||||
* '[algorithm-name] Credential=[userid],Signature=[signature]'
|
||||
* </pre>
|
||||
*
|
||||
* @param authHeader
|
||||
* @return
|
||||
*/
|
||||
public static SignedCredential parseAuthHeader(String authHeader) {
|
||||
Matcher m = AUTH_HEADER_PATTERN.matcher(authHeader.trim());
|
||||
if (!m.matches()) {
|
||||
return null;
|
||||
}
|
||||
String algorithm = m.group(1).trim();
|
||||
String paramStr = m.group(2).trim();
|
||||
Map<String, String> parameters = new HashMap<String, String>(2);
|
||||
m = AUTH_PARAMETER_PATTERN.matcher(paramStr);
|
||||
while (m.find()) {
|
||||
parameters.put(m.group(1).trim().toLowerCase(), m.group(2).trim());
|
||||
}
|
||||
String userid = parameters.get(CRED_FIELD_NAME.toLowerCase());
|
||||
String signature = parameters.get(SIG_FIELD_NAME.toLowerCase());
|
||||
return new SignedCredential(userid, signature, algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a non-chuncked (no newlines) base64 string from bytes
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static final String base64Encode(byte[] bytes) {
|
||||
bytes = Base64.encodeBase64(bytes, false);
|
||||
return org.apache.commons.codec.binary.StringUtils.newStringUtf8(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a base64 encoded string
|
||||
*
|
||||
* @param encString
|
||||
* @return
|
||||
*/
|
||||
public static final byte[] base64Decode(String encString) {
|
||||
return Base64.decodeBase64(encString);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.http.auth;
|
||||
|
||||
/**
|
||||
* Credentials used in an authorization header
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 25, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class SignedCredential {
|
||||
|
||||
private final String userid;
|
||||
|
||||
private final String signature;
|
||||
|
||||
private final String algorithm;
|
||||
|
||||
/**
|
||||
* @param userid
|
||||
* @param signature
|
||||
* @param algorithm
|
||||
*/
|
||||
public SignedCredential(String userid, String signature, String algorithm) {
|
||||
this.userid = userid;
|
||||
this.signature = signature;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the userid
|
||||
*/
|
||||
public String getUserid() {
|
||||
return userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the signature
|
||||
*/
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the algorithm
|
||||
*/
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
}
|
7
edexOsgi/com.raytheon.uf.common.xmpp/.classpath
Normal file
7
edexOsgi/com.raytheon.uf.common.xmpp/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
28
edexOsgi/com.raytheon.uf.common.xmpp/.project
Normal file
28
edexOsgi/com.raytheon.uf.common.xmpp/.project
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.raytheon.uf.common.xmpp</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,7 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
12
edexOsgi/com.raytheon.uf.common.xmpp/META-INF/MANIFEST.MF
Normal file
12
edexOsgi/com.raytheon.uf.common.xmpp/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,12 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Common Xmpp
|
||||
Bundle-SymbolicName: com.raytheon.uf.common.xmpp
|
||||
Bundle-Version: 1.14
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Require-Bundle: org.jivesoftware.smack,
|
||||
org.apache.commons.lang
|
||||
Export-Package: com.raytheon.uf.common.xmpp,
|
||||
com.raytheon.uf.common.xmpp.ext,
|
||||
com.raytheon.uf.common.xmpp.iq
|
4
edexOsgi/com.raytheon.uf.common.xmpp/build.properties
Normal file
4
edexOsgi/com.raytheon.uf.common.xmpp/build.properties
Normal file
|
@ -0,0 +1,4 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.packet.DiscoverInfo.Feature;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
* Base class for XMPP IQ and extension providers which are used to parse XMPP
|
||||
* packets.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 24, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class BaseProvider<T> {
|
||||
|
||||
protected final String tagName;
|
||||
|
||||
/**
|
||||
* @param tagName
|
||||
* packet tag name, used to determine when provider is done
|
||||
* parsing
|
||||
*/
|
||||
public BaseProvider(String tagName) {
|
||||
this.tagName = tagName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse contents of packet from XMPP stream.
|
||||
*
|
||||
* @param parser
|
||||
* @return
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
* when errors occurs with XMPP stream
|
||||
*/
|
||||
abstract protected T parseInternal(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException;
|
||||
|
||||
/**
|
||||
* Parse contents of packet from XMPP stream. Ensures that parser is left in
|
||||
* a good state so the stream isn't corrupted.
|
||||
*
|
||||
* @param parser
|
||||
* @return
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
protected T parse(XmlPullParser parser) throws XmlPullParserException,
|
||||
IOException {
|
||||
try {
|
||||
return parseInternal(parser);
|
||||
} finally {
|
||||
// ensure that we are at the end of the packet so we don't corrupt
|
||||
// stream
|
||||
while (!atEndOfPacket(parser)) {
|
||||
parser.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parser
|
||||
* @return true if parser is at the end tag of the packet
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
protected boolean atEndOfPacket(XmlPullParser parser)
|
||||
throws XmlPullParserException {
|
||||
return atEndOfTag(parser, tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parser
|
||||
* @param tag
|
||||
* @return true if parser is at the end of the specified tag
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
protected boolean atEndOfTag(XmlPullParser parser, String tag)
|
||||
throws XmlPullParserException {
|
||||
return parser.getEventType() == XmlPullParser.END_TAG
|
||||
&& parser.getName().equals(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any text elements under current tag
|
||||
*
|
||||
* @param parser
|
||||
* @return
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
protected String getText(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
if (parser.getEventType() == XmlPullParser.TEXT) {
|
||||
return parser.getText();
|
||||
} else if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
return null;
|
||||
}
|
||||
String tag = parser.getName();
|
||||
StringBuilder allText = new StringBuilder();
|
||||
while (!atEndOfTag(parser, tag)) {
|
||||
if (parser.getEventType() == XmlPullParser.TEXT) {
|
||||
allText.append(parser.getText());
|
||||
}
|
||||
parser.next();
|
||||
}
|
||||
return allText.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param conn
|
||||
* @return true if server has feature listed in supported features
|
||||
* @throws XMPPException
|
||||
*/
|
||||
public static boolean serverSupportsFeature(XMPPConnection conn,
|
||||
String feature) throws XMPPException {
|
||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager
|
||||
.getInstanceFor(conn);
|
||||
boolean rval = false;
|
||||
DiscoverInfo discoverInfo = sdm.discoverInfo(null);
|
||||
Iterator<Feature> iter = discoverInfo.getFeatures();
|
||||
while (iter.hasNext()) {
|
||||
String supportedFeature = iter.next().getVar();
|
||||
if (supportedFeature.equals(feature)) {
|
||||
rval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp;
|
||||
|
||||
/**
|
||||
* Custom XMPP packet constants
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 24, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PacketConstants {
|
||||
|
||||
public static final String COLLAB_XMLNS = "urn:uf:viz:collaboration";
|
||||
|
||||
public static final String XMLNS_ATTRIBUTE = "xmlns";
|
||||
|
||||
public static final String QUERY_ELEMENT_NAME = "query";
|
||||
|
||||
private PacketConstants() {
|
||||
}
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.viz.collaboration.comm.provider;
|
||||
package com.raytheon.uf.common.xmpp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
@ -43,6 +43,7 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 17, 2013 2562 bclement Initial creation
|
||||
* Feb 27, 2013 2756 bclement moved to common.xmpp from collaboration
|
||||
*
|
||||
* </pre>
|
||||
*
|
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Simple XML string builder utility
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 26, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class XmlBuilder {
|
||||
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
/**
|
||||
* Key value pair object
|
||||
*/
|
||||
public static class Pair {
|
||||
public final String name;
|
||||
|
||||
public final String value;
|
||||
|
||||
public Pair(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append open tag to XML
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder startTag(String name){
|
||||
return startTag(name, Collections.<Pair> emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Append open tag to XML
|
||||
*
|
||||
* @param name
|
||||
* @param namespace
|
||||
* xmlns attribute to be included in tag
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder startTag(String name, String namespace) {
|
||||
return startTag(name, namespace, Collections.<Pair> emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Append open tag to XML
|
||||
*
|
||||
* @param name
|
||||
* @param attributes
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder startTag(String name, List<Pair> attributes) {
|
||||
return startTag(name, null, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append open tag to XML
|
||||
*
|
||||
* @param name
|
||||
* @param namespace
|
||||
* xmlns attribute to be included in tag
|
||||
* @param attributes
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder startTag(String name, String namespace,
|
||||
List<Pair> attributes) {
|
||||
return appendTag(name, namespace, attributes, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append self closing tag to XML
|
||||
*
|
||||
* @param name
|
||||
* @param attributes
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder selfClosingTag(String name, List<Pair> attributes) {
|
||||
return appendTag(name, null, attributes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append tag to XML
|
||||
*
|
||||
* @param name
|
||||
* @param namespace
|
||||
* xmlns attribute to be included in tag
|
||||
* @param attributes
|
||||
* @param selfClose
|
||||
* if true, tag will self close
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder appendTag(String name, String namespace,
|
||||
List<Pair> attributes, boolean selfClose) {
|
||||
builder.append("<").append(name);
|
||||
if (namespace != null) {
|
||||
builder.append(" ").append(PacketConstants.XMLNS_ATTRIBUTE)
|
||||
.append("=\"");
|
||||
builder.append(namespace).append("\"");
|
||||
}
|
||||
for (Pair attrib : attributes) {
|
||||
builder.append(" ").append(attrib.name).append("=\"");
|
||||
builder.append(attrib.value).append("\"");
|
||||
}
|
||||
if (selfClose) {
|
||||
builder.append("/>");
|
||||
} else {
|
||||
builder.append(">");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append closing tag to XML
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder endTag(String name) {
|
||||
builder.append("</").append(name).append(">");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append text to XML
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
public XmlBuilder appendText(String text) {
|
||||
builder.append(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string containing the XML added to builder
|
||||
*/
|
||||
public String toXml() {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return toXml();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp.ext;
|
||||
|
||||
import org.jivesoftware.smack.packet.PacketExtension;
|
||||
|
||||
/**
|
||||
* Base packet extension class. Used for custom XMPP packet payloads.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 24, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class BaseExtension implements PacketExtension {
|
||||
|
||||
protected final String elementName;
|
||||
|
||||
protected final String namespace;
|
||||
|
||||
/**
|
||||
* @param elementName
|
||||
* @param namespace
|
||||
*/
|
||||
public BaseExtension(String elementName, String namespace) {
|
||||
this.elementName = elementName;
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jivesoftware.smack.packet.PacketExtension#getElementName()
|
||||
*/
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return elementName;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jivesoftware.smack.packet.PacketExtension#getNamespace()
|
||||
*/
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,13 +17,18 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.viz.collaboration.comm.provider.session;
|
||||
package com.raytheon.uf.common.xmpp.ext;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jivesoftware.smackx.pubsub.Affiliation;
|
||||
import org.jivesoftware.smackx.pubsub.Node;
|
||||
import org.jivesoftware.smackx.pubsub.NodeExtension;
|
||||
import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
||||
|
||||
import com.raytheon.uf.common.xmpp.XmlBuilder;
|
||||
import com.raytheon.uf.common.xmpp.XmlBuilder.Pair;
|
||||
|
||||
/**
|
||||
* Packet extension for changing a user's affiliation with a pubsub topic.
|
||||
* Follows specification at
|
||||
|
@ -36,6 +41,7 @@ import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 18, 2014 2751 bclement Initial creation
|
||||
* Feb 27, 2013 2756 bclement moved to common.xmpp from collaboration
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -74,19 +80,14 @@ public class ChangeAffiliationExtension extends NodeExtension {
|
|||
*/
|
||||
@Override
|
||||
public String toXML() {
|
||||
StringBuilder builder = new StringBuilder("<");
|
||||
builder.append(getElementName());
|
||||
builder.append(" node='");
|
||||
builder.append(getNode());
|
||||
builder.append("'><").append(affiliationName).append(" ");
|
||||
builder.append(jidAttribute).append("='");
|
||||
builder.append(this.id);
|
||||
builder.append("' ").append(affiliationName).append("='");
|
||||
builder.append(this.type.toString());
|
||||
builder.append("'/></");
|
||||
builder.append(getElementName());
|
||||
builder.append(">");
|
||||
return builder.toString();
|
||||
XmlBuilder builder = new XmlBuilder();
|
||||
builder.startTag(getElementName(),
|
||||
Arrays.asList(new Pair("node", getNode())));
|
||||
builder.selfClosingTag(affiliationName, Arrays.asList(new Pair(
|
||||
jidAttribute, this.id),
|
||||
new Pair(affiliationName, this.type.toString())));
|
||||
builder.endTag(getElementName());
|
||||
return builder.toXml();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp.iq;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
import com.raytheon.uf.common.xmpp.PacketConstants;
|
||||
import com.raytheon.uf.common.xmpp.XmlBuilder;
|
||||
import com.raytheon.uf.common.xmpp.XmlBuilder.Pair;
|
||||
|
||||
/**
|
||||
* Custom IQ packet for public key authentication
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 26, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class AuthInfo extends IQ {
|
||||
|
||||
public static final String AUTH_QUERY_XMLNS = "urn:uf:viz:collaboration:iq:auth";
|
||||
|
||||
public static final String INFO_ELEMENT_NAME = "authinfo";
|
||||
|
||||
public static final String PUBKEY_ELEMENT_NAME = "publickey";
|
||||
|
||||
public static final String ALG_ATTRIBUTE = "algorithm";
|
||||
|
||||
public static final String ID_ATTRIBUTE = "jid";
|
||||
|
||||
public static final String SESSION_ATTRIBUTE = "sessionid";
|
||||
|
||||
private String encodedKey;
|
||||
|
||||
private String algorithm;
|
||||
|
||||
private String userid;
|
||||
|
||||
private String sessionid;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AuthInfo() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iq
|
||||
*/
|
||||
public AuthInfo(IQ iq) {
|
||||
super(iq);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param encodedKey
|
||||
* @param algorithm
|
||||
* @param userid
|
||||
* @param sessionid
|
||||
*/
|
||||
public AuthInfo(String encodedKey, String algorithm, String userid,
|
||||
String sessionid) {
|
||||
this.encodedKey = encodedKey;
|
||||
this.algorithm = algorithm;
|
||||
this.userid = userid;
|
||||
this.sessionid = sessionid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a setter packet used to store a new public key on server
|
||||
*
|
||||
* @param encodedKey
|
||||
* @param algorithm
|
||||
* @return
|
||||
*/
|
||||
public static AuthInfo createSetPacket(String encodedKey, String algorithm) {
|
||||
AuthInfo rval = new AuthInfo();
|
||||
rval.setEncodedKey(encodedKey);
|
||||
rval.setAlgorithm(algorithm);
|
||||
rval.setType(Type.SET);
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a getter packet used to query the server for the current public
|
||||
* key
|
||||
*
|
||||
* @param userid
|
||||
* @return
|
||||
*/
|
||||
public static AuthInfo createGetPacket(String userid) {
|
||||
return createGetPacket(userid, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a getter packet used to query the server for the current public
|
||||
* key and check authorization for session ownership.
|
||||
*
|
||||
* @param userid
|
||||
* @param sessionid
|
||||
* @return
|
||||
*/
|
||||
public static AuthInfo createGetPacket(String userid, String sessionid) {
|
||||
AuthInfo rval = new AuthInfo();
|
||||
rval.setUserid(userid);
|
||||
rval.setSessionid(sessionid);
|
||||
rval.setType(Type.GET);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jivesoftware.smack.packet.IQ#getChildElementXML()
|
||||
*/
|
||||
@Override
|
||||
public String getChildElementXML() {
|
||||
XmlBuilder builder = new XmlBuilder();
|
||||
List<Pair> queryAttributes = new ArrayList<Pair>(2);
|
||||
if (userid != null) {
|
||||
queryAttributes.add(new Pair(ID_ATTRIBUTE, userid));
|
||||
}
|
||||
if (sessionid != null) {
|
||||
queryAttributes.add(new Pair(SESSION_ATTRIBUTE, sessionid));
|
||||
}
|
||||
builder.startTag(PacketConstants.QUERY_ELEMENT_NAME, AUTH_QUERY_XMLNS,
|
||||
queryAttributes);
|
||||
builder.startTag(INFO_ELEMENT_NAME, PacketConstants.COLLAB_XMLNS);
|
||||
builder.startTag(PUBKEY_ELEMENT_NAME,
|
||||
Arrays.asList(new Pair(ALG_ATTRIBUTE, algorithm)));
|
||||
builder.appendText(encodedKey);
|
||||
builder.endTag(PUBKEY_ELEMENT_NAME);
|
||||
builder.endTag(INFO_ELEMENT_NAME);
|
||||
builder.endTag(PacketConstants.QUERY_ELEMENT_NAME);
|
||||
return builder.toXml();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the encodedKey
|
||||
*/
|
||||
public String getEncodedKey() {
|
||||
return encodedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the algorithm
|
||||
*/
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the userid
|
||||
*/
|
||||
public String getUserid() {
|
||||
return userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sessionid
|
||||
*/
|
||||
public String getSessionid() {
|
||||
return sessionid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param encodedKey
|
||||
* the encodedKey to set
|
||||
*/
|
||||
public void setEncodedKey(String encodedKey) {
|
||||
this.encodedKey = encodedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param algorithm
|
||||
* the algorithm to set
|
||||
*/
|
||||
public void setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userid
|
||||
* the userid to set
|
||||
*/
|
||||
public void setUserid(String userid) {
|
||||
this.userid = userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sessionid
|
||||
* the sessionid to set
|
||||
*/
|
||||
public void setSessionid(String sessionid) {
|
||||
this.sessionid = sessionid;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp.iq;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import com.raytheon.uf.common.xmpp.BaseProvider;
|
||||
import com.raytheon.uf.common.xmpp.PacketConstants;
|
||||
|
||||
/**
|
||||
* Custom XMPP IQ packet parsing for public key authentication
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 26, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class AuthInfoProvider extends BaseProvider<AuthInfo> implements
|
||||
IQProvider {
|
||||
|
||||
/**
|
||||
* @param extensionTagName
|
||||
*/
|
||||
public AuthInfoProvider() {
|
||||
super(PacketConstants.QUERY_ELEMENT_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.jivesoftware.smack.provider.IQProvider#parseIQ(org.xmlpull.v1.
|
||||
* XmlPullParser)
|
||||
*/
|
||||
@Override
|
||||
public AuthInfo parseIQ(XmlPullParser parser) throws Exception {
|
||||
return parse(parser);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.xmpp.BaseProvider#parseInternal(org.xmlpull.v1
|
||||
* .XmlPullParser)
|
||||
*/
|
||||
@Override
|
||||
protected AuthInfo parseInternal(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
String encodedKey = null;
|
||||
String algorithm = null;
|
||||
String userid = null;
|
||||
String sessionid = null;
|
||||
|
||||
|
||||
do {
|
||||
String tagName = parser.getName();
|
||||
switch (parser.getEventType()) {
|
||||
case XmlPullParser.START_TAG:
|
||||
if (PacketConstants.QUERY_ELEMENT_NAME.equals(tagName)) {
|
||||
sessionid = parser.getAttributeValue(null,
|
||||
AuthInfo.SESSION_ATTRIBUTE);
|
||||
userid = parser.getAttributeValue(null,
|
||||
AuthInfo.ID_ATTRIBUTE);
|
||||
} else if (AuthInfo.PUBKEY_ELEMENT_NAME.equals(tagName)) {
|
||||
algorithm = parser.getAttributeValue(null,
|
||||
AuthInfo.ALG_ATTRIBUTE);
|
||||
encodedKey = getText(parser);
|
||||
}
|
||||
break;
|
||||
}
|
||||
parser.next();
|
||||
} while (!atEndOfPacket(parser));
|
||||
return new AuthInfo(encodedKey, algorithm, userid, sessionid);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp.iq;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
import com.raytheon.uf.common.xmpp.PacketConstants;
|
||||
import com.raytheon.uf.common.xmpp.XmlBuilder;
|
||||
|
||||
/**
|
||||
* Custom XMPP IQ packet for HTTP server configuration
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 26, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class HttpInfo extends IQ {
|
||||
|
||||
public static final String INFO_ELEMENT = "httpinfo";
|
||||
|
||||
public static final String URL_ELEMENT = "url";
|
||||
|
||||
public static final String QUERY_XMLNS = "urn:uf:viz:collaboration:iq:http";
|
||||
|
||||
private String url;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public HttpInfo() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iq
|
||||
*/
|
||||
public HttpInfo(IQ iq) {
|
||||
super(iq);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url
|
||||
* bare HTTP url of data server
|
||||
*/
|
||||
public HttpInfo(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChildElementXML() {
|
||||
XmlBuilder builder = new XmlBuilder();
|
||||
builder.startTag(PacketConstants.QUERY_ELEMENT_NAME, QUERY_XMLNS);
|
||||
builder.startTag(INFO_ELEMENT, PacketConstants.COLLAB_XMLNS);
|
||||
builder.startTag(URL_ELEMENT).appendText(url);
|
||||
builder.endTag(URL_ELEMENT);
|
||||
builder.endTag(INFO_ELEMENT);
|
||||
builder.endTag(PacketConstants.QUERY_ELEMENT_NAME);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the url
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url
|
||||
* the url to set
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.xmpp.iq;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import com.raytheon.uf.common.xmpp.BaseProvider;
|
||||
|
||||
/**
|
||||
* Custom XMPP IQ packet parser for HTTP configuration
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 26, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class HttpInfoProvider extends BaseProvider<HttpInfo> implements
|
||||
IQProvider {
|
||||
|
||||
/**
|
||||
* @param extensionTagName
|
||||
*/
|
||||
public HttpInfoProvider() {
|
||||
super(HttpInfo.QUERY_XMLNS);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jivesoftware.smack.provider.IQProvider#parseIQ(org.xmlpull.v1.XmlPullParser)
|
||||
*/
|
||||
@Override
|
||||
public IQ parseIQ(XmlPullParser parser) throws Exception {
|
||||
return parse(parser);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.xmpp.BaseProvider#parseInternal(org.xmlpull.v1
|
||||
* .XmlPullParser)
|
||||
*/
|
||||
@Override
|
||||
protected HttpInfo parseInternal(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
String url = null;
|
||||
|
||||
do {
|
||||
String tagName = parser.getName();
|
||||
switch (parser.getEventType()) {
|
||||
case XmlPullParser.START_TAG:
|
||||
if (HttpInfo.URL_ELEMENT.equals(tagName)) {
|
||||
url = getText(parser);
|
||||
}
|
||||
break;
|
||||
}
|
||||
parser.next();
|
||||
} while (!atEndOfPacket(parser));
|
||||
return new HttpInfo(url);
|
||||
}
|
||||
|
||||
}
|
|
@ -7,4 +7,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
|||
Require-Bundle: org.eclipse.jetty,
|
||||
com.raytheon.uf.common.util,
|
||||
org.jivesoftware.smack,
|
||||
com.raytheon.uf.common.http
|
||||
com.raytheon.uf.common.http,
|
||||
com.raytheon.uf.common.xmpp,
|
||||
org.apache.http,
|
||||
org.apache.commons.collections
|
||||
|
|
|
@ -34,7 +34,8 @@ import java.util.Properties;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 5, 2014 2756 bclement Initial creation
|
||||
* Feb 5, 2014 2756 bclement Initial creation
|
||||
* Feb 28, 2014 2756 bclement added auth cache size
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -77,6 +78,10 @@ public class Config{
|
|||
|
||||
public static final String XMPP_SERVER_DEFAULT = "localhost";
|
||||
|
||||
public static final String AUTH_CACHE_SIZE_KEY = "auth.key.cache.size";
|
||||
|
||||
public static final int AUTH_CACHE_SIZE_DEFAULT = 64;
|
||||
|
||||
public static final String config = System.getProperty(
|
||||
"collaboration.dataserver.config", "config/settings.properties");
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.storage.FileManager;
|
||||
import com.raytheon.uf.common.http.AcceptHeaderParser;
|
||||
import com.raytheon.uf.common.http.AcceptHeaderValue;
|
||||
|
||||
|
@ -162,7 +163,6 @@ public class DataService extends HttpServlet {
|
|||
@Override
|
||||
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
// TODO auth
|
||||
try {
|
||||
File file = getFile(req);
|
||||
manager.writeFile(req.getInputStream(), file);
|
||||
|
@ -196,7 +196,6 @@ public class DataService extends HttpServlet {
|
|||
@Override
|
||||
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
// TODO auth
|
||||
try {
|
||||
File file = getFile(req);
|
||||
if (!file.exists()) {
|
||||
|
|
|
@ -26,6 +26,8 @@ import java.util.TimeZone;
|
|||
|
||||
import org.eclipse.jetty.util.RolloverFileOutputStream;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.auth.ServerAuthManager;
|
||||
|
||||
/**
|
||||
* Entry class for dataserver
|
||||
*
|
||||
|
@ -35,7 +37,8 @@ import org.eclipse.jetty.util.RolloverFileOutputStream;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 5, 2014 2756 bclement Initial creation
|
||||
* Feb 5, 2014 2756 bclement Initial creation
|
||||
* Feb 28, 2014 2756 bclement added authManager
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -62,15 +65,17 @@ public class DataserverMain {
|
|||
.println("Continuing using standard out and standard error");
|
||||
}
|
||||
final XmppServerConnection xmppConnection;
|
||||
final ServerAuthManager authManager;
|
||||
try {
|
||||
xmppConnection = new XmppServerConnection();
|
||||
authManager = new ServerAuthManager(xmppConnection);
|
||||
} catch (Exception e) {
|
||||
System.err
|
||||
.println("Unable to connect to XMPP server, shutting down");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
final WebServerRunner webServer = new WebServerRunner();
|
||||
final WebServerRunner webServer = new WebServerRunner(authManager);
|
||||
new Thread(webServer).start();
|
||||
wait(CONNECTION_DELAY);
|
||||
new Thread(xmppConnection).start();
|
||||
|
|
|
@ -20,11 +20,22 @@
|
|||
package com.raytheon.collaboration.dataserver;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.auth.AuthFilter;
|
||||
import com.raytheon.collaboration.dataserver.auth.DeleteAuthHandler;
|
||||
import com.raytheon.collaboration.dataserver.auth.MethodAuthHandler;
|
||||
import com.raytheon.collaboration.dataserver.auth.PutAuthHandler;
|
||||
import com.raytheon.collaboration.dataserver.auth.ServerAuthManager;
|
||||
|
||||
/**
|
||||
* Start and run jetty webserver
|
||||
*
|
||||
|
@ -35,6 +46,7 @@ import org.eclipse.jetty.servlet.ServletHolder;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 14, 2014 2756 bclement Initial creation
|
||||
* Feb 28, 2014 2756 bclement added authManager
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -45,6 +57,12 @@ public class WebServerRunner implements Runnable {
|
|||
|
||||
private Server server;
|
||||
|
||||
private final ServerAuthManager authManager;
|
||||
|
||||
public WebServerRunner(ServerAuthManager authManager) {
|
||||
this.authManager = authManager;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
|
@ -66,8 +84,14 @@ public class WebServerRunner implements Runnable {
|
|||
|
||||
String datapath = Config.getPath(Config.DATAPATH_KEY,
|
||||
Config.DATAPATH_DEFAULT);
|
||||
context.addServlet(new ServletHolder(new DataService(base)), datapath
|
||||
+ "*");
|
||||
String pathspec = datapath
|
||||
+ "*";
|
||||
context.addServlet(new ServletHolder(new DataService(base)), pathspec);
|
||||
|
||||
List<MethodAuthHandler> methods = Arrays.asList(new PutAuthHandler(
|
||||
authManager), new DeleteAuthHandler(authManager));
|
||||
context.addFilter(new FilterHolder(new AuthFilter(methods)), pathspec,
|
||||
EnumSet.allOf(DispatcherType.class));
|
||||
try {
|
||||
server.start();
|
||||
System.out.println("Server started");
|
||||
|
|
|
@ -23,15 +23,18 @@ import java.net.UnknownHostException;
|
|||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.jivesoftware.smack.PacketListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.PacketFilter;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.IQ.Type;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.provider.ProviderManager;
|
||||
import org.jivesoftware.smack.util.SyncPacketSend;
|
||||
|
||||
import com.raytheon.uf.common.xmpp.PacketConstants;
|
||||
import com.raytheon.uf.common.xmpp.iq.AuthInfo;
|
||||
import com.raytheon.uf.common.xmpp.iq.AuthInfoProvider;
|
||||
import com.raytheon.uf.common.xmpp.iq.HttpInfo;
|
||||
|
||||
/**
|
||||
* Starts and runs XMPP client thread for communication with XMPP server
|
||||
*
|
||||
|
@ -42,6 +45,7 @@ import org.jivesoftware.smack.util.SyncPacketSend;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 14, 2014 2756 bclement Initial creation
|
||||
* Feb 28, 2014 2756 bclement added custom IQ packet support
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -50,6 +54,12 @@ import org.jivesoftware.smack.util.SyncPacketSend;
|
|||
*/
|
||||
public class XmppServerConnection implements Runnable {
|
||||
|
||||
static {
|
||||
ProviderManager pm = ProviderManager.getInstance();
|
||||
pm.addIQProvider(PacketConstants.QUERY_ELEMENT_NAME,
|
||||
AuthInfo.AUTH_QUERY_XMLNS, new AuthInfoProvider());
|
||||
}
|
||||
|
||||
private static final int PACKET_SEND_TIMEOUT = 5000; // 5 seconds
|
||||
|
||||
private final XMPPConnection conn;
|
||||
|
@ -87,25 +97,7 @@ public class XmppServerConnection implements Runnable {
|
|||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
conn.addPacketListener(new PacketListener() {
|
||||
@Override
|
||||
public void processPacket(Packet packet) {
|
||||
log.debug(packet.toXML());
|
||||
}
|
||||
}, new PacketFilter() {
|
||||
@Override
|
||||
public boolean accept(Packet packet) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
IQ packet = new IQ() {
|
||||
@Override
|
||||
public String getChildElementXML() {
|
||||
return "<query xmlns=\"urn:uf:viz:collaboration:iq:http\">"
|
||||
+ "<httpinfo xmlns=\"urn:uf:viz:collaboration\">"
|
||||
+ "<url>" + dataServerUrl + "</url></httpinfo></query>";
|
||||
}
|
||||
};
|
||||
HttpInfo packet = new HttpInfo(dataServerUrl);
|
||||
packet.setType(Type.SET);
|
||||
try {
|
||||
Packet reply = SyncPacketSend.getReply(conn, packet,
|
||||
|
@ -132,4 +124,11 @@ public class XmppServerConnection implements Runnable {
|
|||
conn.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the conn
|
||||
*/
|
||||
public XMPPConnection getConnection() {
|
||||
return conn;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver.auth;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.RestException;
|
||||
import com.raytheon.uf.common.http.auth.SignatureAuthScheme;
|
||||
import com.raytheon.uf.common.http.auth.SignedCredential;
|
||||
|
||||
/**
|
||||
* Servlet filter for authentication and authorization of requests
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 26, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class AuthFilter implements Filter {
|
||||
|
||||
private final Map<String, MethodAuthHandler> handlerMap;
|
||||
|
||||
/**
|
||||
* If a method handler isn't provided for a method, method requests will be
|
||||
* forwarded on to the servlet
|
||||
*
|
||||
* @param methodHandlers
|
||||
*/
|
||||
public AuthFilter(List<MethodAuthHandler> methodHandlers) {
|
||||
Map<String, MethodAuthHandler> map = new HashMap<String, MethodAuthHandler>(
|
||||
methodHandlers.size());
|
||||
for (MethodAuthHandler handler : methodHandlers) {
|
||||
map.put(handler.getMethod(), handler);
|
||||
}
|
||||
this.handlerMap = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.Filter#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse resp,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest httpReq = (HttpServletRequest) req;
|
||||
MethodAuthHandler handler = handlerMap.get(httpReq.getMethod()
|
||||
.toLowerCase());
|
||||
if (handler == null || !handler.getAuthManager().isEnabled()) {
|
||||
chain.doFilter(req, resp);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SignedCredential credential = parseCredentials(httpReq);
|
||||
ParsedUrl urlparts = ParsedUrl.parse(httpReq);
|
||||
HttpServletResponse httpResp = (HttpServletResponse) resp;
|
||||
handler.authorize(httpReq, httpResp, chain, credential, urlparts);
|
||||
}catch(RestException e){
|
||||
HttpServletResponse httpResp = (HttpServletResponse) resp;
|
||||
httpResp.sendError(e.getCode(), e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Authorization header
|
||||
*
|
||||
* @param httpReq
|
||||
* @return
|
||||
* @throws RestException
|
||||
* if header does not exist or is malformed
|
||||
*/
|
||||
private SignedCredential parseCredentials(HttpServletRequest httpReq)
|
||||
throws RestException {
|
||||
String header = httpReq.getHeader(SignatureAuthScheme.HTTP_AUTH_HEADER);
|
||||
if (header == null || header.trim().isEmpty()) {
|
||||
throw new RestException(HttpServletResponse.SC_UNAUTHORIZED,
|
||||
"Missing header: " + SignatureAuthScheme.HTTP_AUTH_HEADER);
|
||||
}
|
||||
SignedCredential credential = SignatureAuthScheme
|
||||
.parseAuthHeader(header);
|
||||
if (credential == null || credential.getAlgorithm() == null
|
||||
|| credential.getSignature() == null
|
||||
|| credential.getUserid() == null) {
|
||||
throw new RestException(HttpServletResponse.SC_BAD_REQUEST,
|
||||
"Malformed header: " + SignatureAuthScheme.HTTP_AUTH_HEADER);
|
||||
}
|
||||
return credential;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
|
||||
*/
|
||||
@Override
|
||||
public void init(FilterConfig arg0) throws ServletException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver.auth;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.RestException;
|
||||
import com.raytheon.uf.common.http.auth.SignatureAuthScheme;
|
||||
import com.raytheon.uf.common.http.auth.SignedCredential;
|
||||
import com.raytheon.uf.common.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Auth handler for HTTP DELETE requests
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 27, 2014 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class DeleteAuthHandler extends MethodAuthHandler {
|
||||
|
||||
private final Logger log = Log.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* @param authManager
|
||||
*/
|
||||
public DeleteAuthHandler(ServerAuthManager authManager) {
|
||||
super(authManager, "delete");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.raytheon.collaboration.dataserver.auth.MethodAuthHandler#authorize(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain, com.raytheon.uf.common.http.auth.SignedCredential, com.raytheon.collaboration.dataserver.auth.ParsedUrl)
|
||||
*/
|
||||
@Override
|
||||
public void authorize(HttpServletRequest httpReq,
|
||||
HttpServletResponse httpResp, FilterChain chain,
|
||||
SignedCredential credential, ParsedUrl urlParts)
|
||||
throws RestException, ServletException, IOException {
|
||||
String userid = urlParts.getUserid();
|
||||
Signature sig;
|
||||
if (StringUtil.isEmptyString(userid)) {
|
||||
// deleting entire session, verify that user is owner
|
||||
sig = authManager.getAuthorizedSignatureDirect(credential,
|
||||
urlParts.getSessionid());
|
||||
} else {
|
||||
// verify that user owns resource to delete
|
||||
if (!userid.equals(credential.getUserid())) {
|
||||
throw new RestException(HttpServletResponse.SC_FORBIDDEN,
|
||||
"Credential does not own resource");
|
||||
}
|
||||
sig = authManager.getAuthorizedSignature(credential);
|
||||
}
|
||||
try {
|
||||
if (verify(sig, credential, urlParts)) {
|
||||
chain.doFilter(httpReq, httpResp);
|
||||
} else {
|
||||
// possible that we have an outdated public key cached
|
||||
sig = authManager.getAuthorizedSignatureDirect(credential);
|
||||
if (verify(sig, credential, urlParts)) {
|
||||
chain.doFilter(httpReq, httpResp);
|
||||
} else {
|
||||
throw new RestException(HttpServletResponse.SC_FORBIDDEN,
|
||||
"Credentials not authenticated");
|
||||
}
|
||||
}
|
||||
} catch (SignatureException e) {
|
||||
log.warn("Problem using signature object", e);
|
||||
throw new RestException(
|
||||
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Error using authentication server");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sig
|
||||
* @param credential
|
||||
* @param urlParts
|
||||
* @return true if signature matches credentials
|
||||
* @throws SignatureException
|
||||
*/
|
||||
private boolean verify(Signature sig, SignedCredential credential,
|
||||
ParsedUrl urlParts) throws SignatureException {
|
||||
synchronized (sig) {
|
||||
sig.update(urlParts.getHostString().getBytes());
|
||||
sig.update(urlParts.getPathString().getBytes());
|
||||
byte[] sigBytes = SignatureAuthScheme.base64Decode(credential
|
||||
.getSignature());
|
||||
return sig.verify(sigBytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver.auth;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.RestException;
|
||||
import com.raytheon.uf.common.http.auth.SignedCredential;
|
||||
|
||||
/**
|
||||
* Base auth handler for HTTP methods
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 27, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class MethodAuthHandler {
|
||||
|
||||
protected final String method;
|
||||
|
||||
protected final ServerAuthManager authManager;
|
||||
|
||||
|
||||
/**
|
||||
* @param authManager
|
||||
* @param method
|
||||
*/
|
||||
public MethodAuthHandler(ServerAuthManager authManager, String method) {
|
||||
this.authManager = authManager;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize request using provided credentials. Sends the request down the
|
||||
* FilterChain if authorized.
|
||||
*
|
||||
* @param httpReq
|
||||
* @param httpResp
|
||||
* @param chain
|
||||
* @param credential
|
||||
* @param urlParts
|
||||
* @throws RestException
|
||||
* if request is not authorized or invalid
|
||||
* @throws ServletException
|
||||
* @throws IOException
|
||||
*/
|
||||
abstract public void authorize(HttpServletRequest httpReq,
|
||||
HttpServletResponse httpResp, FilterChain chain,
|
||||
SignedCredential credential, ParsedUrl urlParts)
|
||||
throws RestException, ServletException, IOException;
|
||||
|
||||
/**
|
||||
* @return the method
|
||||
*/
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the authManager
|
||||
*/
|
||||
public ServerAuthManager getAuthManager() {
|
||||
return authManager;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver.auth;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.http.client.utils.URIUtils;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.RestException;
|
||||
import com.raytheon.uf.common.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Parsed HTTP request url
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 27, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ParsedUrl {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* /session_data/[sessionid]/[userid]
|
||||
* </pre>
|
||||
*/
|
||||
private static final Pattern PATH_PATTERN = Pattern
|
||||
.compile("^/?([^/]+)/([^/]+)(/([^/]+))?.*$");
|
||||
|
||||
/**
|
||||
* parent directory reference (..) anywhere in path
|
||||
*/
|
||||
private static final Pattern REL_PATH_PATTERN = Pattern
|
||||
.compile("^\\.\\./|/\\.\\./|/\\.\\.$|^\\.\\.$");
|
||||
|
||||
private final String hostString;
|
||||
|
||||
private final String pathString;
|
||||
|
||||
private final String sessionid;
|
||||
|
||||
private final String userid;
|
||||
|
||||
/**
|
||||
* @param hostString
|
||||
* @param pathString
|
||||
* @param sessionid
|
||||
* @param userid
|
||||
*/
|
||||
private ParsedUrl(String hostString, String pathString, String sessionid,
|
||||
String userid) {
|
||||
this.hostString = hostString;
|
||||
this.pathString = pathString;
|
||||
this.sessionid = sessionid;
|
||||
this.userid = userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse URL of request
|
||||
*
|
||||
* @param httpReq
|
||||
* @return
|
||||
* @throws RestException
|
||||
*/
|
||||
public static ParsedUrl parse(HttpServletRequest httpReq)
|
||||
throws RestException {
|
||||
URI uri = URI.create(httpReq.getRequestURL().toString());
|
||||
String hostHeader = URIUtils.extractHost(uri).toHostString();
|
||||
if (StringUtil.isEmptyString(hostHeader)) {
|
||||
throw new RestException(HttpServletResponse.SC_BAD_REQUEST,
|
||||
"Unable to determine host string");
|
||||
}
|
||||
String path = uri.getPath();
|
||||
Matcher m = REL_PATH_PATTERN.matcher(path);
|
||||
if (m.find()) {
|
||||
throw new RestException(HttpServletResponse.SC_BAD_REQUEST,
|
||||
"Relative path inderection is not allowed");
|
||||
}
|
||||
m = PATH_PATTERN.matcher(path);
|
||||
if (!m.matches()) {
|
||||
throw new RestException(HttpServletResponse.SC_BAD_REQUEST,
|
||||
"Malformed session data path");
|
||||
}
|
||||
/*
|
||||
* first part of url will always be the path to the servlet
|
||||
* (session_data). The next is enforced as the sessionid and the data
|
||||
* provider's userid after that. The userid is optional because topic
|
||||
* owners can delete the entire session tree
|
||||
*/
|
||||
String sessionid = getSafeGroup(m, 2);
|
||||
String userid = getSafeGroup(m, 4);
|
||||
return new ParsedUrl(hostHeader, path, sessionid, userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get trimmed matcher group
|
||||
*
|
||||
* @param m
|
||||
* @param group
|
||||
* @return null if group was empty
|
||||
*/
|
||||
public static String getSafeGroup(Matcher m, int group) {
|
||||
String rval = m.group(group);
|
||||
if (rval != null) {
|
||||
rval = rval.trim();
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the hostString
|
||||
*/
|
||||
public String getHostString() {
|
||||
return hostString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pathString
|
||||
*/
|
||||
public String getPathString() {
|
||||
return pathString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sessionid
|
||||
*/
|
||||
public String getSessionid() {
|
||||
return sessionid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the userid
|
||||
*/
|
||||
public String getUserid() {
|
||||
return userid;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver.auth;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.RestException;
|
||||
import com.raytheon.uf.common.http.auth.SignatureAuthScheme;
|
||||
import com.raytheon.uf.common.http.auth.SignedCredential;
|
||||
|
||||
/**
|
||||
* Auth handler for HTTP PUT requests
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 27, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PutAuthHandler extends MethodAuthHandler {
|
||||
|
||||
private final Logger log = Log.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* @param method
|
||||
*/
|
||||
public PutAuthHandler(ServerAuthManager authManager) {
|
||||
super(authManager, "put");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.collaboration.dataserver.auth.MethodAuthHandler#authorize
|
||||
* (javax.servlet.http.HttpServletRequest,
|
||||
* javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain,
|
||||
* com.raytheon.uf.common.http.auth.SignedCredential,
|
||||
* com.raytheon.collaboration.dataserver.auth.ParsedUrl)
|
||||
*/
|
||||
@Override
|
||||
public void authorize(HttpServletRequest httpReq,
|
||||
HttpServletResponse httpResp, FilterChain chain,
|
||||
SignedCredential credential, ParsedUrl urlParts)
|
||||
throws RestException, ServletException {
|
||||
if (!urlParts.getUserid().equals(credential.getUserid())) {
|
||||
throw new RestException(HttpServletResponse.SC_FORBIDDEN,
|
||||
"Credential does not own resource");
|
||||
}
|
||||
Signature sig = authManager.getAuthorizedSignature(credential);
|
||||
try {
|
||||
VerifyingRequest wrapper = new VerifyingRequest(httpReq);
|
||||
if (verify(sig, wrapper, credential, urlParts)) {
|
||||
chain.doFilter(wrapper, httpResp);
|
||||
} else {
|
||||
// possible that we have an outdated public key cached
|
||||
sig = authManager.getAuthorizedSignatureDirect(credential);
|
||||
if (verify(sig, wrapper, credential, urlParts)) {
|
||||
chain.doFilter(wrapper, httpResp);
|
||||
} else {
|
||||
throw new RestException(HttpServletResponse.SC_FORBIDDEN,
|
||||
"Credentials not authenticated");
|
||||
}
|
||||
}
|
||||
} catch (SignatureException e) {
|
||||
log.warn("Problem using signature object", e);
|
||||
throw new RestException(
|
||||
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Error using authentication server");
|
||||
} catch (IOException e) {
|
||||
log.warn("Problem transferring stream", e);
|
||||
throw new RestException(
|
||||
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Problem reading from stream");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sig
|
||||
* @param wrapper
|
||||
* @param credential
|
||||
* @param urlParts
|
||||
* @return true if signature matches the credentials
|
||||
* @throws SignatureException
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean verify(Signature sig, VerifyingRequest wrapper,
|
||||
SignedCredential credential, ParsedUrl urlParts)
|
||||
throws SignatureException, IOException {
|
||||
synchronized (sig) {
|
||||
sig.update(urlParts.getHostString().getBytes());
|
||||
sig.update(urlParts.getPathString().getBytes());
|
||||
byte[] sigBytes = SignatureAuthScheme.base64Decode(credential
|
||||
.getSignature());
|
||||
return wrapper.verify(sig, sigBytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver.auth;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.collections.map.LRUMap;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.XMPPError;
|
||||
import org.jivesoftware.smack.packet.XMPPError.Condition;
|
||||
import org.jivesoftware.smack.util.SyncPacketSend;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.Config;
|
||||
import com.raytheon.collaboration.dataserver.RestException;
|
||||
import com.raytheon.collaboration.dataserver.XmppServerConnection;
|
||||
import com.raytheon.uf.common.http.auth.ServerSignatureAuth;
|
||||
import com.raytheon.uf.common.http.auth.SignedCredential;
|
||||
import com.raytheon.uf.common.xmpp.BaseProvider;
|
||||
import com.raytheon.uf.common.xmpp.iq.AuthInfo;
|
||||
|
||||
/**
|
||||
* Manages authentication credentials for HTTP data server which are stored on
|
||||
* the XMPP server
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 25, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ServerAuthManager {
|
||||
|
||||
private final Logger log = Log.getLogger(this.getClass());
|
||||
|
||||
private final XmppServerConnection xmppServer;
|
||||
|
||||
private final ServerSignatureAuth sigAuth = new ServerSignatureAuth();
|
||||
|
||||
private final boolean isEnabled;
|
||||
|
||||
private final Map<String, Signature> sigCache;
|
||||
|
||||
/**
|
||||
* @param xmppServer
|
||||
* @throws XMPPException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ServerAuthManager(XmppServerConnection xmppServer)
|
||||
throws XMPPException {
|
||||
isEnabled = BaseProvider.serverSupportsFeature(
|
||||
xmppServer.getConnection(), AuthInfo.AUTH_QUERY_XMLNS);
|
||||
this.xmppServer = xmppServer;
|
||||
int cacheSize = Config.getInt(Config.AUTH_CACHE_SIZE_KEY,
|
||||
Config.AUTH_CACHE_SIZE_DEFAULT);
|
||||
this.sigCache = Collections.synchronizedMap(new LRUMap(cacheSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cached signature verification for credential.
|
||||
*
|
||||
* @param credential
|
||||
* @return
|
||||
* @throws RestException
|
||||
* if there was an internal error or credentials are not
|
||||
* authorized for request
|
||||
*/
|
||||
public Signature getAuthorizedSignature(SignedCredential credential)
|
||||
throws RestException {
|
||||
Signature rval;
|
||||
rval = sigCache.get(credential.getUserid());
|
||||
if (rval == null) {
|
||||
rval = getAuthorizedSignatureDirect(credential);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns signature verification for credential from server. Caches result.
|
||||
*
|
||||
* @param credential
|
||||
* @return
|
||||
* @throws RestException
|
||||
* if there was an internal error or credentials are not
|
||||
* authorized for request
|
||||
*/
|
||||
public Signature getAuthorizedSignatureDirect(SignedCredential credential)
|
||||
throws RestException {
|
||||
return getAuthorizedSignatureDirect(credential, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns signature verification for credential from server. Caches result.
|
||||
*
|
||||
* @param credential
|
||||
* @param sessionid
|
||||
* @return
|
||||
* @throws RestException
|
||||
* if there was an internal error or credentials are not
|
||||
* authorized for request
|
||||
*/
|
||||
public Signature getAuthorizedSignatureDirect(SignedCredential credential,
|
||||
String sessionid) throws RestException {
|
||||
AuthInfo query;
|
||||
if (sessionid == null) {
|
||||
query = AuthInfo.createGetPacket(credential.getUserid());
|
||||
} else {
|
||||
query = AuthInfo.createGetPacket(credential.getUserid(),
|
||||
sessionid);
|
||||
}
|
||||
AuthInfo info = queryServerForAuth(query);
|
||||
Signature rval = getSignature(credential, info);
|
||||
sigCache.put(credential.getUserid(), rval);
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query XMPP server for auth information
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
* @throws RestException
|
||||
* if there was an internal error or credentials are not
|
||||
* authorized for request
|
||||
*/
|
||||
private AuthInfo queryServerForAuth(AuthInfo query) throws RestException {
|
||||
AuthInfo rval;
|
||||
try {
|
||||
XMPPConnection conn = xmppServer.getConnection();
|
||||
Packet response = SyncPacketSend.getReply(conn, query);
|
||||
if (response instanceof AuthInfo) {
|
||||
rval = (AuthInfo) response;
|
||||
} else {
|
||||
log.warn("Unexpected return type from XMPP server: "
|
||||
+ response.toXML());
|
||||
throw new RestException(
|
||||
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Problem communicating with authentication server");
|
||||
}
|
||||
} catch (XMPPException e) {
|
||||
XMPPError xmppError = e.getXMPPError();
|
||||
if ( xmppError != null &&xmppError.getCondition().equals(Condition.not_allowed)){
|
||||
log.debug("Credential not authorized for sessionid: "
|
||||
+ xmppError.getMessage());
|
||||
throw new RestException(HttpServletResponse.SC_FORBIDDEN,
|
||||
"Credential not authorized for session");
|
||||
} else {
|
||||
log.warn("Problem getting signature from server", e);
|
||||
throw new RestException(
|
||||
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Problem communicating with authentication server");
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct signature validation object using credentials and private key
|
||||
* from XMPP server.
|
||||
*
|
||||
* @param credential
|
||||
* @param info
|
||||
* @return
|
||||
* @throws RestException
|
||||
* if XMPP server contains malformed auth info
|
||||
*/
|
||||
private Signature getSignature(SignedCredential credential, AuthInfo info)
|
||||
throws RestException {
|
||||
if (info.getAlgorithm() == null || info.getEncodedKey() == null) {
|
||||
log.warn("Missing elements from auth info packet: " + info.toXML());
|
||||
throw new RestException(
|
||||
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Authentication server contains malformed authorization information");
|
||||
}
|
||||
Signature rval;
|
||||
try {
|
||||
PublicKey key = sigAuth.decodePublicKey(info.getEncodedKey(),
|
||||
info.getAlgorithm());
|
||||
rval = Signature.getInstance(credential.getAlgorithm());
|
||||
rval.initVerify(key);
|
||||
} catch (GeneralSecurityException e) {
|
||||
log.warn("Unable to create signature verification", e);
|
||||
throw new RestException(
|
||||
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Authentication server contains malformed authorization information");
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if XMPP server supports public key auth scheme
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver.auth;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.storage.FileManager;
|
||||
|
||||
/**
|
||||
* HTTP Servlet Request Wrapper for public key signature verification. Allows
|
||||
* body of request to be read multiple times.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 26, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class VerifyingRequest extends HttpServletRequestWrapper {
|
||||
|
||||
private final Logger log = Log.getLogger(this.getClass());
|
||||
|
||||
private byte[] body = null;
|
||||
|
||||
/**
|
||||
* @param request
|
||||
*/
|
||||
public VerifyingRequest(HttpServletRequest request) throws IOException {
|
||||
super(request);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.servlet.ServletRequestWrapper#getInputStream()
|
||||
*/
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
if (body == null) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(
|
||||
FileManager.BUFFER_SIZE);
|
||||
FileManager.copy(super.getInputStream(), out);
|
||||
body = out.toByteArray();
|
||||
}
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return bais.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param verification
|
||||
* @param signature
|
||||
* @return true if signature matches request
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean verifyInternal(final Signature verification,
|
||||
byte[] signature) throws IOException {
|
||||
final boolean[] errorFlag = { false };
|
||||
ServletInputStream in = super.getInputStream();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(
|
||||
FileManager.BUFFER_SIZE) {
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] b, int off, int len) {
|
||||
super.write(b, off, len);
|
||||
try {
|
||||
verification.update(b, off, len);
|
||||
} catch (SignatureException e) {
|
||||
log.warn("Problem verifying request", e);
|
||||
errorFlag[0] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(int b) {
|
||||
super.write(b);
|
||||
try {
|
||||
verification.update((byte) b);
|
||||
} catch (SignatureException e) {
|
||||
log.warn("Problem verifying request", e);
|
||||
errorFlag[0] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
FileManager.copy(in, out);
|
||||
this.body = out.toByteArray();
|
||||
boolean rval = false;
|
||||
try {
|
||||
rval = errorFlag[0] ? false : verification.verify(signature);
|
||||
} catch (SignatureException e) {
|
||||
log.warn("Problem verifying request", e);
|
||||
rval = false;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param verification
|
||||
* @param signature
|
||||
* @return true if signature matches request
|
||||
* @throws IOException
|
||||
* @throws SignatureException
|
||||
*/
|
||||
public boolean verify(Signature verification, byte[] signature)
|
||||
throws IOException, SignatureException {
|
||||
if (this.body == null) {
|
||||
return verifyInternal(verification, signature);
|
||||
} else {
|
||||
verification.update(body);
|
||||
return verification.verify(signature);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.collaboration.dataserver;
|
||||
package com.raytheon.collaboration.dataserver.storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -33,6 +33,7 @@ import java.util.ListIterator;
|
|||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.raytheon.collaboration.dataserver.RestException;
|
||||
import com.raytheon.uf.common.util.concurrent.KeyLock;
|
||||
import com.raytheon.uf.common.util.concurrent.KeyLocker;
|
||||
|
||||
|
@ -47,7 +48,8 @@ import com.raytheon.uf.common.util.concurrent.KeyLocker;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 6, 2014 2756 bclement Initial creation
|
||||
* Feb 6, 2014 2756 bclement Initial creation
|
||||
* Feb 28, 2014 2756 bclement moved to storage package, made buffer size public
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -56,7 +58,7 @@ import com.raytheon.uf.common.util.concurrent.KeyLocker;
|
|||
*/
|
||||
public class FileManager {
|
||||
|
||||
private static final int BUFFER_SIZE = 1024 * 256; // 256K
|
||||
public static final int BUFFER_SIZE = 1024 * 256; // 256K
|
||||
|
||||
private static final ThreadLocal<byte[]> localBuffer = new ThreadLocal<byte[]>() {
|
||||
|
|
@ -51,6 +51,7 @@ import org.xmpp.packet.PacketError.Condition;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 12, 2014 2756 bclement Initial creation
|
||||
* Feb 28, 2014 2756 bclement reordered retrieve method operations for clarity
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -264,12 +265,15 @@ public abstract class AbstractConfigHandler extends IQHandler implements
|
|||
*/
|
||||
protected IQ retrieve(IQ requestPacket, String id, Element key) {
|
||||
Element queryElem = requestPacket.getChildElement();
|
||||
Element respElem = storage.get(id, key);
|
||||
IQ rval = IQ.createResultIQ(requestPacket);
|
||||
queryElem.setParent(null);
|
||||
Element respElem = storage.get(id, key);
|
||||
respElem.setParent(null);
|
||||
|
||||
removeChildren(queryElem);
|
||||
queryElem.add(respElem);
|
||||
queryElem.setParent(null);
|
||||
rval.setChildElement(queryElem);
|
||||
queryElem.add(respElem);
|
||||
log.info(rval.toXML());
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.xmpp.packet.PacketError.Condition;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 10, 2014 2756 bclement Initial creation
|
||||
* Feb 28, 2014 2756 bclement if sessionid is not provided, skip authorization step
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -105,25 +106,25 @@ public class DataAuthHandler extends AbstractConfigHandler {
|
|||
}
|
||||
JID target = new JID(jid);
|
||||
String sessionId = queryElem.attributeValue(SESSIONID_ATTRIBUTE);
|
||||
if (StringUtils.isBlank(sessionId)) {
|
||||
String msg = "Missing attribute: " + SESSIONID_ATTRIBUTE;
|
||||
log.debug(msg);
|
||||
return createError(packet, new PacketError(Condition.bad_request,
|
||||
PacketError.Type.modify, msg));
|
||||
}
|
||||
Node node = pubsub.getNode(sessionId);
|
||||
if (node == null) {
|
||||
String msg = "No topic found for session: " + sessionId;
|
||||
log.debug(msg);
|
||||
return createError(packet, new PacketError(Condition.not_allowed,
|
||||
PacketError.Type.cancel, msg));
|
||||
}
|
||||
if (!isOwner(jid, node)){
|
||||
String msg = "User '" + jid + "' is not an owner of session '"
|
||||
+ sessionId + "'";
|
||||
log.debug(msg);
|
||||
return createError(packet, new PacketError(Condition.not_allowed,
|
||||
PacketError.Type.cancel, msg));
|
||||
if (!StringUtils.isBlank(sessionId)) {
|
||||
/*
|
||||
* only check authorization if session id is specified, otherwise we
|
||||
* are just doing authentication
|
||||
*/
|
||||
Node node = pubsub.getNode(sessionId);
|
||||
if (node == null) {
|
||||
String msg = "No topic found for session: " + sessionId;
|
||||
log.debug(msg);
|
||||
return createError(packet, new PacketError(
|
||||
Condition.not_allowed, PacketError.Type.cancel, msg));
|
||||
}
|
||||
if (!isOwner(jid, node)) {
|
||||
String msg = "User '" + jid + "' is not an owner of session '"
|
||||
+ sessionId + "'";
|
||||
log.debug(msg);
|
||||
return createError(packet, new PacketError(
|
||||
Condition.not_allowed, PacketError.Type.cancel, msg));
|
||||
}
|
||||
}
|
||||
return retrieve(packet, target.getNode(),
|
||||
createElement(INFO_ELEMENT_NAME, COLLAB_XMLNS));
|
||||
|
|
Loading…
Add table
Reference in a new issue