Beispiel #1
0
        // expecting ldap v3 distinguished names. https://tools.ietf.org/html/rfc2253
        // That's what nginx 1.11+ passes
        public CertificateSubjectDetail(string subjectDN)
        {
            if (string.IsNullOrEmpty(subjectDN))
            {
                return;
            }

            var rdns = new List <string>();
            int i = 0, j = 0;

            char[] chars = subjectDN.ToCharArray();
            char   last  = '_';

            for (i = 0; i < chars.Length; i++)
            {
                if ((chars[i] == ',' || chars[i] == '+') && last != '\\')
                {
                    rdns.Add(subjectDN.Substring(j, i - j));
                    j = i + 1;
                }
                last = chars[i];
            }
            rdns.Add(subjectDN.Substring(j));

            this.Subject     = subjectDN;
            this.IsAffiliate = Regex.IsMatch(subjectDN, "affiliate|contractor", RegexOptions.IgnoreCase);
            this.ExternalId  = rdns.Where(x => x.StartsWith("UID=")).Select(x => x.Substring(4)).FirstOrDefault();
            this.CommonName  = rdns.Where(x => x.StartsWith("CN=")).Select(x => x.Substring(3)).FirstOrDefault();
            var nameParts = this.CommonName.Split('.');

            //if no externalid, parse from CN, dod-style
            if (String.IsNullOrEmpty(ExternalId) &&
                Int64.TryParse(nameParts.Last(), out long id))
            {
                this.ExternalId = nameParts.Last();
            }

            // if no "UID=", and no '.uid', use the full subject
            if (String.IsNullOrEmpty(ExternalId))
            {
                ExternalId = Subject;
            }

            // ensure ExternalId has an OU/O context.  Some CA's qualify
            // the UID, some assume their number is unique; but we can't
            // rely on that when accepting certs from various orgs.
            var  ou         = rdns.Where(x => x.StartsWith("OU=")).Select(x => x.Substring(3));
            var  o          = rdns.Where(x => x.StartsWith("O=")).Select(x => x.Substring(2));
            bool hasContext = false;

            foreach (string s in ou)
            {
                hasContext |= ExternalId.Contains(s);
            }
            foreach (string s in o)
            {
                hasContext |= ExternalId.Contains(s);
            }
            if (!hasContext)
            {
                DeprecatedExternalId = ExternalId;
                ExternalId          += "." + ou.LastOrDefault() ?? o.LastOrDefault();
            }

            DisplayName = (nameParts.Length > 1) // assume dod-style
                ? $"{nameParts[1]} {nameParts[0]}"
                : CommonName;

            // clean up display name by removing initials and qualifiers
            nameParts = this.DisplayName
                        .Split(' ')
                        .Where(x => x.Length > 1 && !x.StartsWith("("))
                        .ToArray();

            this.DisplayName = String.Join(" ", nameParts).ToTitle();
            this.UserName    = this.DisplayName.ToAccountSlug();
        }