Files
onvif-go/device_certificates.go
T
ProtoTess b4e4982876 Refactor XML response handling in device extended and security tests
- Adjusted formatting in XML response strings for consistency in device_extended_test.go and device_security_test.go.
- Improved readability by aligning XML declaration and body content.
- Updated mock server responses to ensure proper handling of various ONVIF operations.

Enhance device security and storage handling

- Refactored struct field declarations in device_security.go and device_storage_test.go for improved clarity.
- Ensured consistent formatting across struct definitions and XML tags.

Standardize whitespace and formatting across multiple files

- Removed unnecessary blank lines and adjusted indentation in discovery, imaging, media, and PTZ server files.
- Improved overall code readability and maintainability by ensuring consistent formatting.

Update example applications for better readability

- Cleaned up whitespace in example applications to enhance code clarity.
- Ensured consistent formatting in main.go files across various examples.

Refactor server and SOAP handler code for consistency

- Standardized struct field declarations and XML tag formatting in server and SOAP handler files.
- Improved readability by aligning struct fields and ensuring consistent use of whitespace.

General code cleanup and formatting adjustments

- Applied consistent formatting across various files, including types.go and test files.
- Enhanced readability by aligning struct fields and removing unnecessary blank lines.
2025-12-01 00:49:36 +00:00

429 lines
14 KiB
Go

package onvif
import (
"context"
"encoding/xml"
"fmt"
"github.com/0x524a/onvif-go/internal/soap"
)
// GetCertificates retrieves all certificates stored on the device.
//
// ONVIF Specification: GetCertificates operation
func (c *Client) GetCertificates(ctx context.Context) ([]*Certificate, error) {
type GetCertificatesBody struct {
XMLName xml.Name `xml:"tds:GetCertificates"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetCertificatesResponse struct {
XMLName xml.Name `xml:"GetCertificatesResponse"`
Certificates []*Certificate `xml:"Certificate"`
}
request := GetCertificatesBody{
Xmlns: deviceNamespace,
}
var response GetCertificatesResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return nil, fmt.Errorf("GetCertificates failed: %w", err)
}
return response.Certificates, nil
}
// GetCACertificates retrieves all CA certificates stored on the device.
//
// ONVIF Specification: GetCACertificates operation
func (c *Client) GetCACertificates(ctx context.Context) ([]*Certificate, error) {
type GetCACertificatesBody struct {
XMLName xml.Name `xml:"tds:GetCACertificates"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetCACertificatesResponse struct {
XMLName xml.Name `xml:"GetCACertificatesResponse"`
Certificates []*Certificate `xml:"Certificate"`
}
request := GetCACertificatesBody{
Xmlns: deviceNamespace,
}
var response GetCACertificatesResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return nil, fmt.Errorf("GetCACertificates failed: %w", err)
}
return response.Certificates, nil
}
// LoadCertificates uploads certificates to the device.
//
// ONVIF Specification: LoadCertificates operation
func (c *Client) LoadCertificates(ctx context.Context, certificates []*Certificate) error {
type LoadCertificatesBody struct {
XMLName xml.Name `xml:"tds:LoadCertificates"`
Xmlns string `xml:"xmlns:tds,attr"`
Certificate []*Certificate `xml:"tds:Certificate"`
}
type LoadCertificatesResponse struct {
XMLName xml.Name `xml:"LoadCertificatesResponse"`
}
request := LoadCertificatesBody{
Xmlns: deviceNamespace,
Certificate: certificates,
}
var response LoadCertificatesResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return fmt.Errorf("LoadCertificates failed: %w", err)
}
return nil
}
// LoadCACertificates uploads CA certificates to the device.
//
// ONVIF Specification: LoadCACertificates operation
func (c *Client) LoadCACertificates(ctx context.Context, certificates []*Certificate) error {
type LoadCACertificatesBody struct {
XMLName xml.Name `xml:"tds:LoadCACertificates"`
Xmlns string `xml:"xmlns:tds,attr"`
Certificate []*Certificate `xml:"tds:Certificate"`
}
type LoadCACertificatesResponse struct {
XMLName xml.Name `xml:"LoadCACertificatesResponse"`
}
request := LoadCACertificatesBody{
Xmlns: deviceNamespace,
Certificate: certificates,
}
var response LoadCACertificatesResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return fmt.Errorf("LoadCACertificates failed: %w", err)
}
return nil
}
// CreateCertificate creates a self-signed certificate.
//
// ONVIF Specification: CreateCertificate operation
func (c *Client) CreateCertificate(ctx context.Context, certificateID, subject string, validNotBefore, validNotAfter string) (*Certificate, error) {
type CreateCertificateBody struct {
XMLName xml.Name `xml:"tds:CreateCertificate"`
Xmlns string `xml:"xmlns:tds,attr"`
CertificateID string `xml:"tds:CertificateID,omitempty"`
Subject string `xml:"tds:Subject"`
ValidNotBefore string `xml:"tds:ValidNotBefore"`
ValidNotAfter string `xml:"tds:ValidNotAfter"`
}
type CreateCertificateResponse struct {
XMLName xml.Name `xml:"CreateCertificateResponse"`
Certificate *Certificate `xml:"Certificate"`
}
request := CreateCertificateBody{
Xmlns: deviceNamespace,
CertificateID: certificateID,
Subject: subject,
ValidNotBefore: validNotBefore,
ValidNotAfter: validNotAfter,
}
var response CreateCertificateResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return nil, fmt.Errorf("CreateCertificate failed: %w", err)
}
return response.Certificate, nil
}
// DeleteCertificates deletes certificates from the device.
//
// ONVIF Specification: DeleteCertificates operation
func (c *Client) DeleteCertificates(ctx context.Context, certificateIDs []string) error {
type DeleteCertificatesBody struct {
XMLName xml.Name `xml:"tds:DeleteCertificates"`
Xmlns string `xml:"xmlns:tds,attr"`
CertificateID []string `xml:"tds:CertificateID"`
}
type DeleteCertificatesResponse struct {
XMLName xml.Name `xml:"DeleteCertificatesResponse"`
}
request := DeleteCertificatesBody{
Xmlns: deviceNamespace,
CertificateID: certificateIDs,
}
var response DeleteCertificatesResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return fmt.Errorf("DeleteCertificates failed: %w", err)
}
return nil
}
// GetCertificateInformation retrieves information about a certificate.
//
// ONVIF Specification: GetCertificateInformation operation
func (c *Client) GetCertificateInformation(ctx context.Context, certificateID string) (*CertificateInformation, error) {
type GetCertificateInformationBody struct {
XMLName xml.Name `xml:"tds:GetCertificateInformation"`
Xmlns string `xml:"xmlns:tds,attr"`
CertificateID string `xml:"tds:CertificateID"`
}
type GetCertificateInformationResponse struct {
XMLName xml.Name `xml:"GetCertificateInformationResponse"`
CertificateInformation *CertificateInformation `xml:"CertificateInformation"`
}
request := GetCertificateInformationBody{
Xmlns: deviceNamespace,
CertificateID: certificateID,
}
var response GetCertificateInformationResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return nil, fmt.Errorf("GetCertificateInformation failed: %w", err)
}
return response.CertificateInformation, nil
}
// GetCertificatesStatus retrieves the status of certificates.
//
// ONVIF Specification: GetCertificatesStatus operation
func (c *Client) GetCertificatesStatus(ctx context.Context) ([]*CertificateStatus, error) {
type GetCertificatesStatusBody struct {
XMLName xml.Name `xml:"tds:GetCertificatesStatus"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetCertificatesStatusResponse struct {
XMLName xml.Name `xml:"GetCertificatesStatusResponse"`
CertificateStatus []*CertificateStatus `xml:"CertificateStatus"`
}
request := GetCertificatesStatusBody{
Xmlns: deviceNamespace,
}
var response GetCertificatesStatusResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return nil, fmt.Errorf("GetCertificatesStatus failed: %w", err)
}
return response.CertificateStatus, nil
}
// SetCertificatesStatus sets the status of certificates (enabled/disabled).
//
// ONVIF Specification: SetCertificatesStatus operation
func (c *Client) SetCertificatesStatus(ctx context.Context, statuses []*CertificateStatus) error {
type SetCertificatesStatusBody struct {
XMLName xml.Name `xml:"tds:SetCertificatesStatus"`
Xmlns string `xml:"xmlns:tds,attr"`
CertificateStatus []*CertificateStatus `xml:"tds:CertificateStatus"`
}
type SetCertificatesStatusResponse struct {
XMLName xml.Name `xml:"SetCertificatesStatusResponse"`
}
request := SetCertificatesStatusBody{
Xmlns: deviceNamespace,
CertificateStatus: statuses,
}
var response SetCertificatesStatusResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return fmt.Errorf("SetCertificatesStatus failed: %w", err)
}
return nil
}
// GetPkcs10Request generates a PKCS#10 certificate signing request.
//
// ONVIF Specification: GetPkcs10Request operation
func (c *Client) GetPkcs10Request(ctx context.Context, certificateID, subject string, attributes *BinaryData) (*BinaryData, error) {
type GetPkcs10RequestBody struct {
XMLName xml.Name `xml:"tds:GetPkcs10Request"`
Xmlns string `xml:"xmlns:tds,attr"`
CertificateID string `xml:"tds:CertificateID,omitempty"`
Subject string `xml:"tds:Subject"`
Attributes *BinaryData `xml:"tds:Attributes,omitempty"`
}
type GetPkcs10RequestResponse struct {
XMLName xml.Name `xml:"GetPkcs10RequestResponse"`
Pkcs10Request *BinaryData `xml:"Pkcs10Request"`
}
request := GetPkcs10RequestBody{
Xmlns: deviceNamespace,
CertificateID: certificateID,
Subject: subject,
Attributes: attributes,
}
var response GetPkcs10RequestResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return nil, fmt.Errorf("GetPkcs10Request failed: %w", err)
}
return response.Pkcs10Request, nil
}
// LoadCertificateWithPrivateKey uploads a certificate with its private key.
//
// ONVIF Specification: LoadCertificateWithPrivateKey operation
func (c *Client) LoadCertificateWithPrivateKey(ctx context.Context, certificates []*Certificate, privateKey []*BinaryData, certificateIDs []string) error {
type LoadCertificateWithPrivateKeyBody struct {
XMLName xml.Name `xml:"tds:LoadCertificateWithPrivateKey"`
Xmlns string `xml:"xmlns:tds,attr"`
CertificateWithPrivateKey []struct {
CertificateID string `xml:"CertificateID"`
Certificate *Certificate `xml:"Certificate"`
PrivateKey *BinaryData `xml:"PrivateKey"`
} `xml:"tds:CertificateWithPrivateKey"`
}
type LoadCertificateWithPrivateKeyResponse struct {
XMLName xml.Name `xml:"LoadCertificateWithPrivateKeyResponse"`
}
request := LoadCertificateWithPrivateKeyBody{
Xmlns: deviceNamespace,
}
// Build certificate with private key array
for i := 0; i < len(certificates); i++ {
item := struct {
CertificateID string `xml:"CertificateID"`
Certificate *Certificate `xml:"Certificate"`
PrivateKey *BinaryData `xml:"PrivateKey"`
}{
CertificateID: certificateIDs[i],
Certificate: certificates[i],
}
if i < len(privateKey) {
item.PrivateKey = privateKey[i]
}
request.CertificateWithPrivateKey = append(request.CertificateWithPrivateKey, item)
}
var response LoadCertificateWithPrivateKeyResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return fmt.Errorf("LoadCertificateWithPrivateKey failed: %w", err)
}
return nil
}
// GetClientCertificateMode retrieves the client certificate authentication mode.
//
// ONVIF Specification: GetClientCertificateMode operation
func (c *Client) GetClientCertificateMode(ctx context.Context) (bool, error) {
type GetClientCertificateModeBody struct {
XMLName xml.Name `xml:"tds:GetClientCertificateMode"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetClientCertificateModeResponse struct {
XMLName xml.Name `xml:"GetClientCertificateModeResponse"`
Enabled bool `xml:"Enabled"`
}
request := GetClientCertificateModeBody{
Xmlns: deviceNamespace,
}
var response GetClientCertificateModeResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return false, fmt.Errorf("GetClientCertificateMode failed: %w", err)
}
return response.Enabled, nil
}
// SetClientCertificateMode sets the client certificate authentication mode.
//
// ONVIF Specification: SetClientCertificateMode operation
func (c *Client) SetClientCertificateMode(ctx context.Context, enabled bool) error {
type SetClientCertificateModeBody struct {
XMLName xml.Name `xml:"tds:SetClientCertificateMode"`
Xmlns string `xml:"xmlns:tds,attr"`
Enabled bool `xml:"tds:Enabled"`
}
type SetClientCertificateModeResponse struct {
XMLName xml.Name `xml:"SetClientCertificateModeResponse"`
}
request := SetClientCertificateModeBody{
Xmlns: deviceNamespace,
Enabled: enabled,
}
var response SetClientCertificateModeResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", request, &response); err != nil {
return fmt.Errorf("SetClientCertificateMode failed: %w", err)
}
return nil
}