Having looked at various pieces of code in other languages (e.g.
http://crmtroubleshoot.blogspot.co.uk/2013/07/dynamics-crm-2011-php-and-soap-using.html with
http://crmtroubleshoot.blogspot.co.uk/2013/07/dynamics-crm-2011-php-and-soap-calls.html and
http://blogs.msdn.com/b/girishr/archive/2011/02/04/connecting-to-crm-online-2011-web-services-using-soap-requests-only.aspx), I've cobbled this together, which logs into CRM Dynamics from Perl:
use strict;
use warnings;
use WWW::Curl::Easy;
use Data::GUID;
use Date::Manip;
use XML::Simple;
use Data::Dumper;
sub make_guid {
my $guidobj = Data::GUID->new;
return $guidobj->as_string;
}
sub curl_request {
my ($url,$data) = @_;
my $headers = [
'Connection: Keep-Alive',
"Content-type: application/soap+xml; charset=UTF-8",
"Content-length: " . length($data),
];
my $curl = WWW::Curl::Easy->new;
$curl->setopt(CURLOPT_URL, $url);
$curl->setopt(CURLOPT_TIMEOUT, 60);
$curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);
$curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
$curl->setopt(CURLOPT_SSLVERSION, 3);
$curl->setopt(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
$curl->setopt(CURLOPT_HTTPHEADER, $headers);
$curl->setopt(CURLOPT_POST, 1);
$curl->setopt(CURLOPT_POSTFIELDS, $data);
my $response_body;
$curl->setopt(CURLOPT_WRITEDATA,\$response_body);
my $retcode = $curl->perform;
return $retcode, $response_body;
}
my $guid = make_guid;
my $reqguid = make_guid;
my $region = 'urn:crmemea:dynamics.com'; # use your region
my $username = 'youremailaddress';
my $password = 'yourpassword';
my $host = "yourhost.crm4.dynamics.com"; # use crm5 etc depending on r
+egion
my $loginurl = 'https://login.microsoftonline.com/RST2.srf';
my $serviceurl = "https://$host/XRMServices/2011/Organization.svc";
my $OCPRequest = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-
+envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="htt
+p://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utili
+ty-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/200
+5/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:' . $guid . '</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:A
+ddress>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://login.microsoftonline.com/RST
+2.srf</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open
+.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>'. UnixDate(ParseDate("now"), "%Y-%m-%dT%H:%M:%S").'
+Z</u:Created>
<u:Expires>' . UnixDate(ParseDate("24 hours"), "%Y-%m-%dT%H:%M
+:%S") . 'Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-cdb639e6-f9b0-4c01-b454-0fe244de73
+af-1">
<o:Username>' . $username . '</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-
+200401-wss-username-token-profile-1.0#PasswordText">' . $password . '
+</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2
+005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/0
+9/policy">
<a:EndpointReference>
<a:Address>'. $region .'</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Iss
+ue</t:RequestType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>';
my ($retcode, $response);
($retcode, $response) = curl_request($loginurl, $OCPRequest);
if ($retcode) {
die("An error logging in\n");
}
my $xml = XMLin($response);
my $cipher1 = $xml->{"S:Body"}{'wst:RequestSecurityTokenResponse'}{'ws
+t:RequestedSecurityToken'}{'EncryptedData'}{'ds:KeyInfo'}{'EncryptedK
+ey'}{'CipherData' }{'CipherValue'};
my $cipher2 = $xml->{"S:Body"}{'wst:RequestSecurityTokenResponse'}{'ws
+t:RequestedSecurityToken'}{'EncryptedData'}{ 'CipherData'}{'CipherVal
+ue'};
my $keyidentifier = $xml->{"S:Body"}{'wst:RequestSecurityTokenResponse
+'}{'wst:RequestedSecurityToken'}{'EncryptedData'}{ 'ds:KeyInfo'}{'Enc
+ryptedKey'}{'ds:KeyInfo'}{'wsse:SecurityTokenReference'}{'wsse:KeyIde
+ntifier'}{'content'};
my $action = "Execute"; # or Retrieve, Create etc
my $envelope_start = '
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-en
+velope"
xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-
+200401-wss-wssecurity-utility-1.0.xsd">';
my $crmSoapRequestHeader = '
<s:Header>
<a:Action s:mustUnderstand="1">
http://schemas.microsoft.com/xrm/2011/Contracts/Se
+rvices/IOrganizationService/' . $action . '</a:Action>
<a:MessageID>
urn:uuid:' . $reqguid . '</a:MessageID>
<a:ReplyTo>
<a:Address>
http://www.w3.org/2005/08/addressing/anonymous</
+a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">
' . $serviceurl . '</a:To>
<o:Security s:mustUnderstand="1"
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oa
+sis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>' .UnixDate(ParseDate("now"), "%Y-%
+m-%dT%H:%M:%S") . 'Z</u:Created>
<u:Expires>' . UnixDate(ParseDate("24 hours"),
+ "%Y-%m-%dT%H:%M:%S") . 'Z</u:Expires>
</u:Timestamp>
<EncryptedData Id="Assertion0"
Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org
+/2001/04/xmlenc#tripledes-cbc">
</EncryptionMethod>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/0
+9/xmldsig#">
<EncryptedKey>
<EncryptionMethod Algorithm="http://www.w3
+.org/2001/04/xmlenc#rsa-oaep-mgf1p">
</EncryptionMethod>
<ds:KeyInfo Id="keyinfo">
<wsse:SecurityTokenReference xmlns:wsse=
+"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-s
+ecext-1.0.xsd">
<wsse:KeyIdentifier EncodingType="http
+://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-secu
+rity-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/
+wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIde
+ntifier">
' . $keyidentifier . '
</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<CipherData>
<CipherValue>
' . $cipher1 . '
</CipherValue>
</CipherData>
</EncryptedKey>
</ds:KeyInfo>
<CipherData>
<CipherValue>
' . $cipher2 . '
</CipherValue>
</CipherData>
</EncryptedData>
</o:Security>
</s:Header>
';
my $retrieveMultipleRequestBodyTemplate ='
<s:Body>
<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Ser
+vices" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<request i:type="b:WhoAmIRequest" xmlns:a="http://schemas.microsof
+t.com/xrm/2011/Contracts" xmlns:b="http://schemas.microsoft.com/crm/2
+011/Contracts">
<a:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/Sy
+stem.Collections.Generic" />
<a:RequestId i:nil="true" />
<a:RequestName>WhoAmI</a:RequestName>
</request>
</Execute>
</s:Body>
';
my $envelope_end = ' </s:Envelope>';
($retcode, $response) = curl_request($serviceurl,$envelope_start . $cr
+mSoapRequestHeader . $retrieveMultipleRequestBodyTemplate . $envelope
+_end);
if ($retcode == 0) {
print("Transfer went ok\n");
print("Received response: $response\n");
} else {
print("An error happened: $retcode \n");
print $envelope_start . $crmSoapRequestHeader . $retrieveMultipleRe
+questBodyTemplate . $envelope_end
}