changeset 215:f345edb409b2

Made serialisation and deserialisation of sessions more robust (fixed a small bug on the way).
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 24 Jul 2018 11:09:18 +0200
parents da24df80c25d
children 494a257e7715
files auth/connection.go auth/encode.go auth/session.go
diffstat 3 files changed, 83 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/auth/connection.go	Tue Jul 24 10:58:38 2018 +0200
+++ b/auth/connection.go	Tue Jul 24 11:09:18 2018 +0200
@@ -2,7 +2,6 @@
 
 import (
 	"database/sql"
-	"encoding/binary"
 	"errors"
 	"io"
 	"log"
@@ -42,10 +41,13 @@
 		return err
 	}
 	access, err := c.last().MarshalText()
-	if err == nil {
-		err = binary.Write(w, binary.BigEndian, string(access))
+	if err != nil {
+		return err
 	}
-	return err
+	wr := binWriter{w: w}
+	wr.write(uint32(len(access)))
+	wr.write(access)
+	return wr.err
 }
 
 func (c *Connection) deserialize(r io.Reader) error {
@@ -54,13 +56,18 @@
 		return err
 	}
 
-	var access string
-	if err := binary.Read(r, binary.BigEndian, &access); err != nil {
-		return err
+	rd := binReader{r: r}
+	var l uint32
+	rd.read(&l)
+	access := make([]byte, l)
+	rd.read(access)
+
+	if rd.err != nil {
+		return rd.err
 	}
 
 	var t time.Time
-	if err := t.UnmarshalText([]byte(access)); err != nil {
+	if err := t.UnmarshalText(access); err != nil {
 		return err
 	}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auth/encode.go	Tue Jul 24 11:09:18 2018 +0200
@@ -0,0 +1,52 @@
+package auth
+
+import (
+	"encoding/binary"
+	"io"
+)
+
+type binReader struct {
+	r   io.Reader
+	err error
+}
+
+func (r *binReader) read(x interface{}) {
+	if r.err == nil {
+		r.err = binary.Read(r.r, binary.BigEndian, x)
+	}
+}
+
+func (r *binReader) readString(s *string) {
+	if r.err != nil {
+		return
+	}
+	var l uint32
+	if r.err = binary.Read(r.r, binary.BigEndian, &l); r.err != nil {
+		return
+	}
+	b := make([]byte, l)
+	if r.err = binary.Read(r.r, binary.BigEndian, b); r.err != nil {
+		return
+	}
+	*s = string(b)
+}
+
+type binWriter struct {
+	w   io.Writer
+	err error
+}
+
+func (w *binWriter) write(x interface{}) {
+	if w.err == nil {
+		w.err = binary.Write(w.w, binary.BigEndian, x)
+	}
+}
+
+func (w *binWriter) writeString(s string) {
+	if w.err == nil {
+		w.err = binary.Write(w.w, binary.BigEndian, uint32(len(s)))
+	}
+	if w.err == nil {
+		w.err = binary.Write(w.w, binary.BigEndian, []byte(s))
+	}
+}
--- a/auth/session.go	Tue Jul 24 10:58:38 2018 +0200
+++ b/auth/session.go	Tue Jul 24 11:09:18 2018 +0200
@@ -3,7 +3,6 @@
 import (
 	"crypto/rand"
 	"encoding/base64"
-	"encoding/binary"
 	"io"
 	"time"
 )
@@ -32,43 +31,33 @@
 }
 
 func (s *Session) serialize(w io.Writer) error {
-	var err error
-	write := func(data interface{}) {
-		if err == nil {
-			err = binary.Write(w, binary.BigEndian, data)
-		}
+	wr := binWriter{w: w}
+	wr.write(s.ExpiresAt)
+	wr.writeString(s.User)
+	wr.writeString(s.Password)
+	wr.write(uint32(len(s.Roles)))
+	for _, role := range s.Roles {
+		wr.writeString(role)
 	}
-	write(s.ExpiresAt)
-	write(s.User)
-	write(s.Password)
-	write(uint32(len(s.Roles)))
-	for _, role := range s.Roles {
-		write(role)
-	}
-	return err
+	return wr.err
 }
 
 func (s *Session) deserialize(r io.Reader) error {
-	var err error
-	read := func(data interface{}) {
-		if err == nil {
-			err = binary.Read(r, binary.BigEndian, data)
-		}
-	}
 	var x Session
 	var n uint32
-	read(&x.ExpiresAt)
-	read(&x.User)
-	read(&x.Password)
-	read(&n)
+	rd := binReader{r: r}
+	rd.read(&x.ExpiresAt)
+	rd.readString(&x.User)
+	rd.readString(&x.Password)
+	rd.read(&n)
 	x.Roles = make([]string, n)
 	for i := uint32(0); n > 0 && i < n; i++ {
-		read(&x.Roles[i])
+		rd.readString(&x.Roles[i])
 	}
-	if err == nil {
+	if rd.err == nil {
 		*s = x
 	}
-	return err
+	return rd.err
 }
 
 func GenerateSessionKey() string {