Recipient.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / Recipient.cs / 2 / Recipient.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.InfoCards
{ 
    using System;
    using System.IO; 
    using System.Collections.Generic; 
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates; 
    using System.Text;
    using System.ServiceModel.Security.Tokens;
    using Microsoft.InfoCards.Diagnostics;
    using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; 
    using System.IdentityModel.Tokens;
    using System.IdentityModel.Selectors; 
    using System.Globalization; 

    using System.ComponentModel; 
    using System.Runtime.InteropServices;

    internal class Recipient
    { 
        public enum TrustDecision : byte
        { 
            NoTrustDecision,  // Indicating a recipient for whom a trust decision has never been made before 
            IsTrusted,        // Indicating a recipient who has been trusted before
            IsNotTrusted,     // Indicating a recipient who has been set to "untrusted" before 
            PolicyVersionChange
        };

        public enum IdentityType : byte 
        {
            DNS = 0, 
            X509 = 1 
        };
 
        enum IdType : byte
        {
            RecipientId = 0,
            OrganizationId = 1, 
            PPIDSeed = 2
        }; 
 
        public struct RecipientCertParameters
        { 
            //
            // This structure is used to conveniently pass around
            // and update all these parameters in a method/function call.
            // 
            public string m_cn;
            public string m_organization; 
            public string m_locality; 
            public string m_state;
            public string m_country; 
            public Utility.SubjectAtrributeHAFlags m_certHAFlags;

            public RecipientCertParameters(
                       string cn, 
                       string organization,
                       string locality, 
                       string state,		/* SSS_WARNINGS_OFF */ 
                       string country,
                       Utility.SubjectAtrributeHAFlags certHAFlags 
                       )			/* SSS_WARNINGS_ON */
            {
                m_cn = cn;
                m_organization = organization; 
                m_locality = locality;
                m_state = state;		/* SSS_WARNINGS_OFF */ 
                m_country = country;		/* SSS_WARNINGS_ON */ 

                m_certHAFlags = certHAFlags; 
            }

        };
 
        const Int32 InvalidRow = 0;
        const byte Version = 1; 
        const byte m_marker = 29; 

        // Geographic attribute types: 
        public const int CERT_NAME_ATTR_TYPE = 3;
        public const string szOID_SUBJECT_CN = "2.5.4.3";  // case-ignore string
        public const string szOID_ORGANIZATION_NAME = "2.5.4.10"; // case-ignore string
        public const string szOID_LOCALITY_NAME = "2.5.4.7";  // case-ignore string 
        public const string szOID_STATE_OR_PROVINCE_NAME = "2.5.4.8";  // case-ignore string		/* SSS_WARNINGS_OFF */
        public const string szOID_COUNTRY_NAME = "2.5.4.6"; // printable 2char string 
        const int attributeMaxLength = 1024; 

        static readonly RecipientAttribute CNAttr = new RecipientAttribute( szOID_SUBJECT_CN, "CN" ); 
        static readonly RecipientAttribute OrgAttr = new RecipientAttribute( szOID_ORGANIZATION_NAME, "O" );
        static readonly RecipientAttribute LocalityAttr = new RecipientAttribute( szOID_LOCALITY_NAME, "L" );
        static readonly RecipientAttribute StateOrProvinceAttr = new RecipientAttribute( szOID_STATE_OR_PROVINCE_NAME, "S" );
        static readonly RecipientAttribute CountryAttr = new RecipientAttribute( szOID_COUNTRY_NAME, "C" );	/* SSS_WARNINGS_ON */ 

 
        struct RecipientAttribute 
        {
 
            string m_name;
            string m_delimitingString;

            public RecipientAttribute(string name, string delimitingString) 
            {
                m_name = name; 
                m_delimitingString = delimitingString; 
            }
 
            public string DelimitingString
            {
                get { return m_delimitingString; }
            } 

            public string Name 
            { 
                get { return m_name; }
            } 
        }

        //
        // This ID is unique to every site 
        // Used to index into the ledger entries.
        // I.e. one recipient ID --> one ledger entry 
        // 
        string m_recipientId;
 
        //
        // This ID is shared between different sites from the same organization.
        // Used to generate PPID & the pair-wise asymmetric key.
        // 
        string m_recipientOrganizationId;
 
        string m_issuerName; 
        string m_subjectName;
        uint m_privacyNoticeVersion; 
        IdentityType m_type = IdentityType.DNS;
        TrustDecision m_trustDecision;

        // 
        // Recipient Cert parameters - initial to empty values.
        // This will be set only if we initialize with a cert. 
        // 
        RecipientCertParameters m_recipientParams
            = new RecipientCertParameters( 
                      "",
                      "",
                      "",
                      "", 
                      "",
                      Utility.SubjectAtrributeHAFlags.NotEnabled ); 
 
        //
        // Indicates whether the recipients cert is cached on the client request or not. 
        //
        bool m_isCertCached;

        Int32 m_rowId = InvalidRow; 

        byte[] m_publicKey; 
 
        List m_logoMetadata;
 
        //
        // Used by GetRecipientListRequest, LedgerEntry - simply needs to read a Recipient object from the store
        //
        public Recipient(Stream stream) : this( stream, false ) { } 

        // 
        // Used by GetPolicyDetailsRequest - which needs to get logo information for an incoming cert 
        //
        public Recipient(Stream stream, RecipientIdentity identity, bool isCertCached) 
            : this( stream, isCertCached )
        {
            X509RecipientIdentity x509Id = identity as X509RecipientIdentity;
            if( null != x509Id ) 
            {
                m_type = IdentityType.X509; 
 
                AddLogoMetadata( x509Id.LeafCertificate );
                // 
                // Use the recipient parameters from the incoming policy
                //
                m_recipientParams = x509Id.RecipientParams;
            } 
        }
 
        // 
        // Gate constructor for the above
        // 
        private Recipient(Stream stream, bool isCertCached)
        {
            m_isCertCached = isCertCached;
            Deserialize( stream ); 
        }
 
        // 
        // Summary:
        // Recipient constructor - used to construct new recipients as opposed to deserializing from the store 
        //
        // Params:
        // recipientId - recipient identifier
        // isCertCached - flag reflecting if cert is cached or not 
        // privacyNoticeVersion - privacy notice version
        // 
        // 
        //
        public Recipient( 
                   RecipientIdentity identity,
                   bool isCertCached,
                   uint privacyNoticeVersion)
        { 
            m_trustDecision = TrustDecision.NoTrustDecision;
            m_isCertCached = isCertCached; 
            m_privacyNoticeVersion = privacyNoticeVersion; 

            m_recipientId = identity.GetIdentifier(); 

            m_recipientOrganizationId = identity.GetOrganizationIdentifier();

            m_subjectName = identity.GetName(); 

            X509RecipientIdentity x509Id = identity as X509RecipientIdentity; 
 
            if( null != x509Id )
            { 
                m_type = IdentityType.X509;

                m_issuerName = x509Id.LeafCertificate.GetNameInfo( X509NameType.SimpleName, true );
 
                m_recipientParams = x509Id.RecipientParams;
 
                m_publicKey = x509Id.LeafCertificate.GetPublicKey(); 

                AddLogoMetadata( x509Id.LeafCertificate ); 

            }

        } 

        // 
        // Summary: 
        // Recipient constructor - used to construct new recipients as opposed to deserializing from the store
        // 
        // Params:
        // cert - the recipient cert
        // recipientId - recipient identifier
        // recipientOrgId - recipient identifier for the organization 
        // isCertCached - flag reflecting if cert is cached or not
        // privacyNoticeVersion - privacy notice version 
        // RecipientCertParameters - Other useful fields from the certificate 
        //
        // Remarks: 
        // We could have easily calculated the recipientId from the cert,
        // but we pass it in becuase in the normal flow it is already populated in the InfoCardPolicy object.
        // Especially, on some incoming agent requests we need the recipient identifer even before the
        // recipient object is created (to do lookups in the store). 
        //
        // 
        // Used by GetTokenRequest & RemoteTokenFactory [to create and save a recipient] 
        //
        public Recipient( 
                   X509Certificate2 cert,
                   string recipientId,
                   string recipientOrgId,
                   bool isCertCached, 
                   uint privacyNoticeVersion,
                   RecipientCertParameters recipientParameters) 
        { 
            m_type = IdentityType.X509;
            m_trustDecision = TrustDecision.NoTrustDecision; 
            m_publicKey = cert.GetPublicKey();
            m_isCertCached = isCertCached;
            m_privacyNoticeVersion = privacyNoticeVersion;
 

            m_subjectName = cert.FriendlyName; 
            if( string.IsNullOrEmpty( m_subjectName ) ) 
            {
                m_subjectName = cert.GetNameInfo( X509NameType.SimpleName, false ); 
            }

            m_issuerName = cert.GetNameInfo( X509NameType.SimpleName, true );
 
            m_recipientId = recipientId;
 
            m_recipientOrganizationId = recipientOrgId; 

            m_recipientParams = recipientParameters; 

            AddLogoMetadata( cert );
        }
 
        public string RecipientId
        { 
            get 
            {
                IDT.Assert( !String.IsNullOrEmpty( m_recipientId ), "Must be populated before this property is accessed" ); 
                return m_recipientId;
            }
        }
 

 
        public RecipientCertParameters RecipientParameters 
        {
            get 
            {
                return m_recipientParams;
            }
        } 

        public uint PrivacyPolicyVersion 
        { 
            get { return m_privacyNoticeVersion; }
            set { m_privacyNoticeVersion = value; } 
        }


 

 
 

 



 

 
 
        //
        // Summary: 
        // Get the O L S C attributes out of the subject of the cert and construct the string per the
        // RP Identifier DCR.
        //
        // Arguments: 
        // recipientCert - the cert belinging to the recipient
        // supportingRecipientCerts - intermediate certs that may be needed for chain building 
        //                   (if they are not already on the box) 
        // idtype - the type of id that is requested
        // recipientParams - Output struct containing other useful cert fields. 
        //
        // Remarks:
        // 1) If O, L, S, C are empty strings, returns the public key
        // 2) Example: Assume there are 2 faces to an organization, whose chain is trusted by user. 
        //    Suppose Face1.cer and Face2.cer have the same OLSC.
        //    Suppose user visits Face1.com and submits a card. 
        //    Now user goes to Face2.com. 
        //    We will show the RIP page for Face2.com. However to allow co-relation of user
        //    at the organization end, we will send the same pair-wise asymmetric key 
        //    and PPID etc.
        //    And note the above is true whether or not it is HA cert case.
        // 3) If O, L, S, C are not empty the following rules apply
        // HA case: 
        // RPID case example:
        // |CN=\"InfocardBvtHaFace1\"|O=\"IENetTest\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|" 
        // 
        // ORGID case example:
        // |O=\"IENetTest\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|" 
        //
        // ORGPPID case example:
        // |O=\"IENetTest\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|"
        // 
        //
        // For the Non-HA case: 
        // 
        // RPID case example:
        // "|ChainElement=\"C=US, S=Washington, L=Redmond, O=CA2, E=zws@yahoo.com, CN=Root2\" 
        // |ChainElement=\"C=US, S=Washington, L=Redmond, O=CA2, CN=CA2\"
        // |CN=\"END2\"|O=\"IENetTest\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|"
        //
        // ORGID case example: 
        // |Non-EV|O=\"IENetTest\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|"
        // 
        // ORGPPID case example: 
        // |O=\"IENetTest\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|"
        // 
        static byte[] CertGetRecipientIdBytesForChainTrust(
                                 X509Certificate2 recipientCert,
                                 X509Certificate2Collection supportingRecipientCerts,
                                 IdType idtype, 
                                 out RecipientCertParameters recipientParams )
        { 
 
            recipientParams = new RecipientCertParameters(
                                      "", 
                                      "",
                                      "",
                                      "",
                                      "", 
                                      Utility.SubjectAtrributeHAFlags.NotEnabled );
 
            // 
            // Case 2 OR Case 3
            // 
            string recipientIdString = "";


            // 
            // Lets get the OLSC string first
            // 
            string org = GetCertAttribute( OrgAttr.Name, recipientCert.Handle ); 
            string locality = GetCertAttribute( LocalityAttr.Name, recipientCert.Handle );
            string stateOrProvince = GetCertAttribute( StateOrProvinceAttr.Name, recipientCert.Handle );		/* SSS_WARNINGS_OFF */ 
            string country = GetCertAttribute( CountryAttr.Name, recipientCert.Handle );

            recipientParams.m_cn = GetCertAttribute(CNAttr.Name, recipientCert.Handle); ;
            recipientParams.m_organization = org; 
            recipientParams.m_locality = locality;
            recipientParams.m_state = stateOrProvince; 
            recipientParams.m_country = country; 

 
            if( String.IsNullOrEmpty( org ) )
            {
                //
                // Means it is not a org, more a personal cert. So use cn 
                // even though it chains up to a trusted CA.
                // 
                if( !String.IsNullOrEmpty( recipientParams.m_cn ) ) 
                {
                    String cn = String.Format( 
                    CultureInfo.InvariantCulture,
                    "|{0}=\"{1}\"|",
                    CNAttr.DelimitingString, recipientParams.m_cn );
                    return Encoding.Unicode.GetBytes( cn ); 
                }
                else 
                { 
                    return recipientCert.GetPublicKey();
                } 
            }


            // 
            // String.Format uses the StringBuilder to build the string and the StringBuilder buffers the string
            // for performance. 
            // 

 
            //
            // IMPORTANT: Includes CN if !getOrganizationId
            //
            string geographicalAttributes; 

            if( IdType.OrganizationId == idtype || IdType.PPIDSeed == idtype ) 
            { 
                //
                // Only use the OLSC fields 
                // Example geographicalAttributes = "|O=\"InfoCardBvtOrg\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|"
                //
                geographicalAttributes = String.Format(
                    CultureInfo.InvariantCulture, 
                    "|{0}=\"{1}\"|{2}=\"{3}\"|{4}=\"{5}\"|{6}=\"{7}\"|",
                    OrgAttr.DelimitingString, org, 
                    LocalityAttr.DelimitingString, locality, 
                    StateOrProvinceAttr.DelimitingString, stateOrProvince,
                    CountryAttr.DelimitingString, country ); 
            }
            else
            {
                // 
                // Use the cert CN as well
                // Example geographicalAttributes = "|CN=\"InfocardBvtHaFace1\"|O=\"InfoCardBvtOrg\"|L=\"Redmond\"|S=\"Washington\"|C=\"US\"|" 
                // 
                geographicalAttributes = String.Format(
                    CultureInfo.InvariantCulture, 
                    "|{0}=\"{1}\"|{2}=\"{3}\"|{4}=\"{5}\"|{6}=\"{7}\"|{8}=\"{9}\"|",
                    CNAttr.DelimitingString, recipientParams.m_cn,
                    OrgAttr.DelimitingString, org,
                    LocalityAttr.DelimitingString, locality, 
                    StateOrProvinceAttr.DelimitingString, stateOrProvince,
                    CountryAttr.DelimitingString, country ); 
            } 

 
            Utility.SubjectAtrributeHAFlags certHAFlags = Utility.SubjectAtrributeHAFlags.NotEnabled;
            bool isCertHA = Utility.GetCertHAFlags(
                                recipientCert,
                                supportingRecipientCerts, 
                                ref certHAFlags );
 
            // 
            // Lets construct the remainder
            // 
            if( isCertHA )
            {

                // 
                // Case 2: If high assurance, no need to build chain
                // Get the 4 components - O, L, S, C. 
                // Per Kelvin Yui, with either all are HA or they are not. 
                //
 
                recipientParams.m_certHAFlags = certHAFlags;

                if( Utility.IsSubjectAtrributeHAFlagsSet( certHAFlags, Utility.SubjectAtrributeHAFlags.LocStateCountryHA ) ^
                     Utility.IsSubjectAtrributeHAFlagsSet( certHAFlags, Utility.SubjectAtrributeHAFlags.OrganizationHA ) ) 
                {
                    IDT.TraceDebug( "Unexpected but non-fatal: Both LocStateCountry & Organization must be high assurance together" ); 
                } 

                // 
                // NB: For the !getOrganizationId case we already added the CN above.
                //
                recipientIdString = geographicalAttributes;
 

                // 
                // Not legal to flag a certificate with the HA bits if O, L, S, and C are not defined. 
                //
                if( String.IsNullOrEmpty( recipientIdString ) ) 
                {
                    throw IDT.ThrowHelperError(
                                    new UntrustedRecipientException(
                                    SR.GetString( SR.InvalidHACertificateStructure ) ) ); 
                }
            }												/* SSS_WARNINGS_ON */ 
            else 
            {
 

                //
                // Case 3: Else build the chain
                // 
                X509Chain chain;
 
                // 
                // Will throw if validation fails, which is fine.
                // Note the work to do chain.Build is the same as trying to validate it. 
                //
                try
                {
                    InfoCardX509Validator.ValidateChain( recipientCert, supportingRecipientCerts, out chain ); 
                }
                catch( SecurityTokenValidationException ex ) 
                { 
                    //
                    // Extrememly unlikely since validation to trusted root CA has passed at this point. 
                    // Nonetheless, if there is failure, treat is as a untrusted recipient.
                    //
                    throw IDT.ThrowHelperError(
                        new UntrustedRecipientException( 
                            SR.GetString( SR.UnableToBuildChainForNonHARecipient ), ex ) );
                } 
 
                //
                // Only for OrganizationId add a "Non-EV" flag 
                //
                if ( IdType.OrganizationId == idtype )
                {
                    recipientIdString = "|Non-EV"; 
                }
 
                // 
                // Only for a recipientId add the chain elements
                // 
                if( IdType.RecipientId == idtype )
                {

                    // 
                    // Exclude the leaf (the cert we're processing, which is first in the list), include the rest
                    // 
                    for( int i = 1; i < chain.ChainElements.Count; i++ ) 
                    {
                        X509ChainElement ele = chain.ChainElements[ i ]; 

                        recipientIdString = String.Format(
                                CultureInfo.InvariantCulture,
                                "|ChainElement=\"{0}\"{1}", 
                                ele.Certificate.Subject, recipientIdString );
                    } 
                } 

 
                recipientIdString = recipientIdString + geographicalAttributes;

            }
 
            //
            // Get and return unicode bytes 
            // 
            return Encoding.Unicode.GetBytes( recipientIdString );
        } 

        //
        // Summary:
        // Returns Organization PPID seed based on isChainTrusted: 
        //
        // Arguments: 
        // recipientCert - the cert belonging to the recipient 
        // supportingRecipientCerts - intermediate certs that may be needed for chain building
        //                   (if they are not already on the box) 
        // isChainTrusted - indicates if the cert passed chain trust validation
        //
        //
        // Return Value: 
        // the RP organization PPID seed for the recipient.
        // 
        // 
        public static string CertGetRecipientOrganizationPPIDSeedHash(
                                 X509Certificate2 recipientCert, 
                                 X509Certificate2Collection supportingRecipientCerts,
                                 bool isChainTrusted)
        {
            byte[] recipientIdentity; 

            if( !isChainTrusted ) 
            { 
                //
                // Case 1 - simply use public key 
                //
                recipientIdentity = recipientCert.GetPublicKey();

            } 
            else
            { 
                // 
                // Case 2 OR Case 3
                // 
                Recipient.RecipientCertParameters parameters;
                recipientIdentity = CertGetRecipientIdBytesForChainTrust(
                                        recipientCert,
                                        supportingRecipientCerts, 
                                        IdType.PPIDSeed,
                                        out parameters ); 
            } 

            // 
            // 1) Take a SHA256 hash of the bytes, hash gets 32 bytes
            // 2) Convert to base 64. (compression will be 3->4 === 32 bytes -> 44 bytes)
            //
            byte[] theBytes; 

            using( SHA256 sha256 = new SHA256Managed() ) 
            { 
                theBytes = sha256.ComputeHash( recipientIdentity );
            } 

            return Convert.ToBase64String( theBytes );
        }
 

        // 
        // Summary: 
        // Returns Organization RecipientId based on isChainTrusted:
        //     Chain not trusted - Case 1 of RP Identifier DCR 
        //     Chain trusted     - Case 2 or 3 of RP Identifier DCR
        //
        //
        // Arguments: 
        // recipientCert - the cert belinging to the recipient
        // supportingRecipientCerts - intermediate certs that may be needed for chain building 
        //                   (if they are not already on the box) 
        // isChainTrusted - indicates if the cert passed chain trust validation
        // 
        //
        // Return Value:
        // the RP organization identifier for the recipient.
        // 
        //
        public static string CertGetRecipientOrganizationIdHash( 
                                 X509Certificate2 recipientCert, 
                                 X509Certificate2Collection supportingRecipientCerts,
                                 bool isChainTrusted ) 
        {
            byte[] recipientIdentity;

            if( !isChainTrusted ) 
            {
                // 
                // Case 1 - simply use public key 
                //
                recipientIdentity = recipientCert.GetPublicKey(); 

            }
            else
            { 
                //
                // Case 2 OR Case 3 
                // 
                Recipient.RecipientCertParameters parameters;
                recipientIdentity = CertGetRecipientIdBytesForChainTrust( 
                                        recipientCert,
                                        supportingRecipientCerts,
                                        IdType.OrganizationId,
                                        out parameters ); 
            }
 
            // 
            // 1) Take a SHA256 hash of the bytes, hash gets 32 bytes
            // 2) Convert to base 64. (compression will be 3->4 === 32 bytes -> 44 bytes) 
            //
            byte[] theBytes;

            using( SHA256 sha256 = new SHA256Managed() ) 
            {
                theBytes = sha256.ComputeHash( recipientIdentity ); 
            } 

            return Convert.ToBase64String( theBytes ); 
        }

        //
        // Summary: 
        // Returns RecipientId based on isChainTrusted:
        //     Chain not trusted - Case 1 of RP Identifier DCR 
        //     Chain trusted     - Case 2 or 3 of RP Identifier DCR 
        //
        // 
        // Arguments:
        // recipientCert - the cert belinging to the recipient
        // supportingRecipientCerts - intermediate certs that may be needed for chain building
        //                   (if they are not already on the box) 
        // isChainTrusted - indicates if the cert passed chain trust validation
        // recipientParams - Output useful set of cert parameters used by UI. 
        // 
        //
        // Return Value: 
        // the RP identifier for the recipient.
        // recipieintParams are not set for non trusted certs.
        //
        // 
        public static string CertGetRecipientIdHash(
                                 X509Certificate2 recipientCert, 
                                 X509Certificate2Collection supportingRecipientCerts, 
                                 bool isChainTrusted,
                                 out RecipientCertParameters recipientParams) 
        {
            byte[] recipientIdentity;

            if( !isChainTrusted ) 
            {
                // 
                // Case 1 - simply use public key 
                //
                recipientIdentity = recipientCert.GetPublicKey(); 
                recipientParams = new RecipientCertParameters(
                                          GetCertAttribute( CNAttr.Name, recipientCert.Handle ),
                                          GetCertAttribute( OrgAttr.Name, recipientCert.Handle ),
                                          GetCertAttribute( LocalityAttr.Name, recipientCert.Handle ), 
                                          GetCertAttribute( StateOrProvinceAttr.Name, recipientCert.Handle ),	/* SSS_WARNINGS_OFF */
                                          GetCertAttribute( CountryAttr.Name, recipientCert.Handle ),		/* SSS_WARNINGS_ON */ 
                                          Utility.SubjectAtrributeHAFlags.NotEnabled ); 
            }
            else 
            {
                //
                // Case 2 OR Case 3
                // 
                recipientIdentity = CertGetRecipientIdBytesForChainTrust(
                                        recipientCert, 
                                        supportingRecipientCerts, 
                                        IdType.RecipientId,
                                        out recipientParams ); 
            }

            //
            // 1) Take a SHA256 hash of the bytes, hash gets 32 bytes 
            // 2) Convert to base 64. (compression will be 3->4 === 32 bytes -> 44 bytes)
            // 
            byte[] theBytes; 

            using( SHA256 sha256 = new SHA256Managed() ) 
            {
                theBytes = sha256.ComputeHash( recipientIdentity );
            }
 
            return Convert.ToBase64String( theBytes );
        } 
 

 
        private static string GetCertAttribute(string geographicAttributeName, IntPtr certHandle)
        {
            StringBuilder pszNameString = new StringBuilder( attributeMaxLength );
 
            int retVal = NativeMethods.CertGetNameString(
               certHandle, 
               CERT_NAME_ATTR_TYPE, 
               0,
               geographicAttributeName, 
               pszNameString,
               attributeMaxLength );

            // 
            // CertGetNameString returns thenumber of characters converted, including the terminating zero character.
            // Since the underlying API does not talk about errors, we proceed assuming that zero means 
            // no string value. 
            //
            return pszNameString.ToString(); 

        }

 

 
        public TrustDecision Trust 
        {
            set { m_trustDecision = value; } 
            get { return m_trustDecision; }
        }

        private void ThrowIfNotComplete() 
        {
            // 
            // Verify that the Recipient has been populated. 
            //
            bool isComplete = ( null != m_recipientId && 
                null != m_subjectName );
            if( IdentityType.X509 == m_type )
            {
                isComplete = isComplete 
                    && null != m_issuerName
                    && !Utility.ArrayIsNullOrEmpty( m_publicKey ); 
            } 

            if( !isComplete ) 
            {
                throw IDT.ThrowHelperError( new SerializationIncompleteException( this.GetType() ) );
            }
        } 

        private void AddLogoMetadata(X509Certificate2 cert) 
        { 
            X509LogoTypeExtension logoExtension = X509LogoTypeExtension.FromCertificate( cert );
 
            if( null == logoExtension )
            {
                return;
            } 

            logoExtension.TryDecodeExtension(); 
 
            m_logoMetadata = logoExtension.Logos;
        } 

        public void Serialize(System.IO.BinaryWriter writer)
        {
            AgentSerialize( writer ); 
        }
 
        public void AgentSerialize(System.IO.BinaryWriter writer) 
        {
            // 
            // Make sure that we don't serialize an incomplete object. Serializing null values will result in a
            // serialization exception or a corrupt signature.
            //
            ThrowIfNotComplete(); 

            // 
            // Write each member to binary stream 
            //
            writer.Write( Version ); 

            writer.Write( (byte)m_type );
            writer.Write( m_isCertCached );
 
            //
            // Write HA flags and the CN,O,L,S,C fields. 
            // 
            writer.Write( (uint)m_recipientParams.m_certHAFlags );
            Utility.SerializeString( writer, m_recipientParams.m_cn ); 
            Utility.SerializeString( writer, m_recipientParams.m_organization );
            Utility.SerializeString( writer, m_recipientParams.m_locality );
            Utility.SerializeString( writer, m_recipientParams.m_state );
            Utility.SerializeString( writer, m_recipientParams.m_country ); 

            Utility.SerializeString( writer, m_recipientId ); 
            Utility.SerializeString( writer, m_recipientOrganizationId ); 
            Utility.SerializeString( writer, m_issuerName );
            Utility.SerializeString( writer, m_subjectName ); 
            writer.Write( m_privacyNoticeVersion );
            Utility.SerializeBytes( writer, m_publicKey );

            writer.Write( (byte)m_trustDecision ); 

            if( null == m_logoMetadata ) 
            { 
                //
                // Indicate that there are no logos. 
                //
                writer.Write( 0 );
            }
            else 
            {
                // 
                // Write the number of X509Logo objects. 
                //
                writer.Write( m_logoMetadata.Count ); 

                //
                // Write each X509Logo object.
                // 
                foreach( X509Logo logo in m_logoMetadata )
                { 
                    logo.Serialize( writer ); 
                }
            } 
            writer.Write( m_marker );

        }
 
        public void SerializeToStore(System.IO.BinaryWriter writer)
        { 
            // 
            // Make sure that we don't serialize an incomplete object. Serializing null values will result in a
            // serialization exception or a corrupt signature. 
            //
            ThrowIfNotComplete();

            // 
            // Write each member to binary stream
            // 
            writer.Write( Version ); 

            // 
            // Write HA flags and the CN,O,L,S,C fields.
            //
            writer.Write( (uint)m_recipientParams.m_certHAFlags );
            Utility.SerializeString( writer, m_recipientParams.m_cn ); 
            Utility.SerializeString( writer, m_recipientParams.m_organization );
            Utility.SerializeString( writer, m_recipientParams.m_locality ); 
            Utility.SerializeString( writer, m_recipientParams.m_state ); 
            Utility.SerializeString( writer, m_recipientParams.m_country );
 
            Utility.SerializeString( writer, m_recipientId );
            Utility.SerializeString( writer, m_recipientOrganizationId );
            Utility.SerializeString( writer, m_issuerName );
            Utility.SerializeString( writer, m_subjectName ); 
            writer.Write( m_privacyNoticeVersion );
            Utility.SerializeBytes( writer, m_publicKey ); 
 
            writer.Write( (byte)m_trustDecision );
 
            writer.Write( m_marker );
        }

        public void Deserialize(System.IO.Stream stream) 
        {
            // 
            // Populate each member from the stream 
            //
            BinaryReader reader = new InfoCardBinaryReader( stream, Encoding.Unicode ); 
            //
            // Check the version
            //
            if( Version != reader.ReadByte() ) 
            {
                IDT.Assert( false, "version mismatch deserializing recipient stream" ); 
            } 

            // 
            // Read the HA flags and CN,O,L,S,C fields.
            //

            m_recipientParams = new RecipientCertParameters(); 

            m_recipientParams.m_certHAFlags = (Utility.SubjectAtrributeHAFlags)reader.ReadUInt32(); 
            m_recipientParams.m_cn = Utility.DeserializeString( reader ); 
            m_recipientParams.m_organization = Utility.DeserializeString( reader );
            m_recipientParams.m_locality = Utility.DeserializeString( reader ); 
            m_recipientParams.m_state = Utility.DeserializeString( reader );
            m_recipientParams.m_country = Utility.DeserializeString( reader );

            // 
            // Read each property from the stream
            // 
            m_recipientId = Utility.DeserializeString( reader ); 
            m_recipientOrganizationId = Utility.DeserializeString( reader );
            m_issuerName = Utility.DeserializeString( reader ); 
            m_subjectName = Utility.DeserializeString( reader );
            m_privacyNoticeVersion = reader.ReadUInt32();
            m_publicKey = reader.ReadBytes( reader.ReadInt32() );
 
            //
            // This is not a good way to decided is the identity is of the correct type. 
            // In V2 we want to be able to write an explicit identity type, but till then 
            // then we will use the lack of a public key to signify that the recipient is
            // for an X509 type 
            //
            if( 0 == m_publicKey.Length )
            {
                m_type = IdentityType.DNS; 
            }
            else 
            { 
                m_type = IdentityType.X509;
            } 
            m_trustDecision = (TrustDecision)reader.ReadByte();


 
            //
            // Validate the end of the buffer 
            // 
            if( m_marker != reader.ReadByte() )
            { 
                IDT.Assert( false, "Invalid stream detected deserilizing recipient" );
            }

            // 
            // Just a correctness check
            // 
            ThrowIfNotComplete(); 
        }
 

        public void Save(StoreConnection con)
        {
            IDT.TraceDebug( "Saving Recipient..." ); 
            IDT.TraceDebug( ToString() );
 
            // 
            // Write the Recipient object to the store
            // 

            //
            // Try and get the database header information to
            // see if this is an insert or update. 
            //
            // Note: The datafield is not part of the projection 
            // in order to avoid unecessary decryption. 
            //
            DataRow row = TryGetRow( con, QueryDetails.FullHeader ); 

            if( null == row )
            {
                row = new DataRow(); 
                row.ObjectType = (Int32)StorableObjectType.Recipient;
                row.GlobalId = Guid.NewGuid(); 
            } 

            // 
            // Populate the parentId index field
            //
            row.SetIndexValue( SecondaryIndexDefinition.RecipientIdIndex, m_recipientId );
 
            //
            // Populate the data object 
            // 
            MemoryStream ms = new MemoryStream();
            System.IO.BinaryWriter writer = new BinaryWriter( ms, Encoding.Unicode ); 
            SerializeToStore( writer );
            row.SetDataField( ms.ToArray() );

            // 
            // Save the row to the database
            // 
 
            con.Save( row );
 

            //
            // Update the row id in the object in case
            // this was an insert. 
            //
            m_rowId = row.LocalId; 
        } 

        public override string ToString() 
        {
#if DEBUG
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat( "Recipient RecipientId:\t{0}\n", m_recipientId ); 
            sb.AppendFormat( "Recipient Issuer Name:\t{0}\n", m_issuerName );
            sb.AppendFormat( "Recipient Subject Name:\t{0}\n", m_subjectName ); 
            sb.AppendFormat( "Recipient PrivacyNoticeVersion:\t{0}\n", m_privacyNoticeVersion ); 
            sb.AppendFormat( "TrustDecision:\t{0}\n", m_trustDecision.ToString() );
 
            return sb.ToString();
#else
            return base.ToString();
#endif 
        }
 
        // 
        // Summary
        //   Check if the organization is verified 
        //
        public bool IsOrganizationVerified()
        {
            // 
            // Any of these flags being set means that the orgaganization is verified
            // So we create a mask using these two flags 
            // 
            Utility.SubjectAtrributeHAFlags allowedFlags = Utility.SubjectAtrributeHAFlags.Enabled | Utility.SubjectAtrributeHAFlags.OrganizationHA;
 

            return ( this.m_recipientParams.m_certHAFlags & allowedFlags ) == allowedFlags;

        } 

 
        protected DataRow TryGetRow(StoreConnection con, QueryDetails details) 
        {
 
            //
            // Retrieve a single object from the database
            //
            DataRow row = con.GetSingleRow( 
                QueryDetails.FullHeader,
                new QueryParameter( SecondaryIndexDefinition.ObjectTypeIndex, 
                                  (Int32)StorableObjectType.Recipient ), 
                new QueryParameter( SecondaryIndexDefinition.RecipientIdIndex,
                                  m_recipientId ) ); 
            return row;
        }

    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK