InfoPath 2010 Digital Signature Issue - InfoPath Dev
in

InfoPath Dev

InfoPath 2010 Digital Signature Issue

Last post 01-05-2012 06:29 AM by Franccesca. 0 replies.
Page 1 of 1 (1 items)
Sort Posts: Previous Next
  • 01-05-2012 06:29 AM

    InfoPath 2010 Digital Signature Issue

    I have an InfoPath 2010 form template that I have deployed to SharePoint. The form collects four signatures, each signature is setup as independent to the others and I have my own checks coded into the form's sign event. Below is the code in my sign event handler:

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    public void FormEvents_Sign(object sender, SignEventArgs e)

    {

    if (!checkSignatures()) // FUNCTION I WROTE TO TRY TO CATCH THE INVALID SIGNATURE

    {

    MessageBoxes.ShowInvalidCertificate("Invalid Certificate", "One of the previous signatures is invalid. You will be unable to sign and submit this form until a valid certificate is used.", string.Empty, System.Drawing.SystemIcons.Error);e.SignatureWizard = false;

    }

    else

    {

    try

    {

    _invalidSignature = false;

    string curUser = System.Environment.UserName.ToString();

    int isRejected = (int)CreateNavigator().SelectSingleNode("/my:AdjustmentRequest/my:WorkflowFields/my:IsRejected", NamespaceManager).ValueAsInt;

    string sectionSigned = e.SignedDataBlock.Name.ToString();

    string myField = sectionSigned + "_Name";

    string path = "/my:AdjustmentRequest/my:ApprovalSignatures/my:" + sectionSigned.ToString() + "/my:" + myField.ToString();

    XPathNavigator myfield = MainDataSource.CreateNavigator().SelectSingleNode(path.ToString(), this.NamespaceManager);

    string signer = ActiveDirectory.GetUserProperty(LDAP://blablabla, "displayname", myfield.Value.ToString(), "samaccountname");

    bool isPreviousSigned = isPreviousSectionSigned(sectionSigned);

    // CHECK IF CURRENT USER IS THE USER ASSIGNED TO SIGN THIS SECTION

    if (curUser == signer)

    {

    // CHECK IF USER IS TRYING TO SIGN AFTER THE FORM HAS ALREADY BEEN REJECTED

    if (isRejected.ToString() == "1")

    {

    MessageBox.Show("This form has already been rejected and can no longer be signed.");e.SignatureWizard = false;

    }

    else // SIGNATURE CODE

    {

    if (isPreviousSigned)

    {

    // SIGN SECTION

    e.SignatureWizard = false;Microsoft.Office.InfoPath.Signature thisSignature = e.SignedDataBlock.Signatures.CreateSignature();

    thisSignature.Sign();

     

    if (!checkSignatures())

    {

    _invalidSignature =
    true;

    MessageBoxes.ShowInvalidCertificate("Invalid Signature", "You are unable to sign this form due to an invalid signature or signing certificate.", "Please follow the link above to obtain a valid certificate. This form will be closed without saving. You will need to re-open to sign this document once you have obtained a valid certificate.", System.Drawing.SystemIcons.Error);

    this.Application.Quit();

    }

    }

    else

    {

    MessageBox.Show("You cannot sign this form out of sequence.");e.SignatureWizard = false;

    }

    }

    }

    else

    {

    // NOTIFY USER

    MessageBox.Show("You are not the user assigned to sign this section.");e.SignatureWizard = false;

    }

    }

    catch (Exception ex)

    {

    MessageBox.Show(ex.Message.ToString() + " " + ex.StackTrace.ToString() + ", " + ex.InnerException.Message.ToString());

    }

    }

    }

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     

    I wrote this checkSignatures function to try and catch the invalid signature before Infopath does when it runs its own validation. It is the best I could do with what seems like very little documentation of actual working code samples online.

     

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    public bool checkSignatures()

    {

    // CREATE NEW XML DOCUMENT

    XmlDocument xmlDoc = new XmlDocument();

    xmlDoc.PreserveWhitespace = true;

    // LOAD THE XML DOCUMENT

    xmlDoc.LoadXml(this.MainDataSource.CreateNavigator().SelectSingleNode("/my:AdjustmentRequest", this.NamespaceManager).OuterXml.ToString());

    // GET SIGNATURE LIST OFF OF FORM

    XmlNodeList sigList = xmlDoc.GetElementsByTagName("Signature");

    //MessageBox.Show(sigList.Count.ToString() + " signatures on the form.");

    // CREATE RETURN VARIABLE

    bool validSignature = true;

    for (int i = 0; i < sigList.Count; i++) // LOOP THROUGH ALL SIGNATURES

    {

    // Create new SignedXML object.

    System.Security.Cryptography.Xml.SignedXml signedXML = new System.Security.Cryptography.Xml.SignedXml(xmlDoc);

    // LOAD CURRENT SIGNATURE INTO THE SIGNED XML OBJECT

    signedXML.LoadXml((XmlElement)sigList[i]);

    bool hasKeyInfo = false;

    // Get Key Info Data

    XmlNodeList sigNodes = sigList[i].ChildNodes;

    XmlNodeList keyInfoNodes = null;

    foreach (XmlNode node in sigNodes)

    {

    if (node.Name.ToString() == "KeyInfo")

    {

    hasKeyInfo =
    true;

    // GET SIGNATURE INFORMATION

    keyInfoNodes = node.ChildNodes;

    // GET CERTIFICATE INFORMATION

    System.Security.Cryptography.X509Certificates.X509Certificate2 cert = null;

    XmlElement X509Certificate = (XmlElement)keyInfoNodes[0].FirstChild;

    // CREATE CERTIFICATE OBJECT FROM CERTIFICATE INFORMATION

    cert = DigitalSignatures.CreateX509CertificateFromXMLElement(X509Certificate);

    // UPDATE SIGNED XML OBJECT TO USE THE CERTIFICATES PUBLIC KEY

    signedXML.SigningKey = cert.PublicKey.Key;

    // CHECK SIGNATURE

    bool result = signedXML.CheckSignature(cert, false);

    validSignature = result;

    }

    }

    if (!hasKeyInfo)

    {

    // GET SIGNATURE INFORMATION

    XPathNavigator sigNavigator = sigList[i].CreateNavigator();

    sigNavigator.MoveToAttribute("Id", "");

    string signatureBlockName = sigNavigator.Value.ToString();MessageBox.Show("The following signature for: " + signatureBlockName.ToString() + " does not contain any KeyInfo");

    }

    }

    // RETURN STATUS OF SIGNATURE

    return validSignature;

    }

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     

    ISSUE: Ok so what is happening is that when the form is opened for the first time from SharePoint (the form is opened in the client application - it is not a web form) it submits successfully and there is no problem. The first signer goes to open it and sign, and the code executes and validates the signature and says that it is valid - user submits the form. When the form is opened by the second signer on their computer the signature that was showing as valid on the first user's computer is now showing as invalid but the controls that have been signed are locked and no changes have been made.

    I also call the checkSignatures in the Form Load event because I wanted to see if I could capture the same behavior in my code that InfoPath is showing but I can't. Now what is even more confusing to me is that my code above will run and validate the signature ok that InfoPath is now showing as invalid. So this 2nd signer can sign the form and submit it ok, and if the same form is re-opened (now it has two signatures) on the first signer's computer, both signatures show as valid. Re-open it on the second signer's computer, and one of them is invalid. I can open it on the SharePoint server and it shows both signatures as valid.

    So what I have done so far:

    - Verified that our internal CA is issuing the proper certificates

    - Verified that each signer has the same type of digital certificate

    - Checked that each user has the CA listed as a trusted root authority

    So why would a signature show as valid when the form is opened on one computer but invalid when opened on another? Am I missing some setup step on one of these computers?

Page 1 of 1 (1 items)
Copyright © 2003-2019 Qdabra Software. All rights reserved.
View our Terms of Use.