DCMTK movescu not working for file retrieval - dicom

I am new in DICOM and DCMTK. I was trying to retrieve dcm files from a public test server (http://www.dicomserver.co.uk) with movescu command. But it's not working. I was able run findscu successfully but that's only to get data. Here's what I have tried:
findscu -v -P --call COMMON --patient --key 0008,0052=PATIENT --key 0010,0020="PAT004" www.dicomserver.co.uk 104
It works but same thing doesn't work for movescu like this:
movescu -v -P --call COMMON +P 104 --patient --key 0008,0052=PATIENT --key 0010,0020="PAT004" www.dicomserver.co.uk 104
The output:
I: Requesting Association
I: Association Accepted (Max Send PDV: 65524)
I: Sending Move Request (MsgID 1)
I: Request Identifiers:
I:
I: # Dicom-Data-Set
I: # Used TransferSyntax: Little Endian Explicit
I: (0008,0052) CS [PATIENT] # 8, 1 QueryRetrieveLevel
I: (0010,0020) LO [PAT004] # 6, 1 PatientID
I:
W: Move response with error status (Failed: UnableToProcess)
I: Received Final Move Response (Failed: UnableToProcess)
I: Releasing Association
I am not running any local DICOM server or anything else. What is the right way to achieve this?

According to the DICOM standard (PS3.4), you have to specify the unique key of the PATIENT level for the C-MOVE request. Patient's Name (0010,0010) shouldn't be "*" (which is "Wild Card Matching" for the query phase) but Patient ID (0010,0020) should have the real value, i.e. one of those Patient IDs that you have queried using "findscu".
By the way, did you also start a Storage SCP on your system to listen on port 104? See online documentation of http://dicomserver.co.uk/. If not, you could start "movescu" with the additional command line option "+P 104" (because this tool has a one build in).

In case someone still has trouble with this issue:
each query has to include StudyInstanceUID + SeriesInstanceUID + PatientID
Because the retrieval process makes the PACS create an SCP session towards what's running movescu it needs to know how to approach it. AE is the name (of the machine) being sent and default is MOVESCU (can be changed with aec/aet flags flags, but PACS hosts file must have that ip-to-name mapping)
By default this protocol runs on port 104, which is restricted. you can either change this with +P flag to a port higher than 1024 (have not tried to verify PACS recieves this port number) or just run movescu with sudo/root
I don't know what is the default store directory, but this can be defined with -od flag.
working example:
sudo /usr/bin/movescu -v -od /path/to/dir PACS_IP 104 -k StudyInstanceUID=1.2.3.4.5 -k SeriesInstanceUID=1.2.3.4.5 -k PatientID=12345 +P 104

Related

ldapsearch is slow to launch (not slow to search, slow to launch)

On one host ldapsearch was taking 20 seconds to launch.
Even if I just asked it what its version number is, it still took 20 seconds:
time ldapsearch -VV
ldapsearch: #(#) $OpenLDAP: ldapsearch 2.4.44 (Sep 30 2020 17:16:36) $
mockbuild#x86-02.bsys.centos.org:/builddir/build/BUILD/openldap-2.4.44/openldap-2.4.44/clients/tools
(LDAP library: OpenLDAP 20444)
real 0m20.034s
user 0m0.006s
sys 0m0.008s
This isn't a question about time to search - if I asked it to search, it would spend 20 seconds before it even starts searching.
Once it starts, the search succeeds and takes about the same time as it does when invoked from other hosts.
I tried adding various command line parameters.
The only thing that returned a different result was ldapsearch --help which returns basically instantly, suggesting that the problem wasn't in loading libraries or any such.
Running strace showed that the delay was in network traffic, specifically port 53 (DNS):
socket(AF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 3 <0.000038>
connect(3, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "... poll([{fd=3, events=POLLOUT}], 1, 0) = 1 ([{fd=3, revents=POLLOUT}]) <0.000011>
sendto(3, "..."..., 34, MSG_NOSIGNAL, NULL, 0) = 34 <0.000033>
poll([{fd=3, events=POLLIN}], 1, 5000) = 0 (Timeout) <5.005182>
The destination for the connect call turned out to be an IP address that was being set in /etc/resolv.conf.
The IP address was unreachable.
Removing the unreachable IP address from /etc/resolv.conf made the delay go away.

tcpprep: Command line arguments not allowed

I'm not sure, why executing below command on ubuntu terminal throws error. tcpprep syntax and options are mentioned as per in help doc, still throws error.
root#test-vm:~# /usr/bin/tcpprep --cachefile='cachefile1' —-pcap='/pcaps/http.pcap'
tcpprep: Command line arguments not allowed
tcpprep (tcpprep) - Create a tcpreplay cache cache file from a pcap file
root#test-vm:~# /usr/bin/tcpprep -V
tcpprep version: 3.4.4 (build 2450) (debug)
There are two problems with your command (and it doesn't help that tcpprep errors are vague or wrong).
Problem #1: Commands out of order
tcpprep requires that -i/--pcap come before -o/--cachefile. You can fix this as below, but then you get a different error:
bash$ /usr/bin/tcpprep —-pcap='/pcaps/http.pcap' --cachefile='cachefile1'
Fatal Error in tcpprep_api.c:tcpprep_post_args() line 387:
Must specify a processing mode: -a, -c, -r, -p
Note that the error above is not even accurate! -e/--mac can also be used!
Problem #2: Processing mode must be specified
tcpprep is used to preprocess a capture file into client/server using a heuristic that you provide. Looking through the tcpprep manpage, there are 5 valid options (-acerp). Given this capture file as input.pcapng with server 192.168.122.201 and next hop mac 52:54:00:12:35:02,
-a/--auto
Let tcpprep determine based on one of 5 heuristics: bridge, router, client, server, first. Ex:
tcpprep --auto=first —-pcap=input.pcapng --cachefile=input.cache
-c/--cidr
Specify server by cidr range. We see servers at 192.168.122.201, 192.168.122.202, and 192.168.3.40, so summarize with 192.168.0.0/16:
tcpprep --cidr=192.168.0.0/16 --pcap=input.pcapng --cachefile=input.cache
-e/--mac
This is not as useful in this capture as ALL traffic in this capture has dest mac of next hop of 52:54:00:12:35:02, ff:ff:ff:ff:ff:ff (broadcast), or 33:33:00:01:00:02 (multicast). Nonetheless, traffic from the next hop won't be client traffic, so this would look like:
tcpprep --mac=52:54:00:12:35:02 —-pcap=input.pcapng --cachefile=input.cache
-r/--regex
This is for IP ranges, and is an alternative to summarizing subnets with --cidr. This would be more useful if you have several IPs like 10.0.20.1, 10.1.20.1, 10.2.20.1, ... where summarization won't work and regex will. This is one regex we could use to summarize the servers:
tcpprep --regex="192\.168\.(122|3).*" —-pcap=input.pcapng --cachefile=input.cache
-p/--port
Looking at Wireshark > Statistics > Endpoints, we see ports [135,139,445,1024]/tcp, [137,138]/udp are associated with the server IPs. 1024/tcp, used with dcerpc is the only one that falls outside the range 0-1023, and so we'd have to manually specify it. Per services syntax, we'd represent this as 'dcerpc 1024/tcp'. In order to specify port, we also need to specify a --services file. We can specify one inline as a temporary file descriptor with process substitution. Altogether,
tcpprep --port --services=<(echo "dcerpc 1024/tcp") --pcap=input.pcapng --cachefile=input.cache
Further Reading
For more examples and information, check out the online docs.

TPM Owner password and lockout password with Windows 10 & linux

I've setup a dual boot so I have windows 10 and ubuntu.
Following steps on this page I'm able to retrieve the lockout password and the owner password of my TPM in the windows 10 registry. Result looks like this :
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TPM\WMI\Admin
OwnerAuthStatus REG_DWORD 0x1
LastAuthLevel REG_DWORD 0x4
OwnerAuthFull REG_SZ iTcW8t1B+tIKmP/uxXPL94QF2Jw=
LockoutHash REG_SZ Ki1RiIu8d+eqeDoEFYcAqIoi1n4=
SRKPub REG_BINARY A3FEFDE6DBAA425D24717422C46C7E9C85C433CB
StorageOwnerAuth REG_SZ
TPMCleared REG_DWORD 0x0
OwnerAuthFull and LockoutHash are both base64 encoded so I can decode them using this link for instance (it give 893716F2DD41FAD20A98FFEEC573CBF78405D89C in hexa for the owner password).
After that booting on the ubuntu I'm trying to interact with the TPM using these passwords. I'm using tpm2-tools to interact with the TPM under ubuntu.
Tpm2-tools works pretty well when the linux controls the TPM and sets up these passwords. But here I'm trying to let Windows have control of the TPM and still be able to communicate with it under Ubuntu. For instance when I run these commands (which works when ubuntu controls the TPM).
$ tpm2_createprimary --hierarchy e -g sha256 -G rsa -C primary.ctx
attributes:
value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|restricted|decrypt
raw: 0x30072
$ tpm2_create -g sha256 -G rsa -u key.pub -r key.priv -c primary.ctx
algorithm:
value: sha256
raw: 0xb
attributes:
value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign
raw: 0x60072
type:
value: rsa
raw: 0x1
rsa: d14e5b7473972e4430b780dff0ec31a3a021fa0049ea1bafc17e2de4e232cba3afcdd8504c9f7dc2fa57df04ec1f64759f6bb0d8563c1ac53a7ce8d563ab7437f1f4b760960acfde7c414355c371ac8c94bba0e004bb08b499f115ba5e8efd655174c87309d64a23e198f6fce8e5451a851b7e96f7c172ba3d4be8e339176d136752e5d038ad9979585008e35bdedfdabe3236b92c60d5c4eabcafaabc8c65401aab5b479d8471d20ca18631c31404b38f3d373b5612ca906599914865cf281e550a748685fed4d60a7aa9c955d374c1d0852bb36ce9d39209e66fada20e4c473765160988470e93b63d81361613e3f5b918da167048ff8afe5e74768544fe03
$ tpm2_load -c primary.ctx -u key.pub -r key.priv -n key.name -C key.ctx
Load succ.
LoadedHandle: 0x80000100
$ tpm2_evictcontrol --auth o -c key.ctx --persistent 0x81010003 -P hex:893716F2DD41FAD20A98FFEEC573CBF78405D89C
persistentHandle: 0x81010003
ERROR: Tss2_Sys_EvictControl(0x9A2) - tpm:session(1):authorization failure without DA implications
I get ERROR: Tss2_Sys_EvictControl(0x9A2) - tpm:session(1):authorization failure without DA implications.
Does anybody knows why I get this error / why this password doesn't work? Where could I get the right password ? Well any pointer on how to solve this problem is appreciated!
Thx!
I think I got my answer, in fact Windows make a sha1 hash of the password then converts it to base64 and then stores it in the registry if gpedit is configured like so :
https://msdn.microsoft.com/en-us/library/windows/desktop/aa376421(v=vs.85).aspx
b3nj1's answer is incorrect. Using the --auth o option for tpm2_evictcontrol means you're selecting the TPM's owner control domain (note that is true in Feb 2018 when the question was posted, --auth means something else now) which requires owner authorization. OwnerAuthFull and LockoutHash are indeed generated as described in b3nj1's answer, but OwnerAuthFull stores the TPM's lockout authorization, while LockoutHash's purpose is unknown.
The base64-decoded value of OwnerAuthFull is the lockout authorization value. This can be verified using tpm2-tools' tpm2_changeauth - the base64-decoded value enables one to successfully change the lockout authorization. You can use the following powershell command to do base64 decoding to hex string:
([System.BitConverter]::ToString([System.Convert]::FromBase64String('stringToConvert'))).Replace('-','')
So what is the owner authorization value in Windows? As per this page: https://learn.microsoft.com/en-us/windows/security/information-protection/tpm/trusted-platform-module-services-group-policy-settings, it is StorageOwnerAuth for b3nj1. From the result quoted in the question, it is just an empty string, meaning the owner authorization value is just a 0-byte buffer. This is the default value. Again, you can verify this using tpm2_changeauth.
Note that the link claims that the lockout authorization for TPM 2.0 is stored in LockoutAuth. This is incorrect. As seen in b3nj1's results above (as well as in my computers), there is StorageOwnerAuth, so it must be a TPM 2.0, but there is no LockoutAuth. Instead there is LockoutHash, but the article makes no mention of this value. Trying to use tpm2_changeauth with LockoutHash to modify any of the owner, endorsement, and lockout authorizations fails, so it is unclear what this value is for.
For the link in Wang's comment to b3nj1's answer, it is incorrect. One can use tpm2_changeauth to verify that the owner and endorsement authorization values in Windows are both empty strings, and lockout authorization is stored in OwnerAuthFull. This means that none of the authorization values controlled by Windows are unknown and/or discarded.
I've raised these issues with the documentation on GitHub and will update if there are any developments.

Network traffic through a particular port using iftop

I have a process using https. I found its PID using ps and used the command lsof -Pan -p PID -i to get the port number it is running on.
I need iftop to see the data transfer. The filter I am using now is
iftop -f "port http 57787".
I don't think this is giving me the right output.
Can someone help me the right filter to use with iftop so that I know the traffic going through only this port?
I can see 2 problems here:
1/ Is that a typo? The correct option for filtering is -f (small "f"). -F (capital "F") option is for net/mask.
2/ Though not explicitly stated by iftop documentation, the syntax for filtering seems to be the pcap one from the few examples given (and using ldd I can see that yes, the iftop binary is linked with libpcap). So a filter with http is simply not valid. To see the doc for pcap filtering syntax, have a look at pcap-filter (7) - packet filter syntax man page. In your example, a filter such as "tcp port 57787" would be OK. pcap does not do layer 5 and above protocol dissection such as http (pcap filters are handled by BPF in the kernel, so above layer 4 you're on your own, because that's none of the kernel business).
All in all, these looks like iperf bugs. It should refuse your "-F" option, and even with "-f" instead exit with an error code because pcap will refuse the filter expression. No big deal, iftop is a modest program. See edit bellow.
EDIT:
I just checked iftop version 1.0pre4 source code, and there is no such obvious bug from a look at set_filter_code() and its caller packet_init() in iftop.c. It correctly exit with error, but...
Error 2, use the "-f" option, but your incorrect filter syntax:
jbm#sumo:~$ sudo iftop -f "port http 57787"
interface: eth0
IP address is: 192.168.1.67
MAC address is: 8c:89:a5:57:10:3c
set_filter_code: syntax error
That's OK.
Error 1, the "-F" instead of "-f", there is a problem:
jbm#sumo:~$ sudo iftop -F "port http 57787"
(everything seems more or less OK, but then quit the program)
Could not parse net/mask: port http 57787
interface: eth0
IP address is: 192.168.1.67
MAC address is: 8c:89:a5:57:10:3c
Oops! "Could not parse net/mask: port http 57787"! That's a bug: it should exit right away.

Can MPI_Publish_name be used for two separately started applications?

I write an OpenMPI application which consists of a server and a client part which are launched separately:
me#server1:~> mpirun server
and
me#server2:~> mpirun client
server creates a port using MPI_Open_port. The question is: Does OpenMPI have a mechanism to communicate the port to client? I suppose that MPI_Publish_name and MPI_Lookup_name doesn't work here because server wouldn't know to which other computer the information should be sent.
To me, it looks like only processes which were started using a single mpirun can communicate with MPI_Publish_name.
I also found ompi-server, but the documentation is too minimalistic for me to understand this. Does anyone know how this is used?
Related: MPICH: How to publish_name such that a client application can lookup_name it? and https://stackoverflow.com/questions/9263458/client-server-example-using-ompi-does-not-work
MPI_Publish_name is supplied with an MPI info object, which could have an Open MPI specific boolean key ompi_global_scope. If this key is set to true, then the name would be published to the global scope, i.e. to an already running instance of ompi-server. MPI_Lookup_name by default first does a global name lookup if the URI of the ompi-server was provided.
With a dedicated Open MPI server
The process involves several steps:
1) Start the ompi-server somewhere in the cluster where it could be accessed from all nodes. For debugging purposes you may pass it the --no-daemonize -r + argument. It would start and print to the standard output an URI similar to this one:
$ ompi-server --no-daemonize -r +
1221656576.0;tcp://10.1.13.164:36351;tcp://192.168.221.41:36351
2) In the server, build an MPI info object and set the ompi_global_scope key to true:
MPI_Info info;
MPI_Info_create(&info);
MPI_Info_set(info, "ompi_global_scope", "true");
Then pass the info object to MPI_Publish_name:
MPI_Publish_name("server", info, port_name);
3) In the client, the call to MPI_Lookup_name would automatically do the lookup in the global context first (this could be changed by providing the proper key in the MPI info object, but in your case the default behaviour should suffice).
In order for both client and server code to know where the ompi-server is located, you have to give its URI to both mpirun commands with the --ompi-server 1221656576.0;tcp://10.1.13.164:36351;tcp://192.168.221.41:36351 option.
Another option is to have ompi-server write the URI to a file, which can then be read on the node(s) where mpirun is to be run. For example, if you start the server on the same node where both mpirun commands are executed, then you could use a file in /tmp. If you start the ompi-server on a different node, then a shared file system (NFS, Lustre, etc.) would do. Either way, the set of commands would be:
$ ompi-server [--no-daemonize] -r file:/path/to/urifile
...
$ mpirun --ompi-server file:/path/to/urifile server
...
$ mpirun --ompi-server file:/path/to/urifile client
Serverless method
If run both mpirun's on the same node, the --ompi-server could also specify the PID of an already running mpirun instance to be used as a name server. It allows you to use local name publishing in the server (i.e. skip the "run an ompi-server" and "make an info object" parts). The sequence of commands would be:
head-node$ mpirun --report-pid server
[ note the PID of this mpirun instance ]
...
head-node$ mpirun --ompi-server pid:12345 client
where 12345 should be replaced by the real PID of the server's mpirun.
You can also have the server's mpirun print its URI and pass that URI to the client's mpirun:
$ mpirun --report-uri + server
[ note the URI ]
...
$ mpirun --ompi-server URI client
You could also have the URI written to a file if you specify /path/to/file (note: no file: prefix here) instead of + after the --report-uri option:
$ mpirun --report-uri /path/to/urifile server
...
$ mpirun --ompi-server file:/path/to/urifile client
Note that the URI returned by mpirun has the same format as that of an ompi-server, i.e. it includes the host IP address, so it also works if the second mpirun is executed on a different node, which is able to talk to the first node via TCP/IP (and /path/to/urifile lives on a shared file system).
I tested all of the above with Open MPI 1.6.1. Some of the variant might not work with earlier versions.

Resources