mirror of
https://github.com/nabbar/golib.git
synced 2025-09-27 04:06:05 +08:00
Package certificates:
- rework package to allow convert config to model and retrive config from model - add sub package to manage cipher, curves, auth client, tls version, certificates, root ca... - add some small test (can be expande to having more coverage) - optimize some code Package httpcli: - update code following change in certificates Package httpserver: - update code following change in certificates Package Config/Components: - update code following change in certificates Package FTPClient: - update code following change in certificates Package Nats: - update code following change in certificates
This commit is contained in:
89
certificates/auth/encode.go
Normal file
89
certificates/auth/encode.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *ClientAuth) unmarshall(val []byte) error {
|
||||||
|
*a = parseBytes(val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ClientAuth) MarshalJSON() ([]byte, error) {
|
||||||
|
t := a.String()
|
||||||
|
b := make([]byte, 0, len(t)+2)
|
||||||
|
b = append(b, '"')
|
||||||
|
b = append(b, []byte(t)...)
|
||||||
|
b = append(b, '"')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ClientAuth) UnmarshalJSON(bytes []byte) error {
|
||||||
|
return a.unmarshall(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ClientAuth) MarshalYAML() (interface{}, error) {
|
||||||
|
return []byte(a.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ClientAuth) UnmarshalYAML(value *yaml.Node) error {
|
||||||
|
return a.unmarshall([]byte(value.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ClientAuth) MarshalTOML() ([]byte, error) {
|
||||||
|
return []byte(a.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ClientAuth) UnmarshalTOML(i interface{}) error {
|
||||||
|
if p, k := i.([]byte); k {
|
||||||
|
return a.unmarshall(p)
|
||||||
|
}
|
||||||
|
if p, k := i.(string); k {
|
||||||
|
return a.unmarshall([]byte(p))
|
||||||
|
}
|
||||||
|
return fmt.Errorf("tls client Auth: value not in valid format")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ClientAuth) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(a.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ClientAuth) UnmarshalText(bytes []byte) error {
|
||||||
|
return a.unmarshall(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ClientAuth) MarshalCBOR() ([]byte, error) {
|
||||||
|
return []byte(a.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ClientAuth) UnmarshalCBOR(bytes []byte) error {
|
||||||
|
return a.unmarshall(bytes)
|
||||||
|
}
|
55
certificates/auth/format.go
Normal file
55
certificates/auth/format.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a ClientAuth) String() string {
|
||||||
|
switch a {
|
||||||
|
case RequireAndVerifyClientCert:
|
||||||
|
return strict + " " + require + " " + verify
|
||||||
|
case VerifyClientCertIfGiven:
|
||||||
|
return verify
|
||||||
|
case RequireAnyClientCert:
|
||||||
|
return require
|
||||||
|
case RequestClientCert:
|
||||||
|
return request
|
||||||
|
default:
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ClientAuth) Code() string {
|
||||||
|
return strings.ToLower(a.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ClientAuth) TLS() tls.ClientAuthType {
|
||||||
|
return tls.ClientAuthType(a)
|
||||||
|
}
|
99
certificates/auth/interface.go
Normal file
99
certificates/auth/interface.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
strict = "strict"
|
||||||
|
require = "require"
|
||||||
|
verify = "verify"
|
||||||
|
request = "request"
|
||||||
|
none = "none"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientAuth tls.ClientAuthType
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoClientCert = ClientAuth(tls.NoClientCert)
|
||||||
|
RequestClientCert = ClientAuth(tls.RequestClientCert)
|
||||||
|
RequireAnyClientCert = ClientAuth(tls.RequireAnyClientCert)
|
||||||
|
VerifyClientCertIfGiven = ClientAuth(tls.VerifyClientCertIfGiven)
|
||||||
|
RequireAndVerifyClientCert = ClientAuth(tls.RequireAndVerifyClientCert)
|
||||||
|
)
|
||||||
|
|
||||||
|
func List() []ClientAuth {
|
||||||
|
return []ClientAuth{
|
||||||
|
NoClientCert,
|
||||||
|
RequestClientCert,
|
||||||
|
RequireAnyClientCert,
|
||||||
|
VerifyClientCertIfGiven,
|
||||||
|
RequireAndVerifyClientCert,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(s string) ClientAuth {
|
||||||
|
s = strings.ToLower(s)
|
||||||
|
s = strings.Replace(s, "\"", "", -1)
|
||||||
|
s = strings.Replace(s, "'", "", -1)
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case strings.Contains(s, strict) || (strings.Contains(s, require) && strings.Contains(s, verify)):
|
||||||
|
return RequireAndVerifyClientCert
|
||||||
|
case strings.Contains(s, verify):
|
||||||
|
return VerifyClientCertIfGiven
|
||||||
|
case strings.Contains(s, require) && !strings.Contains(s, verify):
|
||||||
|
return RequireAnyClientCert
|
||||||
|
case strings.Contains(s, request):
|
||||||
|
return RequestClientCert
|
||||||
|
default:
|
||||||
|
return NoClientCert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseInt(d int) ClientAuth {
|
||||||
|
switch tls.ClientAuthType(d) {
|
||||||
|
case tls.RequireAndVerifyClientCert:
|
||||||
|
return RequireAndVerifyClientCert
|
||||||
|
case tls.VerifyClientCertIfGiven:
|
||||||
|
return VerifyClientCertIfGiven
|
||||||
|
case tls.RequireAnyClientCert:
|
||||||
|
return RequireAnyClientCert
|
||||||
|
case tls.RequestClientCert:
|
||||||
|
return RequestClientCert
|
||||||
|
default:
|
||||||
|
return NoClientCert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBytes(p []byte) ClientAuth {
|
||||||
|
return Parse(string(p))
|
||||||
|
}
|
62
certificates/auth/models.go
Normal file
62
certificates/auth/models.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
libmap "github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ViperDecoderHook() libmap.DecodeHookFuncType {
|
||||||
|
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
|
||||||
|
var (
|
||||||
|
z = ClientAuth(0)
|
||||||
|
t string
|
||||||
|
k bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the data type matches the expected one
|
||||||
|
if from.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
} else if t, k = data.(string); !k {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the target type matches the expected one
|
||||||
|
if to != reflect.TypeOf(z) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format/decode/parse the data and return the new value
|
||||||
|
if e := z.unmarshall([]byte(t)); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return z, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
certificates/authClient.go
Normal file
86
certificates/authClient.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
|
||||||
|
tlsaut "github.com/nabbar/golib/certificates/auth"
|
||||||
|
tlscas "github.com/nabbar/golib/certificates/ca"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o *config) SetClientAuth(a tlsaut.ClientAuth) {
|
||||||
|
o.clientAuth = a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) GetClientCA() []tlscas.Cert {
|
||||||
|
var res = make([]tlscas.Cert, 0)
|
||||||
|
|
||||||
|
for _, c := range o.clientCA {
|
||||||
|
res = append(res, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) GetClientCAPool() *x509.CertPool {
|
||||||
|
var res = x509.NewCertPool()
|
||||||
|
|
||||||
|
for _, ca := range o.clientCA {
|
||||||
|
ca.AppendPool(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddClientCAString(ca string) bool {
|
||||||
|
if ca != "" {
|
||||||
|
if c, e := tlscas.Parse(ca); e == nil {
|
||||||
|
o.clientCA = append(o.clientCA, c)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddClientCAFile(pemFile string) error {
|
||||||
|
var fct = func(p []byte) error {
|
||||||
|
if c, e := tlscas.ParseByte(p); e != nil {
|
||||||
|
return e
|
||||||
|
} else {
|
||||||
|
o.clientCA = append(o.clientCA, c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if e := checkFile(fct, pemFile); e != nil {
|
||||||
|
return e
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
165
certificates/ca/encode.go
Normal file
165
certificates/ca/encode.go
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ca
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/pem"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/fxamacker/cbor/v2"
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isFile(path string) bool {
|
||||||
|
f, e := os.Stat(path)
|
||||||
|
if e != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !f.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) unMarshall(p []byte) error {
|
||||||
|
if len(p) < 1 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
p = bytes.TrimSpace(p)
|
||||||
|
|
||||||
|
// remove \n\r
|
||||||
|
p = bytes.Trim(p, "\n")
|
||||||
|
p = bytes.Trim(p, "\r")
|
||||||
|
|
||||||
|
// do again if \r\n
|
||||||
|
p = bytes.Trim(p, "\n")
|
||||||
|
p = bytes.Trim(p, "\r")
|
||||||
|
|
||||||
|
p = bytes.TrimSpace(p)
|
||||||
|
v := make([]*x509.Certificate, 0)
|
||||||
|
|
||||||
|
for {
|
||||||
|
block, rest := pem.Decode(p)
|
||||||
|
if block == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if block.Type == "CERTIFICATE" {
|
||||||
|
if c, e := x509.ParseCertificate(block.Bytes); e == nil {
|
||||||
|
v = append(v, c)
|
||||||
|
}
|
||||||
|
} else if fs := string(block.Bytes); isFile(fs) {
|
||||||
|
if b, e := os.ReadFile(fs); e == nil {
|
||||||
|
if crt, err := x509.ParseCertificate(b); err == nil {
|
||||||
|
v = append(v, crt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p = rest
|
||||||
|
}
|
||||||
|
|
||||||
|
o.c = v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) MarshalText() (text []byte, err error) {
|
||||||
|
if s, e := o.Chain(); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return []byte(s), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) UnmarshalText(text []byte) error {
|
||||||
|
return o.unMarshall(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) MarshalBinary() (data []byte, err error) {
|
||||||
|
return o.MarshalCBOR()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) UnmarshalBinary(data []byte) error {
|
||||||
|
return o.UnmarshalCBOR(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) MarshalJSON() ([]byte, error) {
|
||||||
|
if s, e := o.Chain(); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return json.Marshal(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) UnmarshalJSON(bytes []byte) error {
|
||||||
|
return o.unMarshall(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) MarshalYAML() (interface{}, error) {
|
||||||
|
if s, e := o.Chain(); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return yaml.Marshal(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) UnmarshalYAML(value *yaml.Node) error {
|
||||||
|
return o.unMarshall([]byte(value.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) MarshalTOML() ([]byte, error) {
|
||||||
|
if s, e := o.Chain(); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return toml.Marshal(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) UnmarshalTOML(i interface{}) error {
|
||||||
|
if p, k := i.([]byte); k {
|
||||||
|
return o.unMarshall(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, k := i.(string); k {
|
||||||
|
return o.unMarshall([]byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) MarshalCBOR() ([]byte, error) {
|
||||||
|
if s, e := o.Chain(); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return cbor.Marshal(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) UnmarshalCBOR(bytes []byte) error {
|
||||||
|
return o.unMarshall(bytes)
|
||||||
|
}
|
61
certificates/ca/format.go
Normal file
61
certificates/ca/format.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ca
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o *mod) String() string {
|
||||||
|
s, _ := o.Chain()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) Chain() (string, error) {
|
||||||
|
var buf = bytes.NewBuffer(make([]byte, 0))
|
||||||
|
|
||||||
|
for _, c := range o.c {
|
||||||
|
if c == nil {
|
||||||
|
continue
|
||||||
|
} else if e := pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: c.Raw}); e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *mod) AppendPool(p *x509.CertPool) {
|
||||||
|
for _, c := range o.c {
|
||||||
|
if c == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p.AddCert(c)
|
||||||
|
}
|
||||||
|
}
|
78
certificates/ca/interface.go
Normal file
78
certificates/ca/interface.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ca
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fxamacker/cbor/v2"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidPairCertificate = errors.New("invalid pair certificate")
|
||||||
|
ErrInvalidCertificate = errors.New("invalid certificate")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cert interface {
|
||||||
|
encoding.TextMarshaler
|
||||||
|
encoding.TextUnmarshaler
|
||||||
|
encoding.BinaryMarshaler
|
||||||
|
encoding.BinaryUnmarshaler
|
||||||
|
json.Marshaler
|
||||||
|
json.Unmarshaler
|
||||||
|
yaml.Marshaler
|
||||||
|
yaml.Unmarshaler
|
||||||
|
toml.Marshaler
|
||||||
|
toml.Unmarshaler
|
||||||
|
cbor.Marshaler
|
||||||
|
cbor.Unmarshaler
|
||||||
|
fmt.Stringer
|
||||||
|
|
||||||
|
AppendPool(p *x509.CertPool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(str string) (Cert, error) {
|
||||||
|
return ParseByte([]byte(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseByte(p []byte) (Cert, error) {
|
||||||
|
c := &mod{
|
||||||
|
c: make([]*x509.Certificate, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
if e := c.unMarshall(p); e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
69
certificates/ca/models.go
Normal file
69
certificates/ca/models.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ca
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
libmap "github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mod struct {
|
||||||
|
c []*x509.Certificate
|
||||||
|
}
|
||||||
|
|
||||||
|
func ViperDecoderHook() libmap.DecodeHookFuncType {
|
||||||
|
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
|
||||||
|
var (
|
||||||
|
z = &mod{
|
||||||
|
c: make([]*x509.Certificate, 0),
|
||||||
|
}
|
||||||
|
t string
|
||||||
|
k bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the data type matches the expected one
|
||||||
|
if from.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
} else if t, k = data.(string); !k {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the target type matches the expected one
|
||||||
|
if to != reflect.TypeOf(z) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format/decode/parse the data and return the new value
|
||||||
|
if e := z.unMarshall([]byte(t)); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return z, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
certificates/cert.go
Normal file
84
certificates/cert.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
|
||||||
|
tlscrt "github.com/nabbar/golib/certificates/certs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o *config) LenCertificatePair() int {
|
||||||
|
return len(o.cert)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) CleanCertificatePair() {
|
||||||
|
o.cert = make([]tlscrt.Cert, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) GetCertificatePair() []tls.Certificate {
|
||||||
|
var res = make([]tls.Certificate, 0)
|
||||||
|
|
||||||
|
for _, c := range o.cert {
|
||||||
|
res = append(res, c.TLS())
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddCertificatePairString(key, crt string) error {
|
||||||
|
if c, e := tlscrt.ParsePair(key, crt); e != nil {
|
||||||
|
return e
|
||||||
|
} else {
|
||||||
|
o.cert = append(o.cert, c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddCertificatePairFile(keyFile, crtFile string) error {
|
||||||
|
var (
|
||||||
|
key = make([]byte, 0)
|
||||||
|
pub = make([]byte, 0)
|
||||||
|
fct = func(p []byte) error {
|
||||||
|
if len(key) < 1 {
|
||||||
|
copy(key, p)
|
||||||
|
} else {
|
||||||
|
copy(pub, p)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if e := checkFile(fct, keyFile, crtFile); e != nil {
|
||||||
|
return e
|
||||||
|
} else if c, e := tlscrt.ParsePair(string(key), string(pub)); e != nil {
|
||||||
|
return e
|
||||||
|
} else {
|
||||||
|
o.cert = append(o.cert, c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
214
certificates/certificates_config_test.go
Normal file
214
certificates/certificates_config_test.go
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/pem"
|
||||||
|
"math/big"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
|
tlscrt "github.com/nabbar/golib/certificates/certs"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func genCertififcate() ([]byte, []byte) {
|
||||||
|
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(priv).ToNot(BeNil())
|
||||||
|
|
||||||
|
keyUsage := x509.KeyUsageDigitalSignature
|
||||||
|
notBefore := time.Now()
|
||||||
|
notAfter := notBefore.Add(time.Hour * 24 * 365)
|
||||||
|
|
||||||
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
template := x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
Subject: pkix.Name{
|
||||||
|
Organization: []string{"Acme Co"},
|
||||||
|
},
|
||||||
|
NotBefore: notBefore,
|
||||||
|
NotAfter: notAfter,
|
||||||
|
KeyUsage: keyUsage,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
template.DNSNames = append(template.DNSNames, "example.com")
|
||||||
|
template.DNSNames = append(template.DNSNames, "localhost")
|
||||||
|
|
||||||
|
if ip := net.ParseIP("127.0.0.1"); ip != nil {
|
||||||
|
template.IPAddresses = append(template.IPAddresses, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
bufPub := bytes.NewBuffer(make([]byte, 0))
|
||||||
|
err = pem.Encode(bufPub, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
bufKey := bytes.NewBuffer(make([]byte, 0))
|
||||||
|
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = pem.Encode(bufKey, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
return bufPub.Bytes(), bufKey.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeGenCert(pub, key string) {
|
||||||
|
p, k := genCertififcate()
|
||||||
|
|
||||||
|
f, e := os.Create(pub)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
_, e = f.Write(p)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
Expect(f.Close()).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
f, e = os.Create(key)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
_, e = f.Write(k)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
Expect(f.Close()).ToNot(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfigFile() []byte {
|
||||||
|
writeGenCert(pubFile, keyFile)
|
||||||
|
|
||||||
|
str := &tlscrt.ConfigPair{
|
||||||
|
Key: keyFile,
|
||||||
|
Pub: pubFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
p, e := json.Marshal(str)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
var oldConfig string = `{
|
||||||
|
"authClient": "none",
|
||||||
|
"certs": [` + string(p) + `],
|
||||||
|
"cipherList": ["RSA_AES_128_GCM_SHA256", "RSA_AES_256_GCM_SHA384", "ECDHE_RSA_AES_128_GCM_SHA256", "ECDHE_ECDSA_AES_128_GCM_SHA256", "ECDHE_RSA_AES_256_GCM_SHA384", "ECDHE_ECDSA_AES_256_GCM_SHA384", "ECDHE_RSA_CHACHA20_POLY1305_SHA256", "ECDHE_ECDSA_CHACHA20_POLY1305_SHA256", "AES_128_GCM_SHA256", "AES_256_GCM_SHA384", "CHACHA20_POLY1305_SHA256"],
|
||||||
|
"clientCA": [],
|
||||||
|
"curveList": ["X25519", "P256", "P384", "P521"],
|
||||||
|
"dynamicSizingDisable": false,
|
||||||
|
"inheritDefault": false,
|
||||||
|
"rootCA": [],
|
||||||
|
"sessionTicketDisable": false,
|
||||||
|
"versionMax": "1.3",
|
||||||
|
"versionMin": "1.2"
|
||||||
|
}`
|
||||||
|
|
||||||
|
return []byte(oldConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfigChain() []byte {
|
||||||
|
pub, key := genCertififcate()
|
||||||
|
str := "\n" + string(pub) + string(key)
|
||||||
|
buf, err := json.Marshal(str)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
var oldConfig string = `{
|
||||||
|
"authClient": "none",
|
||||||
|
"certs": [` + string(buf) + `],
|
||||||
|
"cipherList": ["RSA_AES_128_GCM_SHA256", "RSA_AES_256_GCM_SHA384", "ECDHE_RSA_AES_128_GCM_SHA256", "ECDHE_ECDSA_AES_128_GCM_SHA256", "ECDHE_RSA_AES_256_GCM_SHA384", "ECDHE_ECDSA_AES_256_GCM_SHA384", "ECDHE_RSA_CHACHA20_POLY1305_SHA256", "ECDHE_ECDSA_CHACHA20_POLY1305_SHA256", "AES_128_GCM_SHA256", "AES_256_GCM_SHA384", "CHACHA20_POLY1305_SHA256"],
|
||||||
|
"clientCA": [],
|
||||||
|
"curveList": ["X25519", "P256", "P384", "P521"],
|
||||||
|
"dynamicSizingDisable": false,
|
||||||
|
"inheritDefault": false,
|
||||||
|
"rootCA": [],
|
||||||
|
"sessionTicketDisable": false,
|
||||||
|
"versionMax": "1.3",
|
||||||
|
"versionMin": "1.2"
|
||||||
|
}`
|
||||||
|
|
||||||
|
return []byte(oldConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Describe("certificates test", func() {
|
||||||
|
|
||||||
|
Context("Using a config json", func() {
|
||||||
|
It("must success to new Config when certificates are paste as file mode", func() {
|
||||||
|
cfg := libtls.Config{}
|
||||||
|
|
||||||
|
p := getConfigFile()
|
||||||
|
Expect(len(p)).To(BeNumerically(">", 0))
|
||||||
|
|
||||||
|
e := json.Unmarshal(p, &cfg)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
cnf := cfg.New()
|
||||||
|
Expect(cnf).ToNot(BeNil())
|
||||||
|
Expect(len(cnf.GetCertificatePair())).To(Equal(1))
|
||||||
|
|
||||||
|
cfgtls := cnf.TLS("localhost")
|
||||||
|
Expect(cfgtls).ToNot(BeNil())
|
||||||
|
Expect(len(cfgtls.Certificates)).To(Equal(1))
|
||||||
|
Expect(len(cfgtls.CipherSuites)).To(BeNumerically(">", 0))
|
||||||
|
Expect(len(cfgtls.CurvePreferences)).To(BeNumerically(">", 0))
|
||||||
|
|
||||||
|
p, e = json.Marshal(cnf.Config())
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
Expect(len(p)).To(BeNumerically(">", 0))
|
||||||
|
})
|
||||||
|
It("must success to new Config when certificates are paste as chain mode", func() {
|
||||||
|
cfg := libtls.Config{}
|
||||||
|
|
||||||
|
p := getConfigChain()
|
||||||
|
Expect(len(p)).To(BeNumerically(">", 0))
|
||||||
|
|
||||||
|
e := json.Unmarshal(p, &cfg)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
cnf := cfg.New()
|
||||||
|
Expect(cnf).ToNot(BeNil())
|
||||||
|
Expect(len(cnf.GetCertificatePair())).To(Equal(1))
|
||||||
|
|
||||||
|
cfgtls := cnf.TLS("localhost")
|
||||||
|
Expect(cfgtls).ToNot(BeNil())
|
||||||
|
Expect(len(cfgtls.Certificates)).To(Equal(1))
|
||||||
|
Expect(len(cfgtls.CipherSuites)).To(BeNumerically(">", 0))
|
||||||
|
Expect(len(cfgtls.CurvePreferences)).To(BeNumerically(">", 0))
|
||||||
|
|
||||||
|
p, e = json.Marshal(cnf)
|
||||||
|
Expect(e).ToNot(HaveOccurred())
|
||||||
|
Expect(len(p)).To(BeNumerically(">", 0))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
75
certificates/certificates_suite_test.go
Normal file
75
certificates/certificates_suite_test.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Using https://onsi.github.io/ginkgo/
|
||||||
|
Running with $> ginkgo -cover .
|
||||||
|
*/
|
||||||
|
|
||||||
|
type EmptyStruct struct{}
|
||||||
|
|
||||||
|
var (
|
||||||
|
keyFile string
|
||||||
|
pubFile string
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestGolibEncodingAESHelper tests the Golib AES Encoding Helper function.
|
||||||
|
func TestGolibArchiveHelper(t *testing.T) {
|
||||||
|
time.Sleep(500 * time.Millisecond) // Adding delay for better testing synchronization
|
||||||
|
RegisterFailHandler(Fail) // Registering fail handler for better test failure reporting
|
||||||
|
RunSpecs(t, "Certificates Helper Suite") // Running the test suite for Encoding AES Helper
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = BeforeSuite(func() {
|
||||||
|
keyFile = filepath.Join(os.Getenv("GOPATH"), "src", strings.Replace(reflect.TypeOf(EmptyStruct{}).PkgPath(), "_test", "", -1), "test_ed25519.key")
|
||||||
|
pubFile = filepath.Join(os.Getenv("GOPATH"), "src", strings.Replace(reflect.TypeOf(EmptyStruct{}).PkgPath(), "_test", "", -1), "test_ed25519.pub")
|
||||||
|
})
|
||||||
|
|
||||||
|
var _ = AfterSuite(func() {
|
||||||
|
if keyFile != "" {
|
||||||
|
if _, e := os.Stat(keyFile); e == nil {
|
||||||
|
Expect(os.Remove(keyFile)).ToNot(HaveOccurred())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pubFile != "" {
|
||||||
|
if _, e := os.Stat(pubFile); e == nil {
|
||||||
|
Expect(os.Remove(pubFile)).ToNot(HaveOccurred())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
165
certificates/certs/config.go
Normal file
165
certificates/certs/config.go
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidPairCertificate = errors.New("invalid pair certificate")
|
||||||
|
ErrInvalidCertificate = errors.New("invalid certificate")
|
||||||
|
ErrInvalidPrivateKey = errors.New("invalid private key")
|
||||||
|
)
|
||||||
|
|
||||||
|
func cleanPem(s string) string {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
|
||||||
|
// remove \n\r
|
||||||
|
s = strings.Trim(s, "\n")
|
||||||
|
s = strings.Trim(s, "\r")
|
||||||
|
|
||||||
|
// do again if \r\n
|
||||||
|
s = strings.Trim(s, "\n")
|
||||||
|
s = strings.Trim(s, "\r")
|
||||||
|
|
||||||
|
return strings.TrimSpace(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config interface {
|
||||||
|
Cert() (*tls.Certificate, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigPair struct {
|
||||||
|
Key string `mapstructure:"key" json:"key" yaml:"key" toml:"key"`
|
||||||
|
Pub string `mapstructure:"pub" json:"pub" yaml:"pub" toml:"pub"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigPair) Cert() (*tls.Certificate, error) {
|
||||||
|
c.Key = cleanPem(c.Key)
|
||||||
|
c.Pub = cleanPem(c.Pub)
|
||||||
|
|
||||||
|
if c == nil {
|
||||||
|
return nil, ErrInvalidPairCertificate
|
||||||
|
} else if len(c.Key) < 1 || len(c.Pub) < 1 {
|
||||||
|
return nil, ErrInvalidPairCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, e := os.Stat(c.Key); e == nil {
|
||||||
|
if b, e := os.ReadFile(c.Key); e == nil {
|
||||||
|
c.Key = cleanPem(string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, e := os.Stat(c.Pub); e == nil {
|
||||||
|
if b, e := os.ReadFile(c.Pub); e == nil {
|
||||||
|
c.Pub = cleanPem(string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if crt, err := tls.X509KeyPair([]byte(c.Pub), []byte(c.Key)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return &crt, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigChain string
|
||||||
|
|
||||||
|
func (c *ConfigChain) Cert() (*tls.Certificate, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
crt tls.Certificate
|
||||||
|
)
|
||||||
|
|
||||||
|
if c == nil {
|
||||||
|
return nil, ErrInvalidPairCertificate
|
||||||
|
} else if len(*c) < 1 {
|
||||||
|
return nil, ErrInvalidPairCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
s := string(*c)
|
||||||
|
|
||||||
|
if _, e := os.Stat(s); e == nil {
|
||||||
|
if b, e := os.ReadFile(s); e == nil {
|
||||||
|
s = cleanPem(string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p := []byte(cleanPem(s))
|
||||||
|
|
||||||
|
for {
|
||||||
|
block, rest := pem.Decode(p)
|
||||||
|
if block == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if block.Type == "CERTIFICATE" {
|
||||||
|
crt.Certificate = append(crt.Certificate, block.Bytes)
|
||||||
|
} else {
|
||||||
|
crt.PrivateKey, err = c.getPrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p = rest
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(crt.Certificate) == 0 {
|
||||||
|
return nil, ErrInvalidCertificate
|
||||||
|
} else if crt.PrivateKey == nil {
|
||||||
|
return nil, ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
return &crt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigChain) getPrivateKey(der []byte) (crypto.PrivateKey, error) {
|
||||||
|
if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
|
||||||
|
switch k := key.(type) {
|
||||||
|
case *rsa.PrivateKey, *ecdsa.PrivateKey:
|
||||||
|
return k, nil
|
||||||
|
default:
|
||||||
|
return nil, ErrInvalidPrivateKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if key, err := x509.ParseECPrivateKey(der); err == nil {
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
return nil, ErrInvalidPrivateKey
|
||||||
|
}
|
244
certificates/certs/encode.go
Normal file
244
certificates/certs/encode.go
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/fxamacker/cbor/v2"
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o *Certif) unMarshall(p []byte) error {
|
||||||
|
if o.UnmarshalJSON(p) == nil {
|
||||||
|
return nil
|
||||||
|
} else if o.UnmarshalYAML(&yaml.Node{Value: string(p)}) != nil {
|
||||||
|
return nil
|
||||||
|
} else if o.UnmarshalTOML(p) != nil {
|
||||||
|
return nil
|
||||||
|
} else if o.UnmarshalCBOR(p) != nil {
|
||||||
|
return nil
|
||||||
|
} else if o.UnmarshalText(p) != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) MarshalText() (text []byte, err error) {
|
||||||
|
return []byte(o.String()), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) UnmarshalText(text []byte) error {
|
||||||
|
var (
|
||||||
|
chn = ConfigChain(text)
|
||||||
|
crt *tls.Certificate
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if crt, err = chn.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) MarshalBinary() (data []byte, err error) {
|
||||||
|
return o.MarshalCBOR()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) UnmarshalBinary(data []byte) error {
|
||||||
|
return o.UnmarshalCBOR(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) MarshalJSON() ([]byte, error) {
|
||||||
|
t := o.String()
|
||||||
|
return json.Marshal(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) UnmarshalJSON(bytes []byte) error {
|
||||||
|
var (
|
||||||
|
cfg ConfigPair
|
||||||
|
chn ConfigChain
|
||||||
|
crt *tls.Certificate
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if err = json.Unmarshal(bytes, &cfg); err == nil {
|
||||||
|
if crt, err = cfg.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else if err = json.Unmarshal(bytes, &chn); err == nil {
|
||||||
|
if crt, err = chn.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) MarshalYAML() (interface{}, error) {
|
||||||
|
t := o.String()
|
||||||
|
return yaml.Marshal(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) UnmarshalYAML(value *yaml.Node) error {
|
||||||
|
var (
|
||||||
|
src = []byte(value.Value)
|
||||||
|
cfg ConfigPair
|
||||||
|
chn ConfigChain
|
||||||
|
crt *tls.Certificate
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if err = yaml.Unmarshal(src, &cfg); err == nil {
|
||||||
|
if crt, err = cfg.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else if err = yaml.Unmarshal(src, &chn); err == nil {
|
||||||
|
if crt, err = chn.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) MarshalTOML() ([]byte, error) {
|
||||||
|
t := o.String()
|
||||||
|
return toml.Marshal(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) UnmarshalTOML(i interface{}) error {
|
||||||
|
var (
|
||||||
|
p []byte
|
||||||
|
s string
|
||||||
|
k bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if p, k = i.([]byte); !k {
|
||||||
|
if s, k = i.(string); k {
|
||||||
|
p = []byte(s)
|
||||||
|
} else {
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p) < 1 {
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
cfg ConfigPair
|
||||||
|
chn ConfigChain
|
||||||
|
crt *tls.Certificate
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if err = toml.Unmarshal(p, &cfg); err == nil {
|
||||||
|
if crt, err = cfg.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else if err = toml.Unmarshal(p, &chn); err == nil {
|
||||||
|
if crt, err = chn.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) MarshalCBOR() ([]byte, error) {
|
||||||
|
t := o.String()
|
||||||
|
return cbor.Marshal(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) UnmarshalCBOR(bytes []byte) error {
|
||||||
|
var (
|
||||||
|
cfg ConfigPair
|
||||||
|
chn ConfigChain
|
||||||
|
crt *tls.Certificate
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if err = cbor.Unmarshal(bytes, &cfg); err == nil {
|
||||||
|
if crt, err = cfg.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else if err = cbor.Unmarshal(bytes, &chn); err == nil {
|
||||||
|
if crt, err = chn.Cert(); err != nil {
|
||||||
|
return err
|
||||||
|
} else if crt == nil || len(crt.Certificate) == 0 {
|
||||||
|
return ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
o.c = *crt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrInvalidCertificate
|
||||||
|
}
|
86
certificates/certs/format.go
Normal file
86
certificates/certs/format.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o *Certif) String() string {
|
||||||
|
str, _ := o.Chain()
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) Pair() (pub string, key string, err error) {
|
||||||
|
var (
|
||||||
|
bufPub = bytes.NewBuffer(make([]byte, 0))
|
||||||
|
bufKey = bytes.NewBuffer(make([]byte, 0))
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, certDER := range o.c.Certificate {
|
||||||
|
block := &pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: certDER,
|
||||||
|
}
|
||||||
|
if err = pem.Encode(bufPub, block); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Afficher la clé privée si disponible
|
||||||
|
if o.c.PrivateKey != nil {
|
||||||
|
var p []byte
|
||||||
|
if p, err = x509.MarshalPKCS8PrivateKey(o.c.PrivateKey); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
} else {
|
||||||
|
privateKeyBlock := &pem.Block{
|
||||||
|
Type: "PRIVATE KEY",
|
||||||
|
Bytes: p,
|
||||||
|
}
|
||||||
|
if err = pem.Encode(bufKey, privateKeyBlock); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bufPub.String(), bufKey.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) Chain() (string, error) {
|
||||||
|
if pub, key, err := o.Pair(); err != nil {
|
||||||
|
return "", err
|
||||||
|
} else {
|
||||||
|
return pub + key, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) TLS() tls.Certificate {
|
||||||
|
return o.c
|
||||||
|
}
|
76
certificates/certs/interface.go
Normal file
76
certificates/certs/interface.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fxamacker/cbor/v2"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cert interface {
|
||||||
|
encoding.TextMarshaler
|
||||||
|
encoding.TextUnmarshaler
|
||||||
|
encoding.BinaryMarshaler
|
||||||
|
encoding.BinaryUnmarshaler
|
||||||
|
json.Marshaler
|
||||||
|
json.Unmarshaler
|
||||||
|
yaml.Marshaler
|
||||||
|
yaml.Unmarshaler
|
||||||
|
toml.Marshaler
|
||||||
|
toml.Unmarshaler
|
||||||
|
cbor.Marshaler
|
||||||
|
cbor.Unmarshaler
|
||||||
|
fmt.Stringer
|
||||||
|
|
||||||
|
TLS() tls.Certificate
|
||||||
|
Model() Certif
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(chain string) (Cert, error) {
|
||||||
|
c := ConfigChain(chain)
|
||||||
|
return parseCert(&c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePair(key, pub string) (Cert, error) {
|
||||||
|
return parseCert(&ConfigPair{Key: key, Pub: pub})
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCert(cfg Config) (Cert, error) {
|
||||||
|
if c, e := cfg.Cert(); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else if c == nil {
|
||||||
|
return nil, ErrInvalidPairCertificate
|
||||||
|
} else {
|
||||||
|
return &Certif{c: *c}, nil
|
||||||
|
}
|
||||||
|
}
|
75
certificates/certs/models.go
Normal file
75
certificates/certs/models.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
libmap "github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Certif struct {
|
||||||
|
c tls.Certificate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) Cert() Cert {
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Certif) Model() Certif {
|
||||||
|
return *o
|
||||||
|
}
|
||||||
|
|
||||||
|
func ViperDecoderHook() libmap.DecodeHookFuncType {
|
||||||
|
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
|
||||||
|
var (
|
||||||
|
z = &Certif{c: tls.Certificate{}}
|
||||||
|
t string
|
||||||
|
k bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the data type matches the expected one
|
||||||
|
if from.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
} else if t, k = data.(string); !k {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the target type matches the expected one
|
||||||
|
if to != reflect.TypeOf(z) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format/decode/parse the data and return the new value
|
||||||
|
if e := z.unMarshall([]byte(t)); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return z, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
certificates/cipher/encode.go
Normal file
89
certificates/cipher/encode.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *Cipher) unmarshall(val []byte) error {
|
||||||
|
*v = parseBytes(val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) MarshalJSON() ([]byte, error) {
|
||||||
|
t := v.String()
|
||||||
|
b := make([]byte, 0, len(t)+2)
|
||||||
|
b = append(b, '"')
|
||||||
|
b = append(b, []byte(t)...)
|
||||||
|
b = append(b, '"')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Cipher) UnmarshalJSON(bytes []byte) error {
|
||||||
|
return v.unmarshall(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) MarshalYAML() (interface{}, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Cipher) UnmarshalYAML(value *yaml.Node) error {
|
||||||
|
return v.unmarshall([]byte(value.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) MarshalTOML() ([]byte, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Cipher) UnmarshalTOML(i interface{}) error {
|
||||||
|
if p, k := i.([]byte); k {
|
||||||
|
return v.unmarshall(p)
|
||||||
|
}
|
||||||
|
if p, k := i.(string); k {
|
||||||
|
return v.unmarshall([]byte(p))
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cipher: value not in valid format")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Cipher) UnmarshalText(bytes []byte) error {
|
||||||
|
return v.unmarshall(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) MarshalCBOR() ([]byte, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Cipher) UnmarshalCBOR(bytes []byte) error {
|
||||||
|
return v.unmarshall(bytes)
|
||||||
|
}
|
100
certificates/cipher/format.go
Normal file
100
certificates/cipher/format.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v Cipher) String() string {
|
||||||
|
return strings.Join(v.Code(), "_")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Code() []string {
|
||||||
|
switch v {
|
||||||
|
case TLS_RSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
return []string{"rsa", "aes", "128", "gcm", "sha256"}
|
||||||
|
case TLS_RSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
return []string{"rsa", "aes", "256", "gcm", "sha384"}
|
||||||
|
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
return []string{"ecdhe", "rsa", "aes", "128", "gcm", "sha256"}
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
return []string{"ecdhe", "ecdsa", "aes", "128", "gcm", "sha256"}
|
||||||
|
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
return []string{"ecdhe", "rsa", "aes", "256", "gcm", "sha384"}
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
return []string{"ecdhe", "ecdsa", "aes", "256", "gcm", "sha384"}
|
||||||
|
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
|
||||||
|
return []string{"ecdhe", "rsa", "chacha20", "poly1305", "sha256"}
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
|
||||||
|
return []string{"ecdhe", "ecdsa", "chacha20", "poly1305", "sha256"}
|
||||||
|
case TLS_AES_128_GCM_SHA256:
|
||||||
|
return []string{"aes", "128", "gcm", "sha256"}
|
||||||
|
case TLS_AES_256_GCM_SHA384:
|
||||||
|
return []string{"aes", "256", "gcm", "sha384"}
|
||||||
|
case TLS_CHACHA20_POLY1305_SHA256:
|
||||||
|
return []string{"chacha20", "poly1305", "sha256"}
|
||||||
|
default:
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Cipher() uint16 {
|
||||||
|
return uint16(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) TLS() uint16 {
|
||||||
|
return v.Cipher()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Uint16() uint16 {
|
||||||
|
return v.Cipher()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Uint() uint {
|
||||||
|
return uint(v.Cipher())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Uint32() uint32 {
|
||||||
|
return uint32(v.Cipher())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Uint64() uint64 {
|
||||||
|
return uint64(v.Cipher())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Int() int {
|
||||||
|
return int(v.Cipher())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Int32() int32 {
|
||||||
|
return int32(v.Cipher())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Cipher) Int64() int64 {
|
||||||
|
return int64(v.Cipher())
|
||||||
|
}
|
199
certificates/cipher/interface.go
Normal file
199
certificates/cipher/interface.go
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"math"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cipher uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
Unknown Cipher = Cipher(0)
|
||||||
|
|
||||||
|
// TLS 1.0 - 1.2 cipher suites.
|
||||||
|
TLS_RSA_WITH_AES_128_GCM_SHA256 = Cipher(tls.TLS_RSA_WITH_AES_128_GCM_SHA256)
|
||||||
|
TLS_RSA_WITH_AES_256_GCM_SHA384 = Cipher(tls.TLS_RSA_WITH_AES_256_GCM_SHA384)
|
||||||
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = Cipher(tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = Cipher(tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
|
||||||
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = Cipher(tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = Cipher(tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
||||||
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = Cipher(tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||||
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = Cipher(tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||||
|
|
||||||
|
// TLS 1.3 cipher suites.
|
||||||
|
TLS_AES_128_GCM_SHA256 = Cipher(tls.TLS_AES_128_GCM_SHA256)
|
||||||
|
TLS_AES_256_GCM_SHA384 = Cipher(tls.TLS_AES_256_GCM_SHA384)
|
||||||
|
TLS_CHACHA20_POLY1305_SHA256 = Cipher(tls.TLS_CHACHA20_POLY1305_SHA256)
|
||||||
|
)
|
||||||
|
|
||||||
|
func List() []Cipher {
|
||||||
|
return []Cipher{
|
||||||
|
TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
TLS_AES_128_GCM_SHA256,
|
||||||
|
TLS_AES_256_GCM_SHA384,
|
||||||
|
TLS_CHACHA20_POLY1305_SHA256,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListString() []string {
|
||||||
|
var res = make([]string, 0)
|
||||||
|
for _, c := range List() {
|
||||||
|
res = append(res, c.String())
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(s string) Cipher {
|
||||||
|
s = strings.ToLower(s)
|
||||||
|
s = strings.Replace(s, "\"", "", -1)
|
||||||
|
s = strings.Replace(s, "'", "", -1)
|
||||||
|
s = strings.Replace(s, "tls", "", -1)
|
||||||
|
s = strings.Replace(s, ".", "_", -1)
|
||||||
|
s = strings.Replace(s, "-", "_", -1)
|
||||||
|
s = strings.Replace(s, " ", "_", -1)
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
|
||||||
|
p := strings.Split(s, "_")
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case containString(p, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256.Code()):
|
||||||
|
return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||||
|
case containString(p, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.Code()):
|
||||||
|
return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
||||||
|
case containString(p, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384.Code()):
|
||||||
|
return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
|
case containString(p, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384.Code()):
|
||||||
|
return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
|
||||||
|
case containString(p, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.Code()):
|
||||||
|
return TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
case containString(p, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.Code()):
|
||||||
|
return TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
case containString(p, TLS_CHACHA20_POLY1305_SHA256.Code()):
|
||||||
|
return TLS_CHACHA20_POLY1305_SHA256
|
||||||
|
case containString(p, TLS_RSA_WITH_AES_128_GCM_SHA256.Code()):
|
||||||
|
return TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||||
|
case containString(p, TLS_RSA_WITH_AES_256_GCM_SHA384.Code()):
|
||||||
|
return TLS_RSA_WITH_AES_256_GCM_SHA384
|
||||||
|
case containString(p, TLS_AES_128_GCM_SHA256.Code()):
|
||||||
|
return TLS_AES_128_GCM_SHA256
|
||||||
|
case containString(p, TLS_AES_256_GCM_SHA384.Code()):
|
||||||
|
return TLS_AES_256_GCM_SHA384
|
||||||
|
default:
|
||||||
|
return Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containString[S ~[]string](s S, v S) bool {
|
||||||
|
keys := []string{
|
||||||
|
"chacha20",
|
||||||
|
"poly1305",
|
||||||
|
"ecdhe",
|
||||||
|
"rsa",
|
||||||
|
"ecdsa",
|
||||||
|
"aes",
|
||||||
|
"128",
|
||||||
|
"256",
|
||||||
|
"sha256",
|
||||||
|
"sha384",
|
||||||
|
"gcm",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range keys {
|
||||||
|
if !keyContainString(s, v, k) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyContainString[S ~[]string](s S, v S, k string) bool {
|
||||||
|
if slices.Contains(s, k) && !slices.Contains(v, k) {
|
||||||
|
return false
|
||||||
|
} else if !slices.Contains(s, k) && slices.Contains(v, k) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseInt(d int) Cipher {
|
||||||
|
if d > math.MaxUint16 {
|
||||||
|
d = math.MaxUint16
|
||||||
|
} else if d < 1 {
|
||||||
|
d = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
switch uint16(d) {
|
||||||
|
case tls.TLS_RSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
return TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||||
|
case tls.TLS_RSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
return TLS_RSA_WITH_AES_256_GCM_SHA384
|
||||||
|
case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||||
|
case tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||||
|
case tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
|
case tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
|
case tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
|
||||||
|
return TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
case tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
|
||||||
|
return TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
case tls.TLS_AES_128_GCM_SHA256:
|
||||||
|
return TLS_AES_128_GCM_SHA256
|
||||||
|
case tls.TLS_AES_256_GCM_SHA384:
|
||||||
|
return TLS_AES_256_GCM_SHA384
|
||||||
|
case tls.TLS_CHACHA20_POLY1305_SHA256:
|
||||||
|
return TLS_CHACHA20_POLY1305_SHA256
|
||||||
|
default:
|
||||||
|
return Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Check(cipher uint16) bool {
|
||||||
|
if c := ParseInt(int(cipher)); c == Unknown {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBytes(p []byte) Cipher {
|
||||||
|
return Parse(string(p))
|
||||||
|
}
|
62
certificates/cipher/models.go
Normal file
62
certificates/cipher/models.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
libmap "github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ViperDecoderHook() libmap.DecodeHookFuncType {
|
||||||
|
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
|
||||||
|
var (
|
||||||
|
z = Cipher(0)
|
||||||
|
t string
|
||||||
|
k bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the data type matches the expected one
|
||||||
|
if from.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
} else if t, k = data.(string); !k {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the target type matches the expected one
|
||||||
|
if to != reflect.TypeOf(z) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format/decode/parse the data and return the new value
|
||||||
|
if e := z.unmarshall([]byte(t)); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return z, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
certificates/ciphers.go
Normal file
52
certificates/ciphers.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates
|
||||||
|
|
||||||
|
import tlscpr "github.com/nabbar/golib/certificates/cipher"
|
||||||
|
|
||||||
|
func (o *config) SetCipherList(c []tlscpr.Cipher) {
|
||||||
|
o.cipherList = make([]tlscpr.Cipher, 0)
|
||||||
|
o.AddCiphers(c...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddCiphers(c ...tlscpr.Cipher) {
|
||||||
|
for _, i := range c {
|
||||||
|
o.cipherList = append(o.cipherList, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) GetCiphers() []tlscpr.Cipher {
|
||||||
|
var res = make([]tlscpr.Cipher, 0)
|
||||||
|
|
||||||
|
for _, i := range o.cipherList {
|
||||||
|
if tlscpr.Check(i.Uint16()) {
|
||||||
|
res = append(res, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
@@ -30,29 +30,27 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
libval "github.com/go-playground/validator/v10"
|
libval "github.com/go-playground/validator/v10"
|
||||||
|
tlsaut "github.com/nabbar/golib/certificates/auth"
|
||||||
|
tlscas "github.com/nabbar/golib/certificates/ca"
|
||||||
|
tlscrt "github.com/nabbar/golib/certificates/certs"
|
||||||
|
tlscpr "github.com/nabbar/golib/certificates/cipher"
|
||||||
|
tlscrv "github.com/nabbar/golib/certificates/curves"
|
||||||
|
tlsvrs "github.com/nabbar/golib/certificates/tlsversion"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Certif struct {
|
|
||||||
Key string `mapstructure:"key" json:"key" yaml:"key" toml:"key"`
|
|
||||||
Pem string `mapstructure:"pem" json:"pem" yaml:"pem" toml:"pem"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
CurveList []string `mapstructure:"curveList" json:"curveList" yaml:"curveList" toml:"curveList"`
|
CurveList []tlscrv.Curves `mapstructure:"curveList" json:"curveList" yaml:"curveList" toml:"curveList"`
|
||||||
CipherList []string `mapstructure:"cipherList" json:"cipherList" yaml:"cipherList" toml:"cipherList"`
|
CipherList []tlscpr.Cipher `mapstructure:"cipherList" json:"cipherList" yaml:"cipherList" toml:"cipherList"`
|
||||||
RootCAString []string `mapstructure:"rootCA" json:"rootCA" yaml:"rootCA" toml:"rootCA"`
|
RootCA []tlscas.Cert `mapstructure:"rootCA" json:"rootCA" yaml:"rootCA" toml:"rootCA"`
|
||||||
RootCAFile []string `mapstructure:"rootCAFiles" json:"rootCAFiles" yaml:"rootCAFiles" toml:"rootCAFiles"`
|
ClientCA []tlscas.Cert `mapstructure:"clientCA" json:"clientCA" yaml:"clientCA" toml:"clientCA"`
|
||||||
ClientCAString []string `mapstructure:"clientCA" json:"clientCA" yaml:"clientCA" toml:"clientCA"`
|
Certs []tlscrt.Certif `mapstructure:"certs" json:"certs" yaml:"certs" toml:"certs"`
|
||||||
ClientCAFiles []string `mapstructure:"clientCAFiles" json:"clientCAFiles" yaml:"clientCAFiles" toml:"clientCAFiles"`
|
VersionMin tlsvrs.Version `mapstructure:"versionMin" json:"versionMin" yaml:"versionMin" toml:"versionMin"`
|
||||||
CertPairString []Certif `mapstructure:"certPair" json:"certPair" yaml:"certPair" toml:"certPair"`
|
VersionMax tlsvrs.Version `mapstructure:"versionMax" json:"versionMax" yaml:"versionMax" toml:"versionMax"`
|
||||||
CertPairFile []Certif `mapstructure:"certPairFiles" json:"certPairFiles" yaml:"certPairFiles" toml:"certPairFiles"`
|
AuthClient tlsaut.ClientAuth `mapstructure:"authClient" json:"authClient" yaml:"authClient" toml:"authClient"`
|
||||||
VersionMin string `mapstructure:"versionMin" json:"versionMin" yaml:"versionMin" toml:"versionMin"`
|
InheritDefault bool `mapstructure:"inheritDefault" json:"inheritDefault" yaml:"inheritDefault" toml:"inheritDefault"`
|
||||||
VersionMax string `mapstructure:"versionMax" json:"versionMax" yaml:"versionMax" toml:"versionMax"`
|
DynamicSizingDisable bool `mapstructure:"dynamicSizingDisable" json:"dynamicSizingDisable" yaml:"dynamicSizingDisable" toml:"dynamicSizingDisable"`
|
||||||
AuthClient string `mapstructure:"authClient" json:"authClient" yaml:"authClient" toml:"authClient"`
|
SessionTicketDisable bool `mapstructure:"sessionTicketDisable" json:"sessionTicketDisable" yaml:"sessionTicketDisable" toml:"sessionTicketDisable"`
|
||||||
InheritDefault bool `mapstructure:"inheritDefault" json:"inheritDefault" yaml:"inheritDefault" toml:"inheritDefault"`
|
|
||||||
DynamicSizingDisable bool `mapstructure:"dynamicSizingDisable" json:"dynamicSizingDisable" yaml:"dynamicSizingDisable" toml:"dynamicSizingDisable"`
|
|
||||||
SessionTicketDisable bool `mapstructure:"sessionTicketDisable" json:"sessionTicketDisable" yaml:"sessionTicketDisable" toml:"sessionTicketDisable"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() liberr.Error {
|
func (c *Config) Validate() liberr.Error {
|
||||||
@@ -76,7 +74,7 @@ func (c *Config) Validate() liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) New() (TLSConfig, liberr.Error) {
|
func (c *Config) New() TLSConfig {
|
||||||
if c.InheritDefault {
|
if c.InheritDefault {
|
||||||
return c.NewFrom(Default)
|
return c.NewFrom(Default)
|
||||||
} else {
|
} else {
|
||||||
@@ -85,117 +83,114 @@ func (c *Config) New() (TLSConfig, liberr.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// nolint #gocognit
|
// nolint #gocognit
|
||||||
func (c *Config) NewFrom(cfg TLSConfig) (TLSConfig, liberr.Error) {
|
func (c *Config) NewFrom(cfg TLSConfig) TLSConfig {
|
||||||
var t *config
|
var t *Config
|
||||||
|
|
||||||
if cfg != nil {
|
if cfg != nil {
|
||||||
t = asStruct(cfg.Clone())
|
t = cfg.Config()
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == nil {
|
if t == nil {
|
||||||
t = asStruct(New())
|
t = &Config{}
|
||||||
t.caRoot = SystemRootCA()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.VersionMin != "" {
|
if c.VersionMin != tlsvrs.VersionUnknown {
|
||||||
t.tlsMinVersion = StringToTlsVersion(c.VersionMin)
|
t.VersionMin = c.VersionMin
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.VersionMax != "" {
|
if c.VersionMax != tlsvrs.VersionUnknown {
|
||||||
t.tlsMaxVersion = StringToTlsVersion(c.VersionMax)
|
t.VersionMax = c.VersionMax
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.DynamicSizingDisable {
|
if c.DynamicSizingDisable {
|
||||||
t.dynSizingDisabled = true
|
t.DynamicSizingDisable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.SessionTicketDisable {
|
if c.SessionTicketDisable {
|
||||||
t.ticketSessionDisabled = true
|
t.SessionTicketDisable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.AuthClient != "" {
|
if c.AuthClient != tlsaut.NoClientCert {
|
||||||
t.clientAuth = StringToClientAuth(c.AuthClient)
|
t.AuthClient = c.AuthClient
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.CipherList) > 0 {
|
if len(c.CipherList) > 0 {
|
||||||
for _, a := range c.CipherList {
|
for _, a := range c.CipherList {
|
||||||
if len(a) < 1 {
|
if tlscpr.Check(a.Uint16()) {
|
||||||
continue
|
t.CipherList = append(t.CipherList, a)
|
||||||
}
|
}
|
||||||
t.cipherList = append(t.cipherList, StringToCipherKey(a))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.CurveList) > 0 {
|
if len(c.CurveList) > 0 {
|
||||||
for _, a := range c.CurveList {
|
for _, a := range c.CurveList {
|
||||||
if len(a) < 1 {
|
if tlscrv.Check(a.Uint16()) {
|
||||||
continue
|
t.CurveList = append(t.CurveList, a)
|
||||||
}
|
|
||||||
t.curveList = append(t.curveList, StringToCurveID(a))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.RootCAString) > 0 {
|
|
||||||
for _, s := range c.RootCAString {
|
|
||||||
if len(s) < 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.AddRootCAString(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.RootCAFile) > 0 {
|
|
||||||
for _, f := range c.RootCAFile {
|
|
||||||
if len(f) < 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if e := t.AddRootCAFile(f); e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.ClientCAString) > 0 {
|
if len(c.RootCA) > 0 {
|
||||||
for _, s := range c.ClientCAString {
|
for _, s := range c.RootCA {
|
||||||
if len(s) < 1 {
|
t.RootCA = append(t.RootCA, s)
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.AddClientCAString(s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.ClientCAFiles) > 0 {
|
if len(c.ClientCA) > 0 {
|
||||||
for _, f := range c.ClientCAFiles {
|
for _, s := range c.ClientCA {
|
||||||
if len(f) < 1 {
|
t.ClientCA = append(t.ClientCA, s)
|
||||||
continue
|
|
||||||
}
|
|
||||||
if e := t.AddClientCAFile(f); e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.CertPairString) > 0 {
|
if len(c.Certs) > 0 {
|
||||||
for _, s := range c.CertPairString {
|
for _, s := range c.Certs {
|
||||||
if len(s.Key) < 1 || len(s.Pem) < 1 {
|
t.Certs = append(t.Certs, s)
|
||||||
continue
|
|
||||||
}
|
|
||||||
if e := t.AddCertificatePairString(s.Key, s.Pem); e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.CertPairFile) > 0 {
|
res := &config{
|
||||||
for _, f := range c.CertPairFile {
|
rand: nil,
|
||||||
if len(f.Key) < 1 || len(f.Pem) < 1 {
|
cert: make([]tlscrt.Cert, 0),
|
||||||
continue
|
cipherList: make([]tlscpr.Cipher, 0),
|
||||||
}
|
curveList: make([]tlscrv.Curves, 0),
|
||||||
if e := t.AddCertificatePairFile(f.Key, f.Pem); e != nil {
|
caRoot: make([]tlscas.Cert, 0),
|
||||||
return nil, e
|
clientAuth: t.AuthClient,
|
||||||
}
|
clientCA: make([]tlscas.Cert, 0),
|
||||||
|
tlsMinVersion: t.VersionMin,
|
||||||
|
tlsMaxVersion: t.VersionMax,
|
||||||
|
dynSizingDisabled: t.DynamicSizingDisable,
|
||||||
|
ticketSessionDisabled: t.SessionTicketDisable,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t.Certs) > 0 {
|
||||||
|
for _, s := range t.Certs {
|
||||||
|
res.cert = append(res.cert, s.Cert())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t, nil
|
if len(t.CipherList) > 0 {
|
||||||
|
for _, s := range t.CipherList {
|
||||||
|
res.cipherList = append(res.cipherList, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t.CurveList) > 0 {
|
||||||
|
for _, s := range t.CurveList {
|
||||||
|
res.curveList = append(res.curveList, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t.RootCA) > 0 {
|
||||||
|
for _, s := range t.RootCA {
|
||||||
|
res.caRoot = append(res.caRoot, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t.ClientCA) > 0 {
|
||||||
|
for _, s := range t.ClientCA {
|
||||||
|
res.clientCA = append(res.clientCA, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
52
certificates/curves.go
Normal file
52
certificates/curves.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates
|
||||||
|
|
||||||
|
import tlscrv "github.com/nabbar/golib/certificates/curves"
|
||||||
|
|
||||||
|
func (o *config) SetCurveList(c []tlscrv.Curves) {
|
||||||
|
o.curveList = make([]tlscrv.Curves, 0)
|
||||||
|
o.AddCurves(c...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddCurves(c ...tlscrv.Curves) {
|
||||||
|
for _, i := range c {
|
||||||
|
o.curveList = append(o.curveList, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) GetCurves() []tlscrv.Curves {
|
||||||
|
var res = make([]tlscrv.Curves, 0)
|
||||||
|
|
||||||
|
for _, i := range o.curveList {
|
||||||
|
if tlscrv.Check(i.Uint16()) {
|
||||||
|
res = append(res, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
89
certificates/curves/encode.go
Normal file
89
certificates/curves/encode.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *Curves) unmarshall(val []byte) error {
|
||||||
|
*v = parseBytes(val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) MarshalJSON() ([]byte, error) {
|
||||||
|
t := v.String()
|
||||||
|
b := make([]byte, 0, len(t)+2)
|
||||||
|
b = append(b, '"')
|
||||||
|
b = append(b, []byte(t)...)
|
||||||
|
b = append(b, '"')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Curves) UnmarshalJSON(bytes []byte) error {
|
||||||
|
return v.unmarshall(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) MarshalYAML() (interface{}, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Curves) UnmarshalYAML(value *yaml.Node) error {
|
||||||
|
return v.unmarshall([]byte(value.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) MarshalTOML() ([]byte, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Curves) UnmarshalTOML(i interface{}) error {
|
||||||
|
if p, k := i.([]byte); k {
|
||||||
|
return v.unmarshall(p)
|
||||||
|
}
|
||||||
|
if p, k := i.(string); k {
|
||||||
|
return v.unmarshall([]byte(p))
|
||||||
|
}
|
||||||
|
return fmt.Errorf("size: value not in valid format")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Curves) UnmarshalText(bytes []byte) error {
|
||||||
|
return v.unmarshall(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) MarshalCBOR() ([]byte, error) {
|
||||||
|
return []byte(v.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Curves) UnmarshalCBOR(bytes []byte) error {
|
||||||
|
return v.unmarshall(bytes)
|
||||||
|
}
|
98
certificates/curves/format.go
Normal file
98
certificates/curves/format.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v Curves) String() string {
|
||||||
|
switch v {
|
||||||
|
case X25519:
|
||||||
|
return "X25519"
|
||||||
|
case P256:
|
||||||
|
return "P256"
|
||||||
|
case P384:
|
||||||
|
return "P384"
|
||||||
|
case P521:
|
||||||
|
return "P521"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Code() string {
|
||||||
|
return strings.ToLower(v.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) CurveID() tls.CurveID {
|
||||||
|
switch v {
|
||||||
|
case X25519:
|
||||||
|
return tls.X25519
|
||||||
|
case P256:
|
||||||
|
return tls.CurveP256
|
||||||
|
case P384:
|
||||||
|
return tls.CurveP384
|
||||||
|
case P521:
|
||||||
|
return tls.CurveP521
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) TLS() tls.CurveID {
|
||||||
|
return v.CurveID()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Uint16() uint16 {
|
||||||
|
return uint16(v.CurveID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Uint() uint {
|
||||||
|
return uint(v.CurveID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Uint32() uint32 {
|
||||||
|
return uint32(v.CurveID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Uint64() uint64 {
|
||||||
|
return uint64(v.CurveID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Int() int {
|
||||||
|
return int(v.CurveID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Int32() int32 {
|
||||||
|
return int32(v.CurveID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Curves) Int64() int64 {
|
||||||
|
return int64(v.CurveID())
|
||||||
|
}
|
120
certificates/curves/interface.go
Normal file
120
certificates/curves/interface.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Curves uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
Unknown Curves = iota
|
||||||
|
X25519 = Curves(tls.X25519)
|
||||||
|
P256 = Curves(tls.CurveP256)
|
||||||
|
P384 = Curves(tls.CurveP384)
|
||||||
|
P521 = Curves(tls.CurveP521)
|
||||||
|
)
|
||||||
|
|
||||||
|
func List() []Curves {
|
||||||
|
return []Curves{
|
||||||
|
X25519,
|
||||||
|
P256,
|
||||||
|
P384,
|
||||||
|
P521,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListString() []string {
|
||||||
|
var res = make([]string, 0)
|
||||||
|
for _, c := range List() {
|
||||||
|
res = append(res, c.String())
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(s string) Curves {
|
||||||
|
s = strings.ToLower(s)
|
||||||
|
s = strings.Replace(s, "\"", "", -1)
|
||||||
|
s = strings.Replace(s, "'", "", -1)
|
||||||
|
s = strings.Replace(s, "x", "", -1)
|
||||||
|
s = strings.Replace(s, "X", "", -1)
|
||||||
|
s = strings.Replace(s, "p", "", -1)
|
||||||
|
s = strings.Replace(s, "P", "", -1)
|
||||||
|
s = strings.Replace(s, ".", "", -1)
|
||||||
|
s = strings.Replace(s, "-", "", -1)
|
||||||
|
s = strings.Replace(s, "_", "", -1)
|
||||||
|
s = strings.Replace(s, " ", "", -1)
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case strings.EqualFold(s, "25519"):
|
||||||
|
return X25519
|
||||||
|
case strings.EqualFold(s, "256"):
|
||||||
|
return P256
|
||||||
|
case strings.EqualFold(s, "384"):
|
||||||
|
return P384
|
||||||
|
case strings.EqualFold(s, "521"):
|
||||||
|
return P521
|
||||||
|
default:
|
||||||
|
return Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseInt(d int) Curves {
|
||||||
|
if d > math.MaxUint16 {
|
||||||
|
d = math.MaxUint16
|
||||||
|
} else if d < 1 {
|
||||||
|
d = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tls.CurveID(d) {
|
||||||
|
case tls.X25519:
|
||||||
|
return X25519
|
||||||
|
case tls.CurveP256:
|
||||||
|
return P256
|
||||||
|
case tls.CurveP384:
|
||||||
|
return P384
|
||||||
|
case tls.CurveP521:
|
||||||
|
return P521
|
||||||
|
default:
|
||||||
|
return Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Check(curves uint16) bool {
|
||||||
|
if c := ParseInt(int(curves)); c == Unknown {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBytes(p []byte) Curves {
|
||||||
|
return Parse(string(p))
|
||||||
|
}
|
62
certificates/curves/models.go
Normal file
62
certificates/curves/models.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package curves
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
libmap "github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ViperDecoderHook() libmap.DecodeHookFuncType {
|
||||||
|
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
|
||||||
|
var (
|
||||||
|
z = Curves(0)
|
||||||
|
t string
|
||||||
|
k bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the data type matches the expected one
|
||||||
|
if from.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
} else if t, k = data.(string); !k {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the target type matches the expected one
|
||||||
|
if to != reflect.TypeOf(z) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format/decode/parse the data and return the new value
|
||||||
|
if e := z.unmarshall([]byte(t)); e != nil {
|
||||||
|
return nil, e
|
||||||
|
} else {
|
||||||
|
return z, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -29,9 +29,15 @@ package certificates
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
liberr "github.com/nabbar/golib/errors"
|
tlsaut "github.com/nabbar/golib/certificates/auth"
|
||||||
|
tlscas "github.com/nabbar/golib/certificates/ca"
|
||||||
|
tlscrt "github.com/nabbar/golib/certificates/certs"
|
||||||
|
tlscpr "github.com/nabbar/golib/certificates/cipher"
|
||||||
|
tlscrv "github.com/nabbar/golib/certificates/curves"
|
||||||
|
tlsvrs "github.com/nabbar/golib/certificates/tlsversion"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FctHttpClient func(def TLSConfig, servername string) *http.Client
|
type FctHttpClient func(def TLSConfig, servername string) *http.Client
|
||||||
@@ -39,50 +45,62 @@ type FctTLSDefault func() TLSConfig
|
|||||||
type FctRootCA func() []string
|
type FctRootCA func() []string
|
||||||
|
|
||||||
type TLSConfig interface {
|
type TLSConfig interface {
|
||||||
|
RegisterRand(rand io.Reader)
|
||||||
|
|
||||||
AddRootCAString(rootCA string) bool
|
AddRootCAString(rootCA string) bool
|
||||||
AddRootCAFile(pemFile string) liberr.Error
|
AddRootCAFile(pemFile string) error
|
||||||
GetRootCA() *x509.CertPool
|
GetRootCA() []tlscas.Cert
|
||||||
|
GetRootCAPool() *x509.CertPool
|
||||||
|
|
||||||
AddClientCAString(ca string) bool
|
AddClientCAString(ca string) bool
|
||||||
AddClientCAFile(pemFile string) liberr.Error
|
AddClientCAFile(pemFile string) error
|
||||||
GetClientCA() *x509.CertPool
|
GetClientCA() []tlscas.Cert
|
||||||
|
GetClientCAPool() *x509.CertPool
|
||||||
|
SetClientAuth(a tlsaut.ClientAuth)
|
||||||
|
|
||||||
AddCertificatePairString(key, crt string) liberr.Error
|
AddCertificatePairString(key, crt string) error
|
||||||
AddCertificatePairFile(keyFile, crtFile string) liberr.Error
|
AddCertificatePairFile(keyFile, crtFile string) error
|
||||||
LenCertificatePair() int
|
LenCertificatePair() int
|
||||||
CleanCertificatePair()
|
CleanCertificatePair()
|
||||||
GetCertificatePair() []tls.Certificate
|
GetCertificatePair() []tls.Certificate
|
||||||
|
|
||||||
SetVersionMin(vers uint16)
|
SetVersionMin(v tlsvrs.Version)
|
||||||
SetVersionMax(vers uint16)
|
GetVersionMin() tlsvrs.Version
|
||||||
SetClientAuth(cAuth tls.ClientAuthType)
|
SetVersionMax(v tlsvrs.Version)
|
||||||
SetCipherList(cipher []uint16)
|
GetVersionMax() tlsvrs.Version
|
||||||
SetCurveList(curves []tls.CurveID)
|
|
||||||
|
SetCipherList(c []tlscpr.Cipher)
|
||||||
|
AddCiphers(c ...tlscpr.Cipher)
|
||||||
|
GetCiphers() []tlscpr.Cipher
|
||||||
|
|
||||||
|
SetCurveList(c []tlscrv.Curves)
|
||||||
|
AddCurves(c ...tlscrv.Curves)
|
||||||
|
GetCurves() []tlscrv.Curves
|
||||||
|
|
||||||
SetDynamicSizingDisabled(flag bool)
|
SetDynamicSizingDisabled(flag bool)
|
||||||
SetSessionTicketDisabled(flag bool)
|
SetSessionTicketDisabled(flag bool)
|
||||||
|
|
||||||
Clone() TLSConfig
|
Clone() TLSConfig
|
||||||
|
TLS(serverName string) *tls.Config
|
||||||
TlsConfig(serverName string) *tls.Config
|
TlsConfig(serverName string) *tls.Config
|
||||||
|
Config() *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var Default = New()
|
var Default = New()
|
||||||
|
|
||||||
func New() TLSConfig {
|
func New() TLSConfig {
|
||||||
return &config{
|
return &config{
|
||||||
caRoot: nil,
|
rand: nil,
|
||||||
cert: nil,
|
cert: make([]tlscrt.Cert, 0),
|
||||||
|
cipherList: make([]tlscpr.Cipher, 0),
|
||||||
tlsMinVersion: 0,
|
curveList: make([]tlscrv.Curves, 0),
|
||||||
tlsMaxVersion: 0,
|
caRoot: make([]tlscas.Cert, 0),
|
||||||
|
clientAuth: tlsaut.NoClientCert,
|
||||||
cipherList: nil,
|
clientCA: make([]tlscas.Cert, 0),
|
||||||
curveList: nil,
|
tlsMinVersion: tlsvrs.VersionUnknown,
|
||||||
|
tlsMaxVersion: tlsvrs.VersionUnknown,
|
||||||
dynSizingDisabled: false,
|
dynSizingDisabled: false,
|
||||||
ticketSessionDisabled: false,
|
ticketSessionDisabled: false,
|
||||||
|
|
||||||
clientAuth: 0,
|
|
||||||
clientCA: nil,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +110,7 @@ func AddRootCAContents(rootContent string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddRootCAFile(rootFile string) liberr.Error {
|
func AddRootCAFile(rootFile string) error {
|
||||||
return Default.AddRootCAFile(rootFile)
|
return Default.AddRootCAFile(rootFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,17 +120,17 @@ func AddCACertificateContents(caContent string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCACertificateFile(caFile string) liberr.Error {
|
func AddCACertificateFile(caFile string) error {
|
||||||
return Default.AddClientCAFile(caFile)
|
return Default.AddClientCAFile(caFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificatePairString(key, crt string) liberr.Error {
|
func AddCertificatePairString(key, crt string) error {
|
||||||
return Default.AddCertificatePairString(key, crt)
|
return Default.AddCertificatePairString(key, crt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificatePairFile(keyFile, crtFile string) liberr.Error {
|
func AddCertificatePairFile(keyFile, crtFile string) error {
|
||||||
return Default.AddCertificatePairFile(keyFile, crtFile)
|
return Default.AddCertificatePairFile(keyFile, crtFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,37 +155,47 @@ func AppendCertificates(cert []tls.Certificate) []tls.Certificate {
|
|||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func GetRootCA() *x509.CertPool {
|
func GetRootCA() *x509.CertPool {
|
||||||
return Default.GetRootCA()
|
return Default.GetRootCAPool()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func GetClientCA() *x509.CertPool {
|
func GetClientCA() *x509.CertPool {
|
||||||
return Default.GetClientCA()
|
return Default.GetClientCAPool()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetVersionMin(vers uint16) {
|
func SetVersionMin(vers uint16) {
|
||||||
Default.SetVersionMin(vers)
|
Default.SetVersionMin(tlsvrs.ParseInt(int(vers)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetVersionMax(vers uint16) {
|
func SetVersionMax(vers uint16) {
|
||||||
Default.SetVersionMax(vers)
|
Default.SetVersionMax(tlsvrs.ParseInt(int(vers)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetClientAuth(auth string) {
|
func SetClientAuth(auth string) {
|
||||||
Default.SetClientAuth(StringToClientAuth(auth))
|
Default.SetClientAuth(tlsaut.Parse(auth))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetCipherList(cipher []uint16) {
|
func SetCipherList(cipher []uint16) {
|
||||||
Default.SetCipherList(cipher)
|
Default.SetCipherList(make([]tlscpr.Cipher, 0))
|
||||||
|
|
||||||
|
for _, i := range cipher {
|
||||||
|
c := tlscpr.ParseInt(int(i))
|
||||||
|
Default.AddCiphers(c)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetCurve(curves []tls.CurveID) {
|
func SetCurve(curves []tls.CurveID) {
|
||||||
Default.SetCurveList(curves)
|
Default.SetCurveList(make([]tlscrv.Curves, 0))
|
||||||
|
|
||||||
|
for _, i := range curves {
|
||||||
|
c := tlscrv.ParseInt(int(i))
|
||||||
|
Default.AddCurves(c)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
@@ -191,11 +219,11 @@ func GetTlsConfigCertificates() *tls.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificateContents(keyContents, certContents string) liberr.Error {
|
func AddCertificateContents(keyContents, certContents string) error {
|
||||||
return Default.AddCertificatePairString(keyContents, certContents)
|
return Default.AddCertificatePairString(keyContents, certContents)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config.
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificateFile(keyFile, certFile string) liberr.Error {
|
func AddCertificateFile(keyFile, certFile string) error {
|
||||||
return Default.AddCertificatePairFile(keyFile, certFile)
|
return Default.AddCertificatePairFile(keyFile, certFile)
|
||||||
}
|
}
|
||||||
|
@@ -27,329 +27,212 @@
|
|||||||
package certificates
|
package certificates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
liberr "github.com/nabbar/golib/errors"
|
tlsaut "github.com/nabbar/golib/certificates/auth"
|
||||||
|
tlscas "github.com/nabbar/golib/certificates/ca"
|
||||||
|
tlscrt "github.com/nabbar/golib/certificates/certs"
|
||||||
|
tlscpr "github.com/nabbar/golib/certificates/cipher"
|
||||||
|
tlscrv "github.com/nabbar/golib/certificates/curves"
|
||||||
|
tlsvrs "github.com/nabbar/golib/certificates/tlsversion"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
cert []tls.Certificate
|
rand io.Reader
|
||||||
cipherList []uint16
|
cert []tlscrt.Cert
|
||||||
curveList []tls.CurveID
|
cipherList []tlscpr.Cipher
|
||||||
caRoot *x509.CertPool
|
curveList []tlscrv.Curves
|
||||||
clientAuth tls.ClientAuthType
|
caRoot []tlscas.Cert
|
||||||
clientCA *x509.CertPool
|
clientAuth tlsaut.ClientAuth
|
||||||
tlsMinVersion uint16
|
clientCA []tlscas.Cert
|
||||||
tlsMaxVersion uint16
|
tlsMinVersion tlsvrs.Version
|
||||||
|
tlsMaxVersion tlsvrs.Version
|
||||||
dynSizingDisabled bool
|
dynSizingDisabled bool
|
||||||
ticketSessionDisabled bool
|
ticketSessionDisabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) checkFile(pemFiles ...string) liberr.Error {
|
func (o *config) RegisterRand(rand io.Reader) {
|
||||||
for _, f := range pemFiles {
|
o.rand = rand
|
||||||
if f == "" {
|
}
|
||||||
return ErrorParamEmpty.Error(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, e := os.Stat(f); e != nil {
|
func (o *config) SetVersionMin(v tlsvrs.Version) {
|
||||||
return ErrorFileStat.Error(e)
|
o.tlsMinVersion = v
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #nosec */
|
func (o *config) GetVersionMin() tlsvrs.Version {
|
||||||
b, e := ioutil.ReadFile(f)
|
return o.tlsMinVersion
|
||||||
if e != nil {
|
}
|
||||||
return ErrorFileRead.Error(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = bytes.Trim(b, "\n")
|
func (o *config) SetVersionMax(v tlsvrs.Version) {
|
||||||
b = bytes.Trim(b, "\r")
|
o.tlsMaxVersion = v
|
||||||
b = bytes.TrimSpace(b)
|
}
|
||||||
|
|
||||||
if len(b) < 1 {
|
func (o *config) GetVersionMax() tlsvrs.Version {
|
||||||
return ErrorFileEmpty.Error(nil)
|
return o.tlsMaxVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) SetDynamicSizingDisabled(flag bool) {
|
||||||
|
o.dynSizingDisabled = flag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) SetSessionTicketDisabled(flag bool) {
|
||||||
|
o.ticketSessionDisabled = flag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) Clone() TLSConfig {
|
||||||
|
cfg := &config{
|
||||||
|
rand: o.rand,
|
||||||
|
cert: make([]tlscrt.Cert, 0),
|
||||||
|
cipherList: make([]tlscpr.Cipher, 0),
|
||||||
|
curveList: make([]tlscrv.Curves, 0),
|
||||||
|
caRoot: make([]tlscas.Cert, 0),
|
||||||
|
clientAuth: o.clientAuth,
|
||||||
|
clientCA: make([]tlscas.Cert, 0),
|
||||||
|
tlsMinVersion: o.tlsMinVersion,
|
||||||
|
tlsMaxVersion: o.tlsMaxVersion,
|
||||||
|
dynSizingDisabled: o.dynSizingDisabled,
|
||||||
|
ticketSessionDisabled: o.ticketSessionDisabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(o.cert) > 0 {
|
||||||
|
for _, c := range o.cert {
|
||||||
|
cfg.cert = append(cfg.cert, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if len(o.cipherList) > 0 {
|
||||||
|
for _, c := range o.cipherList {
|
||||||
|
if tlscpr.Check(c.Uint16()) {
|
||||||
|
cfg.cipherList = append(cfg.cipherList, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(o.curveList) > 0 {
|
||||||
|
for _, c := range o.curveList {
|
||||||
|
if tlscpr.Check(c.Uint16()) {
|
||||||
|
cfg.curveList = append(cfg.curveList, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(o.caRoot) > 0 {
|
||||||
|
for _, c := range o.caRoot {
|
||||||
|
cfg.caRoot = append(cfg.caRoot, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(o.clientCA) > 0 {
|
||||||
|
for _, c := range o.clientCA {
|
||||||
|
cfg.clientCA = append(cfg.clientCA, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) AddRootCAString(rootCA string) bool {
|
func (o *config) TlsConfig(serverName string) *tls.Config {
|
||||||
if c.caRoot == nil {
|
return o.TLS(serverName)
|
||||||
c.caRoot = SystemRootCA()
|
|
||||||
}
|
|
||||||
|
|
||||||
if rootCA != "" {
|
|
||||||
return c.caRoot.AppendCertsFromPEM([]byte(rootCA))
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) AddRootCAFile(pemFile string) liberr.Error {
|
func (o *config) TLS(serverName string) *tls.Config {
|
||||||
if e := c.checkFile(pemFile); e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.caRoot == nil {
|
|
||||||
c.caRoot = SystemRootCA()
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint #nosec
|
|
||||||
/* #nosec */
|
|
||||||
b, _ := ioutil.ReadFile(pemFile)
|
|
||||||
|
|
||||||
if c.caRoot.AppendCertsFromPEM(b) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrorCertAppend.Error(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) AddClientCAString(ca string) bool {
|
|
||||||
if c.clientCA == nil {
|
|
||||||
c.clientCA = x509.NewCertPool()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ca != "" {
|
|
||||||
return c.clientCA.AppendCertsFromPEM([]byte(ca))
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) AddClientCAFile(pemFile string) liberr.Error {
|
|
||||||
if e := c.checkFile(pemFile); e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.clientCA == nil {
|
|
||||||
c.clientCA = x509.NewCertPool()
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint #nosec
|
|
||||||
/* #nosec */
|
|
||||||
b, _ := ioutil.ReadFile(pemFile)
|
|
||||||
|
|
||||||
if c.clientCA.AppendCertsFromPEM(b) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrorCertAppend.Error(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) AddCertificatePairString(key, crt string) liberr.Error {
|
|
||||||
if len(c.cert) == 0 {
|
|
||||||
c.cert = make([]tls.Certificate, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
key = strings.Trim(key, "\n")
|
|
||||||
crt = strings.Trim(crt, "\n")
|
|
||||||
|
|
||||||
key = strings.Trim(key, "\r")
|
|
||||||
crt = strings.Trim(crt, "\r")
|
|
||||||
|
|
||||||
key = strings.TrimSpace(key)
|
|
||||||
crt = strings.TrimSpace(crt)
|
|
||||||
|
|
||||||
if len(key) < 1 || len(crt) < 1 {
|
|
||||||
return ErrorParamEmpty.Error(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := tls.X509KeyPair([]byte(crt), []byte(key))
|
|
||||||
if err != nil {
|
|
||||||
return ErrorCertKeyPairParse.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.cert = append(c.cert, p)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) AddCertificatePairFile(keyFile, crtFile string) liberr.Error {
|
|
||||||
if e := c.checkFile(keyFile, crtFile); e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.cert) == 0 {
|
|
||||||
c.cert = make([]tls.Certificate, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p, e := tls.LoadX509KeyPair(crtFile, keyFile); e != nil {
|
|
||||||
return ErrorCertKeyPairLoad.Error(e)
|
|
||||||
} else {
|
|
||||||
c.cert = append(c.cert, p)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) TlsConfig(serverName string) *tls.Config {
|
|
||||||
/* #nosec */
|
/* #nosec */
|
||||||
cnf := &tls.Config{
|
cnf := &tls.Config{
|
||||||
InsecureSkipVerify: false,
|
Rand: nil,
|
||||||
|
Certificates: make([]tls.Certificate, 0),
|
||||||
|
RootCAs: SystemRootCA(),
|
||||||
|
ServerName: "",
|
||||||
|
ClientAuth: tls.NoClientCert,
|
||||||
|
ClientCAs: x509.NewCertPool(),
|
||||||
|
InsecureSkipVerify: false,
|
||||||
|
CipherSuites: make([]uint16, 0),
|
||||||
|
SessionTicketsDisabled: false,
|
||||||
|
MinVersion: 0,
|
||||||
|
MaxVersion: 0,
|
||||||
|
CurvePreferences: make([]tls.CurveID, 0),
|
||||||
|
DynamicRecordSizingDisabled: false,
|
||||||
|
Renegotiation: tls.RenegotiateNever,
|
||||||
}
|
}
|
||||||
|
|
||||||
if serverName != "" {
|
if serverName != "" {
|
||||||
cnf.ServerName = serverName
|
cnf.ServerName = serverName
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.ticketSessionDisabled {
|
if o.ticketSessionDisabled {
|
||||||
cnf.SessionTicketsDisabled = true
|
cnf.SessionTicketsDisabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.dynSizingDisabled {
|
if o.dynSizingDisabled {
|
||||||
cnf.DynamicRecordSizingDisabled = true
|
cnf.DynamicRecordSizingDisabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.tlsMinVersion != 0 {
|
if o.tlsMinVersion != tlsvrs.VersionUnknown {
|
||||||
cnf.MinVersion = c.tlsMinVersion
|
cnf.MinVersion = o.tlsMinVersion.TLS()
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.tlsMaxVersion != 0 {
|
if o.tlsMaxVersion != tlsvrs.VersionUnknown {
|
||||||
cnf.MaxVersion = c.tlsMaxVersion
|
cnf.MaxVersion = o.tlsMaxVersion.TLS()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.cipherList) > 0 {
|
if len(o.cipherList) > 0 {
|
||||||
cnf.PreferServerCipherSuites = true
|
for _, c := range o.cipherList {
|
||||||
cnf.CipherSuites = c.cipherList
|
if c != tlscpr.Unknown {
|
||||||
|
cnf.CipherSuites = append(cnf.CipherSuites, c.TLS())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.curveList) > 0 {
|
if len(o.curveList) > 0 {
|
||||||
cnf.CurvePreferences = c.curveList
|
for _, c := range o.curveList {
|
||||||
|
if c != tlscrv.Unknown {
|
||||||
|
cnf.CurvePreferences = append(cnf.CurvePreferences, c.TLS())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.caRoot != nil {
|
if o.caRoot != nil {
|
||||||
cnf.RootCAs = c.caRoot
|
for _, c := range o.caRoot {
|
||||||
|
c.AppendPool(cnf.RootCAs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.cert) > 0 {
|
if len(o.cert) > 0 {
|
||||||
cnf.Certificates = c.cert
|
for _, c := range o.cert {
|
||||||
|
cnf.Certificates = append(cnf.Certificates, c.TLS())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.clientAuth != tls.NoClientCert {
|
if o.clientAuth != tlsaut.NoClientCert {
|
||||||
cnf.ClientAuth = c.clientAuth
|
cnf.ClientAuth = o.clientAuth.TLS()
|
||||||
if c.clientCA != nil {
|
if len(o.clientCA) > 0 {
|
||||||
cnf.ClientCAs = c.clientCA
|
for _, c := range o.clientCA {
|
||||||
|
c.AppendPool(cnf.ClientCAs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnf
|
return cnf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) cloneCipherList() []uint16 {
|
func (o *config) Config() *Config {
|
||||||
if c.cipherList == nil {
|
var crt = make([]tlscrt.Certif, 0)
|
||||||
return nil
|
for _, c := range o.cert {
|
||||||
|
crt = append(crt, c.Model())
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(make([]uint16, 0), c.cipherList...)
|
return &Config{
|
||||||
}
|
CurveList: o.curveList,
|
||||||
|
CipherList: o.cipherList,
|
||||||
func (c *config) cloneCurveList() []tls.CurveID {
|
RootCA: o.caRoot,
|
||||||
if c.curveList == nil {
|
ClientCA: o.clientCA,
|
||||||
return nil
|
Certs: crt,
|
||||||
}
|
VersionMin: o.tlsMinVersion,
|
||||||
|
VersionMax: o.tlsMaxVersion,
|
||||||
return append(make([]tls.CurveID, 0), c.curveList...)
|
AuthClient: o.clientAuth,
|
||||||
}
|
InheritDefault: false,
|
||||||
|
DynamicSizingDisable: o.dynSizingDisabled,
|
||||||
func (c *config) cloneCertificates() []tls.Certificate {
|
SessionTicketDisable: o.ticketSessionDisabled,
|
||||||
if c.cert == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(make([]tls.Certificate, 0), c.cert...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) cloneRootCA() *x509.CertPool {
|
|
||||||
if c.caRoot == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
list := *c.caRoot
|
|
||||||
|
|
||||||
return &list
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) cloneClientCA() *x509.CertPool {
|
|
||||||
if c.clientCA == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
list := *c.clientCA
|
|
||||||
|
|
||||||
return &list
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) Clone() TLSConfig {
|
|
||||||
return &config{
|
|
||||||
caRoot: c.cloneRootCA(),
|
|
||||||
cert: c.cloneCertificates(),
|
|
||||||
tlsMinVersion: c.tlsMinVersion,
|
|
||||||
tlsMaxVersion: c.tlsMaxVersion,
|
|
||||||
cipherList: c.cloneCipherList(),
|
|
||||||
curveList: c.cloneCurveList(),
|
|
||||||
dynSizingDisabled: c.dynSizingDisabled,
|
|
||||||
ticketSessionDisabled: c.ticketSessionDisabled,
|
|
||||||
clientAuth: c.clientAuth,
|
|
||||||
clientCA: c.cloneClientCA(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func asStruct(cfg TLSConfig) *config {
|
|
||||||
if c, ok := cfg.(*config); ok {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) GetRootCA() *x509.CertPool {
|
|
||||||
return c.caRoot
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) GetClientCA() *x509.CertPool {
|
|
||||||
return c.clientCA
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) LenCertificatePair() int {
|
|
||||||
return len(c.cert)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) CleanCertificatePair() {
|
|
||||||
c.cert = make([]tls.Certificate, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) GetCertificatePair() []tls.Certificate {
|
|
||||||
return c.cert
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) SetVersionMin(vers uint16) {
|
|
||||||
c.tlsMinVersion = vers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) SetVersionMax(vers uint16) {
|
|
||||||
c.tlsMaxVersion = vers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) SetClientAuth(cAuth tls.ClientAuthType) {
|
|
||||||
c.clientAuth = cAuth
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) SetCipherList(cipher []uint16) {
|
|
||||||
c.cipherList = cipher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) SetCurveList(curves []tls.CurveID) {
|
|
||||||
c.curveList = curves
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) SetDynamicSizingDisabled(flag bool) {
|
|
||||||
c.dynSizingDisabled = flag
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) SetSessionTicketDisabled(flag bool) {
|
|
||||||
c.ticketSessionDisabled = flag
|
|
||||||
}
|
|
||||||
|
79
certificates/rootca.go
Normal file
79
certificates/rootca.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
|
||||||
|
tlscas "github.com/nabbar/golib/certificates/ca"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o *config) GetRootCA() []tlscas.Cert {
|
||||||
|
var res = make([]tlscas.Cert, 0)
|
||||||
|
|
||||||
|
for _, c := range o.caRoot {
|
||||||
|
res = append(res, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) GetRootCAPool() *x509.CertPool {
|
||||||
|
var res = x509.NewCertPool()
|
||||||
|
for _, ca := range o.caRoot {
|
||||||
|
ca.AppendPool(res)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddRootCAString(rootCA string) bool {
|
||||||
|
if rootCA != "" {
|
||||||
|
if c, e := tlscas.Parse(rootCA); e == nil {
|
||||||
|
o.caRoot = append(o.caRoot, c)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *config) AddRootCAFile(pemFile string) error {
|
||||||
|
var fct = func(p []byte) error {
|
||||||
|
if c, e := tlscas.ParseByte(p); e != nil {
|
||||||
|
return e
|
||||||
|
} else {
|
||||||
|
o.caRoot = append(o.caRoot, c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if e := checkFile(fct, pemFile); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@@ -1,29 +1,28 @@
|
|||||||
/***********************************************************************************************************************
|
/*
|
||||||
|
* MIT License
|
||||||
*
|
*
|
||||||
* MIT License
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022 Nicolas JUHEL
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* copies or substantial portions of the Software.
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* copies or substantial portions of the Software.
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
*
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* SOFTWARE.
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
**********************************************************************************************************************/
|
*/
|
||||||
|
|
||||||
package tlsversion
|
package tlsversion
|
||||||
|
|
||||||
|
@@ -1,29 +1,28 @@
|
|||||||
/***********************************************************************************************************************
|
/*
|
||||||
|
* MIT License
|
||||||
*
|
*
|
||||||
* MIT License
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022 Nicolas JUHEL
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* copies or substantial portions of the Software.
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* copies or substantial portions of the Software.
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
*
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* SOFTWARE.
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
**********************************************************************************************************************/
|
*/
|
||||||
|
|
||||||
package tlsversion
|
package tlsversion
|
||||||
|
|
||||||
@@ -53,6 +52,10 @@ func (v Version) Code() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Version) TLS() uint16 {
|
||||||
|
return v.Uint16()
|
||||||
|
}
|
||||||
|
|
||||||
func (v Version) Uint16() uint16 {
|
func (v Version) Uint16() uint16 {
|
||||||
switch v {
|
switch v {
|
||||||
case VersionTLS10:
|
case VersionTLS10:
|
||||||
|
@@ -1,29 +1,28 @@
|
|||||||
/***********************************************************************************************************************
|
/*
|
||||||
|
* MIT License
|
||||||
*
|
*
|
||||||
* MIT License
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022 Nicolas JUHEL
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* copies or substantial portions of the Software.
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* copies or substantial portions of the Software.
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
*
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* SOFTWARE.
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
**********************************************************************************************************************/
|
*/
|
||||||
|
|
||||||
package tlsversion
|
package tlsversion
|
||||||
|
|
||||||
@@ -60,6 +59,8 @@ func ListHigh() []Version {
|
|||||||
|
|
||||||
func Parse(s string) Version {
|
func Parse(s string) Version {
|
||||||
s = strings.ToLower(s)
|
s = strings.ToLower(s)
|
||||||
|
s = strings.Replace(s, "\"", "", -1)
|
||||||
|
s = strings.Replace(s, "'", "", -1)
|
||||||
s = strings.Replace(s, "tls", "", -1)
|
s = strings.Replace(s, "tls", "", -1)
|
||||||
s = strings.Replace(s, "ssl", "", -1)
|
s = strings.Replace(s, "ssl", "", -1)
|
||||||
s = strings.Replace(s, ".", "", -1)
|
s = strings.Replace(s, ".", "", -1)
|
||||||
|
@@ -1,29 +1,28 @@
|
|||||||
/***********************************************************************************************************************
|
/*
|
||||||
|
* MIT License
|
||||||
*
|
*
|
||||||
* MIT License
|
* Copyright (c) 2020 Nicolas JUHEL
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022 Nicolas JUHEL
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* copies or substantial portions of the Software.
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* copies or substantial portions of the Software.
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
*
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* SOFTWARE.
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
**********************************************************************************************************************/
|
*/
|
||||||
|
|
||||||
package tlsversion
|
package tlsversion
|
||||||
|
|
||||||
|
@@ -27,22 +27,12 @@
|
|||||||
package certificates
|
package certificates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"bytes"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deprecated: use StringToCipherKey.
|
|
||||||
func GetCipherKey(cipher string) uint16 {
|
|
||||||
return StringToCipherKey(cipher)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: use StringToCurveID.
|
|
||||||
func GetCurveID(curveRef string) tls.CurveID {
|
|
||||||
return StringToCurveID(curveRef)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SystemRootCA() *x509.CertPool {
|
func SystemRootCA() *x509.CertPool {
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
return x509.NewCertPool()
|
return x509.NewCertPool()
|
||||||
@@ -53,105 +43,36 @@ func SystemRootCA() *x509.CertPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func StringToTlsVersion(tlsVersStr string) uint16 {
|
func checkFile(fct func(p []byte) error, pemFiles ...string) error {
|
||||||
tlsVersStr = strings.ToLower(tlsVersStr)
|
for _, f := range pemFiles {
|
||||||
tlsVersStr = strings.Replace(tlsVersStr, "TLS", "", -1)
|
if f == "" {
|
||||||
tlsVersStr = strings.TrimSpace(tlsVersStr)
|
return ErrorParamEmpty.Error(nil)
|
||||||
|
}
|
||||||
|
|
||||||
switch tlsVersStr {
|
if _, e := os.Stat(f); e != nil {
|
||||||
case "1", "1.0":
|
return e
|
||||||
return tls.VersionTLS10
|
}
|
||||||
case "1.1":
|
|
||||||
return tls.VersionTLS11
|
|
||||||
case "1.2":
|
|
||||||
return tls.VersionTLS12
|
|
||||||
case "1.3":
|
|
||||||
return tls.VersionTLS13
|
|
||||||
default:
|
|
||||||
return tls.VersionTLS12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func StringToClientAuth(auth string) tls.ClientAuthType {
|
/* #nosec */
|
||||||
switch strings.ToLower(auth) {
|
b, e := os.ReadFile(f)
|
||||||
case "request":
|
if e != nil {
|
||||||
return tls.RequestClientCert
|
return e
|
||||||
case "require":
|
}
|
||||||
return tls.RequireAnyClientCert
|
|
||||||
case "verify":
|
|
||||||
return tls.VerifyClientCertIfGiven
|
|
||||||
case "strict":
|
|
||||||
return tls.RequireAndVerifyClientCert
|
|
||||||
default:
|
|
||||||
return tls.NoClientCert
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func StringToCipherKey(cipher string) uint16 {
|
b = bytes.Trim(b, "\n")
|
||||||
cipher = strings.ToLower(cipher)
|
b = bytes.Trim(b, "\r")
|
||||||
cipher = strings.ReplaceAll(cipher, " ", "")
|
b = bytes.TrimSpace(b)
|
||||||
cipher = strings.ReplaceAll(cipher, "_", "")
|
|
||||||
cipher = strings.ReplaceAll(cipher, "-", "")
|
|
||||||
|
|
||||||
rsa := strings.Contains(cipher, "rsa")
|
if len(b) < 1 {
|
||||||
dhe := strings.Contains(cipher, "ecdhe")
|
return ErrorFileEmpty.Error(nil)
|
||||||
dsa := strings.Contains(cipher, "ecdsa")
|
} else if fct == nil {
|
||||||
gcm := strings.Contains(cipher, "gcm")
|
continue
|
||||||
aes1 := strings.Contains(cipher, "aes128")
|
}
|
||||||
aes2 := strings.Contains(cipher, "aes256")
|
|
||||||
cha := strings.Contains(cipher, "chacha20")
|
|
||||||
poly := strings.Contains(cipher, "poly1305")
|
|
||||||
|
|
||||||
switch {
|
|
||||||
// TLS v1.0 - v1.2
|
|
||||||
case !dhe && rsa && aes1 && !gcm:
|
|
||||||
return tls.TLS_RSA_WITH_AES_128_CBC_SHA256
|
|
||||||
case !dhe && rsa && aes1 && gcm:
|
|
||||||
return tls.TLS_RSA_WITH_AES_128_GCM_SHA256
|
|
||||||
case !dhe && rsa && aes2 && gcm:
|
|
||||||
return tls.TLS_RSA_WITH_AES_256_GCM_SHA384
|
|
||||||
case dhe && dsa && aes1 && !gcm:
|
|
||||||
return tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
|
|
||||||
case dhe && rsa && aes1 && !gcm:
|
|
||||||
return tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
|
|
||||||
case dhe && rsa && aes1 && gcm:
|
|
||||||
return tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
|
||||||
case dhe && dsa && aes1 && gcm:
|
|
||||||
return tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
|
||||||
case dhe && rsa && aes2 && gcm:
|
|
||||||
return tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
|
||||||
case dhe && dsa && aes2 && gcm:
|
|
||||||
return tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
|
|
||||||
case rsa && (cha || poly):
|
|
||||||
return tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
|
||||||
case dsa && (cha || poly):
|
|
||||||
return tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
|
||||||
|
|
||||||
// TLS v1.3
|
|
||||||
case aes1 && gcm:
|
|
||||||
return tls.TLS_AES_128_GCM_SHA256
|
|
||||||
case aes2 && gcm:
|
|
||||||
return tls.TLS_AES_256_GCM_SHA384
|
|
||||||
case cha || poly:
|
|
||||||
return tls.TLS_CHACHA20_POLY1305_SHA256
|
|
||||||
|
|
||||||
|
if e = fct(b); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return nil
|
||||||
}
|
|
||||||
|
|
||||||
func StringToCurveID(curveRef string) tls.CurveID {
|
|
||||||
curveRef = strings.ToLower(curveRef)
|
|
||||||
|
|
||||||
if strings.Contains(curveRef, "p2") {
|
|
||||||
return tls.CurveP256
|
|
||||||
} else if strings.Contains(curveRef, "p3") {
|
|
||||||
return tls.CurveP384
|
|
||||||
} else if strings.Contains(curveRef, "p5") {
|
|
||||||
return tls.CurveP521
|
|
||||||
} else if strings.Contains(curveRef, "x25") {
|
|
||||||
return tls.X25519
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
@@ -146,7 +146,7 @@ func (o *componentSmtp) _GetTLS() libtls.TLSConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *componentSmtp) _GetTLSConfig(cfg libtls.Config) *tls.Config {
|
func (o *componentSmtp) _GetTLSConfig(cfg libtls.Config) *tls.Config {
|
||||||
if i, e := cfg.NewFrom(o._GetTLS()); e != nil {
|
if i := cfg.NewFrom(o._GetTLS()); i == nil {
|
||||||
// #nosec
|
// #nosec
|
||||||
return &tls.Config{}
|
return &tls.Config{}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
package tls
|
package tls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
libtls "github.com/nabbar/golib/certificates"
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
cfgtps "github.com/nabbar/golib/config/types"
|
cfgtps "github.com/nabbar/golib/config/types"
|
||||||
libver "github.com/nabbar/golib/version"
|
libver "github.com/nabbar/golib/version"
|
||||||
@@ -159,8 +161,8 @@ func (o *componentTls) _runCli() error {
|
|||||||
|
|
||||||
if cfg, err = o._getConfig(); err != nil {
|
if cfg, err = o._getConfig(); err != nil {
|
||||||
return prt.Error(err)
|
return prt.Error(err)
|
||||||
} else if tls, err = cfg.New(); err != nil {
|
} else if tls = cfg.New(); tls == nil {
|
||||||
return prt.Error(err)
|
return prt.Error(fmt.Errorf("cannot use tls config for new instance"))
|
||||||
} else if o.f != nil {
|
} else if o.f != nil {
|
||||||
for _, s := range o.f() {
|
for _, s := range o.f() {
|
||||||
tls.AddRootCAString(s)
|
tls.AddRootCAString(s)
|
||||||
|
@@ -34,7 +34,6 @@ import (
|
|||||||
libval "github.com/go-playground/validator/v10"
|
libval "github.com/go-playground/validator/v10"
|
||||||
libftp "github.com/jlaffaye/ftp"
|
libftp "github.com/jlaffaye/ftp"
|
||||||
libtls "github.com/nabbar/golib/certificates"
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigTimeZone struct {
|
type ConfigTimeZone struct {
|
||||||
@@ -81,7 +80,7 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate allow checking if the config' struct is valid with the awaiting model
|
// Validate allow checking if the config' struct is valid with the awaiting model
|
||||||
func (c *Config) Validate() liberr.Error {
|
func (c *Config) Validate() error {
|
||||||
var e = ErrorValidatorError.Error(nil)
|
var e = ErrorValidatorError.Error(nil)
|
||||||
|
|
||||||
if err := libval.New().Struct(c); err != nil {
|
if err := libval.New().Struct(c); err != nil {
|
||||||
@@ -110,11 +109,11 @@ func (c *Config) RegisterDefaultTLS(fct func() libtls.TLSConfig) {
|
|||||||
c.ftls = fct
|
c.ftls = fct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) New() (*libftp.ServerConn, liberr.Error) {
|
func (c *Config) New() (*libftp.ServerConn, error) {
|
||||||
var opt = make([]libftp.DialOption, 0)
|
var opt = make([]libftp.DialOption, 0)
|
||||||
|
|
||||||
if tls, err := c.TLS.NewFrom(c.ftls()); err != nil {
|
if tls := c.TLS.NewFrom(c.ftls()); tls == nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("no tls configured")
|
||||||
} else if c.ForceTLS {
|
} else if c.ForceTLS {
|
||||||
opt = append(opt, libftp.DialWithExplicitTLS(tls.TlsConfig("")))
|
opt = append(opt, libftp.DialWithExplicitTLS(tls.TlsConfig("")))
|
||||||
} else {
|
} else {
|
||||||
|
@@ -33,46 +33,45 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
libftp "github.com/jlaffaye/ftp"
|
libftp "github.com/jlaffaye/ftp"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type FTPClient interface {
|
type FTPClient interface {
|
||||||
// Connect establish the connection to server with the given configuration registered.
|
// Connect establish the connection to server with the given configuration registered.
|
||||||
Connect() liberr.Error
|
Connect() error
|
||||||
|
|
||||||
// Check try to retrieve a valid connection to the server and send an NOOP command to check the connection.
|
// Check try to retrieve a valid connection to the server and send an NOOP command to check the connection.
|
||||||
Check() liberr.Error
|
Check() error
|
||||||
|
|
||||||
// Close send the QUID command to the server if the connection is valid (cf Check).
|
// Close send the QUID command to the server if the connection is valid (cf Check).
|
||||||
Close()
|
Close()
|
||||||
|
|
||||||
// NameList issues an NLST FTP command.
|
// NameList issues an NLST FTP command.
|
||||||
NameList(path string) ([]string, liberr.Error)
|
NameList(path string) ([]string, error)
|
||||||
|
|
||||||
// List issues a LIST FTP command.
|
// List issues a LIST FTP command.
|
||||||
List(path string) ([]*libftp.Entry, liberr.Error)
|
List(path string) ([]*libftp.Entry, error)
|
||||||
|
|
||||||
// ChangeDir issues a CWD FTP command, which changes the current directory to the specified path.
|
// ChangeDir issues a CWD FTP command, which changes the current directory to the specified path.
|
||||||
ChangeDir(path string) liberr.Error
|
ChangeDir(path string) error
|
||||||
|
|
||||||
// CurrentDir issues a PWD FTP command, which Returns the path of the current directory.
|
// CurrentDir issues a PWD FTP command, which Returns the path of the current directory.
|
||||||
CurrentDir() (string, liberr.Error)
|
CurrentDir() (string, error)
|
||||||
|
|
||||||
// FileSize issues a SIZE FTP command, which Returns the size of the file.
|
// FileSize issues a SIZE FTP command, which Returns the size of the file.
|
||||||
FileSize(path string) (int64, liberr.Error)
|
FileSize(path string) (int64, error)
|
||||||
|
|
||||||
// GetTime issues the MDTM FTP command to obtain the file modification time.
|
// GetTime issues the MDTM FTP command to obtain the file modification time.
|
||||||
// It returns a UTC time.
|
// It returns a UTC time.
|
||||||
GetTime(path string) (time.Time, liberr.Error)
|
GetTime(path string) (time.Time, error)
|
||||||
|
|
||||||
// SetTime issues the MFMT FTP command to set the file modification time.
|
// SetTime issues the MFMT FTP command to set the file modification time.
|
||||||
// Also it can use a non-standard form of the MDTM command supported by the VsFtpd server instead of MFMT for the same purpose.
|
// Also it can use a non-standard form of the MDTM command supported by the VsFtpd server instead of MFMT for the same purpose.
|
||||||
// See "mdtm_write" in https://security.appspot.com/vsftpd/vsftpd_conf.html
|
// See "mdtm_write" in https://security.appspot.com/vsftpd/vsftpd_conf.html
|
||||||
SetTime(path string, t time.Time) liberr.Error
|
SetTime(path string, t time.Time) error
|
||||||
|
|
||||||
// Retr issues a RETR FTP command to fetch the specified file from the remote FTP server.
|
// Retr issues a RETR FTP command to fetch the specified file from the remote FTP server.
|
||||||
// The returned ReadCloser must be closed to cleanup the FTP data connection.
|
// The returned ReadCloser must be closed to cleanup the FTP data connection.
|
||||||
Retr(path string) (*libftp.Response, liberr.Error)
|
Retr(path string) (*libftp.Response, error)
|
||||||
|
|
||||||
// RetrFrom issues a RETR FTP command to fetch the specified file from the remote FTP server,
|
// RetrFrom issues a RETR FTP command to fetch the specified file from the remote FTP server,
|
||||||
// the server will not send the offset first bytes of the file.
|
// the server will not send the offset first bytes of the file.
|
||||||
@@ -82,38 +81,38 @@ type FTPClient interface {
|
|||||||
// Stor issues a STOR FTP command to store a file to the remote FTP server.
|
// Stor issues a STOR FTP command to store a file to the remote FTP server.
|
||||||
// Stor creates the specified file with the content of the io.Reader.
|
// Stor creates the specified file with the content of the io.Reader.
|
||||||
// Hint: io.Pipe() can be used if an io.Writer is required.
|
// Hint: io.Pipe() can be used if an io.Writer is required.
|
||||||
Stor(path string, r io.Reader) liberr.Error
|
Stor(path string, r io.Reader) error
|
||||||
|
|
||||||
// StorFrom issues a STOR FTP command to store a file to the remote FTP server.
|
// StorFrom issues a STOR FTP command to store a file to the remote FTP server.
|
||||||
// Stor creates the specified file with the content of the io.Reader, writing on the server will start at the given file offset.
|
// Stor creates the specified file with the content of the io.Reader, writing on the server will start at the given file offset.
|
||||||
// Hint: io.Pipe() can be used if an io.Writer is required.
|
// Hint: io.Pipe() can be used if an io.Writer is required.
|
||||||
StorFrom(path string, r io.Reader, offset uint64) liberr.Error
|
StorFrom(path string, r io.Reader, offset uint64) error
|
||||||
|
|
||||||
// Append issues a APPE FTP command to store a file to the remote FTP server.
|
// Append issues a APPE FTP command to store a file to the remote FTP server.
|
||||||
// If a file already exists with the given path, then the content of the io.Reader is appended.
|
// If a file already exists with the given path, then the content of the io.Reader is appended.
|
||||||
// Otherwise, a new file is created with that content. Hint: io.Pipe() can be used if an io.Writer is required.
|
// Otherwise, a new file is created with that content. Hint: io.Pipe() can be used if an io.Writer is required.
|
||||||
Append(path string, r io.Reader) liberr.Error
|
Append(path string, r io.Reader) error
|
||||||
|
|
||||||
// Rename renames a file on the remote FTP server.
|
// Rename renames a file on the remote FTP server.
|
||||||
Rename(from, to string) liberr.Error
|
Rename(from, to string) error
|
||||||
|
|
||||||
// Delete issues a DELE FTP command to delete the specified file from the remote FTP server.
|
// Delete issues a DELE FTP command to delete the specified file from the remote FTP server.
|
||||||
Delete(path string) liberr.Error
|
Delete(path string) error
|
||||||
|
|
||||||
// RemoveDirRecur deletes a non-empty folder recursively using RemoveDir and Delete.
|
// RemoveDirRecur deletes a non-empty folder recursively using RemoveDir and Delete.
|
||||||
RemoveDirRecur(path string) liberr.Error
|
RemoveDirRecur(path string) error
|
||||||
|
|
||||||
// MakeDir issues a MKD FTP command to create the specified directory on the remote FTP server.
|
// MakeDir issues a MKD FTP command to create the specified directory on the remote FTP server.
|
||||||
MakeDir(path string) liberr.Error
|
MakeDir(path string) error
|
||||||
|
|
||||||
// RemoveDir issues a RMD FTP command to remove the specified directory from the remote FTP server.
|
// RemoveDir issues a RMD FTP command to remove the specified directory from the remote FTP server.
|
||||||
RemoveDir(path string) liberr.Error
|
RemoveDir(path string) error
|
||||||
|
|
||||||
//Walk prepares the internal walk function so that the caller can begin traversing the directory.
|
//Walk prepares the internal walk function so that the caller can begin traversing the directory.
|
||||||
Walk(root string) (*libftp.Walker, liberr.Error)
|
Walk(root string) (*libftp.Walker, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *Config) (FTPClient, liberr.Error) {
|
func New(cfg *Config) (FTPClient, error) {
|
||||||
c := &ftpClient{
|
c := &ftpClient{
|
||||||
m: sync.Mutex{},
|
m: sync.Mutex{},
|
||||||
cfg: new(atomic.Value),
|
cfg: new(atomic.Value),
|
||||||
|
@@ -34,7 +34,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
libftp "github.com/jlaffaye/ftp"
|
libftp "github.com/jlaffaye/ftp"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ftpClient struct {
|
type ftpClient struct {
|
||||||
@@ -96,10 +95,9 @@ func (f *ftpClient) setClient(cli *libftp.ServerConn) {
|
|||||||
f.cli.Store(cli)
|
f.cli.Store(cli)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Connect() liberr.Error {
|
func (f *ftpClient) Connect() error {
|
||||||
var (
|
var (
|
||||||
e error
|
e error
|
||||||
err liberr.Error
|
|
||||||
cfg *Config
|
cfg *Config
|
||||||
cli *libftp.ServerConn
|
cli *libftp.ServerConn
|
||||||
)
|
)
|
||||||
@@ -116,8 +114,8 @@ func (f *ftpClient) Connect() liberr.Error {
|
|||||||
return ErrorNotInitialized.Error(nil)
|
return ErrorNotInitialized.Error(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cli, err = cfg.New(); err != nil {
|
if cli, e = cfg.New(); e != nil {
|
||||||
return err
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
if e = cli.NoOp(); e != nil {
|
if e = cli.NoOp(); e != nil {
|
||||||
@@ -128,7 +126,7 @@ func (f *ftpClient) Connect() liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Check() liberr.Error {
|
func (f *ftpClient) Check() error {
|
||||||
var cli *libftp.ServerConn
|
var cli *libftp.ServerConn
|
||||||
|
|
||||||
if cli = f.getClient(); cli == nil {
|
if cli = f.getClient(); cli == nil {
|
||||||
@@ -153,7 +151,7 @@ func (f *ftpClient) Close() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) NameList(path string) ([]string, liberr.Error) {
|
func (f *ftpClient) NameList(path string) ([]string, error) {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -165,7 +163,7 @@ func (f *ftpClient) NameList(path string) ([]string, liberr.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) List(path string) ([]*libftp.Entry, liberr.Error) {
|
func (f *ftpClient) List(path string) ([]*libftp.Entry, error) {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -177,7 +175,7 @@ func (f *ftpClient) List(path string) ([]*libftp.Entry, liberr.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) ChangeDir(path string) liberr.Error {
|
func (f *ftpClient) ChangeDir(path string) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -189,7 +187,7 @@ func (f *ftpClient) ChangeDir(path string) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) CurrentDir() (string, liberr.Error) {
|
func (f *ftpClient) CurrentDir() (string, error) {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -201,7 +199,7 @@ func (f *ftpClient) CurrentDir() (string, liberr.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) FileSize(path string) (int64, liberr.Error) {
|
func (f *ftpClient) FileSize(path string) (int64, error) {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -213,7 +211,7 @@ func (f *ftpClient) FileSize(path string) (int64, liberr.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) GetTime(path string) (time.Time, liberr.Error) {
|
func (f *ftpClient) GetTime(path string) (time.Time, error) {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, err
|
||||||
}
|
}
|
||||||
@@ -225,7 +223,7 @@ func (f *ftpClient) GetTime(path string) (time.Time, liberr.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) SetTime(path string, t time.Time) liberr.Error {
|
func (f *ftpClient) SetTime(path string, t time.Time) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -237,7 +235,7 @@ func (f *ftpClient) SetTime(path string, t time.Time) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Retr(path string) (*libftp.Response, liberr.Error) {
|
func (f *ftpClient) Retr(path string) (*libftp.Response, error) {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -261,7 +259,7 @@ func (f *ftpClient) RetrFrom(path string, offset uint64) (*libftp.Response, erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Stor(path string, r io.Reader) liberr.Error {
|
func (f *ftpClient) Stor(path string, r io.Reader) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -273,7 +271,7 @@ func (f *ftpClient) Stor(path string, r io.Reader) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) StorFrom(path string, r io.Reader, offset uint64) liberr.Error {
|
func (f *ftpClient) StorFrom(path string, r io.Reader, offset uint64) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -285,7 +283,7 @@ func (f *ftpClient) StorFrom(path string, r io.Reader, offset uint64) liberr.Err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Append(path string, r io.Reader) liberr.Error {
|
func (f *ftpClient) Append(path string, r io.Reader) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -297,7 +295,7 @@ func (f *ftpClient) Append(path string, r io.Reader) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Rename(from, to string) liberr.Error {
|
func (f *ftpClient) Rename(from, to string) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -309,7 +307,7 @@ func (f *ftpClient) Rename(from, to string) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Delete(path string) liberr.Error {
|
func (f *ftpClient) Delete(path string) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -321,7 +319,7 @@ func (f *ftpClient) Delete(path string) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) RemoveDirRecur(path string) liberr.Error {
|
func (f *ftpClient) RemoveDirRecur(path string) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -333,7 +331,7 @@ func (f *ftpClient) RemoveDirRecur(path string) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) MakeDir(path string) liberr.Error {
|
func (f *ftpClient) MakeDir(path string) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -345,7 +343,7 @@ func (f *ftpClient) MakeDir(path string) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) RemoveDir(path string) liberr.Error {
|
func (f *ftpClient) RemoveDir(path string) error {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -357,7 +355,7 @@ func (f *ftpClient) RemoveDir(path string) liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ftpClient) Walk(root string) (*libftp.Walker, liberr.Error) {
|
func (f *ftpClient) Walk(root string) (*libftp.Walker, error) {
|
||||||
if err := f.Check(); err != nil {
|
if err := f.Check(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -75,16 +75,13 @@ func (o *dmp) Transport(cfg TransportConfig) *http.Transport {
|
|||||||
prx = http.ProxyURL(cfg.Proxy)
|
prx = http.ProxyURL(cfg.Proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ssl libtls.TLSConfig
|
||||||
err error
|
|
||||||
ssl libtls.TLSConfig
|
|
||||||
)
|
|
||||||
|
|
||||||
if cfg.TLSConfig == nil {
|
if cfg.TLSConfig == nil {
|
||||||
ssl = libtls.New()
|
ssl = libtls.New()
|
||||||
ssl.SetVersionMin(tls.VersionTLS12)
|
ssl.SetVersionMin(tls.VersionTLS12)
|
||||||
ssl.SetVersionMax(tls.VersionTLS13)
|
ssl.SetVersionMax(tls.VersionTLS13)
|
||||||
} else if ssl, err = cfg.TLSConfig.New(); err != nil {
|
} else if ssl = cfg.TLSConfig.New(); ssl == nil {
|
||||||
ssl = libtls.New()
|
ssl = libtls.New()
|
||||||
ssl.SetVersionMin(tls.VersionTLS12)
|
ssl.SetVersionMin(tls.VersionTLS12)
|
||||||
ssl.SetVersionMax(tls.VersionTLS13)
|
ssl.SetVersionMax(tls.VersionTLS13)
|
||||||
|
@@ -37,7 +37,6 @@ import (
|
|||||||
libtls "github.com/nabbar/golib/certificates"
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
libctx "github.com/nabbar/golib/context"
|
libctx "github.com/nabbar/golib/context"
|
||||||
libdur "github.com/nabbar/golib/duration"
|
libdur "github.com/nabbar/golib/duration"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
|
||||||
srvtps "github.com/nabbar/golib/httpserver/types"
|
srvtps "github.com/nabbar/golib/httpserver/types"
|
||||||
liblog "github.com/nabbar/golib/logger"
|
liblog "github.com/nabbar/golib/logger"
|
||||||
logcfg "github.com/nabbar/golib/logger/config"
|
logcfg "github.com/nabbar/golib/logger/config"
|
||||||
@@ -210,12 +209,9 @@ func (c *Config) Clone() Config {
|
|||||||
TLS: libtls.Config{
|
TLS: libtls.Config{
|
||||||
CurveList: c.TLS.CurveList,
|
CurveList: c.TLS.CurveList,
|
||||||
CipherList: c.TLS.CipherList,
|
CipherList: c.TLS.CipherList,
|
||||||
RootCAString: c.TLS.RootCAString,
|
RootCA: c.TLS.RootCA,
|
||||||
RootCAFile: c.TLS.RootCAFile,
|
ClientCA: c.TLS.ClientCA,
|
||||||
ClientCAString: c.TLS.ClientCAString,
|
Certs: c.TLS.Certs,
|
||||||
ClientCAFiles: c.TLS.ClientCAFiles,
|
|
||||||
CertPairString: c.TLS.CertPairString,
|
|
||||||
CertPairFile: c.TLS.CertPairFile,
|
|
||||||
VersionMin: c.TLS.VersionMin,
|
VersionMin: c.TLS.VersionMin,
|
||||||
VersionMax: c.TLS.VersionMax,
|
VersionMax: c.TLS.VersionMax,
|
||||||
AuthClient: c.TLS.AuthClient,
|
AuthClient: c.TLS.AuthClient,
|
||||||
@@ -239,17 +235,21 @@ func (c *Config) SetContext(f libctx.FuncContext) {
|
|||||||
c.getParentContext = f
|
c.getParentContext = f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetTLS() (libtls.TLSConfig, liberr.Error) {
|
func (c *Config) GetTLS() (libtls.TLSConfig, error) {
|
||||||
var def libtls.TLSConfig
|
var def libtls.TLSConfig
|
||||||
|
|
||||||
if c.TLS.InheritDefault && c.getTLSDefault != nil {
|
if c.TLS.InheritDefault && c.getTLSDefault != nil {
|
||||||
def = c.getTLSDefault()
|
def = c.getTLSDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.TLS.NewFrom(def)
|
if cfg := c.TLS.NewFrom(def); cfg != nil {
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("no tls configuration found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) CheckTLS() (libtls.TLSConfig, liberr.Error) {
|
func (c *Config) CheckTLS() (libtls.TLSConfig, error) {
|
||||||
if ssl, err := c.GetTLS(); err != nil {
|
if ssl, err := c.GetTLS(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if ssl == nil || ssl.LenCertificatePair() < 1 {
|
} else if ssl == nil || ssl.LenCertificatePair() < 1 {
|
||||||
@@ -337,7 +337,7 @@ func (c *Config) GetHandlerKey() string {
|
|||||||
return c.HandlerKey
|
return c.HandlerKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() liberr.Error {
|
func (c *Config) Validate() error {
|
||||||
err := ErrorServerValidate.Error(nil)
|
err := ErrorServerValidate.Error(nil)
|
||||||
|
|
||||||
if er := libval.New().Struct(c); er != nil {
|
if er := libval.New().Struct(c); er != nil {
|
||||||
|
@@ -91,11 +91,11 @@ func (p Config) Walk(fct FuncWalkConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Config) Validate() liberr.Error {
|
func (p Config) Validate() error {
|
||||||
var e = ErrorPoolValidate.Error(nil)
|
var e = ErrorPoolValidate.Error(nil)
|
||||||
|
|
||||||
p.Walk(func(cfg libhtp.Config) bool {
|
p.Walk(func(cfg libhtp.Config) bool {
|
||||||
var err liberr.Error
|
var err error
|
||||||
|
|
||||||
if err = cfg.Validate(); err != nil {
|
if err = cfg.Validate(); err != nil {
|
||||||
e.Add(err)
|
e.Add(err)
|
||||||
|
@@ -33,7 +33,6 @@ import (
|
|||||||
|
|
||||||
libval "github.com/go-playground/validator/v10"
|
libval "github.com/go-playground/validator/v10"
|
||||||
libtls "github.com/nabbar/golib/certificates"
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
|
||||||
natcli "github.com/nats-io/nats.go"
|
natcli "github.com/nats-io/nats.go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -147,7 +146,7 @@ type Client struct {
|
|||||||
TLSConfig libtls.Config
|
TLSConfig libtls.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) Validate() liberr.Error {
|
func (c Client) Validate() error {
|
||||||
err := ErrorConfigValidation.Error(nil)
|
err := ErrorConfigValidation.Error(nil)
|
||||||
|
|
||||||
if er := libval.New().Struct(c); er != nil {
|
if er := libval.New().Struct(c); er != nil {
|
||||||
@@ -168,7 +167,7 @@ func (c Client) Validate() liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) NewClient(defTls libtls.TLSConfig) (*natcli.Conn, liberr.Error) {
|
func (c Client) NewClient(defTls libtls.TLSConfig) (*natcli.Conn, error) {
|
||||||
opts := natcli.GetDefaultOptions()
|
opts := natcli.GetDefaultOptions()
|
||||||
|
|
||||||
if c.Url != "" {
|
if c.Url != "" {
|
||||||
@@ -273,8 +272,8 @@ func (c Client) NewClient(defTls libtls.TLSConfig) (*natcli.Conn, liberr.Error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.Secure {
|
if c.Secure {
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return nil, e
|
return nil, fmt.Errorf("no valid tls configuration")
|
||||||
} else {
|
} else {
|
||||||
opts.TLSConfig = t.TlsConfig("")
|
opts.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,6 @@ import (
|
|||||||
|
|
||||||
libval "github.com/go-playground/validator/v10"
|
libval "github.com/go-playground/validator/v10"
|
||||||
libtls "github.com/nabbar/golib/certificates"
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
|
||||||
libiot "github.com/nabbar/golib/ioutils"
|
libiot "github.com/nabbar/golib/ioutils"
|
||||||
liblog "github.com/nabbar/golib/logger"
|
liblog "github.com/nabbar/golib/logger"
|
||||||
loglvl "github.com/nabbar/golib/logger/level"
|
loglvl "github.com/nabbar/golib/logger/level"
|
||||||
@@ -63,7 +62,7 @@ type Config struct {
|
|||||||
Customs *ConfigCustom `mapstructure:"-" json:"-" yaml:"-" toml:"-"`
|
Customs *ConfigCustom `mapstructure:"-" json:"-" yaml:"-" toml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) Validate() liberr.Error {
|
func (c Config) Validate() error {
|
||||||
err := ErrorConfigValidation.Error(nil)
|
err := ErrorConfigValidation.Error(nil)
|
||||||
|
|
||||||
if er := libval.New().Struct(c); er != nil {
|
if er := libval.New().Struct(c); er != nil {
|
||||||
@@ -84,7 +83,7 @@ func (c Config) Validate() liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) LogConfigJson() liberr.Error {
|
func (c Config) LogConfigJson() error {
|
||||||
if c.Logs.LogFile == "" {
|
if c.Logs.LogFile == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -129,7 +128,7 @@ func (c Config) LogConfigJson() liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) NatsOption(defaultTls libtls.TLSConfig, log liblog.Logger) (*natsrv.Options, liberr.Error) {
|
func (c Config) NatsOption(defaultTls libtls.TLSConfig, log liblog.Logger) (*natsrv.Options, error) {
|
||||||
cfg := &natsrv.Options{
|
cfg := &natsrv.Options{
|
||||||
CheckConfig: false,
|
CheckConfig: false,
|
||||||
}
|
}
|
||||||
@@ -187,7 +186,7 @@ func (c Config) NatsOption(defaultTls libtls.TLSConfig, log liblog.Logger) (*nat
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConfigCustom) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) liberr.Error {
|
func (c *ConfigCustom) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) error {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return ErrorParamsInvalid.Error(nil)
|
return ErrorParamsInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
@@ -209,8 +208,8 @@ func (c *ConfigCustom) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) lib
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.AccountResolverTLS {
|
if c.AccountResolverTLS {
|
||||||
if t, e := c.AccountResolverTLSConfig.NewFrom(defTls); e != nil {
|
if t := c.AccountResolverTLSConfig.NewFrom(defTls); t == nil {
|
||||||
return e
|
return fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
cfg.AccountResolverTLSConfig = t.TlsConfig("")
|
cfg.AccountResolverTLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -221,7 +220,7 @@ func (c *ConfigCustom) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) lib
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigAuth) makeOpt(cfg *natsrv.Options) liberr.Error {
|
func (c ConfigAuth) makeOpt(cfg *natsrv.Options) error {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return ErrorParamsInvalid.Error(nil)
|
return ErrorParamsInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
@@ -285,7 +284,7 @@ func (c ConfigAuth) makeOpt(cfg *natsrv.Options) liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigNkey) makeOpt(auth ConfigAuth, cfg *natsrv.Options) (*natsrv.NkeyUser, liberr.Error) {
|
func (c ConfigNkey) makeOpt(auth ConfigAuth, cfg *natsrv.Options) (*natsrv.NkeyUser, error) {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return nil, ErrorParamsInvalid.Error(nil)
|
return nil, ErrorParamsInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
@@ -342,7 +341,7 @@ func (c ConfigNkey) makeOpt(auth ConfigAuth, cfg *natsrv.Options) (*natsrv.NkeyU
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigUser) makeOpt(auth ConfigAuth, cfg *natsrv.Options) (*natsrv.User, liberr.Error) {
|
func (c ConfigUser) makeOpt(auth ConfigAuth, cfg *natsrv.Options) (*natsrv.User, error) {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return nil, ErrorParamsInvalid.Error(nil)
|
return nil, ErrorParamsInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
@@ -473,7 +472,7 @@ func (c ConfigPermissionResponse) makeOpt() *natsrv.ResponsePermission {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigLogger) makeOpt(log liblog.Logger, cfg *natsrv.Options) liberr.Error {
|
func (c ConfigLogger) makeOpt(log liblog.Logger, cfg *natsrv.Options) error {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return ErrorParamsInvalid.Error(nil)
|
return ErrorParamsInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
@@ -540,7 +539,7 @@ func (c ConfigLogger) makeOpt(log liblog.Logger, cfg *natsrv.Options) liberr.Err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigLimits) makeOpt(cfg *natsrv.Options) liberr.Error {
|
func (c ConfigLimits) makeOpt(cfg *natsrv.Options) error {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return ErrorParamsInvalid.Error(nil)
|
return ErrorParamsInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
@@ -604,7 +603,7 @@ func (c ConfigLimits) makeOpt(cfg *natsrv.Options) liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigSrv) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) liberr.Error {
|
func (c ConfigSrv) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) error {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return ErrorParamsInvalid.Error(nil)
|
return ErrorParamsInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
@@ -733,8 +732,8 @@ func (c ConfigSrv) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) liberr.
|
|||||||
if c.TLS {
|
if c.TLS {
|
||||||
cfg.TLS = true
|
cfg.TLS = true
|
||||||
|
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return e
|
return fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
cfg.TLSConfig = t.TlsConfig("")
|
cfg.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -757,7 +756,7 @@ func (c ConfigSrv) makeOpt(cfg *natsrv.Options, defTls libtls.TLSConfig) liberr.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigCluster) makeOpt(defTls libtls.TLSConfig) (natsrv.ClusterOpts, liberr.Error) {
|
func (c ConfigCluster) makeOpt(defTls libtls.TLSConfig) (natsrv.ClusterOpts, error) {
|
||||||
cfg := natsrv.ClusterOpts{
|
cfg := natsrv.ClusterOpts{
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
Host: c.Host,
|
Host: c.Host,
|
||||||
@@ -786,8 +785,8 @@ func (c ConfigCluster) makeOpt(defTls libtls.TLSConfig) (natsrv.ClusterOpts, lib
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.TLS {
|
if c.TLS {
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return cfg, e
|
return cfg, fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
cfg.TLSConfig = t.TlsConfig("")
|
cfg.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -803,7 +802,7 @@ func (c ConfigCluster) makeOpt(defTls libtls.TLSConfig) (natsrv.ClusterOpts, lib
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigGateway) makeOpt(defTls libtls.TLSConfig) (natsrv.GatewayOpts, liberr.Error) {
|
func (c ConfigGateway) makeOpt(defTls libtls.TLSConfig) (natsrv.GatewayOpts, error) {
|
||||||
cfg := natsrv.GatewayOpts{
|
cfg := natsrv.GatewayOpts{
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
Host: c.Host,
|
Host: c.Host,
|
||||||
@@ -826,8 +825,8 @@ func (c ConfigGateway) makeOpt(defTls libtls.TLSConfig) (natsrv.GatewayOpts, lib
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.TLS {
|
if c.TLS {
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return cfg, e
|
return cfg, fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
cfg.TLSConfig = t.TlsConfig("")
|
cfg.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -850,7 +849,7 @@ func (c ConfigGateway) makeOpt(defTls libtls.TLSConfig) (natsrv.GatewayOpts, lib
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigGatewayRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteGatewayOpts, liberr.Error) {
|
func (c ConfigGatewayRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteGatewayOpts, error) {
|
||||||
res := &natsrv.RemoteGatewayOpts{
|
res := &natsrv.RemoteGatewayOpts{
|
||||||
Name: "",
|
Name: "",
|
||||||
TLSConfig: nil,
|
TLSConfig: nil,
|
||||||
@@ -863,8 +862,8 @@ func (c ConfigGatewayRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteGat
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.TLS {
|
if c.TLS {
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return nil, e
|
return nil, fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
res.TLSConfig = t.TlsConfig("")
|
res.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -891,7 +890,7 @@ func (c ConfigGatewayRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteGat
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigLeaf) makeOpt(cfg *natsrv.Options, auth ConfigAuth, defTls libtls.TLSConfig) (natsrv.LeafNodeOpts, liberr.Error) {
|
func (c ConfigLeaf) makeOpt(cfg *natsrv.Options, auth ConfigAuth, defTls libtls.TLSConfig) (natsrv.LeafNodeOpts, error) {
|
||||||
res := natsrv.LeafNodeOpts{
|
res := natsrv.LeafNodeOpts{
|
||||||
Host: c.Host,
|
Host: c.Host,
|
||||||
Port: c.Port,
|
Port: c.Port,
|
||||||
@@ -924,8 +923,8 @@ func (c ConfigLeaf) makeOpt(cfg *natsrv.Options, auth ConfigAuth, defTls libtls.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.TLS {
|
if c.TLS {
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return res, e
|
return res, fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
res.TLSConfig = t.TlsConfig("")
|
res.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -951,7 +950,7 @@ func (c ConfigLeaf) makeOpt(cfg *natsrv.Options, auth ConfigAuth, defTls libtls.
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigLeafRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteLeafOpts, liberr.Error) {
|
func (c ConfigLeafRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteLeafOpts, error) {
|
||||||
res := &natsrv.RemoteLeafOpts{
|
res := &natsrv.RemoteLeafOpts{
|
||||||
LocalAccount: c.LocalAccount,
|
LocalAccount: c.LocalAccount,
|
||||||
URLs: make([]*url.URL, 0),
|
URLs: make([]*url.URL, 0),
|
||||||
@@ -974,8 +973,8 @@ func (c ConfigLeafRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteLeafOp
|
|||||||
if c.TLS {
|
if c.TLS {
|
||||||
res.TLS = true
|
res.TLS = true
|
||||||
|
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return nil, e
|
return nil, fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
res.TLSConfig = t.TlsConfig("")
|
res.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -1009,7 +1008,7 @@ func (c ConfigLeafRemote) makeOpt(defTls libtls.TLSConfig) (*natsrv.RemoteLeafOp
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigWebsocket) makeOpt(defTls libtls.TLSConfig) (natsrv.WebsocketOpts, liberr.Error) {
|
func (c ConfigWebsocket) makeOpt(defTls libtls.TLSConfig) (natsrv.WebsocketOpts, error) {
|
||||||
cfg := natsrv.WebsocketOpts{
|
cfg := natsrv.WebsocketOpts{
|
||||||
Host: c.Host,
|
Host: c.Host,
|
||||||
Port: c.Port,
|
Port: c.Port,
|
||||||
@@ -1044,8 +1043,8 @@ func (c ConfigWebsocket) makeOpt(defTls libtls.TLSConfig) (natsrv.WebsocketOpts,
|
|||||||
if !c.NoTLS {
|
if !c.NoTLS {
|
||||||
cfg.NoTLS = false
|
cfg.NoTLS = false
|
||||||
|
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return cfg, e
|
return cfg, fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
cfg.TLSConfig = t.TlsConfig("")
|
cfg.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
@@ -1063,7 +1062,7 @@ func (c ConfigWebsocket) makeOpt(defTls libtls.TLSConfig) (natsrv.WebsocketOpts,
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConfigMQTT) makeOpt(defTls libtls.TLSConfig) (natsrv.MQTTOpts, liberr.Error) {
|
func (c ConfigMQTT) makeOpt(defTls libtls.TLSConfig) (natsrv.MQTTOpts, error) {
|
||||||
cfg := natsrv.MQTTOpts{
|
cfg := natsrv.MQTTOpts{
|
||||||
Host: c.Host,
|
Host: c.Host,
|
||||||
Port: c.Port,
|
Port: c.Port,
|
||||||
@@ -1084,8 +1083,8 @@ func (c ConfigMQTT) makeOpt(defTls libtls.TLSConfig) (natsrv.MQTTOpts, liberr.Er
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !c.TLS {
|
if !c.TLS {
|
||||||
if t, e := c.TLSConfig.NewFrom(defTls); e != nil {
|
if t := c.TLSConfig.NewFrom(defTls); t == nil {
|
||||||
return cfg, e
|
return cfg, fmt.Errorf("no valid tls config")
|
||||||
} else {
|
} else {
|
||||||
cfg.TLSConfig = t.TlsConfig("")
|
cfg.TLSConfig = t.TlsConfig("")
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,6 @@ import (
|
|||||||
|
|
||||||
libtls "github.com/nabbar/golib/certificates"
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
libctx "github.com/nabbar/golib/context"
|
libctx "github.com/nabbar/golib/context"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
|
||||||
montps "github.com/nabbar/golib/monitor/types"
|
montps "github.com/nabbar/golib/monitor/types"
|
||||||
libver "github.com/nabbar/golib/version"
|
libver "github.com/nabbar/golib/version"
|
||||||
natsrv "github.com/nats-io/nats-server/v2/server"
|
natsrv "github.com/nats-io/nats-server/v2/server"
|
||||||
@@ -50,8 +49,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Server interface {
|
type Server interface {
|
||||||
Listen(ctx context.Context) liberr.Error
|
Listen(ctx context.Context) error
|
||||||
Restart(ctx context.Context) liberr.Error
|
Restart(ctx context.Context) error
|
||||||
Shutdown()
|
Shutdown()
|
||||||
|
|
||||||
GetOptions() *natsrv.Options
|
GetOptions() *natsrv.Options
|
||||||
@@ -62,9 +61,9 @@ type Server interface {
|
|||||||
IsReadyTimeout(parent context.Context, dur time.Duration) bool
|
IsReadyTimeout(parent context.Context, dur time.Duration) bool
|
||||||
WaitReady(ctx context.Context, tick time.Duration)
|
WaitReady(ctx context.Context, tick time.Duration)
|
||||||
|
|
||||||
ClientAdvertise(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err liberr.Error)
|
ClientAdvertise(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err error)
|
||||||
ClientCluster(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err liberr.Error)
|
ClientCluster(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err error)
|
||||||
ClientServer(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err liberr.Error)
|
ClientServer(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err error)
|
||||||
|
|
||||||
Monitor(ctx libctx.FuncContext, vrs libver.Version) (montps.Monitor, error)
|
Monitor(ctx libctx.FuncContext, vrs libver.Version) (montps.Monitor, error)
|
||||||
}
|
}
|
||||||
@@ -89,11 +88,11 @@ type server struct {
|
|||||||
o *atomic.Value
|
o *atomic.Value
|
||||||
s *atomic.Value
|
s *atomic.Value
|
||||||
r *atomic.Value
|
r *atomic.Value
|
||||||
e liberr.Error
|
e error
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) Listen(ctx context.Context) liberr.Error {
|
func (s *server) Listen(ctx context.Context) error {
|
||||||
if s.IsRunning() || s.IsReady() {
|
if s.IsRunning() || s.IsReady() {
|
||||||
s.Shutdown()
|
s.Shutdown()
|
||||||
}
|
}
|
||||||
@@ -123,7 +122,7 @@ func (s *server) Listen(ctx context.Context) liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) Restart(ctx context.Context) liberr.Error {
|
func (s *server) Restart(ctx context.Context) error {
|
||||||
return s.Listen(ctx)
|
return s.Listen(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +211,7 @@ func (s *server) WaitReady(ctx context.Context, tick time.Duration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ClientAdvertise(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err liberr.Error) {
|
func (s *server) ClientAdvertise(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err error) {
|
||||||
if o := s.GetOptions(); o != nil && o.ClientAdvertise != "" {
|
if o := s.GetOptions(); o != nil && o.ClientAdvertise != "" {
|
||||||
opt.Url = s._FormatAddress(o.ClientAdvertise)
|
opt.Url = s._FormatAddress(o.ClientAdvertise)
|
||||||
} else {
|
} else {
|
||||||
@@ -222,7 +221,7 @@ func (s *server) ClientAdvertise(ctx context.Context, tick time.Duration, defTls
|
|||||||
return opt.NewClient(defTls)
|
return opt.NewClient(defTls)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ClientCluster(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err liberr.Error) {
|
func (s *server) ClientCluster(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err error) {
|
||||||
s.WaitReady(ctx, tick)
|
s.WaitReady(ctx, tick)
|
||||||
|
|
||||||
if srv := s._GetServer(); srv != nil {
|
if srv := s._GetServer(); srv != nil {
|
||||||
@@ -236,7 +235,7 @@ func (s *server) ClientCluster(ctx context.Context, tick time.Duration, defTls l
|
|||||||
return opt.NewClient(defTls)
|
return opt.NewClient(defTls)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ClientServer(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err liberr.Error) {
|
func (s *server) ClientServer(ctx context.Context, tick time.Duration, defTls libtls.TLSConfig, opt Client) (cli *natcli.Conn, err error) {
|
||||||
var o *natsrv.Options
|
var o *natsrv.Options
|
||||||
|
|
||||||
if o = s.GetOptions(); o == nil {
|
if o = s.GetOptions(); o == nil {
|
||||||
@@ -290,14 +289,14 @@ func (s *server) _SetServer(srv *natsrv.Server) {
|
|||||||
s.s.Store(srv)
|
s.s.Store(srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) _GetError() liberr.Error {
|
func (s *server) _GetError() error {
|
||||||
s.m.Lock()
|
s.m.Lock()
|
||||||
defer s.m.Unlock()
|
defer s.m.Unlock()
|
||||||
|
|
||||||
return s.e
|
return s.e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) _SetError(err liberr.Error) {
|
func (s *server) _SetError(err error) {
|
||||||
s.m.Lock()
|
s.m.Lock()
|
||||||
defer s.m.Unlock()
|
defer s.m.Unlock()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user