[prev in list] [next in list] [prev in thread] [next in thread]
List: wss4j-dev
Subject: svn commit: r785171 - in /webservices/wss4j/trunk:
From: coheigea () apache ! org
Date: 2009-06-16 12:06:08
Message-ID: 20090616120609.2ED982388895 () eris ! apache ! org
[Download RAW message or body]
Author: coheigea
Date: Tue Jun 16 12:06:08 2009
New Revision: 785171
URL: http://svn.apache.org/viewvc?rev=785171&view=rev
Log:
Some improvements to searching for elements by ID
- ReferenceListProcessor now searches for "general" ID first and then wsu:Id, not \
the other way around...as it should always hit the general ID first
- I added a boolean to the findElementById method in WSSecurityUtil which controls \
whether to search the entire message for duplicates or not
- Message creation functions now do not check for duplicates as this is unnecessary
- Message processing functions do check for duplicates as \
before...EnvelopeIdResolver does not, as SignatureProcessor later does check for \
duplicates
- This should speed things up a bit....
- Added a test as well for some signature modification attacks.
Added:
webservices/wss4j/trunk/test/wssec/TestModifiedRequest.java (with props)
Modified:
webservices/wss4j/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignature.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java
webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java
webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java
webservices/wss4j/trunk/test/wssec/PackageTests.java
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java?rev=785171&r1=785170&r2=785171&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java \
(original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java \
Tue Jun 16 12:06:08 2009 @@ -106,9 +106,9 @@
}
String cId = selectedElem.getAttributeNS(WSConstants.WSU_NS, "Id");
if (!id.equals(cId)) {
- selectedElem = WSSecurityUtil.getElementByWsuId(doc, uriNodeValue);
+ selectedElem = WSSecurityUtil.getElementByWsuId(doc, uriNodeValue, \
false); if (selectedElem == null) {
- selectedElem = WSSecurityUtil.getElementByGenId(doc, uriNodeValue);
+ selectedElem = WSSecurityUtil.getElementByGenId(doc, uriNodeValue, \
false); }
if (selectedElem == null) {
throw new ResourceResolverException(
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java?rev=785171&r1=785170&r2=785171&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java \
(original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java Tue \
Jun 16 12:06:08 2009 @@ -430,11 +430,13 @@
if (idToEnc != null) {
elementToEncrypt =
WSSecurityUtil.findElementById(
- doc.getDocumentElement(), idToEnc, WSConstants.WSU_NS
+ doc.getDocumentElement(), idToEnc, WSConstants.WSU_NS, \
false );
if (elementToEncrypt == null) {
elementToEncrypt =
- WSSecurityUtil.findElementById(doc.getDocumentElement(), \
idToEnc, null); + WSSecurityUtil.findElementById(
+ doc.getDocumentElement(), idToEnc, null, false
+ );
}
} else {
elementToEncrypt =
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignature.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignature.java?rev=785171&r1=785170&r2=785171&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignature.java \
(original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignature.java \
Tue Jun 16 12:06:08 2009 @@ -360,12 +360,12 @@
if (idToSign != null) {
Element toSignById =
WSSecurityUtil.findElementById(
- envelope, idToSign, WSConstants.WSU_NS
+ envelope, idToSign, WSConstants.WSU_NS, false
);
if (toSignById == null) {
toSignById =
WSSecurityUtil.findElementById(
- envelope, idToSign, null
+ envelope, idToSign, null, false
);
}
\
transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java?rev=785171&r1=785170&r2=785171&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java \
(original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java \
Tue Jun 16 12:06:08 2009 @@ -164,8 +164,8 @@
/**
- * Look up the encrypted data. First try wsu:Id="someURI". If no such Id then \
try the
- * generic lookup to find Id="someURI"
+ * Look up the encrypted data. First try Id="someURI". If no such Id then try
+ * wsu:Id="someURI".
*
* @param doc The document in which to find EncryptedData
* @param dataRefURI The URI of EncryptedData
@@ -178,9 +178,9 @@
Document doc,
String dataRefURI
) throws WSSecurityException {
- Element encryptedDataElement = WSSecurityUtil.getElementByWsuId(doc, \
dataRefURI); + Element encryptedDataElement = \
WSSecurityUtil.getElementByGenId(doc, dataRefURI); if (encryptedDataElement == null) \
{
- encryptedDataElement = WSSecurityUtil.getElementByGenId(doc, \
dataRefURI); + encryptedDataElement = \
WSSecurityUtil.getElementByWsuId(doc, dataRefURI); }
if (encryptedDataElement == null) {
throw new WSSecurityException(
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java?rev=785171&r1=785170&r2=785171&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java \
(original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java \
Tue Jun 16 12:06:08 2009 @@ -515,12 +515,12 @@
if (idToSign != null) {
Element toSignById =
WSSecurityUtil.findElementById(
- document.getDocumentElement(), idToSign, \
WSConstants.WSU_NS + document.getDocumentElement(), \
idToSign, WSConstants.WSU_NS, false );
if (toSignById == null) {
toSignById =
WSSecurityUtil.findElementById(
- document.getDocumentElement(), idToSign, null
+ document.getDocumentElement(), idToSign, null, false
);
}
\
transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java?rev=785171&r1=785170&r2=785171&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java \
(original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java Tue \
Jun 16 12:06:08 2009 @@ -351,35 +351,36 @@
* faster than XPath, and we do not deal with prefixes, just with the real
* namespace URI
*
- * If there are multiple elements, we log a warning and return null as this
- * can be used to get around the signature checking.
+ * If checkMultipleElements is true and there are multiple elements, we log a
+ * warning and return null as this can be used to get around the signature \
checking.
*
* @param startNode Where to start the search
* @param value Value of the Id attribute
* @param namespace Namespace URI of the Id
+ * @param checkMultipleElements If true then go through the entire tree and \
return + * null if there are multiple elements with the same Id
* @return The found element if there was exactly one match, or
* <code>null</code> otherwise
*/
- public static Element findElementById(Node startNode, String value, String \
namespace) {
- Element foundElement = null;
-
+ public static Element findElementById(
+ Node startNode, String value, String namespace, boolean \
checkMultipleElements + ) {
//
- // Replace the formerly recursive implementation with a depth-first-loop
- // lookup
+ // Replace the formerly recursive implementation with a depth-first-loop \
lookup //
- if (startNode == null) {
- return null;
- }
Node startParent = startNode.getParentNode();
Node processedNode = null;
+ Element foundElement = null;
while (startNode != null) {
// start node processing at this point
if (startNode.getNodeType() == Node.ELEMENT_NODE) {
Element se = (Element) startNode;
- if (se.hasAttributeNS(namespace, "Id")
- && value.equals(se.getAttributeNS(namespace, "Id"))) {
- if (foundElement == null) {
+ String attributeNS = se.getAttributeNS(namespace, "Id");
+ if (!"".equals(attributeNS) && value.equals(attributeNS)) {
+ if (!checkMultipleElements) {
+ return se;
+ } else if (foundElement == null) {
foundElement = se; // Continue searching to find duplicates
} else {
log.warn("Multiple elements with the same 'Id' attribute \
value!"); @@ -537,13 +538,30 @@
* @return the found element or null if no element with the Id exists
*/
public static Element getElementByWsuId(Document doc, String id) {
+ return getElementByWsuId(doc, id, true);
+ }
+
+ /**
+ * Search for an element given its wsu:id. <p/>
+ *
+ * @param doc the DOM document (SOAP request)
+ * @param id the Id of the element
+ * @param checkMultipleElements If true then returns null if there are multiple
+ * elements with the same id
+ * @return the found element or null if no element with the Id exists
+ */
+ public static Element getElementByWsuId(
+ Document doc, String id, boolean checkMultipleElements
+ ) {
if (id == null) {
return null;
}
id = getIDFromReference(id);
- return WSSecurityUtil.findElementById(doc.getDocumentElement(), id, \
WSConstants.WSU_NS); + return WSSecurityUtil.findElementById(
+ doc.getDocumentElement(), id, WSConstants.WSU_NS, checkMultipleElements
+ );
}
-
+
/**
* Turn a reference (eg "#5") into an ID (eg "5").
*
@@ -570,11 +588,29 @@
* @return the found element or null if no element with the Id exists
*/
public static Element getElementByGenId(Document doc, String id) {
+ return getElementByGenId(doc, id, true);
+ }
+
+ /**
+ * Search for an element given its generic id. <p/>
+ *
+ * @param doc the DOM document (SOAP request)
+ * @param id the Id of the element
+ * @param checkMultipleElements If true then returns null if there are multiple
+ * elements with the same id
+ *
+ * @return the found element or null if no element with the Id exists
+ */
+ public static Element getElementByGenId(
+ Document doc, String id, boolean checkMultipleElements
+ ) {
if (id == null) {
return null;
}
id = getIDFromReference(id);
- return WSSecurityUtil.findElementById(doc.getDocumentElement(), id, null);
+ return WSSecurityUtil.findElementById(
+ doc.getDocumentElement(), id, null, checkMultipleElements
+ );
}
/**
@@ -929,7 +965,7 @@
}
/**
- * Ensure that this covers all required elements (identified by
+ * Ensure that this covers all required elements (identified by
* their wsu:Id attributes).
*
* @param resultItem the signature to check
@@ -959,7 +995,11 @@
boolean found = false;
for (int j = 0; j < signedElemsRefList.size(); j++) {
WSDataRef dataRef = (WSDataRef)signedElemsRefList.get(j);
- if (dataRef.getWsuId().equals(requiredIDs[i])) {
+ String wsuId = dataRef.getWsuId();
+ if (wsuId.charAt(0) == '#') {
+ wsuId = wsuId.substring(1);
+ }
+ if (wsuId.equals(requiredIDs[i])) {
found = true;
}
}
Modified: webservices/wss4j/trunk/test/wssec/PackageTests.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/PackageTests.java?rev=785171&r1=785170&r2=785171&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/wssec/PackageTests.java (original)
+++ webservices/wss4j/trunk/test/wssec/PackageTests.java Tue Jun 16 12:06:08 2009
@@ -75,6 +75,7 @@
suite.addTestSuite(TestWSSecurityWSS178.class);
suite.addTestSuite(SignatureConfirmationTest.class);
suite.addTestSuite(TestWSSecurityWSS194.class);
+ suite.addTestSuite(TestModifiedRequest.class);
return suite;
}
Added: webservices/wss4j/trunk/test/wssec/TestModifiedRequest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/TestModifiedRequest.java?rev=785171&view=auto
==============================================================================
--- webservices/wss4j/trunk/test/wssec/TestModifiedRequest.java (added)
+++ webservices/wss4j/trunk/test/wssec/TestModifiedRequest.java Tue Jun 16 12:06:08 \
2009 @@ -0,0 +1,251 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * This class tests the modification of requests to see if signature verification \
fails. + */
+public class TestModifiedRequest extends TestCase implements CallbackHandler {
+ private static final Log LOG = LogFactory.getLog(TestModifiedRequest.class);
+ private static final String SOAPMSG =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + "<SOAP-ENV:Envelope "
+ + "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+ + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+ + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+ + "<SOAP-ENV:Body>"
+ + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">"
+ + "<value xmlns=\"http://blah.com\">15</value>"
+ + "</add>"
+ + "</SOAP-ENV:Body>"
+ + "</SOAP-ENV:Envelope>";
+
+ private WSSecurityEngine secEngine = new WSSecurityEngine();
+ private Crypto crypto = CryptoFactory.getInstance();
+
+ /**
+ * TestWSSecurity constructor
+ * <p/>
+ *
+ * @param name name of the test
+ */
+ public TestModifiedRequest(String name) {
+ super(name);
+ }
+
+ /**
+ * JUnit suite
+ * <p/>
+ *
+ * @return a junit test suite
+ */
+ public static Test suite() {
+ return new TestSuite(TestModifiedRequest.class);
+ }
+
+ /**
+ * Test that signs a SOAP body element "value". The SOAP request is then \
modified + * so that the signed "value" element is put in the header, and the \
value of the + * original element is changed. This test will fail as the request \
will contain + * multiple elements with the same wsu:Id.
+ */
+ public void testMovedElement() throws Exception {
+ WSSecSignature builder = new WSSecSignature();
+ builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+ LOG.info("Before Signing....");
+ Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+
+ List parts = new Vector();
+ WSEncryptionPart encP =
+ new WSEncryptionPart(
+ "value",
+ "http://blah.com",
+ "");
+ parts.add(encP);
+ builder.setParts(parts);
+
+ Document signedDoc = builder.build(doc, crypto, secHeader);
+
+ //
+ // Replace the signed element with a modified element, and move the original
+ // signed element into the SOAP header
+ //
+ org.w3c.dom.Element secHeaderElement = secHeader.getSecurityHeader();
+ org.w3c.dom.Element envelopeElement = signedDoc.getDocumentElement();
+ org.w3c.dom.Node valueNode =
+ envelopeElement.getElementsByTagNameNS("http://blah.com", \
"value").item(0); + org.w3c.dom.Node clonedValueNode = \
valueNode.cloneNode(true); + secHeaderElement.appendChild(clonedValueNode);
+ valueNode.getFirstChild().setNodeValue("250");
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("After Signing....");
+ String outputString =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+
+ try {
+ verify(signedDoc);
+ fail("Failure expected on multiple elements with the same wsu:Id");
+ } catch (Exception ex) {
+ // expected
+ }
+ }
+
+
+ /**
+ * Test that signs a SOAP body element "value". The SOAP request is then \
modified + * so that the signed "value" element is put in the header, and the \
value of the + * original element is changed. The wsu:Id value of the original \
element is also + * changed. Signature verification will pass, so we need to \
check that wsu:Id's. + */
+ public void testMovedElementChangedId() throws Exception {
+ WSSecSignature builder = new WSSecSignature();
+ builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+ LOG.info("Before Signing....");
+ Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+
+ List parts = new Vector();
+ WSEncryptionPart encP =
+ new WSEncryptionPart(
+ "value",
+ "http://blah.com",
+ "");
+ parts.add(encP);
+ builder.setParts(parts);
+
+ Document signedDoc = builder.build(doc, crypto, secHeader);
+
+ //
+ // Replace the signed element with a modified element, and move the original
+ // signed element into the SOAP header
+ //
+ org.w3c.dom.Element secHeaderElement = secHeader.getSecurityHeader();
+ org.w3c.dom.Element envelopeElement = signedDoc.getDocumentElement();
+ org.w3c.dom.Node valueNode =
+ envelopeElement.getElementsByTagNameNS("http://blah.com", \
"value").item(0); + org.w3c.dom.Node clonedValueNode = \
valueNode.cloneNode(true); + secHeaderElement.appendChild(clonedValueNode);
+ valueNode.getFirstChild().setNodeValue("250");
+ String savedId =
+ ((org.w3c.dom.Element)valueNode).getAttributeNS(WSConstants.WSU_NS, \
"Id"); + ((org.w3c.dom.Element)valueNode).setAttributeNS(
+ WSConstants.WSU_NS, "wsu:Id", "id-250"
+ );
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("After Signing....");
+ String outputString =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+
+ //
+ // Now we check that the wsu:Id of the element we want signed corresponds to \
the + // wsu:Id that was actually signed...again, this should pass
+ //
+ List results = verify(signedDoc);
+ WSSecurityEngineResult actionResult =
+ WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
+ WSSecurityUtil.checkSignsAllElements(actionResult, new String[]{savedId});
+
+ //
+ // Finally we need to check that the wsu:Id of the element we want signed in \
the + // SOAP request is the same as the wsu:Id that was actually signed
+ //
+ envelopeElement = signedDoc.getDocumentElement();
+ org.w3c.dom.Node bodyNode =
+ envelopeElement.getElementsByTagNameNS(
+ WSConstants.URI_SOAP11_ENV, "Body"
+ ).item(0);
+ valueNode =
+ ((org.w3c.dom.Element)bodyNode).getElementsByTagNameNS(
+ "http://blah.com", "value"
+ ).item(0);
+ String actualId =
+ ((org.w3c.dom.Element)valueNode).getAttributeNS(WSConstants.WSU_NS, \
"Id"); + try {
+ WSSecurityUtil.checkSignsAllElements(actionResult, new \
String[]{actualId}); + fail("Failure expected on bad wsu:Id");
+ } catch (Exception ex) {
+ // expected
+ }
+ }
+
+
+
+ /**
+ * Verifies the soap envelope
+ * <p/>
+ *
+ * @param env soap envelope
+ * @throws java.lang.Exception Thrown when there is a problem in verification
+ */
+ private List verify(Document doc) throws Exception {
+ return secEngine.processSecurityHeader(doc, null, this, crypto);
+ }
+
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof WSPasswordCallback) {
+ WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+ /*
+ * here call a function/method to lookup the password for
+ * the given identifier (e.g. a user name or keystore alias)
+ * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+ * for Testing we supply a fixed name here.
+ */
+ pc.setPassword("password");
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i], "Unrecognized \
Callback"); + }
+ }
+ }
+}
Propchange: webservices/wss4j/trunk/test/wssec/TestModifiedRequest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: webservices/wss4j/trunk/test/wssec/TestModifiedRequest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic