Exemple #1
0
        // TODO: find a proper place for this
        public static async Task <Application <TPrimitiveContent> > RegisterAsync(Connection.IConnectionConfiguration m2mConfig, IApplicationConfiguration appConfig, string inCse, Uri?caUri = null)
        {
            var con = new HttpConnection <TPrimitiveContent>(m2mConfig);

            var ae = await con.FindApplicationAsync(inCse, appConfig.AppId) ?? await con.RegisterApplicationAsync(appConfig);

            if (ae == null)
            {
                throw new InvalidOperationException("Unable to register application");
            }

            if (con.ClientCertificate == null && caUri != null)
            {
                var csrUri = new Uri(caUri, "CertificateSigning");
                var ccrUri = new Uri(caUri, "CertificateConfirm");

                var tokenId = ae.Labels?.FirstOrDefault(l => l.StartsWith("token="))?.Substring("token=".Length);
                if (string.IsNullOrWhiteSpace(tokenId))
                {
                    throw new InvalidDataException("registered AE is missing 'token' label");
                }

                using var privateKey = RSA.Create(4096);
                var certificateRequest = new CertificateRequest(
                    $"CN={appConfig.AppId}",
                    privateKey,
                    HashAlgorithmName.SHA256,
                    RSASignaturePadding.Pkcs1);

                var sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName(appConfig.AppId);
                sanBuilder.AddDnsName(ae.AE_ID);
                certificateRequest.CertificateExtensions.Add(sanBuilder.Build());

                //Debug.WriteLine(certificateRequest.ToPemString());
                var signingRequest = new CertificateSigningRequestBody
                {
                    Request = new CertificateSigningRequest
                    {
                        Application = new Aetheros.OneM2M.Api.Registration.Application
                        {
                            AeId    = ae.AE_ID,
                            TokenId = tokenId
                        },
                        X509Request = certificateRequest.ToPemString(),
                    }
                };

                using var handler = new HttpClientHandler
                      {
                          ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
                      };
                using var client = new HttpClient(handler);

                CertificateSigningResponseBody signingResponse;
                using (var httpSigningResponse = await client.PostJsonAsync(csrUri, signingRequest))
                    signingResponse = await httpSigningResponse.DeserializeAsync <CertificateSigningResponseBody>();
                if (signingResponse.Response == null)
                {
                    throw new InvalidDataException("CertificateSigningResponse does not contain a response");
                }
                if (signingResponse.Response.X509Certificate == null)
                {
                    throw new InvalidDataException("CertificateSigningResponse does not contain a certificate");
                }

                var signedCert = AosUtils.CreateX509Certificate(signingResponse.Response.X509Certificate);

                var confirmationRequest = new ConfirmationRequestBody
                {
                    Request = new ConfirmationRequest
                    {
                        CertificateHash = Convert.ToBase64String(signedCert.GetCertHash(HashAlgorithmName.SHA256)),
                        CertificateId   = new CertificateId
                        {
                            Issuer       = signedCert.Issuer,
                            SerialNumber = int.Parse(signedCert.SerialNumber, System.Globalization.NumberStyles.HexNumber).ToString()
                        },
                        TransactionId = signingResponse.Response.TransactionId,
                    }
                };

                using (var httpConfirmationResponse = await client.PostJsonAsync(ccrUri, confirmationRequest))
                {
                    var confirmationResponse = await httpConfirmationResponse.DeserializeAsync <ConfirmationResponseBody>();

                    if (confirmationResponse.Response == null)
                    {
                        throw new InvalidDataException("Invalid ConfirmationResponse");
                    }
                    Debug.Assert(confirmationResponse.Response.Status == CertificateSigningStatus.Accepted);
                }

                using (var pubPrivEphemeral = signedCert.CopyWithPrivateKey(privateKey))
                    await File.WriteAllBytesAsync(m2mConfig.CertificateFilename, pubPrivEphemeral.Export(X509ContentType.Cert));

                con = new HttpConnection <TPrimitiveContent>(m2mConfig.M2MUrl, signedCert);
            }

            return(new Application <TPrimitiveContent>(con, appConfig.AppId, ae.AE_ID, appConfig.UrlPrefix, appConfig.PoaUrl));
        }