XUDSIGVALIDATE ;OAK/WJY - XML digital signature validation; May 6, 2025@13:37
;;8.0;KERNEL;**824**;Jul 10, 1995;Build 11
;Per VA Directive 6402, this routine should not be modified.
;;
Q
; Checks the validity of a signed XML document
; Input: XMLFILEPATH = (Required) The path of a signed XML document
; PUBLICKEYPATH = (Optional) The path of the certificate that corresponds with the private key that signed the XML document
; If no public key is passed here, the code will default to using the certificate in the signed XML document
; IDNAME = (Optional) If a specific element of the XML was signed (rather than the entire payload), you must specific the name
; of the ID that is referenced by the XML signature.
; IDELEMENT = (Optional) If a specific element of the XML was signed, you must specify which element was signed here.
; ELAPSEDTIMEMS = (Optional) The amount of time that this function took to complete, in milliseconds.
;
; Output: 1 If the XML digital signature is valid
; 0 If the XML digital signature is invalid or if an error occurred
; -1 The operating system is not supported
VALIDATESIG(XMLFILEPATH,PUBLICKEYPATH,IDNAME,IDELEMENT,ELAPSEDTIMEMS) ;
N SC,START,END,FLAGS,FLAGPREFIX,ARGS,PATH,FILE,GUID,CERT,CMD,FULLCMD
S $ETRAP="D ERR^XUDSIGVALIDATE Q 0"
;
; check operating system
I $$OS^%ZOSV'="UNIX" Q -1
; start a timer
S START=$ZH
;
; check inputs
I '$D(IDNAME)!'$D(IDELEMENT) S IDNAME="" S IDELEMENT=""
I '$$VALIDATEINPUT(IDNAME)!'$$VALIDATEINPUT(IDELEMENT) Q 0
I '(##CLASS(%Library.File).Exists(XMLFILEPATH)) Q 0
I $D(PUBLICKEYPATH) S EXISTS=##CLASS(%Library.File).Exists(PUBLICKEYPATH) I 'EXISTS Q 0
;
; build the linux command
S CMD="xmlsec1 --verify"
I '$D(PUBLICKEYPATH) D
. S GUID=$System.Util.CreateGUID()
. S CERT=$$GETCERTIFICATE(XMLFILEPATH)
. S PATH="/tmp/vista-kernel-dsigcert-"_GUID_""
. D SAVETOFILE(PATH,CERT)
. S PUBLICKEYPATH=PATH
I $D(PUBLICKEYPATH) S FLAGS("pubkey-cert-pem")=PUBLICKEYPATH S FLAGS("enabled-key-data")="raw-x509-cert"
I ((IDNAME'="")&(IDELEMENT'="")) S FLAGS("id-attr:"_IDNAME)=IDELEMENT
S ARGS("XMLFILEPATH")=XMLFILEPATH
S FLAGPREFIX="--"
S FULLCMD=$$BUILDCMD(CMD,.FLAGS,FLAGPREFIX,.ARGS)
;
; run the command
S SC=$ZF(-1,FULLCMD)
S END=$ZH
S ELAPSEDTIMEMS=(END-START)*100
;
; return 1 if successful, otherwise return 0
I SC=0 Q 1
Q 0
VERIFYCHAIN(CACERT,XMLFILEPATH,TEMPCERTPATH,CHECKINDCA,CASUBJECT,CACONTENT,ELAPSEDTIMEMS) ;
; Validates that the cert (with corresponding private key) used to sign the xml was generated by a specific cert (root CA or intermediate CA)
;
; Input: CACERT = (Required) A Certificate Authority or bundle of Certificate Authorities in PEM format.
; XMLFILEPATH = (Required) The file path of a signed XML document.
; TEMPCERTFILEPATH = (Optional, By Reference) In order to verify a cert chain, the cert from the XML must be saved as a file.
; This param allows the user to specify a file location where the cert will be saved to.
; If left blank, the cert will be saved to a temp directory.
; If this param is pased by reference the file path will be returned.
; CHECKINDCA = (Optional) This is a boolean (1 or 0) that determines if the code will iterate through the list of certificates
; in a certificate bundle passed in CACERT. If set to 1, the code will look for a certficate whose subject matches the
; issuer of the certificate of the cert in the XML (TEMPCERTFILEPATH). If there is a match, the code will
; proceed to verify the certificate using openssl. If the openssl verify command succeeds, VERIFYCHAIN returns 1. Otherwise 0 is returned.
; If this parameter is left blank or set to 0, then the entire bundle in CACERT will be used for chain validation and if there is one match in the entire bundle,
; then verification will succeed.
; CASUBJECT = (Optional, By Reference) If CHECKINDCA is set to 1, and a successful match is found, then CASUBJECT will be set to the matching CA Subeject.
; CACONTENT = (Optional, By Reference) If CHECKINDCA is set to 1, and a successful match is found, then CACONTENT will be set to the certficate content of the matching CA.
; ELAPSEDTIMEMS = (Optional) The amount of time that this function took to complete, in milliseconds.
;
; Output: 1 On successful chain validation
; 0 Chain validation failed or an error occured
; -1 The operating system is not supported
N START,END,GUID,STATUS,CERT
S $ETRAP="D ERR^XUDSIGVALIDATE Q 0"
; check operating system
I $$OS^%ZOSV'="UNIX" Q -1
S START=$ZH
S GUID=$System.Util.CreateGUID()
I '$D(TEMPCERTPATH) S TEMPCERTPATH="/tmp/vista-kernel-dsigcert-"_GUID_""
I '$$CHECKPATH(TEMPCERTPATH)!'$$CHECKPATH(CACERT) Q 0
I '##CLASS(%Library.File).Exists(CACERT) Q 0
S CERT=$$GETCERTIFICATE(XMLFILEPATH)
D SAVETOFILE(TEMPCERTPATH,CERT)
I '$D(CHECKINDCA) S CHECKINDCA=0
I CHECKINDCA=1 S STATUS=$$VERIFYINDCA(TEMPCERTPATH,CACERT,.CASUBJECT,.CACONTENT)
I '$D(STATUS) S STATUS=$$VERIFYCA(CACERT,TEMPCERTPATH)
S END=$ZH
S ELAPSEDTIMEMS=(END-START)*100
I STATUS=1 Q 1
Q 0
; Builds a linux command that will be executed by $ZF
BUILDCMD(CMD,FLAGS,FLAGPREFIX,ARGS) ;
N I,FULLCMD,KEY,ARG
S FULLCMD=CMD
S KEY=""
F S KEY=$O(FLAGS(KEY)) Q:KEY="" D
. I KEY[":" D S FULLCMD=FULLCMD_" "_FLAGPREFIX_KEY_" "_""""_FLAGS(KEY)_""""
. E I FLAGS(KEY)'="" D S FULLCMD=FULLCMD_" "_FLAGPREFIX_KEY_" "_""""_FLAGS(KEY)_""""
. E D S FULLCMD=FULLCMD_" "_FLAGPREFIX_KEY
. Q
S ARG=""
F S ARG=$O(ARGS(ARG)) Q:ARG="" D
. S FULLCMD=FULLCMD_" "_ARGS(ARG)
. Q
S FULLCMD=FULLCMD_" > /dev/null 2>&1"
Q FULLCMD
; Given a leaf certificate path and a CA (or CA bundle), verify that the CA that generated the leaf certificate
; is present and perform the chain verification.
;
; Input: LEAFCERTPATH = (Required) The path of the leaf certificate (typically this is the certificate in the signed XML document)
; CABUNDLE = (Required) The bundle of CA certificates (can contain just 1 certificate)
; SUBJECT = (Optional, By Reference) The subject of the CA certificate that generated the leaf certificate
; CACONTENT = (Optional, By Reference) The contents of the CA certificate that generated the leaf certificate
; Output: 1 Success - If there was CA present in the CA bundle with a Subject equal to the Issuer of the leaf certificate,
; and openssl verify determines that the CA generated the leaf certificate.
; 0 Failure - All other scenarios
VERIFYINDCA(LEAFCERTPATH,CABUNDLE,SUBJECT,CACONTENT) ;
N LEAFCERTFILE,LEAFCERT,LEAFCERTSUBJECT,CABUNDLEFILE,STARTTAG,ENDTAG,START,END,CERT,CAPATH,FILE,STATUS,DONE
S LEAFCERTFILE=##CLASS(%Stream.FileCharacter).%New()
D LEAFCERTFILE.LinkToFile(LEAFCERTPATH)
S LEAFCERT=LEAFCERTFILE.Read($SYSTEM.SYS.MaxLocalLength())
S LEAFCERTSUBJECT=$SYSTEM.Encryption.X509GetField(LEAFCERT,"Issuer")
S CABUNDLEFILE=##CLASS(%Stream.FileCharacter).%New()
D CABUNDLEFILE.LinkToFile(CABUNDLE)
S CABUNDLE=CABUNDLEFILE.Read($SYSTEM.SYS.MaxLocalLength())
S STARTTAG="-----BEGIN CERTIFICATE-----"
S ENDTAG="-----END CERTIFICATE-----"
S DONE=0
S STATUS=0
F Q:DONE=1 D
. S START=$F(CABUNDLE,STARTTAG)
. I START=0 S DONE=1 Q
. S START=START-$L(STARTTAG)
. S END=$F(CABUNDLE,ENDTAG,START)
. S END=END+$L(ENDTAG)-1
. I END=0 S DONE=1 Q
. S CERT=$E(CABUNDLE,START,END)
. S SUBJECT=$SYSTEM.Encryption.X509GetField(CERT,"Subject")
. I SUBJECT=LEAFCERTSUBJECT D
. . S CAPATH=LEAFCERTPATH_"-CA"
. . D SAVETOFILE^XUDSIGVALIDATE(CAPATH,CERT)
. . S STATUS=$$VERIFYCA(CAPATH,LEAFCERTPATH)
. . I STATUS=1 S CACONTENT=CERT S DONE=1 Q
. S CABUNDLE=$E(CABUNDLE,END-$L(STARTTAG),*)
I STATUS=1 Q 1
S CACONTENT=""
S SUBJECT=""
Q 0
VERIFYCA(CACERT,TEMPCERTPATH) ;
N VCMD,FLAGS,ARGS,FLAGPREFIX,STATUS
S VCMD="openssl verify"
S FLAGS("partial_chain")=""
S FLAGS("CAfile")=CACERT
S ARGS("0")=TEMPCERTPATH
S FLAGPREFIX="-"
S VCMD=$$BUILDCMD(VCMD,.FLAGS,FLAGPREFIX,.ARGS)
S STATUS=$ZF(-1,VCMD)
I STATUS=0 Q 1
Q STATUS
; Retrieve the certificate embedded in a signed XML document.
; Typically the certificate is contained in the X509Certificate element.
;
; Input: XMLFILE = The path of the signed XML document.
; Output: The X509 certificate that was contained in the signed XML document.
; If no certificate was found, "" is returned.
GETCERTIFICATE(XMLFILE) ;
N XPATHDOC,RESULTS,CERTIFICATE
D ##CLASS(%XML.XPATH.Document).CreateFromFile(XMLFILE,.XPATHDOC)
D XPATHDOC.EvaluateExpression("/","//*[local-name()='X509Certificate']/text()",.RESULTS)
I RESULTS.Size'=1 Q ""
S CERTIFICATE=RESULTS.Oref(1).Value
S CERTIFICATE="-----BEGIN CERTIFICATE-----"_$C(13,10)_CERTIFICATE_$C(13,10)_"-----END CERTIFICATE-----"
Q CERTIFICATE
SAVETOFILE(PATH,CONTENT) ;
N FILE
S FILE=##CLASS(%Stream.FileCharacter).%New()
D FILE.LinkToFile(PATH)
D FILE.Write(CONTENT)
D FILE.%Save()
Q
CHECKPATH(PATH) ;
I PATH'?1"/".E Q 0
I PATH?.E1(1"|",1"&",1";",1"`",1"$",1">",1"<",1"\",1"'").E Q 0
;I PATH'?1"/tmp/".E Q 0
Q 1
VALIDATEINPUT(INPUT) ;
I '$D(INPUT) Q 1
I INPUT="" Q 1
I $MATCH(INPUT,"^[A-Za-z_][A-za-z0-9._-]*$") Q 1
Q 0
ERR ;
D ^%ZTER
Q
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HXUDSIGVALIDATE 9728 printed Mar 25, 2026@15:33:53 Page 2
XUDSIGVALIDATE ;OAK/WJY - XML digital signature validation; May 6, 2025@13:37
+1 ;;8.0;KERNEL;**824**;Jul 10, 1995;Build 11
+2 ;Per VA Directive 6402, this routine should not be modified.
+3 ;;
+4 QUIT
+5 ; Checks the validity of a signed XML document
+6 ; Input: XMLFILEPATH = (Required) The path of a signed XML document
+7 ; PUBLICKEYPATH = (Optional) The path of the certificate that corresponds with the private key that signed the XML document
+8 ; If no public key is passed here, the code will default to using the certificate in the signed XML document
+9 ; IDNAME = (Optional) If a specific element of the XML was signed (rather than the entire payload), you must specific the name
+10 ; of the ID that is referenced by the XML signature.
+11 ; IDELEMENT = (Optional) If a specific element of the XML was signed, you must specify which element was signed here.
+12 ; ELAPSEDTIMEMS = (Optional) The amount of time that this function took to complete, in milliseconds.
+13 ;
+14 ; Output: 1 If the XML digital signature is valid
+15 ; 0 If the XML digital signature is invalid or if an error occurred
+16 ; -1 The operating system is not supported
VALIDATESIG(XMLFILEPATH,PUBLICKEYPATH,IDNAME,IDELEMENT,ELAPSEDTIMEMS) ;
+1 NEW SC,START,END,FLAGS,FLAGPREFIX,ARGS,PATH,FILE,GUID,CERT,CMD,FULLCMD
+2 SET $ETRAP="D ERR^XUDSIGVALIDATE Q 0"
+3 ;
+4 ; check operating system
+5 IF $$OS^%ZOSV'="UNIX"
QUIT -1
+6 ; start a timer
+7 SET START=$ZH
+8 ;
+9 ; check inputs
+10 IF '$DATA(IDNAME)!'$DATA(IDELEMENT)
SET IDNAME=""
SET IDELEMENT=""
+11 IF '$$VALIDATEINPUT(IDNAME)!'$$VALIDATEINPUT(IDELEMENT)
QUIT 0
+12 IF '(##CLASS(%Library.File).Exists(XMLFILEPATH))
QUIT 0
+13 IF $DATA(PUBLICKEYPATH)
SET EXISTS=##CLASS(%Library.File).Exists(PUBLICKEYPATH)
IF 'EXISTS
QUIT 0
+14 ;
+15 ; build the linux command
+16 SET CMD="xmlsec1 --verify"
+17 IF '$DATA(PUBLICKEYPATH)
Begin DoDot:1
+18
*** ERROR ***
SET GUID=$System.Util.CreateGUID()
+19 SET CERT=$$GETCERTIFICATE(XMLFILEPATH)
+20 SET PATH="/tmp/vista-kernel-dsigcert-"_GUID_""
+21 DO SAVETOFILE(PATH,CERT)
+22 SET PUBLICKEYPATH=PATH
End DoDot:1
+23 IF $DATA(PUBLICKEYPATH)
SET FLAGS("pubkey-cert-pem")=PUBLICKEYPATH
SET FLAGS("enabled-key-data")="raw-x509-cert"
+24 IF ((IDNAME'="")&(IDELEMENT'=""))
SET FLAGS("id-attr:"_IDNAME)=IDELEMENT
+25 SET ARGS("XMLFILEPATH")=XMLFILEPATH
+26 SET FLAGPREFIX="--"
+27 SET FULLCMD=$$BUILDCMD(CMD,.FLAGS,FLAGPREFIX,.ARGS)
+28 ;
+29 ; run the command
+30 SET SC=$ZF(-1,FULLCMD)
+31 SET END=$ZH
+32 SET ELAPSEDTIMEMS=(END-START)*100
+33 ;
+34 ; return 1 if successful, otherwise return 0
+35 IF SC=0
QUIT 1
+36 QUIT 0
VERIFYCHAIN(CACERT,XMLFILEPATH,TEMPCERTPATH,CHECKINDCA,CASUBJECT,CACONTENT,ELAPSEDTIMEMS) ;
+1 ; Validates that the cert (with corresponding private key) used to sign the xml was generated by a specific cert (root CA or intermediate CA)
+2 ;
+3 ; Input: CACERT = (Required) A Certificate Authority or bundle of Certificate Authorities in PEM format.
+4 ; XMLFILEPATH = (Required) The file path of a signed XML document.
+5 ; TEMPCERTFILEPATH = (Optional, By Reference) In order to verify a cert chain, the cert from the XML must be saved as a file.
+6 ; This param allows the user to specify a file location where the cert will be saved to.
+7 ; If left blank, the cert will be saved to a temp directory.
+8 ; If this param is pased by reference the file path will be returned.
+9 ; CHECKINDCA = (Optional) This is a boolean (1 or 0) that determines if the code will iterate through the list of certificates
+10 ; in a certificate bundle passed in CACERT. If set to 1, the code will look for a certficate whose subject matches the
+11 ; issuer of the certificate of the cert in the XML (TEMPCERTFILEPATH). If there is a match, the code will
+12 ; proceed to verify the certificate using openssl. If the openssl verify command succeeds, VERIFYCHAIN returns 1. Otherwise 0 is returned.
+13 ; If this parameter is left blank or set to 0, then the entire bundle in CACERT will be used for chain validation and if there is one match in the entire bundle,
+14 ; then verification will succeed.
+15 ; CASUBJECT = (Optional, By Reference) If CHECKINDCA is set to 1, and a successful match is found, then CASUBJECT will be set to the matching CA Subeject.
+16 ; CACONTENT = (Optional, By Reference) If CHECKINDCA is set to 1, and a successful match is found, then CACONTENT will be set to the certficate content of the matching CA.
+17 ; ELAPSEDTIMEMS = (Optional) The amount of time that this function took to complete, in milliseconds.
+18 ;
+19 ; Output: 1 On successful chain validation
+20 ; 0 Chain validation failed or an error occured
+21 ; -1 The operating system is not supported
+22 NEW START,END,GUID,STATUS,CERT
+23 SET $ETRAP="D ERR^XUDSIGVALIDATE Q 0"
+24 ; check operating system
+25 IF $$OS^%ZOSV'="UNIX"
QUIT -1
+26 SET START=$ZH
+27
*** ERROR ***
SET GUID=$System.Util.CreateGUID()
+28 IF '$DATA(TEMPCERTPATH)
SET TEMPCERTPATH="/tmp/vista-kernel-dsigcert-"_GUID_""
+29 IF '$$CHECKPATH(TEMPCERTPATH)!'$$CHECKPATH(CACERT)
QUIT 0
+30 IF '##CLASS(%Library.File).Exists(CACERT)
QUIT 0
+31 SET CERT=$$GETCERTIFICATE(XMLFILEPATH)
+32 DO SAVETOFILE(TEMPCERTPATH,CERT)
+33 IF '$DATA(CHECKINDCA)
SET CHECKINDCA=0
+34 IF CHECKINDCA=1
SET STATUS=$$VERIFYINDCA(TEMPCERTPATH,CACERT,.CASUBJECT,.CACONTENT)
+35 IF '$DATA(STATUS)
SET STATUS=$$VERIFYCA(CACERT,TEMPCERTPATH)
+36 SET END=$ZH
+37 SET ELAPSEDTIMEMS=(END-START)*100
+38 IF STATUS=1
QUIT 1
+39 QUIT 0
+40 ; Builds a linux command that will be executed by $ZF
BUILDCMD(CMD,FLAGS,FLAGPREFIX,ARGS) ;
+1 NEW I,FULLCMD,KEY,ARG
+2 SET FULLCMD=CMD
+3 SET KEY=""
+4 FOR
SET KEY=$ORDER(FLAGS(KEY))
if KEY=""
QUIT
Begin DoDot:1
+5 IF KEY[":"
Begin DoDot:2
End DoDot:2
SET FULLCMD=FULLCMD_" "_FLAGPREFIX_KEY_" "_""""_FLAGS(KEY)_""""
+6 IF '$TEST
IF FLAGS(KEY)'=""
Begin DoDot:2
End DoDot:2
SET FULLCMD=FULLCMD_" "_FLAGPREFIX_KEY_" "_""""_FLAGS(KEY)_""""
+7 IF '$TEST
Begin DoDot:2
End DoDot:2
SET FULLCMD=FULLCMD_" "_FLAGPREFIX_KEY
+8 QUIT
End DoDot:1
+9 SET ARG=""
+10 FOR
SET ARG=$ORDER(ARGS(ARG))
if ARG=""
QUIT
Begin DoDot:1
+11 SET FULLCMD=FULLCMD_" "_ARGS(ARG)
+12 QUIT
End DoDot:1
+13 SET FULLCMD=FULLCMD_" > /dev/null 2>&1"
+14 QUIT FULLCMD
+15 ; Given a leaf certificate path and a CA (or CA bundle), verify that the CA that generated the leaf certificate
+16 ; is present and perform the chain verification.
+17 ;
+18 ; Input: LEAFCERTPATH = (Required) The path of the leaf certificate (typically this is the certificate in the signed XML document)
+19 ; CABUNDLE = (Required) The bundle of CA certificates (can contain just 1 certificate)
+20 ; SUBJECT = (Optional, By Reference) The subject of the CA certificate that generated the leaf certificate
+21 ; CACONTENT = (Optional, By Reference) The contents of the CA certificate that generated the leaf certificate
+22 ; Output: 1 Success - If there was CA present in the CA bundle with a Subject equal to the Issuer of the leaf certificate,
+23 ; and openssl verify determines that the CA generated the leaf certificate.
+24 ; 0 Failure - All other scenarios
VERIFYINDCA(LEAFCERTPATH,CABUNDLE,SUBJECT,CACONTENT) ;
+1 NEW LEAFCERTFILE,LEAFCERT,LEAFCERTSUBJECT,CABUNDLEFILE,STARTTAG,ENDTAG,START,END,CERT,CAPATH,FILE,STATUS,DONE
+2 SET LEAFCERTFILE=##CLASS(%Stream.FileCharacter).%New()
+3 DO LEAFCERTFILE.LinkToFile(LEAFCERTPATH)
+4 SET LEAFCERT=LEAFCERTFILE.Read($SYSTEM.SYS.MaxLocalLength())
+5 SET LEAFCERTSUBJECT=$SYSTEM.Encryption.X509GetField(LEAFCERT,"Issuer")
+6 SET CABUNDLEFILE=##CLASS(%Stream.FileCharacter).%New()
+7 DO CABUNDLEFILE.LinkToFile(CABUNDLE)
+8 SET CABUNDLE=CABUNDLEFILE.Read($SYSTEM.SYS.MaxLocalLength())
+9 SET STARTTAG="-----BEGIN CERTIFICATE-----"
+10 SET ENDTAG="-----END CERTIFICATE-----"
+11 SET DONE=0
+12 SET STATUS=0
+13 FOR
if DONE=1
QUIT
Begin DoDot:1
+14 SET START=$FIND(CABUNDLE,STARTTAG)
+15 IF START=0
SET DONE=1
QUIT
+16 SET START=START-$LENGTH(STARTTAG)
+17 SET END=$FIND(CABUNDLE,ENDTAG,START)
+18 SET END=END+$LENGTH(ENDTAG)-1
+19 IF END=0
SET DONE=1
QUIT
+20 SET CERT=$EXTRACT(CABUNDLE,START,END)
+21 SET SUBJECT=$SYSTEM.Encryption.X509GetField(CERT,"Subject")
+22 IF SUBJECT=LEAFCERTSUBJECT
Begin DoDot:2
+23 SET CAPATH=LEAFCERTPATH_"-CA"
+24 DO SAVETOFILE^XUDSIGVALIDATE(CAPATH,CERT)
+25 SET STATUS=$$VERIFYCA(CAPATH,LEAFCERTPATH)
+26 IF STATUS=1
SET CACONTENT=CERT
SET DONE=1
QUIT
End DoDot:2
+27 SET CABUNDLE=$EXTRACT(CABUNDLE,END-$LENGTH(STARTTAG),*)
End DoDot:1
+28 IF STATUS=1
QUIT 1
+29 SET CACONTENT=""
+30 SET SUBJECT=""
+31 QUIT 0
VERIFYCA(CACERT,TEMPCERTPATH) ;
+1 NEW VCMD,FLAGS,ARGS,FLAGPREFIX,STATUS
+2 SET VCMD="openssl verify"
+3 SET FLAGS("partial_chain")=""
+4 SET FLAGS("CAfile")=CACERT
+5 SET ARGS("0")=TEMPCERTPATH
+6 SET FLAGPREFIX="-"
+7 SET VCMD=$$BUILDCMD(VCMD,.FLAGS,FLAGPREFIX,.ARGS)
+8 SET STATUS=$ZF(-1,VCMD)
+9 IF STATUS=0
QUIT 1
+10 QUIT STATUS
+11 ; Retrieve the certificate embedded in a signed XML document.
+12 ; Typically the certificate is contained in the X509Certificate element.
+13 ;
+14 ; Input: XMLFILE = The path of the signed XML document.
+15 ; Output: The X509 certificate that was contained in the signed XML document.
+16 ; If no certificate was found, "" is returned.
GETCERTIFICATE(XMLFILE) ;
+1 NEW XPATHDOC,RESULTS,CERTIFICATE
+2 DO ##CLASS(%XML.XPATH.Document).CreateFromFile(XMLFILE,.XPATHDOC)
+3 DO XPATHDOC.EvaluateExpression("/","//*[local-name()='X509Certificate']/text()",.RESULTS)
+4 IF RESULTS.Size'=1
QUIT ""
+5 SET CERTIFICATE=RESULTS.Oref(1).Value
+6 SET CERTIFICATE="-----BEGIN CERTIFICATE-----"_$CHAR(13,10)_CERTIFICATE_$CHAR(13,10)_"-----END CERTIFICATE-----"
+7 QUIT CERTIFICATE
SAVETOFILE(PATH,CONTENT) ;
+1 NEW FILE
+2 SET FILE=##CLASS(%Stream.FileCharacter).%New()
+3 DO FILE.LinkToFile(PATH)
+4 DO FILE.Write(CONTENT)
+5 DO FILE.%Save()
+6 QUIT
CHECKPATH(PATH) ;
+1 IF PATH'?1"/".E
QUIT 0
+2 IF PATH?.E1(1"|",1"&",1";",1"`",1"$",1">",1"<",1"\",1"'").E
QUIT 0
+3 ;I PATH'?1"/tmp/".E Q 0
+4 QUIT 1
VALIDATEINPUT(INPUT) ;
+1 IF '$DATA(INPUT)
QUIT 1
+2 IF INPUT=""
QUIT 1
+3
*** ERROR ***
IF $MATCH(INPUT,"^[A-Za-z_][A-za-z0-9._-]*$")
QUIT 1
+4 QUIT 0
ERR ;
+1 DO ^%ZTER
+2 QUIT