Skip to content

Library does not respond to A-ASSOCIATE-RQ if Extended Negotiation item is present #725

@pgimeno4d

Description

@pgimeno4d

When an SCU tries to connect to a server that uses the library, and the SCU includes an Extended Negotiation sub-item in the association request, the library completely fails to respond, and the SCU eventually times out.

It can be tested like this:

  1. Install pynetdicom (it can be done in a virtual environment if you don't want to pollute your Python installation)
  2. Open the dicom-storescp utility included in dicom-rs, with suitable parameters.
  3. Use pynetdicom's findscu --relational-query -k "0010,0010=" <host> <port> to target the above storescp. --relational-query is an example; any extended negotiation option will do.

This is the result with Wireshark, taken before the client times out:

No.     Time           Source                Destination           Protocol Length Info
      6 10.798361668   10.0.0.11             10.0.128.11           DICOM    2771   A-ASSOCIATE request FINDSCU --> SERVER

Frame 6: 2771 bytes on wire (22168 bits), 2771 bytes captured (22168 bits) on interface any, id 0
Linux cooked capture v1
Internet Protocol Version 4, Src: 10.0.0.11, Dst: 10.0.128.11
Transmission Control Protocol, Src Port: 45971, Dst Port: 11111, Seq: 1, Ack: 1, Len: 2703
DICOM, A-ASSOCIATE request FINDSCU --> SERVER
    PDU Type: ASSOC Request (0x01)
    PDU Length: 2697
    A-ASSOCIATE request FINDSCU --> SERVER
        Protocol Version: 1
        Called  AE Title: SERVER          
        Calling AE Title: FINDSCU         
        Application Context: DICOM Application Context Name (1.2.840.10008.3.1.1.1)
        Presentation Context: 1.2.840.10008.5.1.4.1.1.201.6
            Item Type: Presentation Context (0x20)
            Item Length: 130
            Context ID: 0x01
            Abstract Syntax: 1.2.840.10008.5.1.4.1.1.201.6
            Transfer Syntax: Implicit VR Little Endian: Default Transfer Syntax for DICOM (1.2.840.10008.1.2)
            Transfer Syntax: Explicit VR Little Endian (1.2.840.10008.1.2.1)
            Transfer Syntax: Deflated Explicit VR Little Endian (1.2.840.10008.1.2.1.99)
            Transfer Syntax: Explicit VR Big Endian (Retired) (1.2.840.10008.1.2.2)
<snipped the other presentation contexts for brevity>
        User Info: Max PDU Length 16382, Implementation UID 1.2.826.0.1.3680043.9.3811.3.0.4, Version PYNETDICOM_304
            Item Type: User Info (0x50)
            Item Length: 100
            Max PDU Length: 16382
                Item Type: Max Length (0x51)
                Item Length: 4
                Max PDU Length: 16382
            Implementation UID: 1.2.826.0.1.3680043.9.3811.3.0.4
                Item Type: Implementation Class UID (0x52)
                Item Length: 32
                Implementation Class UID: 1.2.826.0.1.3680043.9.3811.3.0.4
            Implementation Version: PYNETDICOM_304
                Item Type: Implementation Version (0x55)
                Item Length: 14
                Implementation Version: PYNETDICOM_304
            Ext. Neg.: Patient Root Query/Retrieve Information Model - FIND (1.2.840.10008.5.1.4.1.2.1.1)
                Item Type: SOP Class Extended Negotiation (0x56)
                Item Length: 34
                SOP Class UID Length: 27
                SOP Class UID: Patient Root Query/Retrieve Information Model - FIND (1.2.840.10008.5.1.4.1.2.1.1)
                Relational-queries: 0x01
                Combined Date-Time matching: 0x00
                Fuzzy semantic matching: 0x00
                Timezone query adjustment: 0x00

The capture ends there; there's no A-ASSOCIATE-AC or anything else. Note that at this point, there hasn't even been a chance for the server to know what kind of SCU the SCU is, so it doesn't really matter that it's a C-STORE-only SCP driven by a C-FIND-only SCU: the association never reaches the established state.

The cause is that the Service-class-application-information field in the Extended Negotiation Sub-item (see Table D.3-11 in PS3.7) is not prefixed by a length, but the library expects one in reader.rs. This causes the stream reader to de-synchronize, interpreting the Relational-queries boolean as if it was the high byte of the length field, and the Combined Date-Time matching boolean as if it was the low byte, resulting in a length of 0x0100 (256 bytes). That's more data than remains in the buffer, causing the reader to return Ok(None), which somehow causes the whole association request to be ignored.

Similarly, writer.rs writes a length field that should not be there.

I also wonder if returning Ok(None) is the right thing to do in some circumstances where something like that fails, as that would apparently cause the above behaviour in situations where the failure is serious enough to grant an abort.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-libArea: libraryC-ulCrate: dicom-ulbugThis is a bug

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions