server/libfic/certificate.go

113 lines
3.3 KiB
Go
Raw Normal View History

package fic
import (
2018-01-21 13:18:26 +00:00
"database/sql"
"math/big"
2018-01-21 13:18:26 +00:00
"time"
)
2018-01-21 13:18:26 +00:00
2018-03-09 18:07:08 +00:00
// Certificate represents a client certificate, which can be associated to a team.
//
// This is one method usable to handle authentication.
// To use it in nginx, you'll need to add following lines in your configuration:
//
// ssl_client_certificate PKI/shared/ca.pem;
// ssl_trusted_certificate PKI/shared/ca.pem;
// ssl_verify_client optional;
//
// Non-recognized clients will have access to a registration form.
2018-01-21 13:18:26 +00:00
type Certificate struct {
Id uint64 `json:"id,string"`
2018-01-21 13:18:26 +00:00
Creation time.Time `json:"creation"`
Password string `json:"password"`
Revoked *time.Time `json:"revoked"`
}
2018-03-09 18:07:08 +00:00
// GetCertificates returns the list of all generated certificates.
2021-11-22 14:35:07 +00:00
func GetCertificates() (certificates []*Certificate, err error) {
2018-01-21 13:18:26 +00:00
var rows *sql.Rows
if rows, err = DBQuery("SELECT id_cert, creation, password, revoked FROM certificates ORDER BY creation"); err == nil {
2018-01-21 13:18:26 +00:00
defer rows.Close()
2021-11-22 14:35:07 +00:00
certificates = []*Certificate{}
2018-01-21 13:18:26 +00:00
for rows.Next() {
2021-11-22 14:35:07 +00:00
c := &Certificate{}
if err = rows.Scan(&c.Id, &c.Creation, &c.Password, &c.Revoked); err != nil {
2018-01-21 13:18:26 +00:00
return
}
certificates = append(certificates, c)
}
err = rows.Err()
}
return
}
2018-03-09 18:07:08 +00:00
// GetCertificate retrieves a certificate from its serial number.
2021-11-22 14:35:07 +00:00
func GetCertificate(serial uint64) (c *Certificate, err error) {
c = &Certificate{}
err = DBQueryRow("SELECT id_cert, creation, password, revoked FROM certificates WHERE id_cert = ?", serial).Scan(&c.Id, &c.Creation, &c.Password, &c.Revoked)
2018-01-21 13:18:26 +00:00
return
}
2018-03-09 18:07:08 +00:00
// ExistingCertSerial tells you if the given bytes correspond to a know certificate.
func ExistingCertSerial(serial [8]byte) bool {
var m big.Int
m.SetBytes(serial[:])
c, _ := GetCertificate(m.Uint64())
2018-01-21 13:18:26 +00:00
return c.Id > 0
}
2018-03-09 18:07:08 +00:00
// RegisterCertificate registers a certificate in the database.
//
// "serial" is the certificate serial number
// "password" is the one used to crypt privatekey and .p12
func RegisterCertificate(serial uint64, password string) (Certificate, error) {
2018-01-21 13:18:26 +00:00
now := time.Now()
if _, err := DBExec("INSERT INTO certificates (id_cert, creation, password) VALUES (?, ?, ?)", serial, now, password); err != nil {
return Certificate{}, err
} else {
return Certificate{serial, now, password, nil}, nil
2018-01-21 13:18:26 +00:00
}
}
2018-03-09 18:07:08 +00:00
// Update applies modifications back to the database.
2021-11-22 14:35:07 +00:00
func (c *Certificate) Update() (int64, error) {
if res, err := DBExec("UPDATE certificates SET creation = ?, password = ?, revoked = ? WHERE id_cert = ?", c.Creation, c.Password, c.Revoked, c.Id); err != nil {
2018-01-21 13:18:26 +00:00
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// Revoke the certificate in database.
2018-01-21 13:18:26 +00:00
func (c *Certificate) Revoke() (int64, error) {
now := time.Now()
c.Revoked = &now
return c.Update()
}
2018-03-09 18:07:08 +00:00
// Delete the certificate entry in the database.
2018-01-21 13:18:26 +00:00
func (c Certificate) Delete() (int64, error) {
if res, err := DBExec("DELETE FROM certificates WHERE id_cert = ?", c.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// ClearCertificates removes all certificates from database.
2018-01-21 13:18:26 +00:00
func ClearCertificates() (int64, error) {
if res, err := DBExec("DELETE FROM certificates"); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}