You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/rtsp/auth.go

98 lines
2.4 KiB
Go

// Copyright 2020, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package rtsp
import (
"fmt"
"strings"
"github.com/q191201771/naza/pkg/nazalog"
"github.com/q191201771/naza/pkg/nazamd5"
)
// TODO chef: 考虑部分内容移入naza中
const (
AuthTypeDigest = "Digest"
AuthTypeBasic = "Basic"
AuthAlgorithm = "MD5"
)
type Auth struct {
Username string
Password string
Typ string
Realm string
Nonce string
Algorithm string
}
func (a *Auth) FeedWWWAuthenticate(s, username, password string) {
a.Username = username
a.Password = password
s = strings.TrimPrefix(s, HeaderWWWAuthenticate)
s = strings.TrimSpace(s)
if strings.HasPrefix(s, AuthTypeBasic) {
a.Typ = AuthTypeBasic
return
}
if !strings.HasPrefix(s, AuthTypeDigest) {
nazalog.Warnf("FeedWWWAuthenticate type invalid. v=%s", s)
return
}
a.Typ = AuthTypeDigest
a.Realm = a.getV(s, `realm="`)
a.Nonce = a.getV(s, `nonce="`)
a.Algorithm = a.getV(s, `algorithm="`)
if a.Realm == "" {
nazalog.Warnf("FeedWWWAuthenticate realm invalid. v=%s", s)
}
if a.Nonce == "" {
nazalog.Warnf("FeedWWWAuthenticate realm invalid. v=%s", s)
}
if a.Algorithm != AuthAlgorithm {
nazalog.Warnf("FeedWWWAuthenticate algorithm invalid, only support MD5. v=%s", s)
}
}
// 如果没有调用`FeedWWWAuthenticate`初始化过,则直接返回空字符串
func (a *Auth) MakeAuthorization(method, uri string) string {
if a.Username == "" {
return ""
}
switch a.Typ {
case AuthTypeBasic:
ha1 := nazamd5.MD5([]byte(fmt.Sprintf(`%s:%s`, a.Username, a.Password)))
return fmt.Sprintf(`%s %s`, a.Typ, ha1)
case AuthTypeDigest:
ha1 := nazamd5.MD5([]byte(fmt.Sprintf("%s:%s:%s", a.Username, a.Realm, a.Password)))
ha2 := nazamd5.MD5([]byte(fmt.Sprintf("%s:%s", method, uri)))
response := nazamd5.MD5([]byte(fmt.Sprintf("%s:%s:%s", ha1, a.Nonce, ha2)))
return fmt.Sprintf(`%s username="%s", realm="%s", nonce="%s", uri="%s", response="%s", algorithm="%s"`, a.Typ, a.Username, a.Realm, a.Nonce, uri, response, a.Algorithm)
}
return ""
}
func (a *Auth) getV(s string, pre string) string {
b := strings.Index(s, pre)
if b == -1 {
return ""
}
e := strings.Index(s[b+len(pre):], `"`)
if e == -1 {
return ""
}
return s[b+len(pre) : b+len(pre)+e]
}