@ -21,6 +21,7 @@ limitations under the License.
package messages
import (
"crypto"
"crypto/x509"
"encoding/pem"
"fmt"
@ -32,6 +33,8 @@ import (
// required for msgpackgen
_ "github.com/dave/jennifer"
"github.com/google/uuid"
"git.cacert.org/cacert-gosigner/internal/x509/signing"
)
type CommandCode int8
@ -126,12 +129,23 @@ func BuildResponseAnnounce(code ResponseCode, commandID string) *ResponseAnnounc
return & ResponseAnnounce { Code : code , ID : commandID , Created : time . Now ( ) . UTC ( ) }
}
type HealthCommand struct { }
type CAProfile struct {
Name string ` msgpack:"name" `
Description string ` msgpack:"description" `
UseFor signing . ProfileUsage ` msgpack:"use-for" `
}
func ( h * HealthCommand ) String ( ) string {
return ""
func ( p CAProfile ) String ( ) string {
return fmt . Sprintf ( " profile['%s': '%s'] ", p . Name , p . UseFor )
}
type CertificateStatus string
const (
CertStatusOk CertificateStatus = "ok"
CertStatusFailed CertificateStatus = "failed"
)
type CAInfoCommand struct {
Name string ` msgpack:"name" `
}
@ -140,6 +154,25 @@ func (r *CAInfoCommand) String() string {
return fmt . Sprintf ( "name=%s" , r . Name )
}
type CAInfoResponse struct {
Name string ` msgpack:"name" `
Certificate [ ] byte ` msgpack:"certificate" `
Signing bool ` msgpack:"signing" `
Profiles [ ] CAProfile ` msgpack:"profiles" `
}
func ( i CAInfoResponse ) String ( ) string {
return fmt . Sprintf ( "certificate name=%s, signing=%t, profiles=[%s]" , i . Name , i . Signing , i . Profiles )
}
type ErrorResponse struct {
Message string ` msgpack:"message" `
}
func ( e * ErrorResponse ) String ( ) string {
return fmt . Sprintf ( "message=%s" , e . Message )
}
type FetchCRLCommand struct {
IssuerID string ` msgpack:"issuer_id" `
LastKnownID [ ] byte ` msgpack:"last_known_id" `
@ -157,121 +190,64 @@ func (f *FetchCRLCommand) String() string {
return builder . String ( )
}
type ProfileUsage uint8
const (
UsageInvalid ProfileUsage = iota
UsageOCSP
UsageClient
UsageCode
UsagePerson
UsageServer
UsageServerClient
UsageOrgClient
UsageOrgCode
UsageOrgEmail
UsageOrgPerson
UsageOrgServer
UsageOrgServerClient
)
var validProfileUsages = map [ string ] ProfileUsage {
"ocsp" : UsageOCSP ,
"client" : UsageClient ,
"code" : UsageCode ,
"person" : UsagePerson ,
"server" : UsageServer ,
"server_client" : UsageServerClient ,
"org_client" : UsageOrgClient ,
"org_code" : UsageOrgCode ,
"org_email" : UsageOrgEmail ,
"org_person" : UsageOrgPerson ,
"org_server" : UsageOrgServer ,
"org_server_client" : UsageOrgServerClient ,
type FetchCRLResponse struct {
IssuerID string ` msgpack:"issuer_id" `
IsDelta bool ` msgpack:"is_delta" `
UnChanged bool ` msgpack:"unchanged" `
CRLData [ ] byte ` msgpack:"crl_data" `
CRLNumber [ ] byte ` msgpack:"crl_number" `
}
var profileUsageDetails = map [ ProfileUsage ] struct {
Name string
Description string
} {
UsageInvalid : { "invalid" , "Invalid certificate profile, not to be used" } ,
UsageOCSP : { "ocsp" , "OCSP responder signing certificate" } ,
UsageClient : { "client" , "machine TLS client certificate" } ,
UsageCode : { "code" , "individual code signing certificate" } ,
UsagePerson : { "person" , "person identity certificate" } ,
UsageServer : { "server" , "TLS server certificate" } ,
UsageServerClient : { "server_client" , "combined TLS server and client certificate" } ,
UsageOrgClient : { "org_client" , "organization machine TLS client certificate" } ,
UsageOrgCode : { "org_code" , "organization code signing certificate" } ,
UsageOrgEmail : { "org_email" , "organization email certificate" } ,
UsageOrgPerson : { "org_person" , "organizational person identity certificate" } ,
UsageOrgServer : { "org_server" , "organization TLS server certificate" } ,
UsageOrgServerClient : {
"org_server_client" ,
"combined organization TLS server and client certificate" ,
} ,
}
func ( r * FetchCRLResponse ) String ( ) string {
builder := & strings . Builder { }
func ( p ProfileUsage ) String ( ) string {
name , ok := profileUsageDetails [ p ]
if ! ok {
return fmt . Sprintf ( "unknown profile usage %d" , p )
_ , _ = fmt . Fprintf (
builder ,
"issuer id=%s, delta=%t, unchanged=%t, CRL number=0x%x" ,
r . IssuerID ,
r . IsDelta ,
r . UnChanged ,
new ( big . Int ) . SetBytes ( r . CRLNumber ) ,
)
if r . UnChanged {
return builder . String ( )
}
return name . Name
}
if r . IsDelta {
_ , _ = fmt . Fprintf ( builder , ", delta CRL data of %d bytes not shown" , len ( r . CRLData ) )
func ( p ProfileUsage ) Description ( ) string {
name , ok := profileUsageDetails [ p ]
if ! ok {
return fmt . Sprintf ( "unknown profile usage %d" , p )
return builder . String ( )
}
return name . Description
}
revocationList , err := x509 . ParseRevocationList ( r . CRLData )
if err != nil {
_ , _ = fmt . Fprintf ( builder , ", could not parse CRL: %s" , err . Error ( ) )
func ParseUsage ( u string ) ( ProfileUsage , error ) {
usage , ok := validProfileUsages [ u ]
if ! ok {
return UsageInvalid , fmt . Errorf ( "unsupported profile usage: %s" , u )
return builder . String ( )
}
return usage , nil
}
type CAProfile struct {
Name string ` msgpack:"name" `
UseFor ProfileUsage ` msgpack:"use-for" `
}
_ , _ = fmt . Fprintf (
builder ,
", CRL info: issuer=%s, number=0x%x, next update=%s, revoked certificates=%d" ,
revocationList . Issuer ,
revocationList . Number ,
revocationList . NextUpdate ,
len ( revocationList . RevokedCertificates ) ,
)
_ , _ = builder . WriteString ( ", CRL data:\n" )
_ = pem . Encode ( builder , & pem . Block {
Type : "CERTIFICATE REVOCATION LIST" ,
Bytes : r . CRLData ,
} )
func ( p CAProfile ) String ( ) string {
return fmt . Sprintf ( "profile['%s': '%s']" , p . Name , p . UseFor )
return builder . String ( )
}
type CertificateStatus string
const (
CertStatusOk CertificateStatus = "ok"
CertStatusFailed CertificateStatus = "failed"
)
type CAInfoResponse struct {
Name string ` msgpack:"name" `
Certificate [ ] byte ` msgpack:"certificate" `
Signing bool ` msgpack:"signing" `
Profiles [ ] CAProfile ` msgpack:"profiles,omitempty" `
}
type HealthCommand struct { }
func ( i CAInfoResponse ) String ( ) string {
return fmt . Sprintf ( " certificate name=%s, signing=%t, profiles=[%s] ", i . Name , i . Signing , i . Profiles )
func ( h * HealthCommand ) String ( ) string {
return ""
}
type HealthInfo struct {
@ -331,64 +307,56 @@ func (h *HealthResponse) String() string {
return builder . String ( )
}
type FetchCRLResponse struct {
IssuerID string ` msgpack:"issuer_id" `
IsDelta bool ` msgpack:"is_delta" `
UnChanged bool ` msgpack:"unchanged" `
CRLData [ ] byte ` msgpack:"crl_data" `
CRLNumber [ ] byte ` msgpack:"crl_number" `
type SignCertificateCommand struct {
IssuerID string ` msgpack:"issuer_id" `
ProfileName string ` msgpack:"profile_name" `
CSRData [ ] byte ` msgpack:"csr_data" `
CommonName string ` msgpack:"cn" `
Organization string ` msgpack:"o" `
OrganizationalUnit string ` msgpack:"ou" `
Hostnames [ ] string ` msgpack:"hostnames" `
EmailAddresses [ ] string ` msgpack:"email_addresses" `
PreferredHash crypto . Hash ` msgpack:"preferred_hash" `
}
func ( r * FetchCRLResponse ) String ( ) string {
func ( s * SignCertificateCommand ) String ( ) string {
builder := & strings . Builder { }
_ , _ = fmt . Fprintf (
builder ,
"issuer id=%s, delta=%t, unchanged=%t, CRL number=0x%x" ,
r . IssuerID ,
r . IsDelta ,
r . UnChanged ,
new ( big . Int ) . SetBytes ( r . CRLNumber ) ,
builder , "issuer_id=%s, profile_name=%s, cn=%s" , s . IssuerID , s . ProfileName , s . CommonName ,
)
if r. UnChanged {
return builder . String ( )
if s . Organization != "" {
_ , _ = fmt . Fprintf ( builder , ", o=%s" , s . Organization )
}
if r . IsDelta {
_ , _ = fmt . Fprintf ( builder , ", delta CRL data of %d bytes not shown" , len ( r . CRLData ) )
return builder . String ( )
if s . OrganizationalUnit != "" {
_ , _ = fmt . Fprintf ( builder , ", ou=%s" , s . OrganizationalUnit )
}
revocationList , err := x509 . ParseRevocationList ( r . CRLData )
if err != nil {
_ , _ = fmt . Fprintf ( builder , ", could not parse CRL: %s" , err . Error ( ) )
if len ( s . Hostnames ) > 0 {
builder . WriteString ( ", hostnames=[" )
return builder . String ( )
builder . WriteString ( strings . Join ( s . Hostnames , ", " ) )
builder . WriteRune ( ']' )
}
_ , _ = fmt . Fprintf (
builder ,
", CRL info: issuer=%s, number=0x%x, next update=%s, revoked certificates=%d" ,
revocationList . Issuer ,
revocationList . Number ,
revocationList . NextUpdate ,
len ( revocationList . RevokedCertificates ) ,
)
_ , _ = builder . WriteString ( ", CRL data:\n" )
_ = pem . Encode ( builder , & pem . Block {
Type : "CERTIFICATE REVOCATION LIST" ,
Bytes : r . CRLData ,
} )
if len ( s . EmailAddresses ) > 0 {
builder . WriteString ( ", email_addresses=[" )
builder . WriteString ( strings . Join ( s . Hostnames , ", " ) )
builder . WriteRune ( ']' )
}
return builder . String ( )
}
type Error Response struct {
Message string ` msgpack:"message "`
type SignCertificateResponse struct {
CertificateData [ ] byte ` msgpack:"cert_data" `
}
func ( e * Error Response) String ( ) string {
return fmt . Sprintf ( " message=%s", e . Message )
func ( r * SignCertificate Response) String ( ) string {
return fmt . Sprintf ( " cert_data of %d bytes", len ( r . CertificateData ) )
}