Skip to content

Commit

Permalink
Modify the security fix to support both SOAP protocols
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuvindu committed Oct 11, 2024
1 parent 850e22a commit 8ce2ab1
Show file tree
Hide file tree
Showing 15 changed files with 143 additions and 270 deletions.
8 changes: 2 additions & 6 deletions ballerina/modules/soap11/tests/http_secured_service.bal
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ import ballerina/http;

service / on new http:Listener(9091) {

resource function post .() returns xml|error {
return xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:MustUnderstand</faultcode><faultstring>System.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood.
at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client)
at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance()
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring></soap:Fault></soap:Body></soap:Envelope>`;
resource function post .(http:Request request) returns xml|error {
return check request.getXmlPayload();
}
}
137 changes: 28 additions & 109 deletions ballerina/modules/soap11/tests/soap11_client_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certifi
const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding";
const wssec:NoPolicy NO_POLICY = "NoPolicy";

const KEY_STORE_PATH_2 = "modules/wssec/tests/resources/keystore.jks";
const ALIAS = "mykey";
const PASSWORD = "password";

const crypto:KeyStore clientKeyStore = {
path: X509_KEY_STORE_PATH_2,
password: KEY_PASSWORD
Expand Down Expand Up @@ -326,38 +330,6 @@ function testSendReceiveError() returns error? {
test:assertEquals((<Error>response).message(), SOAP_ERROR);
}

@test:Config {
groups: ["soap11", "send_receive"]
}
function testSendReceiveWithTimestampTokenSecurity() returns error? {
Client soapClient = check new ("http://localhost:9091",
{
outboundSecurity: [
{
timeToLive: 600
}
]
}
);
xml body = xml `<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
<quer:Add xmlns:quer="http://tempuri.org/">
<quer:intA>2</quer:intA>
<quer:intB>3</quer:intB>
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml expected = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:MustUnderstand</faultcode><faultstring>System.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood.
at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client)
at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance()
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring></soap:Fault></soap:Body></soap:Envelope>`;
test:assertEquals(response.toString(), expected.toString());
}

@test:Config {
groups: ["soap11", "send_receive"]
}
Expand All @@ -372,7 +344,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? {
inboundSecurity: {}
}
);
xml body = xml `<soap:Envelope
xml envelope = xml `<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
Expand All @@ -382,43 +354,33 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? {
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml expected = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:MustUnderstand</faultcode><faultstring>System.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood.
at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client)
at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance()
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring></soap:Fault></soap:Body></soap:Envelope>`;
test:assertEquals(response.toString(), expected.toString());
xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add");
xmlns "http://schemas.xmlsoap.org/soap/envelope" as soap11;
error? assertUsernameToken = soap:assertUsernameToken(response.toString(), "user", "password", soap:TEXT, (envelope/<soap11:Body>/*).toString());
test:assertTrue(assertUsernameToken !is error);
}

@test:Config {
groups: ["soap11", "send_receive"]
groups: ["soap11", "send_receive", "new"]
}
function testSendReceiveWithAsymmetricBindingSecurity() returns error? {
crypto:KeyStore serverKeyStore = {
path: X509_KEY_STORE_PATH,
password: KEY_PASSWORD
};

crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS);

crypto:KeyStore clientKeyStore = {
path: X509_KEY_STORE_PATH_2,
password: KEY_PASSWORD
};
crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD);

Client soapClient = check new ("http://localhost:9091",
{
outboundSecurity: {
signatureAlgorithm: soap:RSA_SHA256,
encryptionAlgorithm: soap:RSA_ECB,
signatureKey: clientPrivateKey,
encryptionKey: serverPublicKey
signatureConfig: {
keystore: {
path: KEY_STORE_PATH_2,
password: PASSWORD
},
privateKeyAlias: ALIAS,
privateKeyPassword: PASSWORD,
signatureAlgorithm: wssec:RSA_SHA512,
canonicalizationAlgorithm: wssec:C14N_EXCL_OMIT_COMMENTS,
digestAlgorithm: wssec:SHA512
}
}
}
);

xml body = xml `<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
Expand All @@ -430,57 +392,14 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? {
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml expected = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:MustUnderstand</faultcode><faultstring>System.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood.
at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client)
at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance()
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring></soap:Fault></soap:Body></soap:Envelope>`;
test:assertEquals(response.toString(), expected.toString());
}

@test:Config {
groups: ["soap11", "send_receive"]
}
function testSendReceiveWithSymmetricBindingSecurity() returns error? {
crypto:KeyStore serverKeyStore = {
path: X509_KEY_STORE_PATH,
password: KEY_PASSWORD
};
crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS);

crypto:KeyStore keyStore = {
path: KEY_STORE_PATH,
password: KEY_PASSWORD
};
crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD);

Client soapClient = check new ("http://localhost:9091",
{
outboundSecurity: {
signatureAlgorithm: soap:RSA_SHA256,
encryptionAlgorithm: soap:RSA_ECB,
symmetricKey: symmetricKey,
servicePublicKey: serverPublicKey
}
wssec:InboundConfig inboundConfig = {
keystore: {
path: KEY_STORE_PATH_2,
password: PASSWORD
}
);
xml body = xml `<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
<quer:Add xmlns:quer="http://tempuri.org/">
<quer:intA>2</quer:intA>
<quer:intB>3</quer:intB>
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml expected = xml `<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:MustUnderstand</faultcode><faultstring>System.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood.
at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client)
at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance()
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring></soap:Fault></soap:Body></soap:Envelope>`;
test:assertEquals(response.toString(), expected.toString());
};
boolean verifySignature = check wssec:verifySignature(response, inboundConfig);
test:assertTrue(verifySignature);
}

@test:Config {
Expand Down
2 changes: 1 addition & 1 deletion ballerina/modules/soap12/soap12.bal
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public isolated client class Client {
} external;

isolated function generateResponse(xml|mime:Entity[] body, string? action = (),
map<string|string[]> headers = {}, string path = "")
map<string|string[]> headers = {}, string path = "")
returns xml|mime:Entity[]|Error {
do {
xml securedBody;
Expand Down
9 changes: 2 additions & 7 deletions ballerina/modules/soap12/tests/http_secured_service.bal
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,7 @@ import ballerina/http;

service / on new http:Listener(9091) {

resource function post .() returns xml|error {
return xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:Sender</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.Web.Services.Protocols.SoapException: Unable to handle request without a valid action parameter. Please supply a valid soap action.
at System.Web.Services.Protocols.Soap12ServerProtocolHelper.RouteRequest()
at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean&amp; abortProcessing)</soap:Text></soap:Reason><soap:Detail/></soap:Fault></soap:Body></soap:Envelope>`;
resource function post .(http:Request request) returns xml|error {
return check request.getXmlPayload();
}
}
Loading

0 comments on commit 8ce2ab1

Please sign in to comment.