Ejemplo n.º 1
0
        private ServiceResult OnFinishRequest(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            NodeId applicationId,
            NodeId requestId,
            ref byte[] certificate,
            ref byte[] privateKey,
            ref byte[][] issuerCertificates)
        {
            issuerCertificates = null;
            HasApplicationAdminAccess(context);

            var done = m_database.CompleteCertificateRequest(applicationId, requestId, out certificate, out privateKey);

            if (!done)
            {
                return(new ServiceResult(StatusCodes.BadNothingToDo, "The request has not been approved by the administrator."));
            }

            CertificateGroup certificateGroup = GetGroupForCertificate(certificate);

            issuerCertificates    = new byte[1][];
            issuerCertificates[0] = certificateGroup.Certificate.RawData;

            return(ServiceResult.Good);
        }
Ejemplo n.º 2
0
        private NodeId GetTrustListId(NodeId certificateGroupId)
        {
            if (NodeId.IsNull(certificateGroupId))
            {
                certificateGroupId = DefaultApplicationGroupId;
            }

            CertificateGroup certificateGroup = null;

            if (m_certificateGroups.TryGetValue(certificateGroupId, out certificateGroup))
            {
                return(certificateGroup.DefaultTrustList?.NodeId);
            }

            return(null);
        }
Ejemplo n.º 3
0
        private string GetSubjectName(ApplicationRecordDataType application, CertificateGroup certificateGroup, string subjectName)
        {
            bool contextFound = false;

            var fields = Utils.ParseDistinguishedName(subjectName);

            StringBuilder builder = new StringBuilder();

            foreach (var field in fields)
            {
                if (builder.Length > 0)
                {
                    builder.Append(",");
                }

                if (field.StartsWith("CN=", StringComparison.Ordinal))
                {
                    if (certificateGroup.Id == DefaultHttpsGroupId)
                    {
                        var error = CheckHttpsDomain(application, field.Substring(3));

                        if (StatusCode.IsBad(error.StatusCode))
                        {
                            builder.Append("CN=");
                            builder.Append(GetDefaultHttpsDomain(application));
                            continue;
                        }
                    }
                }

                contextFound |= (field.StartsWith("DC=", StringComparison.Ordinal) || field.StartsWith("O=", StringComparison.Ordinal));

                builder.Append(field);
            }

            if (!contextFound)
            {
                if (!String.IsNullOrEmpty(m_configuration.DefaultSubjectNameContext))
                {
                    builder.Append(m_configuration.DefaultSubjectNameContext);
                }
            }

            return(builder.ToString());
        }
Ejemplo n.º 4
0
        protected void SetCertificateGroupNodes(CertificateGroup certificateGroup)
        {
            certificateGroup.CertificateType  = Opc.Ua.ObjectTypeIds.ApplicationCertificateType;
            certificateGroup.DefaultTrustList = null;
            switch (certificateGroup.Configuration.Id)
            {
            case "Https":
                certificateGroup.Id = DefaultHttpsGroupId;
                certificateGroup.CertificateType  = Opc.Ua.ObjectTypeIds.HttpsCertificateType;
                certificateGroup.DefaultTrustList = (TrustListState)FindPredefinedNode(ExpandedNodeId.ToNodeId(Opc.Ua.Gds.ObjectIds.Directory_CertificateGroups_DefaultHttpsGroup_TrustList, Server.NamespaceUris), typeof(TrustListState));
                break;

            case "UserToken":
                certificateGroup.Id = DefaultUserTokenGroupId;
                certificateGroup.CertificateType  = null;
                certificateGroup.DefaultTrustList = (TrustListState)FindPredefinedNode(ExpandedNodeId.ToNodeId(Opc.Ua.Gds.ObjectIds.Directory_CertificateGroups_DefaultUserTokenGroup_TrustList, Server.NamespaceUris), typeof(TrustListState));
                break;

            case "Default":
                certificateGroup.Id = DefaultApplicationGroupId;
                if (certificateGroup.Configuration.DefaultCertificateHashSize < 256)
                {
                    certificateGroup.CertificateType = Opc.Ua.ObjectTypeIds.RsaMinApplicationCertificateType;
                }
                else if (certificateGroup.Configuration.DefaultCertificateHashSize == 256)
                {
                    certificateGroup.CertificateType = Opc.Ua.ObjectTypeIds.RsaSha256ApplicationCertificateType;
                }
                certificateGroup.DefaultTrustList = (TrustListState)FindPredefinedNode(ExpandedNodeId.ToNodeId(Opc.Ua.Gds.ObjectIds.Directory_CertificateGroups_DefaultApplicationGroup_TrustList, Server.NamespaceUris), typeof(TrustListState));
                break;

            default:
                throw new NotImplementedException("Custom certificate groups are not implemented. Use Default, Https or UserToken");
            }

            if (certificateGroup.DefaultTrustList != null)
            {
                certificateGroup.DefaultTrustList.Handle = new TrustList(
                    certificateGroup.DefaultTrustList,
                    certificateGroup.Configuration.TrustedListPath,
                    certificateGroup.Configuration.IssuerListPath,
                    new TrustList.SecureAccess(HasApplicationUserAccess),
                    new TrustList.SecureAccess(HasApplicationAdminAccess));
            }
        }
Ejemplo n.º 5
0
        protected async Task <CertificateGroup> InitializeCertificateGroup(CertificateGroupConfiguration certificateGroupConfiguration)
        {
            if (String.IsNullOrEmpty(certificateGroupConfiguration.SubjectName))
            {
                throw new ArgumentNullException("SubjectName not specified");
            }

            if (String.IsNullOrEmpty(certificateGroupConfiguration.BaseStorePath))
            {
                throw new ArgumentNullException("BaseStorePath not specified");
            }

            CertificateGroup certificateGroup = m_certificateGroupProvider.Create(
                m_configuration.AuthoritiesStorePath, certificateGroupConfiguration);

            SetCertificateGroupNodes(certificateGroup);
            await certificateGroup.Init();

            return(certificateGroup);
        }
Ejemplo n.º 6
0
        private async Task RevokeCertificateAsync(byte[] certificate)
        {
            if (certificate != null && certificate.Length > 0)
            {
                CertificateGroup certificateGroup = GetGroupForCertificate(certificate);

                if (certificateGroup != null)
                {
                    try
                    {
                        var x509 = new X509Certificate2(certificate);
                        await certificateGroup.RevokeCertificateAsync(x509);
                    }
                    catch (Exception e)
                    {
                        Utils.Trace(e, "Unexpected error revoking certificate. {0} for Authority={1}", new X509Certificate2(certificate).Subject, certificateGroup.Id);
                    }
                }
            }
        }
Ejemplo n.º 7
0
        private Boolean?GetCertificateStatus(
            NodeId certificateGroupId,
            NodeId certificateTypeId)
        {
            CertificateGroup certificateGroup = null;

            if (m_certificateGroups.TryGetValue(certificateGroupId, out certificateGroup))
            {
                if (!NodeId.IsNull(certificateTypeId))
                {
                    if (!Utils.IsEqual(certificateGroup.CertificateType, certificateTypeId))
                    {
                        return(null);
                    }
                }
                return(certificateGroup.UpdateRequired);
            }

            return(null);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Does any initialization required before the address space can be used.
        /// </summary>
        /// <remarks>
        /// The externalReferences is an out parameter that allows the node manager to link to nodes
        /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and
        /// should have a reference to the root folder node(s) exposed by this node manager.
        /// </remarks>
        public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences)
        {
            lock (Lock)
            {
                base.CreateAddressSpace(externalReferences);

                m_database.NamespaceIndex = NamespaceIndexes[0];

                foreach (var certificateGroupConfiguration in m_configuration.CertificateGroups)
                {
                    try
                    {
                        CertificateGroup certificateGroup = InitializeCertificateGroup(certificateGroupConfiguration).Result;
                        m_certificateGroups[certificateGroup.Id] = certificateGroup;
                    }
                    catch (Exception e)
                    {
                        Utils.Trace(e, "Unexpected error initializing certificateGroup: " + certificateGroupConfiguration.Id + "\r\n" + e.StackTrace);
                        // make sure gds server doesn't start without cert groups!
                        throw e;
                    }
                }
            }
        }
Ejemplo n.º 9
0
        private ServiceResult OnStartSigningRequest(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            NodeId applicationId,
            NodeId certificateGroupId,
            NodeId certificateTypeId,
            byte[] certificateRequest,
            ref NodeId requestId)
        {
            HasApplicationAdminAccess(context);

            var application = m_database.GetApplication(applicationId);

            if (application == null)
            {
                return(new ServiceResult(StatusCodes.BadNotFound, "The ApplicationId does not refer to a valid application."));
            }

            if (NodeId.IsNull(certificateGroupId))
            {
                certificateGroupId = ExpandedNodeId.ToNodeId(Opc.Ua.Gds.ObjectIds.Directory_CertificateGroups_DefaultApplicationGroup, Server.NamespaceUris);
            }

            CertificateGroup certificateGroup = null;

            if (!m_certificateGroups.TryGetValue(certificateGroupId, out certificateGroup))
            {
                return(new ServiceResult(StatusCodes.BadInvalidArgument, "The CertificateGroupId does not refer to a supported certificateGroup."));
            }

            if (!NodeId.IsNull(certificateTypeId))
            {
                if (!Server.TypeTree.IsTypeOf(certificateGroup.CertificateType, certificateTypeId))
                {
                    return(new ServiceResult(StatusCodes.BadInvalidArgument, "The CertificateTypeId is not supported by the certificateGroup."));
                }
            }

            X509Certificate2 certificate = null;

            try
            {
                string[] domainNames = GetDefaultDomainNames(application);
                certificate = certificateGroup.SigningRequestAsync(
                    application,
                    domainNames,
                    certificateRequest
                    ).Result;
            }
            catch (Exception e)
            {
                StringBuilder error = new StringBuilder();

                error.Append("Error Generating Certificate=" + e.Message);
                error.Append("\r\nApplicationId=" + applicationId.ToString());
                error.Append("\r\nApplicationUri=" + application.ApplicationUri);
                error.Append("\r\nApplicationName=" + application.ApplicationNames[0].Text);

                return(new ServiceResult(StatusCodes.BadConfigurationError, error.ToString()));
            }

            requestId = m_database.CreateCertificateRequest(
                applicationId,
                certificate.RawData,
                null,
                certificateGroup.Id.Identifier as string);

            // store new app certificate
            using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_configuration.ApplicationCertificatesStorePath))
            {
                store.Add(new X509Certificate2(certificate.RawData)).Wait();
            }

            if (m_autoApprove)
            {
                m_database.ApproveCertificateRequest(requestId, false);
            }

            return(ServiceResult.Good);
        }
Ejemplo n.º 10
0
        private ServiceResult OnStartNewKeyPairRequest(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            NodeId applicationId,
            NodeId certificateGroupId,
            NodeId certificateTypeId,
            string subjectName,
            string[] domainNames,
            string privateKeyFormat,
            string privateKeyPassword,
            ref NodeId requestId)
        {
            HasApplicationAdminAccess(context);

            var application = m_database.GetApplication(applicationId);

            if (application == null)
            {
                return(new ServiceResult(StatusCodes.BadNotFound, "The ApplicationId does not refer to a valid application."));
            }

            if (NodeId.IsNull(certificateGroupId))
            {
                certificateGroupId = ExpandedNodeId.ToNodeId(Opc.Ua.Gds.ObjectIds.Directory_CertificateGroups_DefaultApplicationGroup, Server.NamespaceUris);
            }

            CertificateGroup certificateGroup = null;

            if (!m_certificateGroups.TryGetValue(certificateGroupId, out certificateGroup))
            {
                return(new ServiceResult(StatusCodes.BadInvalidArgument, "The certificateGroup is not supported."));
            }

            if (!NodeId.IsNull(certificateTypeId))
            {
                if (!Server.TypeTree.IsTypeOf(certificateGroup.CertificateType, certificateTypeId))
                {
                    return(new ServiceResult(StatusCodes.BadInvalidArgument, "The CertificateType is not supported by the certificateGroup."));
                }
            }

            if (!String.IsNullOrEmpty(subjectName))
            {
                subjectName = GetSubjectName(application, certificateGroup, subjectName);
            }
            else
            {
                StringBuilder buffer = new StringBuilder();

                buffer.Append("CN=");

                if ((NodeId.IsNull(certificateGroup.Id) || (certificateGroup.Id == DefaultApplicationGroupId)) && (application.ApplicationNames.Count > 0))
                {
                    buffer.Append(application.ApplicationNames[0]);
                }
                else if (certificateGroup.Id == DefaultHttpsGroupId)
                {
                    buffer.Append(GetDefaultHttpsDomain(application));
                }
                else if (certificateGroup.Id == DefaultUserTokenGroupId)
                {
                    buffer.Append(GetDefaultUserToken());
                }

                if (!String.IsNullOrEmpty(m_configuration.DefaultSubjectNameContext))
                {
                    buffer.Append(m_configuration.DefaultSubjectNameContext);
                }

                subjectName = buffer.ToString();
            }

            if (domainNames != null && domainNames.Length > 0)
            {
                foreach (var domainName in domainNames)
                {
                    if (Uri.CheckHostName(domainName) == UriHostNameType.Unknown)
                    {
                        return(new ServiceResult(StatusCodes.BadInvalidArgument, "The domainName ({0}) is not a valid DNS Name or IPAddress.", domainName));
                    }
                }
            }
            else
            {
                domainNames = GetDefaultDomainNames(application);
            }

            X509Certificate2 newCertificate = null;

            try
            {
                newCertificate = certificateGroup.NewKeyPairRequestAsync(
                    application,
                    subjectName,
                    domainNames,
                    privateKeyFormat,
                    privateKeyPassword).Result;
            }
            catch (Exception e)
            {
                StringBuilder error = new StringBuilder();

                error.Append("Error Generating New Key Pair Certificate=" + e.Message);
                error.Append("\r\nApplicationId=" + applicationId.ToString());
                error.Append("\r\nApplicationUri=" + application.ApplicationUri);

                return(new ServiceResult(StatusCodes.BadConfigurationError, error.ToString()));
            }

            byte[] privateKey;
            if (privateKeyFormat == "PFX")
            {
                privateKey = newCertificate.Export(X509ContentType.Pfx, privateKeyPassword);
            }
            else if (privateKeyFormat == "PEM")
            {
                privateKey = CertificateFactory.ExportPrivateKeyAsPEM(newCertificate);
            }
            else
            {
                return(new ServiceResult(StatusCodes.BadInvalidArgument, "Invalid private key format"));
            }

            // store only app certificate
            using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_configuration.ApplicationCertificatesStorePath))
            {
                store.Add(new X509Certificate2(newCertificate.RawData)).Wait();
            }

            requestId = m_database.CreateCertificateRequest(
                applicationId,
                newCertificate.RawData,
                privateKey,
                certificateGroup.Id.Identifier as string);

            if (m_autoApprove)
            {
                m_database.ApproveCertificateRequest(requestId, false);
            }

            return(ServiceResult.Good);
        }