< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.SpnEndpointIdentity
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/SpnEndpointIdentity.cs
Line coverage
7%
Covered lines: 5
Uncovered lines: 59
Coverable lines: 64
Total lines: 168
Line coverage: 7.8%
Branch coverage
3%
Covered branches: 1
Total branches: 30
Branch coverage: 3.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
.ctor(...)50%2283.33%
.ctor(...)0%440%
WriteContentsTo(...)0%220%
GetSpnSid()0%16160%
GetDirectoryEntry()0%440%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/SpnEndpointIdentity.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.DirectoryServices;
 6using System.Runtime.InteropServices;
 7using System.Security.Principal;
 8using System.Xml;
 9using CoreWCF.IdentityModel.Claims;
 10using CoreWCF.Runtime;
 11using CoreWCF.Security;
 12
 13namespace CoreWCF
 14{
 15    public class SpnEndpointIdentity : EndpointIdentity
 16    {
 017        private static TimeSpan s_spnLookupTime = TimeSpan.FromMinutes(1);
 18        private SecurityIdentifier _spnSid;
 19
 20        // Double-checked locking pattern requires volatile for read/write synchronization
 21        private bool _hasSpnSidBeenComputed;
 1222        private readonly object _thisLock = new object();
 023        private static readonly object s_typeLock = new object();
 24
 25        // Double-checked locking pattern requires volatile for read/write synchronization
 26        private static DirectoryEntry s_directoryEntry;
 27
 28        public static TimeSpan SpnLookupTime
 29        {
 30            get
 31            {
 032                return s_spnLookupTime;
 33            }
 34            set
 35            {
 036                if (value.Ticks < 0)
 37                {
 038                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(val
 039                                                    SRCommon.ValueMustBeNonNegative));
 40                }
 041                s_spnLookupTime = value;
 042            }
 43        }
 44
 1245        public SpnEndpointIdentity(string spnName)
 46        {
 1247            if (spnName == null)
 48            {
 049                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(spnName));
 50            }
 51
 1252            Initialize(Claim.CreateSpnClaim(spnName));
 1253        }
 54
 055        public SpnEndpointIdentity(Claim identity)
 56        {
 057            if (identity == null)
 58            {
 059                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(identity));
 60            }
 61
 062            if (!ClaimTypes.Spn.Equals(identity.ClaimType))
 63            {
 064                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.Format(SR.UnrecognizedClaimTypeForIdenti
 65            }
 66
 067            Initialize(identity);
 068        }
 69
 70        internal override void WriteContentsTo(XmlDictionaryWriter writer)
 71        {
 072            if (writer == null)
 73            {
 074                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writer));
 75            }
 76
 077            writer.WriteElementString(XD.AddressingDictionary.Spn, XD.AddressingDictionary.IdentityExtensionNamespace, (
 078        }
 79
 80        internal SecurityIdentifier GetSpnSid()
 81        {
 82            Fx.Assert(ClaimTypes.Spn.Equals(IdentityClaim.ClaimType) || ClaimTypes.Dns.Equals(IdentityClaim.ClaimType), 
 083            if (!_hasSpnSidBeenComputed)
 84            {
 085                lock (_thisLock)
 86                {
 087                    if (!_hasSpnSidBeenComputed)
 88                    {
 089                        string spn = null;
 90                        try
 91                        {
 092                            if (ClaimTypes.Dns.Equals(IdentityClaim.ClaimType))
 93                            {
 094                                spn = "host/" + (string)IdentityClaim.Resource;
 95                            }
 96                            else
 97                            {
 098                                spn = (string)IdentityClaim.Resource;
 99                            }
 100                            // canonicalize SPN for use in LDAP filter following RFC 1960:
 0101                            if (spn != null)
 102                            {
 0103                                spn = spn.Replace("*", @"\*").Replace("(", @"\(").Replace(")", @"\)");
 104                            }
 105
 0106                            DirectoryEntry de = GetDirectoryEntry();
 0107                            using (DirectorySearcher searcher = new DirectorySearcher(de))
 108                            {
 0109                                searcher.CacheResults = true;
 0110                                searcher.ClientTimeout = SpnLookupTime;
 0111                                searcher.Filter = "(&(objectCategory=Computer)(objectClass=computer)(servicePrincipalNam
 0112                                searcher.PropertiesToLoad.Add("objectSid");
 0113                                SearchResult result = searcher.FindOne();
 0114                                if (result != null)
 115                                {
 0116                                    byte[] sidBinaryForm = (byte[])result.Properties["objectSid"][0];
 0117                                    _spnSid = new SecurityIdentifier(sidBinaryForm, 0);
 118                                }
 119                                else
 120                                {
 121                                    //SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(spn, null);
 122                                }
 0123                            }
 0124                        }
 125#pragma warning disable 56500 // covered by FxCOP
 0126                        catch (Exception e)
 127                        {
 128                            // Always immediately rethrow fatal exceptions.
 0129                            if (Fx.IsFatal(e))
 130                            {
 0131                                throw;
 132                            }
 133
 0134                            if (e is NullReferenceException || e is SEHException)
 135                            {
 0136                                throw;
 137                            }
 138
 139                            //SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(spn, e);
 0140                        }
 141                        finally
 142                        {
 0143                            _hasSpnSidBeenComputed = true;
 0144                        }
 145                    }
 0146                }
 147            }
 0148            return _spnSid;
 149        }
 150
 151        private static DirectoryEntry GetDirectoryEntry()
 152        {
 0153            if (s_directoryEntry == null)
 154            {
 0155                lock (s_typeLock)
 156                {
 0157                    if (s_directoryEntry == null)
 158                    {
 0159                        DirectoryEntry tmp = new DirectoryEntry(@"LDAP://" + SecurityUtils.GetPrimaryDomain());
 0160                        tmp.RefreshCache(new string[] { "name" });
 0161                        s_directoryEntry = tmp;
 162                    }
 0163                }
 164            }
 0165            return s_directoryEntry;
 166        }
 167    }
 168}