mirror of
https://github.com/jech/galene.git
synced 2024-11-09 18:25:58 +01:00
Obfuscate WHIP ids.
If the WHIP session is not authenticated, then the only thing preventing an attacker from DELETEing the session is the session URL. Since client ids are known, obfuscate the id before using it in the session URL.
This commit is contained in:
parent
9f3bee8e37
commit
03038eaf45
2 changed files with 86 additions and 4 deletions
|
@ -136,3 +136,23 @@ func TestFormatICEServer(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestObfuscate(t *testing.T) {
|
||||||
|
id := newId()
|
||||||
|
obfuscated, err := obfuscate(id)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("obfuscate: %v", err)
|
||||||
|
}
|
||||||
|
id2, err := deobfuscate(obfuscated)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("deobfuscate: %v", err)
|
||||||
|
}
|
||||||
|
if id != id2 {
|
||||||
|
t.Errorf("not equal: %v, %v", id, id2)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = obfuscate("toto")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("obfuscate: no errror")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,11 @@ package webserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
@ -37,12 +40,58 @@ func parseWhip(pth string) (string, string) {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var idSecret []byte
|
||||||
|
var idCipher cipher.Block
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
idSecret = make([]byte, 16)
|
||||||
|
_, err := crand.Read(idSecret)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("crand.Read: %v", err)
|
||||||
|
}
|
||||||
|
idCipher, err = aes.NewCipher(idSecret)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("NewCipher: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newId() string {
|
func newId() string {
|
||||||
b := make([]byte, 16)
|
b := make([]byte, idCipher.BlockSize())
|
||||||
crand.Read(b)
|
crand.Read(b)
|
||||||
return base64.RawURLEncoding.EncodeToString(b)
|
return base64.RawURLEncoding.EncodeToString(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we obfuscate ids to avoid exposing the WHIP session URL
|
||||||
|
func obfuscate(id string) (string, error) {
|
||||||
|
v, err := base64.RawURLEncoding.DecodeString(id)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v) != idCipher.BlockSize() {
|
||||||
|
return "", errors.New("bad length")
|
||||||
|
}
|
||||||
|
|
||||||
|
idCipher.Encrypt(v, v)
|
||||||
|
|
||||||
|
return base64.RawURLEncoding.EncodeToString(v), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deobfuscate(id string) (string, error) {
|
||||||
|
v, err := base64.RawURLEncoding.DecodeString(id)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v) != idCipher.BlockSize() {
|
||||||
|
return "", errors.New("bad length")
|
||||||
|
}
|
||||||
|
|
||||||
|
idCipher.Decrypt(v, v)
|
||||||
|
|
||||||
|
return base64.RawURLEncoding.EncodeToString(v), nil
|
||||||
|
}
|
||||||
|
|
||||||
func canPresent(perms []string) bool {
|
func canPresent(perms []string) bool {
|
||||||
for _, p := range perms {
|
for _, p := range perms {
|
||||||
if p == "present" {
|
if p == "present" {
|
||||||
|
@ -186,6 +235,13 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
id := newId()
|
id := newId()
|
||||||
|
obfuscated, err := obfuscate(id)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Internal Server Error",
|
||||||
|
http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c := rtpconn.NewWhipClient(g, id, token)
|
c := rtpconn.NewWhipClient(g, id, token)
|
||||||
|
|
||||||
_, err = group.AddClient(g.Name(), c, creds)
|
_, err = group.AddClient(g.Name(), c, creds)
|
||||||
|
@ -214,7 +270,7 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.StatusInternalServerError)
|
http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Location", path.Join(r.URL.Path, id))
|
w.Header().Set("Location", path.Join(r.URL.Path, obfuscated))
|
||||||
w.Header().Set("Access-Control-Expose-Headers",
|
w.Header().Set("Access-Control-Expose-Headers",
|
||||||
"Location, Content-Type, Link")
|
"Location, Content-Type, Link")
|
||||||
whipICEServers(w)
|
whipICEServers(w)
|
||||||
|
@ -226,8 +282,14 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func whipResourceHandler(w http.ResponseWriter, r *http.Request) {
|
func whipResourceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
pth, id := parseWhip(r.URL.Path)
|
pth, obfuscated := parseWhip(r.URL.Path)
|
||||||
if pth == "" || id == "" {
|
if pth == "" || obfuscated == "" {
|
||||||
|
http.Error(w, "Internal server error",
|
||||||
|
http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, err := deobfuscate(obfuscated)
|
||||||
|
if err != nil {
|
||||||
http.Error(w, "Internal server error",
|
http.Error(w, "Internal server error",
|
||||||
http.StatusInternalServerError)
|
http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue