return an error in case the random number generator fails (#2120)

This commit is contained in:
Alessandro Ros 2023-07-30 22:30:41 +02:00 committed by GitHub
parent dfc8e1fa91
commit b42154fa6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 84 additions and 25 deletions

View File

@ -177,9 +177,8 @@ func TestConfEncryption(t *testing.T) {
copy(secretKey[:], key)
var nonce [24]byte
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
panic(err)
}
_, err := io.ReadFull(rand.Reader, nonce[:])
require.NoError(t, err)
encrypted := secretbox.Seal(nonce[:], []byte(plaintext), &nonce, &secretKey)
return base64.StdEncoding.EncodeToString(encrypted)

View File

@ -160,7 +160,7 @@ func marshalICEFragment(offer *webrtc.SessionDescription, candidates []*webrtc.I
type webRTCHTTPServerParent interface {
logger.Writer
generateICEServers() []webrtc.ICEServer
generateICEServers() ([]webrtc.ICEServer, error)
sessionNew(req webRTCSessionNewReq) webRTCSessionNewRes
sessionAddCandidates(req webRTCSessionAddCandidatesReq) webRTCSessionAddCandidatesRes
}
@ -346,9 +346,15 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
case "whip", "whep":
switch ctx.Request.Method {
case http.MethodOptions:
servers, err := s.parent.generateICEServers()
if err != nil {
ctx.Writer.WriteHeader(http.StatusInternalServerError)
return
}
ctx.Writer.Header().Set("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PATCH")
ctx.Writer.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, If-Match")
ctx.Writer.Header()["Link"] = iceServersToLinkHeader(s.parent.generateICEServers())
ctx.Writer.Header()["Link"] = iceServersToLinkHeader(servers)
ctx.Writer.WriteHeader(http.StatusOK)
case http.MethodPost:
@ -376,12 +382,18 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
return
}
servers, err := s.parent.generateICEServers()
if err != nil {
ctx.Writer.WriteHeader(http.StatusInternalServerError)
return
}
ctx.Writer.Header().Set("Content-Type", "application/sdp")
ctx.Writer.Header().Set("Access-Control-Expose-Headers", "E-Tag, Accept-Patch, Link")
ctx.Writer.Header().Set("E-Tag", res.sx.secret.String())
ctx.Writer.Header().Set("ID", res.sx.uuid.String())
ctx.Writer.Header().Set("Accept-Patch", "application/trickle-ice-sdpfrag")
ctx.Writer.Header()["Link"] = iceServersToLinkHeader(s.parent.generateICEServers())
ctx.Writer.Header()["Link"] = iceServersToLinkHeader(servers)
ctx.Writer.Header().Set("Location", ctx.Request.URL.String())
ctx.Writer.WriteHeader(http.StatusCreated)
ctx.Writer.Write(res.answer)

View File

@ -31,33 +31,57 @@ const (
webrtcTurnSecretExpiration = 24 * 3600 * time.Second
)
func randInt63() int64 {
func randInt63() (int64, error) {
var b [8]byte
rand.Read(b[:])
_, err := rand.Read(b[:])
if err != nil {
return 0, err
}
return int64(uint64(b[0]&0b01111111)<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 |
uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7]))
uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7])), nil
}
// https://cs.opensource.google/go/go/+/refs/tags/go1.20.4:src/math/rand/rand.go;l=119
func randInt63n(n int64) int64 {
func randInt63n(n int64) (int64, error) {
if n&(n-1) == 0 { // n is power of two, can mask
return randInt63() & (n - 1)
r, err := randInt63()
if err != nil {
return 0, err
}
return r & (n - 1), nil
}
max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
v := randInt63()
for v > max {
v = randInt63()
v, err := randInt63()
if err != nil {
return 0, err
}
return v % n
for v > max {
v, err = randInt63()
if err != nil {
return 0, err
}
}
return v % n, nil
}
func randomTurnUser() string {
func randomTurnUser() (string, error) {
const charset = "abcdefghijklmnopqrstuvwxyz1234567890"
b := make([]byte, 20)
for i := range b {
b[i] = charset[int(randInt63n(int64(len(charset))))]
j, err := randInt63n(int64(len(charset)))
if err != nil {
return "", err
}
b[i] = charset[int(j)]
}
return string(b)
return string(b), nil
}
type webRTCManagerAPISessionsListRes struct {
@ -363,14 +387,23 @@ func (m *webRTCManager) findSessionByUUID(uuid uuid.UUID) *webRTCSession {
return nil
}
func (m *webRTCManager) generateICEServers() []webrtc.ICEServer {
func (m *webRTCManager) generateICEServers() ([]webrtc.ICEServer, error) {
ret := make([]webrtc.ICEServer, len(m.iceServers))
for i, server := range m.iceServers {
if server.Username == "AUTH_SECRET" {
expireDate := time.Now().Add(webrtcTurnSecretExpiration).Unix()
server.Username = strconv.FormatInt(expireDate, 10) + ":" + randomTurnUser()
user, err := randomTurnUser()
if err != nil {
return nil, err
}
server.Username = strconv.FormatInt(expireDate, 10) + ":" + user
h := hmac.New(sha1.New, []byte(server.Password))
h.Write([]byte(server.Username))
server.Password = base64.StdEncoding.EncodeToString(h.Sum(nil))
}
@ -380,7 +413,8 @@ func (m *webRTCManager) generateICEServers() []webrtc.ICEServer {
Credential: server.Password,
}
}
return ret
return ret, nil
}
// sessionNew is called by webRTCHTTPServer.

View File

@ -274,8 +274,13 @@ func (s *webRTCSession) runPublish() (int, error) {
defer res.path.publisherRemove(pathPublisherRemoveReq{author: s})
servers, err := s.parent.generateICEServers()
if err != nil {
return http.StatusInternalServerError, err
}
pc, err := newPeerConnection(
s.parent.generateICEServers(),
servers,
s.iceHostNAT1To1IPs,
s.iceUDPMux,
s.iceTCPMux,
@ -446,8 +451,13 @@ func (s *webRTCSession) runRead() (int, error) {
return http.StatusBadRequest, err
}
servers, err := s.parent.generateICEServers()
if err != nil {
return http.StatusInternalServerError, err
}
pc, err := newPeerConnection(
s.parent.generateICEServers(),
servers,
s.iceHostNAT1To1IPs,
s.iceUDPMux,
s.iceTCPMux,

View File

@ -119,7 +119,10 @@ func (c *C1S1) Write(w io.Writer, isC1 bool) error {
copy(buf[4:], []byte{0, 0, 0, 0})
if c.Random == nil {
rand.Read(buf[8:])
_, err := rand.Read(buf[8:])
if err != nil {
return err
}
c.Random = buf[8:]
} else {
copy(buf[8:], c.Random)

View File

@ -63,7 +63,8 @@ func TestHandshakeFallback(t *testing.T) {
require.NoError(t, err)
c1 := make([]byte, 1536)
rand.Read(c1[8:])
_, err = rand.Read(c1[8:])
require.NoError(t, err)
_, err = conn.Write(c1)
require.NoError(t, err)