nuSOAP: Header Authentication on server side - php

Can any one please advice how to parse nuSOAP headers and checking the username/password/Signature from the below SOAP Request
<SOAP-ENV:Header>
<SOAP-ENV:Header xmlns:wsa="http://admin.example.com">
<Username>testuser</Username>
<Password>test123456</Password>
<Signature>5595610031002</Signature>
</SOAP-ENV:Header>
</SOAP-ENV:Header>
i.e: i need to parse this header on server side and validate the credentials for every request.

Am not sure but i found an alternative to track the credentials by using the following code.
let me explain.
The code $sSoapRequest = file_get_contents('php://input'); which returns the entire SOAP request to the server side...
The following 2 functions helps me to bring out the values..
function doAuthenticate()
{
$sSoapRequest = file_get_contents('php://input');
if(isset($sSoapRequest))
{
$sUsername = hookTextBetweenTags($sSoapRequest, 'Username');
$sPassword = hookTextBetweenTags($sSoapRequest, 'Password');
$sSignature = hookTextBetweenTags($sSoapRequest, 'Signature');
if($sUsername=='testuser' && $sPassword=='test123456' && $sSignature=='5595610031002')
return true;
else
return false;
}
}
function hookTextBetweenTags($string, $tagname) {
$pattern = "/<$tagname ?.*>(.*)<\/$tagname>/";
preg_match($pattern, $string, $matches);
return $matches[1];
}
and, use doAuthenticate() method for every process in server side.

Related

Unrecognized soap action

I am not familiar with SOAP webservices and I need to send a request to one.
I wrote the next snippet:
# WSDL http://webservices.sathomologa.sef.sc.gov.br/wsDfeSiv/Recepcao.asmx?WSDL
$this->client = new SoapClient(static::SERVICE_WSDL, ['exceptions' => 0]);
# Raw XML data
$data = $this->xml->saveXML();
# URL http://webservices.sathomologa.sef.sc.gov.br/wsDfeSiv/Recepcao.asmx
$location = static:SERVICE_URL;
$action = static::SERVICE_URL . '?op=Enviar';
$v = SOAP_1_1;
$response = $this->client->__doRequest($data, $location, $action, $v);
And I get the next test response:
soap:ClientServer did not recognize the value of HTTP Header
SOAPAction:
http://webservices.sathomologa.sef.sc.gov.br/wsDfeSiv/Recepcao.asmx?op=Enviar.
Any ideas?
Reading the specification of Enviar method, i saw the next header:
SOAPAction: "http://tempuri.org/Enviar"
So, i changed $action = static::SERVICE_URL . '?op=Enviar'; to $action = http://tempuri.org/Enviar; and works for me.

Calling REST API to retrieve data from a website using URL and parameters

Hi I have to get an information from a website using url and login parameters and some XML parameters as input Using a PHP. I am new to any API calls so please explain me how can I use these parameters in my PHP code and make a request to a server to get the information
When I use these in SOAP UI I can get the demo result, I need to build the same in PHP.
https://transact-prelive.litle.com/vap/communicator/online
Username: u82917418420715660
Password: dENteSXnXwfqKHF
Merchant Id: 01183990
<litleOnlineRequest version="9.4" xmlns="http://www.litle.com/schema" merchantId="01183990">
<authentication>
<user>u82917418420715660</user>
<password>dENteSXnXwfqKHF</password>
</authentication>
<authorization id="834262" reportGroup="ABC Division" customerId="038945">
<orderId>65347567</orderId>
<amount>40000</amount>
<orderSource>3dsAuthenticated</orderSource>
<billToAddress>
<name>John Smith</name>
<addressLine1>100 Main St</addressLine1>
<city>Boston</city>
<state>MA</state>
<zip>12345</zip>
<email>jsmith#someaddress.com</email>
<phone>555-123-4567</phone>
</billToAddress>
<card>
<type>VI</type>
<number>4000000000000001</number>
<expDate>1209</expDate>
<cardValidationNum>555</cardValidationNum>
</card>
<cardholderAuthentication>
<authenticationValue></authenticationValue>
<authenticationTransactionId></authenticationTransactionId>
</cardholderAuthentication>
</authorization>
</litleOnlineRequest>
You can use nusoap library to use SOAP with PHP. Here is an example how you can use it. It is just similar to your query.
$this->load->library("lib_nusoap");
$wsdl = "https://transact-prelive.litle.com/vap/communicator/online";
$client = new nusoap_client($wsdl, 'wsdl');
//$client->setCredentials($api_username,$api_password);
$error = $client->getError();
if ($error)
{
echo "\nSOAP Error\n".$error."\n";
return false;
}
else
{
$params = array ('user' => "u82917418420715660 ", 'Password' => "dENteSXnXwfqKHF ");
$result = $client->call('retrive', $params);
if ($client->fault)
{
print_r($result);
print $client->fault;
}
else
{
$result_arr = json_decode($result, true);
}
}
print_r($result_arr);
Nusoap library will handle CURL API call.

PHP stream_get_contents from TCP client hangs if called more than once

I am writing a program that connects to a tcp server with stream_socket_client in php. My problem is that if I echo the contents of the $client object before I perform any additional fwrites, the page hangs. Currently it will work if I send all of my requests before calling stream_get_contents, but once I call stream_get_contents, its like the client no longer responds? I would be thankful for any help given.
**EDIT
This is the API I am using:
https://www.onlinenic.com/cp_english/template_api/download/ONLINENIC_API2.0.pdf
**EDIT
//see full code below
//------Client creation code, precho function
function getTESTClient($address, $port)
{
$client = stream_socket_client("$address:$port", $errno, $errorMessage);
if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}
return $client;
}
function precho($s)
{
echo "<pre>";
echo $s;
echo "</pre>";
}
//-------Problem code
//$loginRequest, $domainAvailableRequest, and $logoutRequest - see full code below
//-----------------------------------------
$address = "www.somesite.com";//This is where I would fill in the address
$port = "12345";//This is where I would fill in the port
$client = getTESTClient($address, $port);
//-----------------------------------------
fwrite($client, $loginRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $domainAvailableRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $logoutRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fclose($client);
//-------Alternative working code, if I read all responses at once...
//*But I want to be able to read each response individually...
fwrite($client, $loginRequest);
fwrite($client, $domainAvailableRequest);
fwrite($client, $logoutRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fclose($client);
Full Code:
<?php
function getDomainType($ext)
{
$domaintypes = ['com'=>0, 'net'=>0, 'org'=>807, 'biz'=>800, 'info'=>805, 'us'=>806, 'in'=>808,
'mobi'=>903, 'eu'=>902, 'asia'=>905, 'me'=>906, 'name'=>804, 'tel'=>907, 'cc'=>[600,610], 'tv'=>400,
'tw'=>302, 'uk'=>901, 'co'=>908, 'xxx'=>930, 'pw'=>940, 'club'=>740, 'bike'=>2001, 'clothing'=>2002,
'guru'=>2003, 'holdings'=>2004, 'plumbing'=>2005, 'singles'=>2006, 'ventures'=>2007, 'camera'=>2008,
'equipment'=>2009, 'estate'=>2010, 'gallery'=>2011, 'graphics'=>2012, 'lighting'=>2013, 'photography'=>2014,
'construction'=>2015, 'contractors'=>2016, 'site'=>950, 'online'=>951, 'sex'=>936,
'directory'=>2017, 'kitchen'=>2018, 'land'=>2019, 'technology'=>2020, 'today'=>2021, 'diamonds'=>2022,
'enterprises'=>2023, 'tips'=>2024, 'voyage'=>2025, 'careers'=>2026, 'photos'=>2027,
'recipes'=>2028, 'shoes'=>2029, 'cab'=>2030, 'company'=>2031, 'domains'=>2032, 'limo'=>2033,
'academy'=>2034, 'center'=>2035, 'computer'=>2036, 'management'=>2037, 'systems'=>2038,
'builders'=>2039, 'email'=>2040, 'solutions'=>2041, 'support'=>2042, 'training'=>2043, 'camp'=>2044,
'education'=>2045, 'glass'=>2046, 'institute'=>2047, 'repair'=>2048, 'coffee'=>2049, 'florist'=>2050,
'house'=>2051, 'international'=>2052, 'solar'=>2053, 'marketing'=>2054, 'viajes'=>2055, 'farm'=>2056,
'codes'=>2057, 'cheap'=>2058, 'zone'=>2059, 'agency'=>2060, 'bargains'=>2061, 'boutique'=>2062,
'cool'=>2063, 'watch'=>2064, 'works'=>2065, 'expert'=>2066, 'foundation'=>2067, 'exposed'=>2068,
'villas'=>2069, 'flights'=>2070, 'rentals'=>2071, 'cruises'=>2072, 'vacations'=>2073, 'condos'=>2074,
'properties'=>2075, 'maison'=>2076, 'tienda'=>2077, 'dating'=>2078, 'events'=>2079, 'partners'=>2080,
'productions'=>2081, 'community'=>2082, 'catering'=>2083, 'cards'=>2084, 'cleaning'=>2085, 'tools'=>2086,
'industries'=>2087, 'parts'=>2088, 'supplies'=>2089, 'supply'=>2090, 'report'=>2091, 'vision'=>2092,
'fish'=>2093, 'services'=>2094, 'capital'=>2095, 'engineering'=>2096, 'exchange'=>2097, 'gripe'=>2098,
'associates'=>2099, 'lease'=>2100, 'media'=>2101, 'pictures'=>2102, 'reisen'=>2103, 'toys'=>2104,
'university'=>2105, 'town'=>2106, 'wtf'=>2107, 'fail'=>2108, 'financial'=>2109, 'limited'=>2110,
'care'=>2111, 'clinic'=>2112, 'surgery'=>2113, 'dental'=>2114, 'tax'=>2115, 'cash'=>2116,
'fund'=>2117, 'investments'=>2118, 'furniture'=>2119, 'discount'=>2120, 'fitness'=>2121, 'schule'=>2122,
'sexy'=>2500, 'tattoo'=>2501, 'link'=>2502, 'guitars'=>2503, 'gift'=>2504, 'pics'=>2505, 'photo'=>2506,
'christmas'=>2507, 'blackfriday'=>2508, 'hiphop'=>2509, 'juegos'=>2510, 'audio'=>2511, 'click'=>2512,
'hosting'=>2513, 'property'=>2514, 'top'=>770, 'porn'=>932, 'adult'=>934, 'city'=>2129, 'ceo'=>742];
if(isset($domaintypes[strtolower($ext)]))
{
return $domaintypes[strtolower($ext)];
}
return "unknown";
}
function getTCPClient()
{
}
function getTESTClient($address, $port)
{
$client = stream_socket_client("$address:$port", $errno, $errorMessage);
if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}
return $client;
}
function uniqueInvoiceID()
{
$legend = "0123456789";
$len = 22;
$result = "";
for($i=0;$i<$len;$i++)
{
$result .= $legend[rand(0,9)];
}
return "client".$result;
}
function precho($s)
{
echo "<pre>";
echo $s;
echo "</pre>";
}
$clid = "135610";//OnlineNic's test account username
$clpass = "654123";//OnlineNic's test account password
$cltrid = uniqueInvoiceID();//Client Record ID/Invoice
echo $cltrid."<br><br>";
//md5(clid + md5(clpass) + cltrid + “login”)
$checkSumLogin = md5($clid.md5($clpass).$cltrid."login");//Checksum
$checkSumLogout = md5($clid.md5($clpass).$cltrid."logout");//Checksum
$loginRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<request>
<category>client</category>
<action>Login</action>
<params>
<param name=\"clid\">$clid</param>
</params>
<cltrid>$cltrid</cltrid>
<chksum>$checkSumLogin</chksum>
</request>";
$logoutRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<request>
<category>client</category>
<action>Logout</action>
<params>
<param name=\"clid\">$clid</param>
</params>
<cltrid>$cltrid</cltrid>
<chksum>$checkSumLogout</chksum>
</request>";
$checkDomain = "somedomain.com";
$ext = "com";
$dType = getDomainType($ext);
$requestID = uniqueInvoiceID();
$domainAvailChecksum = md5($clid.md5($clpass).$requestID."checkdomain".$dType.$checkDomain);
$domainAvailableRequest = "<?xml version=\"1.0\"?>
<request>
<category>domain</category>
<action>CheckDomain</action>
<params>
<param name=\"domaintype\">$dType</param>
<param name=\"domain\">$checkDomain</param>
</params>
<cltrid>$requestID</cltrid>
<chksum>$domainAvailChecksum</chksum>
</request>";
$client = getTESTClient("tcp://ote.onlinenic.com", "30009");
fwrite($client, $loginRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $domainAvailableRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $logoutRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fclose($client);
?>
The second parameter to stream_get_contents is $maxlength, the maximum number of bytes to read. When not set (or the default of -1 is passed), the entire stream is read, up to the end of the stream.
This means that stream_get_contents will continue to read all the data from the stream until there is no more, when the stream is closed by the other end. (stream_get_contents does not know the details of your protocol, so it can not know that it is "supposed" to stop reading after "one response" from the server; it doesn't have any concept of what that even means.)
This means, if you have a query-response protocol on your TCP connection, you will have to either stream_get_contents() exactly the length of data you want to receive (if you know exactly what the response size will be), or you will have to read the data from the server and process it it yourself.
How exactly you do that is going to depend greatly on your protocol. If it is line-oriented, you can use fgets($client) to retrieve one line at a time. If it is a binary protocol, you can use stream_get_contents($client, $sizeOfYourPacket).
Since you have an XML-based protocol, you will probably want to create a new function that handles reading responses and that understands XML, so that it knows how much data to read and when it can send the response (possibly already processed) back to your application.
Without actually having credentials, it's a little hard to see how exactly the server behaves, so beyond this, you're going to have to experiment.

Checking Response from php curl_exec()?

I have the following cUrl function call that is returning the response code.
$result = curl_exec($ch);
I need to check the $result for the following response property.
<isValidPost>true</isValidPost>
I could always parse through and check for that exact string, but is there an alternative way to check this?
Presuming that the API is set in stone (i.e. won't change at a moment's notice), in this case it's probably safe to a simple string search
if (false !== strpos($result, '<isValidPost>true</isValidPost>')) {
However, to do this in a more reliable way, you may want to do DOM parsing:
$dom = new DOMDocument;
$dom->parseXML($result);
$isValidPostTag = $dom->getElementsByTagName('isValidPost')->item(0);
if ($isValidPostTag) {
$isValidPost = $isValidPostTag->nodeValue == 'true';
} else {
$isValidPost = false;
}
Are you getting XML response? Then parse the XML
$xml = new SimpleXMLElement($result);
if(isset($xml->your_element->isValidPost)){
//do what you need
}

HTTP Digest authenticating in PHP

I want to authenticate to another site using HTTP Digest authorization in PHP script.
My function has as parameter just content of the WWW-Authenticate header and I want to generate correct response (Authorization header). I have found many examples that explain how to implement this the other way (browser authenticate to my script) but not this way. I am missing function that is able to parse WWW-Authenticate header content a generate response. Is there some standard function or common library that implements this?
Ok, no answer yet, I have investigated python implementation that lied around here and rewrite it to PHP. It is the simplest possible piece of code. Supports only md5 hashing, but works for me:
function H($param) {
return md5($param);
}
function KD($a,$b) {
return H("$a:$b");
}
function parseHttpDigest($digest) {
$data = array();
$parts = explode(", ", $digest);
foreach ($parts as $element) {
$bits = explode("=", $element);
$data[$bits[0]] = str_replace('"','', $bits[1]);
}
return $data;
}
function response($wwwauth, $user, $pass, $httpmethod, $uri) {
list($dummy_digest, $value) = split(' ', $wwwauth, 2);
$x = parseHttpDigest($value);
$realm = $x['realm'];
$A1 = $user.":".$realm.":".$pass;
$A2 = $httpmethod.":".$uri;
if ($x['qop'] == 'auth') {
$cnonce = time();
$ncvalue = 1;
$noncebit = $x['nonce'].":".$ncvalue.":".$cnonce.":auth:".H($A2);
$respdig = KD(H($A1), $noncebit);
}else {
# FIX: handle error here
}
$base = 'Digest username="'.$user.'", realm="';
$base .= $x['realm'].'", nonce="'.$x['nonce'].'",';
$base .= ' uri="'.$uri.'", cnonce="'.$cnonce;
$base .= '", nc="'.$ncvalue.'", response="'.$respdig.'", qop="auth"';
return $base;
}
Usage:
# TEST
$www_header = 'Digest realm="TEST", nonce="356f2dbb8ce08174009d53c6f02c401f", algorithm="MD5", qop="auth"';
print response($www_header, "user", "password", "POST", "/my_url_query");
Don't know of a ready-made client-side implementation in PHP; you have to implement the RFC as if your script were the browser, authenticating to a remote server. Wikipedia's page on HTTP Digest has a nice example.
(it's not that hard - a couple of MD5 hashes. Some gotchas I encontered when building the server-side: string delimiter is ":" (colon), request method is also a part of the hash)

Categories