Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding aChBillingChargingCharacteristics in CAP #23

Open
nickvsnetworking opened this issue Dec 3, 2024 · 2 comments
Open

Decoding aChBillingChargingCharacteristics in CAP #23

nickvsnetworking opened this issue Dec 3, 2024 · 2 comments
Assignees
Labels
question Further information is requested

Comments

@nickvsnetworking
Copy link

G'day folks,

I've been pulling my hair out thanks to an issue parsing aChBillingChargingCharacteristics in CAP.

My code is very simple, I take the raw hex, covert to bytes, decode into a PyCrate CAP object:

from pycrate_asn1dir.CAP import *
from pycrate_asn1rt.utils import *
from pycrate_asn1dir import TCAP_CAP
from pycrate_asn1dir import CAP
from binascii import hexlify, unhexlify
import pprint
import json


tcap_camel = CAP.TCAPMessages
msg = TCAP_CAP.TCAP_CAP_Messages.TCAP_CAP_Message
msg.from_ber(unhexlify('65274801234904b20001916c1ca11a0201050201233012800ba00980020122a1030101ffa203800101'))
pprint.pprint(msg.__dict__)

This yields:

('continue',
          {'components': [('basicROS',
                           ('invoke',
                            {'argument': ('ApplyChargingArg',
                                          {'aChBillingChargingCharacteristics': b'\xa0\t\x80\x02'
                                                                                b'\x01"\xa1\x03'
                                                                                b'\x01\x01\xff',
                                           'partyToCharge': ('sendingSideID',
                                                             b'\x01')}),
                             'invokeId': ('present', 5),
                             'opcode': ('local', 35)}))],
           'dtid': b'\xb2\x00\x01\x91',
           'otid': b'#'})}

Which is perfect except aChBillingChargingCharacteristics isn't decoded.

I can see this issue from the old repo that suggested the resolution was to change the ASN1 spec, then recompiling, but after following that (and double checking I was calling the updated libraries) I've got the same behavior.

I'm not sure if I'm just using it wrong - I can create a new AChBillingChargingCharacteristics object from CAP_datatypes with:

x = TCAP_CAP.CAP_datatypes.AChBillingChargingCharacteristics and then try to decode the contents with x.from_ber(unhexlify(a00980020122a1030101ff)) but that gives me:

Traceback (most recent call last):
  File "/home/nick/Documents/PySS7/camel_scratchpad.py", line 25, in <module>
    AChBillingChargingCharacteristics_object.from_ber(unhexlify(aChBillingChargingCharacteristics_hex))
  File "/usr/local/lib/python3.12/dist-packages/pycrate-0.7.7-py3.12.egg/pycrate_asn1rt/asnobj.py", line 1625, in from_ber
    raise(ASN1ObjErr('Parameterized object cannot be used for decoding'))
pycrate_asn1rt.err.ASN1ObjErr: Parameterized object cannot be used for decoding

I know I'm probably missing something stupid simple, but I'd appreciate any pointers,
Cheers,
Nick

@nickvsnetworking
Copy link
Author

I've done some more digging on this,
One thing I notice after making the change in the ASN1 sec mentioend in the old issue is that I get this error:

OCT_STR.__from_ber_buf: aChBillingChargingCharacteristics, CONTAINING object decoding failed

Which I don't get if I don't change the ASN1 spec,

I've also tried checking out the commit that was current at the time of the ticket in case there were other changes in the repo that led to this, but no dice sadly.

@mitshell mitshell self-assigned this Dec 9, 2024
@mitshell
Copy link
Member

mitshell commented Dec 9, 2024

The definition of AChBillingChargingCharacteristics is in CAP-datatypes.asn:

AChBillingChargingCharacteristics {PARAMETERS-BOUND : bound} ::= OCTET STRING (SIZE
	(bound.&minAChBillingChargingLength .. bound.&maxAChBillingChargingLength))
	(CONSTRAINED BY {-- shall be the result of the BER-encoded value of the type --
	CAMEL-AChBillingChargingCharacteristics {bound}})
-- The AChBillingChargingCharacteristics parameter specifies the charging related information
-- to be provided by the gsmSSF and the conditions on which this information has to be reported
-- back to the gsmSCF with the ApplyChargingReport operation. The value of the
-- AChBillingChargingCharacteristics of type OCTET STRING carries a value of the ASN.1 data type:
-- CAMEL-AChBillingChargingCharacteristics. The normal encoding rules are used to encode this
-- value.
-- The violation of the UserDefinedConstraint shall be handled as an ASN.1 syntax error.

It's an OCTET STRING which is constrained with SIZE and CONSTRAINED BY:

  • SIZE is provided with a BOUND parameter,
  • CONSTRAINED BY is a semi manual type of constraint, which pycrate does not support (as it's not formally defined).
    For this reason, the current TCAP CAP ASN.1 module in pycrate won't decode any content within AChBillingChargingCharacteristics. And this object itself cannot be called as such, as it is parameterized (consider it is incomplete).

If you change the definition to :

AChBillingChargingCharacteristics {PARAMETERS-BOUND : bound} ::= OCTET STRING (SIZE
	(bound.&minAChBillingChargingLength .. bound.&maxAChBillingChargingLength))
	(CONTAINING CAMEL-AChBillingChargingCharacteristics {bound})

This is formally defined and supported, meaning the content of the OCTET STRING would correspond to the BER-encoded buffer of the contained object. But as you checked: this is failing. This means the buffer within aChBillingChargingCharacteristics: 'A00980020122A1030101FF'H does not correspond to the contained object.

Let's check why:

In [26]: b = unhexlify('A00980020122A1030101FF') # our OCTET STRING buffer

In [27]: bchar = msg.get_at(('continue', 'components', 'basicROS', 'basicROS', 'invoke', 'argument', 'ApplyChargingArg', 'aChBillingChargingCharacteristics'))._const_cont

In [28]: bchar # the object contained in the OCTET STRING
Out[28]: <_cont_AChBillingChargingCharacteristics ([CAMEL-AChBillingChargingCharacteristics] CHOICE)>

In [29]: bchar.from_ber(b)
---------------------------------------------------------------------------
ASN1BERDecodeErr                          Traceback (most recent call last)
Cell In [29], line 1
----> 1 bchar.from_ber(b)

[...]

ASN1BERDecodeErr: _cont_AChBillingChargingCharacteristics.timeDurationCharging.releaseIfdurationExceeded: invalid BOOLEAN constructed structure

So, something looks invalid in the buffer. That's why the contained object can't decode the OCTET STRING buffer.

@mitshell mitshell added the question Further information is requested label Dec 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants