Merge pull request #6 from luscis/verify_cert_1

fix: not verify cert when login
This commit is contained in:
Daniel Ding
2022-09-24 17:26:58 +08:00
committed by GitHub
12 changed files with 130 additions and 34 deletions

2
.gitignore vendored
View File

@@ -3,7 +3,7 @@
*.dll
*.so
*.dylib
*.patch
*.exe
*.x86_64
*.rpm

View File

@@ -38,5 +38,4 @@ func main() {
fmt.Println(b, bb)
//fmt.Println(cap(bb), len(bb))
//fmt.Println(cap(b), len(b))
}

61
misc/learn/cert.go Normal file
View File

@@ -0,0 +1,61 @@
package main
import (
"bytes"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
"time"
)
func CertificateText(cert *x509.Certificate) (string, error) {
var buf bytes.Buffer
buf.Grow(4096) // 4KiB should be enough
buf.WriteString(fmt.Sprintf("Certificate:\n"))
buf.WriteString(fmt.Sprintf("%4sData:\n", ""))
buf.WriteString(fmt.Sprintf("%8sSerial Number: %d (%#x)\n", "", cert.SerialNumber, cert.SerialNumber))
buf.WriteString(fmt.Sprintf("%4sSignature Algorithm: %s\n", "", cert.SignatureAlgorithm))
// Issuer information
buf.WriteString(fmt.Sprintf("%8sIssuer: ", ""))
// Validity information
buf.WriteString(fmt.Sprintf("%8sValidity\n", ""))
buf.WriteString(fmt.Sprintf("%12sNot Before: %s\n", "", cert.NotBefore.Format("Jan 2 15:04:05 2006 MST")))
buf.WriteString(fmt.Sprintf("%12sNot After : %s\n", "", cert.NotAfter.Format("Jan 2 15:04:05 2006 MST")))
now := time.Now()
if now.Before(cert.NotBefore) {
buf.WriteString(fmt.Sprintf("current time %s is before %s\n", now.Format(time.RFC3339), cert.NotBefore.Format(time.RFC3339)))
} else if now.After(cert.NotAfter) {
buf.WriteString(fmt.Sprintf("current time %s is after %s\n", now.Format(time.RFC3339), cert.NotAfter.Format(time.RFC3339)))
}
return buf.String(), nil
}
func main() {
// Read and parse the PEM certificate file
pemData, err := ioutil.ReadFile("cert.pem")
if err != nil {
log.Fatal(err)
}
block, rest := pem.Decode(pemData)
if block == nil || len(rest) > 0 {
log.Fatal("Certificate decoding error")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
log.Fatal(err)
}
// Print the certificate
result, err := CertificateText(cert)
if err != nil {
log.Fatal(err)
}
fmt.Print(result)
}

View File

@@ -116,7 +116,7 @@ func GetSocketClient(p *config.Point) libol.SocketClient {
WrQus: p.Queue.SockWr,
}
if p.Cert != nil {
c.Cert = &libol.WebCert{
c.Cert = &libol.CertConfig{
Insecure: p.Cert.Insecure,
RootCa: p.Cert.CaFile,
}

View File

@@ -65,7 +65,7 @@ func (p *Access) handleLogin(client libol.SocketClient, data []byte) error {
}
user.Update()
out.Info("Access.handleLogin: %s on %s", user.Id(), user.Alias)
if now, _ := cache.User.Check(user); now != nil {
if now, err := cache.User.Check(user); now != nil {
if now.Role != "admin" && now.Last != nil {
// To offline lastly client if guest.
p.master.OffClient(now.Last)
@@ -76,10 +76,11 @@ func (p *Access) handleLogin(client libol.SocketClient, data []byte) error {
out.Info("Access.handleLogin: success")
_ = p.onAuth(client, user)
return nil
} else {
p.failed++
client.SetStatus(libol.ClUnAuth)
return err
}
p.failed++
client.SetStatus(libol.ClUnAuth)
return libol.NewErr("Auth failed.")
}
func (p *Access) onAuth(client libol.SocketClient, user *models.User) error {

32
pkg/cache/user.go vendored
View File

@@ -2,8 +2,11 @@ package cache
import (
"bufio"
"crypto/x509"
"encoding/pem"
"github.com/luscis/openlan/pkg/libol"
"github.com/luscis/openlan/pkg/models"
"io/ioutil"
"strings"
"sync"
"time"
@@ -12,6 +15,7 @@ import (
type user struct {
Lock sync.RWMutex
File string
Cert string
Users *libol.SafeStrMap
LdapCfg *libol.LDAPConfig
LdapSvc *libol.LDAPService
@@ -168,6 +172,26 @@ func (w *user) Timeout(user *models.User) bool {
}
func (w *user) Check(obj *models.User) (*models.User, error) {
if w.Cert != "" {
pemData, err := ioutil.ReadFile(w.Cert)
if err != nil {
return nil, err
}
block, rest := pem.Decode(pemData)
if block == nil || len(rest) > 0 {
return nil, libol.NewErr("certificate decoding error")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
now := time.Now()
if now.Before(cert.NotBefore) {
return nil, libol.NewErr("certificate isn't yet valid")
} else if now.After(cert.NotAfter) {
return nil, libol.NewErr("certificate has expired")
}
}
if u := w.Get(obj.Id()); u != nil {
if u.Role == "" || u.Role == "admin" || u.Role == "guest" {
if u.Password == obj.Password {
@@ -183,7 +207,7 @@ func (w *user) Check(obj *models.User) (*models.User, error) {
if u := w.CheckLdap(obj); u != nil {
return u, nil
}
return nil, libol.NewErr("wrong user or password")
return nil, libol.NewErr("wrong password")
}
func (w *user) GetLdap() *libol.LDAPService {
@@ -217,6 +241,12 @@ func (w *user) SetLdap(cfg *libol.LDAPConfig) {
}
}
func (w *user) SetCert(cfg *libol.CertConfig) {
w.Lock.Lock()
defer w.Lock.Unlock()
w.Cert = cfg.Crt
}
var User = user{
Users: libol.NewSafeStrMap(1024),
}

View File

@@ -34,7 +34,7 @@ type Cert struct {
func (c *Cert) Correct() {
if c.Dir == "" {
return
c.Dir = VarDir("cert")
}
if c.CrtFile == "" {
c.CrtFile = fmt.Sprintf("%s/crt", c.Dir)

View File

@@ -96,6 +96,7 @@ func DefaultSwitch() *Switch {
Listen: "0.0.0.0:10000",
},
Listen: "0.0.0.0:10002",
Cert: &Cert{},
}
obj.Correct(nil)
return obj
@@ -142,6 +143,8 @@ func (s *Switch) Correct(obj *Switch) {
s.File = filepath.Join(s.ConfDir, "switch.json")
if s.Cert != nil {
s.Cert.Correct()
} else {
s.Cert = obj.Cert
}
perf := &s.Perf
perf.Correct(DefaultPerf())

View File

@@ -67,8 +67,9 @@ func (l *logger) Write(level int, format string, v ...interface{}) {
func (l *logger) Save(level string, format string, v ...interface{}) {
m := fmt.Sprintf(format, v...)
now := time.Now()
if l.FileLog != nil {
l.FileLog.Println(level + "|" + m)
l.FileLog.Printf("%s %s|%s\n", now.Format(time.RFC3339), level, m)
}
l.Lock.Lock()
defer l.Lock.Unlock()
@@ -77,11 +78,9 @@ func (l *logger) Save(level string, format string, v ...interface{}) {
l.Errors.Remove(e)
}
}
yy, mm, dd := time.Now().Date()
hh, mn, se := time.Now().Clock()
ele := &Message{
Level: level,
Date: fmt.Sprintf("%d/%02d/%02d %02d:%02d:%02d", yy, mm, dd, hh, mn, se),
Date: now.Format(time.RFC3339),
Message: m,
}
l.Errors.PushBack(ele)

View File

@@ -27,7 +27,7 @@ func (ws *wsConn) RemoteAddr() net.Addr {
return nil
}
type WebCert struct {
type CertConfig struct {
Key string
Crt string
RootCa string
@@ -35,7 +35,7 @@ type WebCert struct {
}
type WebConfig struct {
Cert *WebCert
Cert *CertConfig
Block kcp.BlockCrypt
Timeout time.Duration // ns
RdQus int // per frames

View File

@@ -51,7 +51,7 @@ func GetSocketServer(s *co.Switch) libol.SocketServer {
WrQus: s.Queue.SockWr,
}
if s.Cert != nil {
c.Cert = &libol.WebCert{
c.Cert = &libol.CertConfig{
Crt: s.Cert.CrtFile,
Key: s.Cert.KeyFile,
}
@@ -405,22 +405,6 @@ func (v *Switch) preAllow() {
}
}
func (v *Switch) SetLdap(ldap *co.LDAP) {
if ldap == nil || ldap.Server == "" {
return
}
cfg := libol.LDAPConfig{
Server: ldap.Server,
BindUser: ldap.BindDN,
BindPass: ldap.BindPass,
BaseDN: ldap.BaseDN,
Attr: ldap.Attribute,
Filter: ldap.Filter,
EnableTls: ldap.EnableTls,
}
cache.User.SetLdap(&cfg)
}
func (v *Switch) SetPass(file string) {
cache.User.SetFile(file)
}
@@ -451,7 +435,26 @@ func (v *Switch) Initialize() {
// Load password for guest access
v.SetPass(v.cfg.PassFile)
v.LoadPass()
v.SetLdap(v.cfg.Ldap)
ldap := v.cfg.Ldap
if ldap != nil {
cache.User.SetLdap(&libol.LDAPConfig{
Server: ldap.Server,
BindUser: ldap.BindDN,
BindPass: ldap.BindPass,
BaseDN: ldap.BaseDN,
Attr: ldap.Attribute,
Filter: ldap.Filter,
EnableTls: ldap.EnableTls,
})
}
// Enable cert verify for access
cert := v.cfg.Cert
if cert != nil {
cache.User.SetCert(&libol.CertConfig{
Crt: cert.CrtFile,
})
}
// Start confd monitor
v.confd.Initialize()
}