Allow setting local credentials via AgentConfig

Add local credential support to the AgentConfig and
validate credentials per RFC standard. If no credentials
are passed we still generate random ones ourselves.
This commit is contained in:
Nevio Vesic
2019-11-07 03:37:51 +01:00
committed by Sean DuBois
parent a4b52cdf38
commit a077bc201a
5 changed files with 79 additions and 13 deletions

View File

@@ -46,6 +46,7 @@ Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contribu
* [Aaron France](https://github.com/AeroNotix)
* [Chao Yuan](https://github.com/yuanchao0310)
* [Jason Maldonis](https://github.com/jjmaldonis)
* [Nevio Vesic](https://github.com/0x19)
### License
MIT License - see [LICENSE](LICENSE) for full text

View File

@@ -185,6 +185,13 @@ type AgentConfig struct {
PortMin uint16
PortMax uint16
// LocalUfrag and LocalPwd values used to perform connectivity
// checks. The values MUST be unguessable, with at least 128 bits of
// random number generator output used to generate the password, and
// at least 24 bits of output to generate the username fragment.
LocalUfrag string
LocalPwd string
// Trickle specifies whether or not ice agent should trickle candidates or
// work perform synchronous gathering.
Trickle bool
@@ -310,6 +317,26 @@ func NewAgent(config *AgentConfig) (*Agent, error) {
return nil, ErrPort
}
// local username fragment and password
localUfrag := randSeq(16)
localPwd := randSeq(32)
if config.LocalUfrag != "" {
if len([]rune(config.LocalUfrag))*8 < 24 {
return nil, ErrLocalUfragInsufficientBits
}
localUfrag = config.LocalUfrag
}
if config.LocalPwd != "" {
if len([]rune(config.LocalPwd))*8 < 128 {
return nil, ErrLocalPwdInsufficientBits
}
localPwd = config.LocalPwd
}
mDNSName, err := generateMulticastDNSName()
if err != nil {
return nil, err
@@ -350,9 +377,8 @@ func NewAgent(config *AgentConfig) (*Agent, error) {
checklist: make([]*candidatePair, 0),
urls: config.Urls,
networkTypes: config.NetworkTypes,
localUfrag: randSeq(16),
localPwd: randSeq(32),
localUfrag: localUfrag,
localPwd: localPwd,
taskChan: make(chan task),
onConnected: make(chan struct{}),
buffer: packetio.NewBuffer(),

View File

@@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/pion/logging"
"github.com/pion/stun"
"github.com/pion/transport/test"
"github.com/pion/transport/vnet"
@@ -1231,3 +1232,32 @@ func TestBindingRequestTimeout(t *testing.T) {
assert.Equal(t, len(a.pendingBindingRequests), expectedRemovalCount, "Binding invalidation due to timeout did not remove the correct number of binding requests")
assert.NoError(t, a.Close())
}
// TestAgentCredentials checks if local username fragments and passwords (if set) meet RFC standard
// and ensure it's backwards compatible with previous versions of the pion/ice
func TestAgentCredentials(t *testing.T) {
// Make sure to pass travis check by disabling the logs
log := logging.NewDefaultLoggerFactory()
log.DefaultLogLevel = logging.LogLevelDisabled
// Agent should not require any of the usernames and password to be set
// If set, they should follow the default 16/128 bits random number generator strategy
agent, err := NewAgent(&AgentConfig{Trickle: true, LoggerFactory: log})
assert.NoError(t, err)
assert.GreaterOrEqual(t, len([]rune(agent.localUfrag))*8, 24)
assert.GreaterOrEqual(t, len([]rune(agent.localPwd))*8, 128)
assert.NoError(t, agent.Close())
// Should honor RFC standards
// Local values MUST be unguessable, with at least 128 bits of
// random number generator output used to generate the password, and
// at least 24 bits of output to generate the username fragment.
_, err = NewAgent(&AgentConfig{Trickle: true, LocalUfrag: "xx", LoggerFactory: log})
assert.EqualError(t, err, ErrLocalUfragInsufficientBits.Error())
_, err = NewAgent(&AgentConfig{Trickle: true, LocalPwd: "xxxxxx", LoggerFactory: log})
assert.EqualError(t, err, ErrLocalPwdInsufficientBits.Error())
}

View File

@@ -21,6 +21,14 @@ var (
// ErrPort indicates malformed port is provided.
ErrPort = errors.New("invalid port")
// ErrLocalUfragInsufficientBits indicates local username fragment insufficient bits are provided.
// Have to be at least 24 bits long
ErrLocalUfragInsufficientBits = errors.New("local username fragment is less than 24 bits long")
// ErrLocalPwdInsufficientBits indicates local passoword insufficient bits are provided.
// Have to be at least 128 bits long
ErrLocalPwdInsufficientBits = errors.New("local password is less than 128 bits long")
// ErrProtoType indicates an unsupported transport type was provided.
ErrProtoType = errors.New("invalid transport protocol type")

1
go.sum
View File

@@ -31,6 +31,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b h1:lkjdUzSyJ5P1+eal9fxXX9Xg2BTfswsonKUse48C0uE=
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9 h1:DPz9iiH3YoKiKhX/ijjoZvT0VFwK2c6CWYWQ7Zyr8TU=
golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=