package main import ( "time" ) func (s *OpenVpnMgt) GenerateOTP(user string) ([]string, error) { return s.GenerateOTPGeneric(user, 30, "sha1", 10, 6) } // alternative OTP generator, not used at the moment // func (s *OpenVpnMgt) GenerateSlackOTP(user string) ([]string, error) { // return s.GenerateOTPGeneric(user, 60, "sha256", 30, 8) // } func (s *OpenVpnMgt) TokenPassword(c *vpnSession) (bool, string) { now := time.Now().Unix() if len(c.password) > 40 { salt := c.password[:4] for i := 0; i < 3; i++ { test := encode64(ComputeHmac256(c.baseHash(salt, now/30-int64(i)), s.otpMasterSecrets[0])) if salt+test == c.password { return true, c.password } } } salt := NewSalt() return false, salt + encode64(ComputeHmac256(c.baseHash(salt, now/30), s.otpMasterSecrets[0])) } func (s *OpenVpnMgt) GenerateOTPGeneric(user string, period int, algo string, secretLen int, digits int) ([]string, error) { codes := []string{} now := time.Now() secret := encodeSecret(ComputeHmac256(user, s.otpMasterSecrets[0])[:secretLen]) code, err := GenericTotpCode(secret, now, algo, digits, period) if err != nil { return codes, err } // the first code is the generic one codes = append(codes, code) for i := 1; i < 4; i++ { code, _ = GenericTotpCode(secret, now.Add(-1*time.Second*time.Duration(period*i)), algo, digits, period) codes = append(codes, code) } for j := 1; j < len(s.otpMasterSecrets); j++ { secret = encodeSecret(ComputeHmac256(user, s.otpMasterSecrets[j])[:secretLen]) for i := 0; i < 3; i++ { code, _ = GenericTotpCode(secret, now.Add(-1*time.Second*time.Duration(period*i)), algo, digits, period) codes = append(codes, code) } } return codes, nil }