phpepp

Catch EPP server response after sending XML request


Currently we are developing domain registrar API.

    $options = [
        'ssl' => [
            'verify_peer' => true,
            'local_cert' => __DIR__ . '/Domain.pem',
            'local_pk' => __DIR__ . '/Domain.pem',
            'allow_self_signed' => true,
        ]
    ];
    $context = stream_context_create($options);
    $ch = stream_socket_client($serverPath.':'.$parentClass->port, $errorNumber, $errorString, 60, STREAM_CLIENT_CONNECT, $context);
    stream_set_timeout($ch, 60);

    fwrite($ch, $command);

    $data = '';

    while (!feof($ch)) {
        $data .= fread($ch, 1024);
    }

    fclose($ch);

After fwriting XML request

<epp xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<login>
<clID>User</clID>
<pw>Password</pw>
<options>
<version>1.0</version>
<lang>en</lang>
</options>
<svcs>
<objURI>urn:ietf:params:xml:ns:obj1</objURI>
<objURI>urn:ietf:params:xml:ns:obj2</objURI>
<objURI>urn:ietf:params:xml:ns:obj3</objURI>
<svcExtension>
<extURI>http://custom/obj1ext-1.0</extURI>
</svcExtension>
</svcs>
</login>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

fread gives greeting message, not status code about login request. Is this method of reading the response right? What can be a reason not getting the right answer from the server? Thanks


Solution

  • EPP does not work like you think. As a start, I recommend you take some time to read RFC5730 and 5734 in full details, they are discussed below. After you made that work, you will need a full grasp of all EPP details in RFCs 5731 5732 and 5733. Do not expect to be able to write a successful EPP client without having read all of them.

    Now back to your problem, and why you are not following EPP specifications.

    See section 2 of RFC5730, reproduced here:

              |
              V
      +-----------------+                  +-----------------+
      |   Waiting for   |     Connected    |     Prepare     |
      |      Client     |----------------->|     Greeting    |
      +-----------------+    or <hello>    +-----------------+
         ^                                           |
         | Close Connection                     Send |
         |     or Idle                      Greeting |
      +-----------------+                            V
      |       End       |     Timeout      +-----------------+
      |     Session     |<-----------------|   Waiting for   |
      +-----------------+                  |      Client     |
         ^    ^    ^        Send +-------->|  Authentication |
         |    |    |    Response |         +-----------------+
         |    |    |     +--------------+            |
         |    |    |     | Prepare Fail |            | <login>
         |    |    +-----|   Response   |            | Received
         |    |    Send  +--------------+            V
         |    |    2501          ^         +-----------------+
         |    |   Response       |         |   Processing    |
         |    |                  +---------|     <login>     |
         |    |                  Auth Fail +-----------------+
         |    |       Timeout                         |
         |    +-------------------------------+       | Auth OK
         |                                    |       V
         |   +-----------------+  <hello>  +-----------------+
         |   |     Prepare     |<----------|   Waiting for   |
         |   |     Greeting    |---------->|   Command or    |
         |   +-----------------+   Send    |     <hello>     |
         | Send x5xx             Greeting  +-----------------+
         | Response  +-----------------+  Send    ^  |
         +-----------|     Prepare     | Response |  | Command
                     |     Response    |----------+  | Received
                     +-----------------+             V
                                ^          +-----------------+
                        Command |          |   Processing    |
                      Processed +----------|     Command     |
                                           +-----------------+
    

    Said differently here is how your client should behave:

    The error in your program is that your client is speaking first, sending something to the server. This is not allowed per the above state schema, so please read the server reply first.

    So your problem is not specifically in sending XML (while you also have a problem on that, see below), first it is not respecting the order of who speaks first.

    Also do not do this:

        while (!feof($ch)) {
            $data .= fread($ch, 1024);
        }
    

    See RFC 5734 that explains how EPP is transported. In summary and to reply also to some comments above on your question:

    So when you expect a message from server you do it like that:

    But note that you need to do the same when you send content to the server! Do not send just the XML content, you need to form a proper EPP frame which means:

    Also, as a "veteran" in the industry (been there for 20 years, having written both EPP servers, clients, and having participated in the RFCs that define it), please take this advice out of experience: if your job is to connect only to a single registry, then life is simple; you may even be able to use a toolkit provided by the registry, as long as it is in a language of your choice.

    However, as soon as you need to write a client being able to properly connect to multiple registries, you will suffer pain. Even if it is a standard you will find A LOT of variations among registries, on many topics such how extended error data is reported, what EPP extensions exist and how they work, the content of responses for a domain:check, and so on, the list of small differences is just to long to enumerate here.

    For all the above reasons, you may want not to reinvent the wheel either. There are libraries that do all the EPP stuff for you, for example https://github.com/centralnic/php-epp I am not endorsing it in any way as I do not know it as I do not use PHP, but maybe it could help you, either to just reuse as is so that you do not have code to write, or at least have a look at it to see how they solved specific issues so that you can be inspired.

    For example the above issue on the length and the 4 bytes at beginning of each EPP frame, see getFrame and sendFrame in https://github.com/centralnic/php-epp/blob/master/Net/EPP/Protocol.php