2021-09-17 11:44:35 +07:00
|
|
|
package ntp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2021-09-17 16:53:59 +07:00
|
|
|
"errors"
|
2021-09-17 11:44:35 +07:00
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
2021-11-23 16:45:38 +07:00
|
|
|
"github.com/authelia/authelia/v4/internal/logging"
|
2021-09-17 11:44:35 +07:00
|
|
|
"github.com/authelia/authelia/v4/internal/utils"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewProvider instantiate a ntp provider given a configuration.
|
|
|
|
func NewProvider(config *schema.NTPConfiguration) *Provider {
|
2021-11-23 16:45:38 +07:00
|
|
|
return &Provider{
|
|
|
|
config: config,
|
|
|
|
log: logging.Logger(),
|
|
|
|
}
|
2021-09-17 11:44:35 +07:00
|
|
|
}
|
|
|
|
|
2021-09-17 16:53:59 +07:00
|
|
|
// StartupCheck implements the startup check provider interface.
|
2021-11-23 16:45:38 +07:00
|
|
|
func (p *Provider) StartupCheck() (err error) {
|
2021-09-17 11:44:35 +07:00
|
|
|
conn, err := net.Dial("udp", p.config.Address)
|
|
|
|
if err != nil {
|
2021-11-23 16:45:38 +07:00
|
|
|
p.log.Warnf("Could not connect to NTP server to validate the system time is properly synchronized: %+v", err)
|
2021-09-17 16:53:59 +07:00
|
|
|
|
|
|
|
return nil
|
2021-09-17 11:44:35 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
|
|
if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
|
2021-11-23 16:45:38 +07:00
|
|
|
p.log.Warnf("Could not connect to NTP server to validate the system time is properly synchronized: %+v", err)
|
2021-09-17 16:53:59 +07:00
|
|
|
|
|
|
|
return nil
|
2021-09-17 11:44:35 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
version := ntpV4
|
|
|
|
if p.config.Version == 3 {
|
|
|
|
version = ntpV3
|
|
|
|
}
|
|
|
|
|
|
|
|
req := &ntpPacket{LeapVersionMode: ntpLeapVersionClientMode(false, version)}
|
|
|
|
|
|
|
|
if err := binary.Write(conn, binary.BigEndian, req); err != nil {
|
2021-11-23 16:45:38 +07:00
|
|
|
p.log.Warnf("Could not write to the NTP server socket to validate the system time is properly synchronized: %+v", err)
|
2021-09-17 16:53:59 +07:00
|
|
|
|
|
|
|
return nil
|
2021-09-17 11:44:35 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
now := time.Now()
|
|
|
|
|
|
|
|
resp := &ntpPacket{}
|
|
|
|
|
|
|
|
if err := binary.Read(conn, binary.BigEndian, resp); err != nil {
|
2021-11-23 16:45:38 +07:00
|
|
|
p.log.Warnf("Could not read from the NTP server socket to validate the system time is properly synchronized: %+v", err)
|
2021-09-17 16:53:59 +07:00
|
|
|
|
|
|
|
return nil
|
2021-09-17 11:44:35 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
maxOffset, _ := utils.ParseDurationString(p.config.MaximumDesync)
|
|
|
|
|
|
|
|
ntpTime := ntpPacketToTime(resp)
|
|
|
|
|
2021-09-17 16:53:59 +07:00
|
|
|
if result := ntpIsOffsetTooLarge(maxOffset, now, ntpTime); result {
|
|
|
|
return errors.New("the system clock is not synchronized accurately enough with the configured NTP server")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2021-09-17 11:44:35 +07:00
|
|
|
}
|