Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / ASP.NET / Web Services / November 2004

Tip: Looking for answers? Try searching our database.

Single message encrypted twice

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
NetStuff - 03 Nov 2004 21:34 GMT
Problem
I want to construct a single encrypted message using X509 certs that can be
decripted by both Server1 and Server2.
When sending this message to server1, server1 should use the corresponding
server1 private key to decrypt it. At the same time when sending it to
server2, server2 should use it's own private key to decrypt it.

Repro
I simple wrote the following client code:

if (chkEncrypt.Checked)
{
    // let the user select a certificate
    X509SecurityToken x509token1 = GetSecurityToken(false);

    // encrypt the data to Server1
    svc.RequestSoapContext.Security.Elements.Add(new EncryptedData(x509token1));

    if (chkEncryptDouble.Checked)
    {

        // encrypt the data to Server2
        X509SecurityToken x509token2 = GetSecurityToken(false);
        svc.RequestSoapContext.Security.Elements.Add(new EncryptedData(x509token2));
    }
}

  // finally, make the call
  MessageBox.Show( svc.HelloWorld("erik"));

I simply deployed the service to server1 and server2 and installed the
corresponding certificates. so far so good....

However when the message hits server1 it says: cannot find private key. I
checked the traces and the message is ok. My assumption is that server1 is
trying to decrypt all security elements including the encrypted key of
server2. Of course the privatekey of server2 is not available on server1 so
it fails.

Is there an easy way to make this work, or should I add a custom filter at
the receiving end ????
Is there a sample available ?

Any help would be appreciated...
Martin Kulov - 04 Nov 2004 14:01 GMT
Hi,
I am just guessing, but it seems to me that the second time you add new EncryptedData element it will overwrite the existing one that you have created. What are you trying to achieve?

Best,
Martin Kulov
www.codeattest.com
NetStuff - 04 Nov 2004 14:29 GMT
Hi Martin

what I'm trying to achieve is to construct a single message that can be
encrypted by two servers. Doing so both server1 can decrypt the message and
forward it to server2 which can also decrypt it.
because wse uses the a pseudo assymmetric encryption  it should work if the
assymetric encryption reuses the same symmetric key that was used the first
time. In this case both private of server1 and private of server2 can be used
to open the lockbox that contains the symmetric key of the message

> Hi,
> I am just guessing, but it seems to me that the second time you add new EncryptedData element it will overwrite the existing one that you have created. What are you trying to achieve?
>
> Best,
> Martin Kulov
> www.codeattest.com
Martin Kulov - 04 Nov 2004 20:31 GMT
Can you turn on the diagnostics files and paste the outgoing message to server1 or server2?

Martin
William Stacey [MVP] - 05 Nov 2004 04:20 GMT
This should be not problem.  Actually S1 gets the message and just starts at
same place C1 was before it encrypted the symetric key(s).  So in effect S1
is now like C1 sending to S2 instead of S1 (hope that makes sense.)
Steps I would do using RSA as Example.
Send Side
1) Get RSA public key of S1.
2) Gen random Rijndael key and IV and encrypt data.
3) Encrypt keys with RSA public key.
4) Hash crypt data using SHA1 (or other) and encrypt hash bytes with public
key and store in envelope.
5) Send digital envelope to S1.

S1
1) Get message.
2) Decrypt Rijndael keys using S1 private key.
3) Verify hash and/or signature to determine if message is valid.
3) Encrypt Rijndael keys using S2's public key.
4) Gen new encrypted hash of crypt data using something like rsa.SignData()
and store.
5) Send to S2

S2
1) Decrypt keys using S2 private key.
2) Verify hash and/or signature.
3) Decrypt data using Rijndael keys.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

> Hi Martin
>
[quoted text clipped - 8 lines]
> > Hi,
> > I am just guessing, but it seems to me that the second time you add new EncryptedData element it will overwrite the existing one that you have
created. What are you trying to achieve?

> > Best,
> > Martin Kulov
> > www.codeattest.com
NetStuff - 08 Nov 2004 08:32 GMT
William, Martin,

thanks for your response. I would like to construct a solution without
introducing custom code. So my question is can I do this without introducing
custom code and simply use to statements like defined in my original post
(just add EncryptedData twice with two different tokens)

Below is the message I'm sending out from the client. The firste
EncryptedKey element is based on the public of S1. The second EncryptedKey
element is based on the public of S2. When this message hits S1 the default
WSE implementaties tries to decrypt all the keys in the message. Decypting
the second key will fail of course. Put it antoher way, is there a way to
define at S1 which key to use to decrypt the message.

Is there a configuration possibiliy to define which key to use to decrypt
incoming message or should I implement my own SecurityInputFilter ?

Here is the message I'm sending out from the client
<?xml version="1.0" encoding="utf-8"?>
<log>
 <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"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
   <soap:Header>
     <wsa:Action>http://tempuri.org/HelloWorld</wsa:Action>
     <wsa:MessageID>uuid:40caa6c7-42e6-4e56-ba96-f96c2ddb45d9</wsa:MessageID>
     <wsa:ReplyTo>
       
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address>
     </wsa:ReplyTo>
     <wsa:To>http://localhost/wseSec/wseSec.asmx</wsa:To>
     <wsse:Security soap:mustUnderstand="1">
       <wsu:Timestamp
wsu:Id="Timestamp-abe491d4-6d7b-40e2-a597-69a1c38efd80">
         <wsu:Created>2004-11-04T10:01:38Z</wsu:Created>
         <wsu:Expires>2004-11-04T10:06:38Z</wsu:Expires>
       </wsu:Timestamp>
       <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
         <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
         <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
           <wsse:SecurityTokenReference>
             <wsse:KeyIdentifier
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X
509SubjectKeyIdentifier">SkDUlwStz7Mrfv1gD8lu+6SkVOU=</wsse:KeyIdentifier
>
           </wsse:SecurityTokenReference>
         </KeyInfo>
         <xenc:CipherData>
           
<xenc:CipherValue>kuIIS9ASh3TFbd099YeoAB83G37j2eWXR0IoLSPoiFfDzIo7oQ3CowGEcGkNQQQpcq8IPDHPvWuYKmaIsYsQnFmp6oYqpFgfY8yJncCtGFJLzmWsWpipazauORHwxyWnb4Nq9R04kcv00ABoMQBp1i7algEILrVzUY+j1dq4mhw=</xenc:CipherValue>
         </xenc:CipherData>
         <xenc:ReferenceList>
           <xenc:DataReference
URI="#EncryptedContent-d3af9906-9438-4746-a4a1-90c7b3e4dafd" />
         </xenc:ReferenceList>
       </xenc:EncryptedKey>
       <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
         <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
         <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
           <wsse:SecurityTokenReference>
             <wsse:KeyIdentifier
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X
509SubjectKeyIdentifier">fzwA9+0MGnuqxoZ5TmqrInYbmPg=</wsse:KeyIdentifier
>
           </wsse:SecurityTokenReference>
         </KeyInfo>
         <xenc:CipherData>
           
<xenc:CipherValue>olL09Vy4Xu2hdW6o2euV/v4VdLHiqkCrFpqLDdjCLKN6/aEGiNlpKYLRf0cWb/uzk9RfjgqmobTUVTMotqOeqxWo4uzCmYzW/UZlMnzmy6wx5yMlBOZvYJirWhG509n0g95jLr+K43nh+za0H2ZZDz2x7SS8uSs2ltdOiQtwYlo=</xenc:CipherValue>
         </xenc:CipherData>
         <xenc:ReferenceList>
           <xenc:DataReference
URI="#EncryptedContent-2a37d734-b179-4459-8896-272c740e0cfb" />
         </xenc:ReferenceList>
       </xenc:EncryptedKey>
     </wsse:Security>
   </soap:Header>
   <soap:Body>
     <xenc:EncryptedData
Id="EncryptedContent-d3af9906-9438-4746-a4a1-90c7b3e4dafd"
Type="http://www.w3.org/2001/04/xmlenc#Content"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
       <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
       <xenc:CipherData>
         
<xenc:CipherValue>qV6SeJeh3Ar0jq3iTV8z9NnYDyJz8Z9yfNz+qiPQC2mpTYR4+lF786J6AJeWFM+p/Cy00a90HDPrEY/aBj6vUkoAU4hyJzO9VVEBsYnaUx4Hhtp1PJGc8INlCyCauibcYu3HM2azuinhQ8jgOM3MBRyXKDwS7QhJljACeuYWlx1nLiQdFYB96zKbvbOfhx36YjKVihCJgs8p+r5aedh7GdkE2EZxiEzjAw9h6NDpuFrdbNg9chjwtZLOaU8puyZ6zEhzzXVAkbWzRJfICRoWl/p16rXrLNO19cCNuSaY7C3pylm64QhDdE3e6xfLMqaNXBElLJK3/QAvA6HOBNwAhq7Xa1DtTJq2z1MBk36Itz4HxT3ksQ41IUd8sssgvtAs9kQwAvmwyjj7rehj9jOiYfd8qr2qx33VzCmJWxuKXShmReg6zXT2hUTOLLaCTfHXNjuNRg6yprBNcVq6/nxq0jxZRZsWE62qhhIDha3KuOp6us4koQbFLAaXdHEGvi9QbP/a1F7U8ljQF5a4km8uMZCBwHjx0V7bjNd6vOroxCgUUDDXu8Q7HixlsQ/Ie5OxaXsAwE2WJJuJnleIG+OigKETCUT++yT9XHIDwhrTXltVZHnkUqo2EAtrd2GmEQAM11LloS65rJvJP73HhZuTPg==</xenc:CipherValue>
       </xenc:CipherData>
     </xenc:EncryptedData>
   </soap:Body>
 </soap:Envelope>
</log>

> This should be not problem.  Actually S1 gets the message and just starts at
> same place C1 was before it encrypted the symetric key(s).  So in effect S1
[quoted text clipped - 44 lines]
> > > Martin Kulov
> > > www.codeattest.com
Softwaremaker - 15 Nov 2004 09:09 GMT
Pardon my ignorance here. I have read this post a few times BUT I still
cannot figure out what you are trying to do.

Are you
1) Trying to implement a single message meant for 2 different parties ?
2) Trying to (as your header say) encrypt a single message twice ? >>>
Alice's Boss encrypts Alice's Encrypted Message.

Both have very different and I am curious as to which you are trying to
achieve.

Signature

Thank you.

Regards,
Softwaremaker
http://www.softwaremaker.net/blog

=========================================

> William, Martin,
>
[quoted text clipped - 20 lines]
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"

xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecuri
ty-secext-1.0.xsd"

xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurit
y-utility-1.0.xsd">
>     <soap:Header>
>       <wsa:Action>http://tempuri.org/HelloWorld</wsa:Action>

<wsa:MessageID>uuid:40caa6c7-42e6-4e56-ba96-f96c2ddb45d9</wsa:MessageID>
>       <wsa:ReplyTo>

<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous
</wsa:Address>
>       </wsa:ReplyTo>
>       <wsa:To>http://localhost/wseSec/wseSec.asmx</wsa:To>
[quoted text clipped - 10 lines]
>             <wsse:SecurityTokenReference>
>               <wsse:KeyIdentifier

ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-toke
n-profile-1.0#X509SubjectKeyIdentifier">SkDUlwStz7Mrfv1gD8lu+6SkVOU=</wsse:K
eyIdentifier>
>             </wsse:SecurityTokenReference>
>           </KeyInfo>
>           <xenc:CipherData>

<xenc:CipherValue>kuIIS9ASh3TFbd099YeoAB83G37j2eWXR0IoLSPoiFfDzIo7oQ3CowGEcG
kNQQQpcq8IPDHPvWuYKmaIsYsQnFmp6oYqpFgfY8yJncCtGFJLzmWsWpipazauORHwxyWnb4Nq9R
04kcv00ABoMQBp1i7algEILrVzUY+j1dq4mhw=</xenc:CipherValue>
>           </xenc:CipherData>
>           <xenc:ReferenceList>
[quoted text clipped - 8 lines]
>             <wsse:SecurityTokenReference>
>               <wsse:KeyIdentifier

ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-toke
n-profile-1.0#X509SubjectKeyIdentifier">fzwA9+0MGnuqxoZ5TmqrInYbmPg=</wsse:K
eyIdentifier>
>             </wsse:SecurityTokenReference>
>           </KeyInfo>
>           <xenc:CipherData>

<xenc:CipherValue>olL09Vy4Xu2hdW6o2euV/v4VdLHiqkCrFpqLDdjCLKN6/aEGiNlpKYLRf0
cWb/uzk9RfjgqmobTUVTMotqOeqxWo4uzCmYzW/UZlMnzmy6wx5yMlBOZvYJirWhG509n0g95jLr
+K43nh+za0H2ZZDz2x7SS8uSs2ltdOiQtwYlo=</xenc:CipherValue>
>           </xenc:CipherData>
>           <xenc:ReferenceList>
[quoted text clipped - 12 lines]
> Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
>         <xenc:CipherData>

<xenc:CipherValue>qV6SeJeh3Ar0jq3iTV8z9NnYDyJz8Z9yfNz+qiPQC2mpTYR4+lF786J6AJ
eWFM+p/Cy00a90HDPrEY/aBj6vUkoAU4hyJzO9VVEBsYnaUx4Hhtp1PJGc8INlCyCauibcYu3HM2
azuinhQ8jgOM3MBRyXKDwS7QhJljACeuYWlx1nLiQdFYB96zKbvbOfhx36YjKVihCJgs8p+r5aed
h7GdkE2EZxiEzjAw9h6NDpuFrdbNg9chjwtZLOaU8puyZ6zEhzzXVAkbWzRJfICRoWl/p16rXrLN
O19cCNuSaY7C3pylm64QhDdE3e6xfLMqaNXBElLJK3/QAvA6HOBNwAhq7Xa1DtTJq2z1MBk36Itz
4HxT3ksQ41IUd8sssgvtAs9kQwAvmwyjj7rehj9jOiYfd8qr2qx33VzCmJWxuKXShmReg6zXT2hU
TOLLaCTfHXNjuNRg6yprBNcVq6/nxq0jxZRZsWE62qhhIDha3KuOp6us4koQbFLAaXdHEGvi9QbP
/a1F7U8ljQF5a4km8uMZCBwHjx0V7bjNd6vOroxCgUUDDXu8Q7HixlsQ/Ie5OxaXsAwE2WJJuJnl
eIG+OigKETCUT++yT9XHIDwhrTXltVZHnkUqo2EAtrd2GmEQAM11LloS65rJvJP73HhZuTPg==</
xenc:CipherValue>
>         </xenc:CipherData>
>       </xenc:EncryptedData>
[quoted text clipped - 50 lines]
> > > > Martin Kulov
> > > > www.codeattest.com
William Stacey [MVP] - 15 Nov 2004 14:50 GMT
Well I will probably take from flake for reinvending the wheel here...
Secure xml sounds like what you want.  I found it confusing so I rolled my
own xml digital envelope.  If S1 does not care about the data (just that it
is valid) then you could just sign a hash of the data using c1.  That way S1
knows C1 sent the data and data has not been changed.  As your using xml and
xml is easy to stringize, it is just a string payload and you can nest your
data.  So invision your xml class:

class DigEnv
{
     string Key;  // Encrypted with S1 public key.
     string IV;    // Encrypted with S1 public key.
     string Signature; // Signed-Hash of data using senders private key.
     string Data;    // Encrypted data with key and iv.
} // Now just use XmlSerializer to serialize and deserialize the DE.

All strings are byte[]s using base64 encoding.
1) The second (last) DigEnv could be the Data in the first.  S1 would verify
sig and decrypt the data, which is just an xml DE already created for the
S2.
-or-
2) The the keys would be encrypted using *S2's public key so only S2 can
decrypt.  Both servers could verify the Signature was C1's using C1s public
key.

This is flexible as you can encrypt data or not (if you just want to sign
for example.) And send a signature or not depending on your needs.  Your web
method may just take and return DigEnv types or what ever you come up with.
This is not dependent on any other support in wse or other as your doing it
at the data level (i.e. your own protocol.)  WSE is just passing around
strings.  Naturally, you could just use secure xml to do the same thing if
that makes more sense to use.  Have not used, but wse has ws-routing, which
sounds like something that may work for you.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

> William, Martin,
>
[quoted text clipped - 20 lines]
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"

xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecuri
ty-secext-1.0.xsd"

xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurit
y-utility-1.0.xsd">
>     <soap:Header>
>       <wsa:Action>http://tempuri.org/HelloWorld</wsa:Action>

<wsa:MessageID>uuid:40caa6c7-42e6-4e56-ba96-f96c2ddb45d9</wsa:MessageID>
>       <wsa:ReplyTo>

<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous
</wsa:Address>
>       </wsa:ReplyTo>
>       <wsa:To>http://localhost/wseSec/wseSec.asmx</wsa:To>
[quoted text clipped - 10 lines]
>             <wsse:SecurityTokenReference>
>               <wsse:KeyIdentifier

ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-toke
n-profile-1.0#X509SubjectKeyIdentifier">SkDUlwStz7Mrfv1gD8lu+6SkVOU=</wsse:K
eyIdentifier>
>             </wsse:SecurityTokenReference>
>           </KeyInfo>
>           <xenc:CipherData>

<xenc:CipherValue>kuIIS9ASh3TFbd099YeoAB83G37j2eWXR0IoLSPoiFfDzIo7oQ3CowGEcG
kNQQQpcq8IPDHPvWuYKmaIsYsQnFmp6oYqpFgfY8yJncCtGFJLzmWsWpipazauORHwxyWnb4Nq9R
04kcv00ABoMQBp1i7algEILrVzUY+j1dq4mhw=</xenc:CipherValue>
>           </xenc:CipherData>
>           <xenc:ReferenceList>
[quoted text clipped - 8 lines]
>             <wsse:SecurityTokenReference>
>               <wsse:KeyIdentifier

ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-toke
n-profile-1.0#X509SubjectKeyIdentifier">fzwA9+0MGnuqxoZ5TmqrInYbmPg=</wsse:K
eyIdentifier>
>             </wsse:SecurityTokenReference>
>           </KeyInfo>
>           <xenc:CipherData>

<xenc:CipherValue>olL09Vy4Xu2hdW6o2euV/v4VdLHiqkCrFpqLDdjCLKN6/aEGiNlpKYLRf0
cWb/uzk9RfjgqmobTUVTMotqOeqxWo4uzCmYzW/UZlMnzmy6wx5yMlBOZvYJirWhG509n0g95jLr
+K43nh+za0H2ZZDz2x7SS8uSs2ltdOiQtwYlo=</xenc:CipherValue>
>           </xenc:CipherData>
>           <xenc:ReferenceList>
[quoted text clipped - 12 lines]
> Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
>         <xenc:CipherData>

<xenc:CipherValue>qV6SeJeh3Ar0jq3iTV8z9NnYDyJz8Z9yfNz+qiPQC2mpTYR4+lF786J6AJ
eWFM+p/Cy00a90HDPrEY/aBj6vUkoAU4hyJzO9VVEBsYnaUx4Hhtp1PJGc8INlCyCauibcYu3HM2
azuinhQ8jgOM3MBRyXKDwS7QhJljACeuYWlx1nLiQdFYB96zKbvbOfhx36YjKVihCJgs8p+r5aed
h7GdkE2EZxiEzjAw9h6NDpuFrdbNg9chjwtZLOaU8puyZ6zEhzzXVAkbWzRJfICRoWl/p16rXrLN
O19cCNuSaY7C3pylm64QhDdE3e6xfLMqaNXBElLJK3/QAvA6HOBNwAhq7Xa1DtTJq2z1MBk36Itz
4HxT3ksQ41IUd8sssgvtAs9kQwAvmwyjj7rehj9jOiYfd8qr2qx33VzCmJWxuKXShmReg6zXT2hU
TOLLaCTfHXNjuNRg6yprBNcVq6/nxq0jxZRZsWE62qhhIDha3KuOp6us4koQbFLAaXdHEGvi9QbP
/a1F7U8ljQF5a4km8uMZCBwHjx0V7bjNd6vOroxCgUUDDXu8Q7HixlsQ/Ie5OxaXsAwE2WJJuJnl
eIG+OigKETCUT++yT9XHIDwhrTXltVZHnkUqo2EAtrd2GmEQAM11LloS65rJvJP73HhZuTPg==</
xenc:CipherValue>
>         </xenc:CipherData>
>       </xenc:EncryptedData>
[quoted text clipped - 50 lines]
> > > > Martin Kulov
> > > > www.codeattest.com

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.