2022-03-10 09:44:48 +00:00
|
|
|
package turn
|
|
|
|
|
|
|
|
import ( //nolint:gci
|
|
|
|
"crypto/hmac"
|
|
|
|
"crypto/sha1" //nolint:gosec,gci
|
|
|
|
"encoding/base64"
|
|
|
|
"net"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pion/logging"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GenerateLongTermCredentials can be used to create credentials valid for [duration] time
|
|
|
|
func GenerateLongTermCredentials(sharedSecret string, duration time.Duration) (string, string, error) {
|
|
|
|
t := time.Now().Add(duration).Unix()
|
|
|
|
username := strconv.FormatInt(t, 10)
|
|
|
|
password, err := longTermCredentials(username, sharedSecret)
|
|
|
|
return username, password, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func longTermCredentials(username string, sharedSecret string) (string, error) {
|
|
|
|
mac := hmac.New(sha1.New, []byte(sharedSecret))
|
|
|
|
_, err := mac.Write([]byte(username))
|
|
|
|
if err != nil {
|
|
|
|
return "", err // Not sure if this will ever happen
|
|
|
|
}
|
|
|
|
password := mac.Sum(nil)
|
|
|
|
return base64.StdEncoding.EncodeToString(password), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewLongTermAuthHandler returns a turn.AuthAuthHandler used with Long Term (or Time Windowed) Credentials.
|
|
|
|
// https://tools.ietf.org/search/rfc5389#section-10.2
|
|
|
|
func NewLongTermAuthHandler(sharedSecret string, l logging.LeveledLogger) AuthHandler {
|
|
|
|
if l == nil {
|
|
|
|
l = logging.NewDefaultLoggerFactory().NewLogger("turn")
|
|
|
|
}
|
|
|
|
return func(username, realm string, srcAddr net.Addr) (key []byte, ok bool) {
|
2024-01-03 21:57:33 +00:00
|
|
|
l.Tracef("Authentication username=%q realm=%q srcAddr=%v", username, realm, srcAddr)
|
2022-03-10 09:44:48 +00:00
|
|
|
t, err := strconv.Atoi(username)
|
|
|
|
if err != nil {
|
|
|
|
l.Errorf("Invalid time-windowed username %q", username)
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
if int64(t) < time.Now().Unix() {
|
|
|
|
l.Errorf("Expired time-windowed username %q", username)
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
password, err := longTermCredentials(username, sharedSecret)
|
|
|
|
if err != nil {
|
|
|
|
l.Error(err.Error())
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
return GenerateAuthKey(username, realm, password), true
|
|
|
|
}
|
|
|
|
}
|