mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2024-05-15 20:16:34 +02:00
Validate received SDP earlier.
This commit is contained in:
parent
0aed690463
commit
d27bfe4cf6
|
@ -32,6 +32,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
"github.com/pion/sdp/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -563,12 +564,33 @@ type MessageClientMessageData struct {
|
||||||
RoomType string `json:"roomType"`
|
RoomType string `json:"roomType"`
|
||||||
Bitrate int `json:"bitrate,omitempty"`
|
Bitrate int `json:"bitrate,omitempty"`
|
||||||
Payload map[string]interface{} `json:"payload"`
|
Payload map[string]interface{} `json:"payload"`
|
||||||
|
|
||||||
|
offerSdp *sdp.SessionDescription // Only set if Type == "offer"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageClientMessageData) CheckValid() error {
|
func (m *MessageClientMessageData) CheckValid() error {
|
||||||
if !IsValidStreamType(m.RoomType) {
|
if !IsValidStreamType(m.RoomType) {
|
||||||
return fmt.Errorf("invalid room type: %s", m.RoomType)
|
return fmt.Errorf("invalid room type: %s", m.RoomType)
|
||||||
}
|
}
|
||||||
|
if m.Type == "offer" {
|
||||||
|
sdpValue, found := m.Payload["sdp"]
|
||||||
|
if !found {
|
||||||
|
return NewError("no_offer_sdp", "Offer does not contain a SDP.")
|
||||||
|
}
|
||||||
|
sdpText, ok := sdpValue.(string)
|
||||||
|
if !ok {
|
||||||
|
return NewError("invalid_offer_sdp", "Offer does not contain a valid SDP.")
|
||||||
|
}
|
||||||
|
|
||||||
|
var sdp sdp.SessionDescription
|
||||||
|
if err := sdp.Unmarshal([]byte(sdpText)); err != nil {
|
||||||
|
return NewErrorDetail("invalid_offer_sdp", "Error parsing offer SDP.", map[string]interface{}{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
m.offerSdp = &sdp
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -740,23 +740,6 @@ func (s *ClientSession) SubscriberClosed(subscriber McuSubscriber) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SdpError struct {
|
|
||||||
message string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SdpError) Error() string {
|
|
||||||
return e.message
|
|
||||||
}
|
|
||||||
|
|
||||||
type WrappedSdpError struct {
|
|
||||||
SdpError
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *WrappedSdpError) Unwrap() error {
|
|
||||||
return e.err
|
|
||||||
}
|
|
||||||
|
|
||||||
type PermissionError struct {
|
type PermissionError struct {
|
||||||
permission Permission
|
permission Permission
|
||||||
}
|
}
|
||||||
|
@ -769,23 +752,10 @@ func (e *PermissionError) Error() string {
|
||||||
return fmt.Sprintf("permission \"%s\" not found", e.permission)
|
return fmt.Sprintf("permission \"%s\" not found", e.permission)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClientSession) isSdpAllowedToSendLocked(payload map[string]interface{}) (MediaType, error) {
|
func (s *ClientSession) isSdpAllowedToSendLocked(sdp *sdp.SessionDescription) (MediaType, error) {
|
||||||
sdpValue, found := payload["sdp"]
|
if sdp == nil {
|
||||||
if !found {
|
// Should have already been checked when data was validated.
|
||||||
return 0, &SdpError{"payload does not contain a sdp"}
|
return 0, fmt.Errorf("no offer sdp provided")
|
||||||
}
|
|
||||||
sdpText, ok := sdpValue.(string)
|
|
||||||
if !ok {
|
|
||||||
return 0, &SdpError{"payload does not contain a valid sdp"}
|
|
||||||
}
|
|
||||||
var sdp sdp.SessionDescription
|
|
||||||
if err := sdp.Unmarshal([]byte(sdpText)); err != nil {
|
|
||||||
return 0, &WrappedSdpError{
|
|
||||||
SdpError: SdpError{
|
|
||||||
message: fmt.Sprintf("could not parse sdp: %s", err),
|
|
||||||
},
|
|
||||||
err: err,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var mediaTypes MediaType
|
var mediaTypes MediaType
|
||||||
|
@ -823,8 +793,8 @@ func (s *ClientSession) IsAllowedToSend(data *MessageClientMessageData) error {
|
||||||
// Client is allowed to publish any media (audio / video).
|
// Client is allowed to publish any media (audio / video).
|
||||||
return nil
|
return nil
|
||||||
} else if data != nil && data.Type == "offer" {
|
} else if data != nil && data.Type == "offer" {
|
||||||
// Parse SDP to check what user is trying to publish and check permissions accordingly.
|
// Check what user is trying to publish and check permissions accordingly.
|
||||||
if _, err := s.isSdpAllowedToSendLocked(data.Payload); err != nil {
|
if _, err := s.isSdpAllowedToSendLocked(data.offerSdp); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,7 +824,7 @@ func (s *ClientSession) checkOfferTypeLocked(streamType StreamType, data *Messag
|
||||||
|
|
||||||
return MediaTypeScreen, nil
|
return MediaTypeScreen, nil
|
||||||
} else if data != nil && data.Type == "offer" {
|
} else if data != nil && data.Type == "offer" {
|
||||||
mediaTypes, err := s.isSdpAllowedToSendLocked(data.Payload)
|
mediaTypes, err := s.isSdpAllowedToSendLocked(data.offerSdp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
5
hub.go
5
hub.go
|
@ -2178,11 +2178,6 @@ func (h *Hub) processMcuMessage(session *ClientSession, client_message *ClientMe
|
||||||
sendNotAllowed(session, client_message, "Not allowed to publish.")
|
sendNotAllowed(session, client_message, "Not allowed to publish.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err, ok := err.(*SdpError); ok {
|
|
||||||
log.Printf("Session %s sent unsupported offer %s, ignoring (%s)", session.PublicId(), data.RoomType, err)
|
|
||||||
sendNotAllowed(session, client_message, "Not allowed to publish.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "selectStream":
|
case "selectStream":
|
||||||
if session.PublicId() == message.Recipient.SessionId {
|
if session.PublicId() == message.Recipient.SessionId {
|
||||||
log.Printf("Not selecting substream for own %s stream in session %s", data.RoomType, session.PublicId())
|
log.Printf("Not selecting substream for own %s stream in session %s", data.RoomType, session.PublicId())
|
||||||
|
|
|
@ -777,9 +777,10 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s
|
||||||
fallthrough
|
fallthrough
|
||||||
case "candidate":
|
case "candidate":
|
||||||
mcuData = &signaling.MessageClientMessageData{
|
mcuData = &signaling.MessageClientMessageData{
|
||||||
Type: payload.Type,
|
RoomType: string(mcuClient.StreamType()),
|
||||||
Sid: payload.Sid,
|
Type: payload.Type,
|
||||||
Payload: payload.Payload,
|
Sid: payload.Sid,
|
||||||
|
Payload: payload.Payload,
|
||||||
}
|
}
|
||||||
case "endOfCandidates":
|
case "endOfCandidates":
|
||||||
// Ignore but confirm, not passed along to Janus anyway.
|
// Ignore but confirm, not passed along to Janus anyway.
|
||||||
|
@ -796,14 +797,21 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s
|
||||||
fallthrough
|
fallthrough
|
||||||
case "sendoffer":
|
case "sendoffer":
|
||||||
mcuData = &signaling.MessageClientMessageData{
|
mcuData = &signaling.MessageClientMessageData{
|
||||||
Type: payload.Type,
|
RoomType: string(mcuClient.StreamType()),
|
||||||
Sid: payload.Sid,
|
Type: payload.Type,
|
||||||
|
Sid: payload.Sid,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
session.sendMessage(message.NewErrorServerMessage(UnsupportedPayload))
|
session.sendMessage(message.NewErrorServerMessage(UnsupportedPayload))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := mcuData.CheckValid(); err != nil {
|
||||||
|
log.Printf("Received invalid payload %+v for %s client %s: %s", mcuData, mcuClient.StreamType(), payload.ClientId, err)
|
||||||
|
session.sendMessage(message.NewErrorServerMessage(UnsupportedPayload))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
mcuClient.SendMessage(ctx, nil, mcuData, func(err error, response map[string]interface{}) {
|
mcuClient.SendMessage(ctx, nil, mcuData, func(err error, response map[string]interface{}) {
|
||||||
var responseMsg *signaling.ProxyServerMessage
|
var responseMsg *signaling.ProxyServerMessage
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue