NAME
Net::AS2 - AS2 Protocol implementation (RFC 4130) used in Electronic Data Exchange (EDI)
VERSION
This documentation is for AS2 Protocol Version 1.0.
SYNOPSIS
### Create an AS2 handler
my $as2 = Net::AS2->new(
MyId => 'alice',
MyKey => '...RSA KEY in PEM...',
MyCert => '...X509 Cert in PEM...'
PartnerId => 'bob',
CertificateDirectory => '/etc/AS2',
PartnerCertFile => 'partner.certificate.file',
);
### Sending Message (Sync MDN)
my $mdn = $as2->send($body, Type => 'application/xml', MessageId => 'my-message-id-12345@localhost')
### Receiving MDN (Async MDN)
my $mdn = $as2->decode_mdn($headers, $body);
### Receiving Message and sending MDN
my $message = $as2->decode_message($headers, $post_body);
if ($message->is_success) {
print $message->content;
}
if ($message->is_mdn_async) {
# ASYNC MDN is expected
# stored the state for later use
my $state = $message->serialized_state;
# ...in another perl instance...
my $message = Net::AS2::Message->create_from_serialized_state($state);
$as2->send_async_mdn(
$message->is_success ?
Net::AS2::MDN->create_success($message) :
Net::AS2::MDN->create_from_unsuccessful_message($message),
'id-23456@localhost'
);
} else
{
# SYNC MDN is expected
my ($new_headers, $mdn_body) = $as2->prepare_sync_mdn(
$message->is_success ?
Net::AS2::MDN->create_success($message) :
Net::AS2::MDN->create_from_unsuccessful_message($message),
'id-23456@localhost'
);
# ... Send headers and body ...
}
DESCRIPTION
This is a class for handling AS2 (RFC 4130) communication - sending message (optionally sign and encrypt), decoding Message Disposition Notification. Receiving message and produce corresponding Message Disposition Notification.
Protocol Introduction
AS2 is a protocol that defines communication over HTTP(s), and optionally using SMIME as payload container, plus a mandated multipart/report machine readable Message Disposition Notification response (MDN).
When encryption and signature are used in SMIME payload (agree between parties), as well as a signed MDN, the protocol offers data confidentiality, data integrity/authenticity, non-repudiation of origin, and non-repudiation of receipt over HTTP.
In AS2, MDN can only be signed but not encrypted, some MIME headers are also exposed in the HTTP headers when sending. Use HTTPS if this is a concerns.
Encryption and Signature are done in PKCS7/SMIME favor. The certificate are usually exchanged out of band before establishing communication. The certificates could be self-signed.
PUBLIC INTERFACE
Constructor
- $as2 = Net::AS2->new(%ARGS)
-
Create an AS2 handler. For preparing keys and certificates, see Preparing Certificates
The arguments are:
- MyId
-
Required. Your AS2 name. This will be used in the AS2-From header.
- PartnerId
-
Required. The AS2 name of the partner. This will be used in the AS2-To header.
- PartnerUrl
-
Required. The Url of partner where message would be sent to.
- MyKey
-
Required. Our private key in PEM format. Please includes the
-----BEGIN RSA PRIVATE KEY-----
and-----END RSA PRIVATE KEY-----
line. - MyEncryptionKey, MySignatureKey
-
Optional. Different private keys could be used for encryption and signing.
MyKey
will be used if not independently supplied. - MyCertificate
-
Required. Our corresponding certificate in PEM format. Please includes the
-----BEGIN CERTIFICATE-----
and-----END CERTIFICATE-----
line. - MyEncryptionCertificate, MySignatureCertificate
-
Optional. Different certificate could be used for encryption and signing.
MyCertificate
will be used if not independently supplied. - PartnerCertificate
-
Required. Partner's certificate in PEM format. Please includes the
-----BEGIN CERTIFICATE-----
and-----END CERTIFICATE-----
line. - PartnerEncryptionCertificate, PartnerSignatureCertificate
-
Optional. Different certificate could be used for encryption and signing. If so, load them here. PartnerCertificate will be used if not independently supplied.
- CertificateDirectory
-
A directory from which the private key and public certificate files may be read from.
- MyKeyFile
-
Sets
MyKey
using a filename or pattern that contains the private key.The files are located under
CertificateDirectory
. - MyEncryptionKeyFile, MySignatureKeyFile
-
Optional. Sets
MyEncryptionKey
and/orMySignatureKey
using a filename or pattern that contains the private keys. MyKeyFile will be used if not supplied. - MyCertificateFile
-
Sets
MyCertificate
using a filename or pattern that contains the corresponding public certificate.The files are located under
CertificateDirectory
. - MyEncryptionCertificateFile, MySignatureCertificateFile
-
Optional. Sets
MyEncryptionCertificate
and/orMySignatureCertificate
using a filename or pattern that contains the certificate files for encryption and signing. MyCertificateFile will be used if not independently supplied. - PartnerCertificateFile
-
Sets
PartnerCertificate
using a filename or pattern that contains the partner's public certificate.The files are located under
CertificateDirectory
. - PartnerEncryptionCertificateFile, PartnerSignatureCertificateFile
-
Optional. Sets
PartnerEncryptionCertificate
and/orPartnerSignatureCertificate
using a filename or pattern that contains the certificate files for encryption and signing, otherwise PartnerCertificateFile will be used - Encryption
-
Optional. Encryption alogrithm used in SMIME encryption operation. Only
3des
is supported at this moment.If left undefined, encryption is enabled and
3des
would be used. A false value must be specified to disable encryption.If enabled, encryption would also be required for receiving. Otherwise, encryption would be optional for receiving.
- Signature
-
Optional. Signing alogrithm used in SMIME signing operation..
If left undefined, signing is enabled and
sha1
will be used. A false value must be specified to disable signature.If enabled, signature would also be required for receiving. Otherwise, signature would be optional for receiving.
Also, if enabled, signed MDN would be requested.
- Mdn
-
Optional. The preferred MDN method -
sync
orasync
. The default issync
. - MdnAsyncUrl
-
Required if Mdn is async. The URL where the async MDN should be sent back to the partner.
- UserAgentClass
-
Optional. The class used to create the User Agent object. If not given, it will default to Net::AS2::HTTP.
- Timeout
-
Optional. The timeout in seconds for HTTP communication. The default is 30.
This option is passed to
UserAgentClass
. - UserAgent
-
Optional. User Agent name used in HTTP communication.
This option is passed to
UserAgentClass
.
Methods
- $message = $as2->decode_message($headers, $content)
-
Decode the incoming HTTP request as AS2 Message.
$headers
is either an HTTP::Headers compatible object or a hash ref supplied in PSGI format, or\%ENV
in CGI mode.$content
is the raw POST body of the request.This method always returns a
Net::AS2::Message
object and never dies. The message could be successfully parsed, or contains corresponding error message.Check the
$message->is_async
property and send the MDN accordingly.If ASYNC MDN is requested, it should be sent after this HTTP request is returned or in another thread - some AS2 server might block otherwise, YMMV. How to handle this is out of topic.
- $mdn = $as2->decode_mdn($headers, $content)
-
Decode the incoming HTTP request as AS2 MDN.
$headers
is either an HTTP::Headers compatible object or a hash ref supplied in PSGI format, or\%ENV
in CGI mode.$content
is the raw POST body of the request.This method always returns a
Net::AS2::MDN
object and never dies. The MDN could be successfully parsed, or contains unparsable error details if it is malformed, or signature could not be verified.$mdn->match_mic($content_mic)
should be called afterward with the pre-calculated MIC from the outgoing message to verify the correctness of the MIC. - ($headers, $content) = $as2->prepare_sync_mdn($mdn, $message_id)
-
Returns the headers and content to be sent in a HTTP response for a sync MDN.
The MDN is usually created after an incoming message is received, with
Net::AS2::MDN->create_success
orNet::AS2::MDN->create_from_unsuccessful_message
.The headers are in arrayref format in PSGI response format. The content is raw and ready to be sent.
For CGI, it should be sent like this:
my ($headers, $content) = $as2->prepare_sync_mdn($mdn, $message_id); my $mh = ''; for (my $i = 0; $i < scalar @{$headers}; $i += 2) { $mh .= $headers->[$i] . ': ' . $headers->[$i+1] . "\x0d\x0a"; } binmode(STDOUT); print $mh . "\x0d\x0a" . $content;
If message id not specified, a random one will be generated.
- $resp = $as2->send_async_mdn($mdn, $message_id)
-
Send an ASYNC MDN requested by partner. Returns a HTTP::Response.
The MDN is usually created after an incoming message is received, with
Net::AS2::MDN->create_success
orNet::AS2::MDN->create_from_unsuccessful_message
.If message id is not specified, a random one will be generated.
Note that the destination URL is passed by the partner in its request, but not specified during construction.
- ($mdn, $mic) = $as2->send($data, %MIMEHEADERS)
-
Send a message to the partner. Returns a
Net::AS2::MDN
object and the calculated SHA Digest MIC.The data should be encoded (or assumed to be UTF-8 encoded).
The mime headers should be listed in a hash. It will be passed to
MIME::Entity
almost transparently with some defaults dedicated for AS2, at least the following must also be supplied- MessageId
-
Message id of this request should be supplied, or a random one would be generated.
- Type
-
Content type of the message should be supplied.
- Filename
-
Optional. Sets the Content-Disposition filename. Default is "payload".
In case of HTTP failure, the MDN object will be marked with
$mdn->is_error
.In case ASYNC MDN is expected, the MDN object returned will most likely be marked with
$mdn->is_unparsable
and should be ignored. A misbehave AS2 server could returns a valid MDN even if async was requested - in this case the$mdn->is_success
would be true. - $as2->create_useragent()
-
This returns an object for handling requests.
It is configured via the
UserAgentClass
option. It defaults to Net::AS2::HTTP. - $as2->encode_as2_id( $id )
-
Return an AS2 ID quoted appropriately.
- $as2->parse_as2_id( $id )
-
Parse an AS2 ID from the given string,
$id
, removing surrounding spaces and quotes. - $id = $as2->get_message_id( $message_id, generate => ? )
-
Returns, or generates, a message id. Any angle brackets surrounding the id are removed.
If
$message_id
is defined and not an empty string and conforms to RFC 2822, then this id is returned.If
$message_id
is defined and not an empty string but does not conform to RFC 2822, then the method dies with an error message.If
generate
is true then a basic random message ID is created usingtime()
,rand()
andhostname()
.If
generate
is false (default) then the method dies with an error message.For production systems, it is strongly recommended to generate and use an ID using a better random generator function and pass it in to this module.
BUGS
A bug in Crypt::SMIME may cause tests to fail - specifically failed to add public key after decryption failure. It appears to be related to a memory leak in Crypt::SMIME.
SEE ALSO
Net::AS2::HTTP, Net::AS2::HTTPS
Net::AS2::FAQ, Net::AS2::Message, Net::AS2::MDN, MIME::Entity
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Sam Wong.
This software is copyright (c) 2019 by Catalyst IT. Additional contributions by Andrew Maguire <ajm@cpan.org>
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
DISCLAIMER OF WARRANTY
This module is not certificated by any AS2 body. This module generates MDN on your behalf. When using this module, you must have reviewed and be responsible for all the actions and in-actions caused by this module.
More legal jargon follows:
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.