Make deleteTokens strings

This commit is contained in:
Daan Sprenkels 2019-09-21 21:03:31 +02:00
parent 1c926a4864
commit f45c132b41
3 changed files with 28 additions and 51 deletions

View File

@ -0,0 +1,3 @@
{{define "title"}}
Success - rushlink
{{end}}

View File

@ -0,0 +1 @@
{{.Request.Host}}/{{.Paste.Key}}?deleteToken={{.Paste.DeleteToken}}

View File

@ -28,7 +28,7 @@ type storedPaste struct {
State pasteState
Content []byte
Key string
DeleteToken [16]byte
DeleteToken string
TimeCreated time.Time
}
@ -126,13 +126,11 @@ func viewPasteHandlerInner(w http.ResponseWriter, r *http.Request, flags viewPas
Bool bool
String string
}{Bool: false}
deleteToken, err := getDeleteTokenFromRequest(r)
if err != nil {
canDelete.String = "invalid"
} else if deleteToken == nil {
deleteToken := getDeleteTokenFromRequest(r)
if deleteToken == "" {
canDelete.String = "undefined"
} else {
if subtle.ConstantTimeCompare(deleteToken[:], storedPaste.DeleteToken[:]) == 1 {
if subtle.ConstantTimeCompare([]byte(deleteToken), []byte(storedPaste.DeleteToken)) == 1 {
canDelete.Bool = true
canDelete.String = "correct"
} else {
@ -162,7 +160,7 @@ func viewPasteHandlerInner(w http.ResponseWriter, r *http.Request, flags viewPas
}
w.Write(storedPaste.Content)
case stateDeleted:
renderError(w, r, http.StatusGone, "key has been deleted")
renderError(w, r, http.StatusGone, "paste has been deleted")
default:
log.Printf("error: invalid storedPaste.State (%v) for key '%v'\n", storedPaste.State, storedPaste.Key)
msg := fmt.Sprintf("internal server error: invalid storedPaste.State (%v\n)", storedPaste.State)
@ -215,33 +213,16 @@ func newRedirectPasteHandler(w http.ResponseWriter, r *http.Request) {
var storedPaste *storedPaste
if err := db.DB.Update(func(tx *bolt.Tx) error {
// Generate a new delete token for this paste
deleteToken, err := generateDeleteToken()
if err != nil {
return errors.Wrap(err, "generating delete token")
}
sp, err := shortenURL(tx, userURL, deleteToken)
storedPaste = sp
var err error
storedPaste, err = shortenURL(tx, userURL)
return err
}); err != nil {
log.Printf("error: %v\n", err)
renderInternalServerError(w, r, err)
return
}
deleteToken := hex.EncodeToString(storedPaste.DeleteToken[:])
saveRawurl := fmt.Sprintf("%v/%v?deleteToken=%v", r.Host, string(storedPaste.Key), deleteToken)
saveURL, err := r.URL.Parse(saveRawurl)
if err != nil {
err = errors.Wrap(err, "parsing url")
log.Printf("error: %v\n", err)
renderInternalServerError(w, r, err)
return
}
// TODO(dsprenkels) Put this into a template
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "%v\n", saveURL)
data := map[string]interface{}{"Paste": storedPaste}
render(w, r, "newRedirectPasteSuccess", data)
}
// Delete a URL from the database
@ -250,11 +231,8 @@ func deletePasteHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
key := vars["key"]
deleteToken, err := getDeleteTokenFromRequest(r)
if err != nil {
renderError(w, r, http.StatusBadRequest, "invalid delete token")
return
} else if deleteToken == nil {
deleteToken := getDeleteTokenFromRequest(r)
if deleteToken == "" {
renderError(w, r, http.StatusBadRequest, "no delete token provided")
return
}
@ -266,7 +244,7 @@ func deletePasteHandler(w http.ResponseWriter, r *http.Request) {
errorCode = http.StatusNotFound
return err
}
if subtle.ConstantTimeCompare(deleteToken[:], paste.DeleteToken[:]) == 1 {
if subtle.ConstantTimeCompare([]byte(deleteToken), []byte(paste.DeleteToken)) == 1 {
// Replace the old paste with a new empty paste
return savePaste(tx, key, storedPaste{
Key: paste.Key,
@ -301,7 +279,7 @@ func getURL(tx *bolt.Tx, key string) (*storedPaste, error) {
// Add a new URL to the database
//
// Returns the new ID if the url was successfully shortened
func shortenURL(tx *bolt.Tx, userURL *url.URL, deleteToken [16]byte) (*storedPaste, error) {
func shortenURL(tx *bolt.Tx, userURL *url.URL) (*storedPaste, error) {
pastesBucket := tx.Bucket([]byte(db.BUCKET_PASTES))
if pastesBucket == nil {
return nil, errors.Errorf("bucket %v does not exist", db.BUCKET_PASTES)
@ -337,6 +315,12 @@ func shortenURL(tx *bolt.Tx, userURL *url.URL, deleteToken [16]byte) (*storedPas
epoch++
}
// Also generate a deleteToken
deleteToken, err := generateDeleteToken()
if err != nil {
return nil, errors.Wrap(err, "generating delete token")
}
// Store the new key
storedPaste := storedPaste{
Type: typeRedirect,
@ -403,26 +387,15 @@ func generateURLKey(epoch int) (string, error) {
return string(urlKey), nil
}
func generateDeleteToken() ([16]byte, error) {
func generateDeleteToken() (string, error) {
var deleteToken [16]byte
_, err := rand.Read(deleteToken[:])
if err != nil {
return deleteToken, err
return "", err
}
return deleteToken, nil
return hex.EncodeToString(deleteToken[:]), nil
}
func getDeleteTokenFromRequest(r *http.Request) (*[16]byte, error) {
deleteTokenQuery := r.URL.Query().Get("deleteToken")
if deleteTokenQuery == "" {
return nil, nil
}
var deleteToken [16]byte
n, err := hex.Decode(deleteToken[:], []byte(deleteTokenQuery))
if err != nil {
return nil, errors.Wrap(err, "decoding hex")
} else if n != 16 {
return nil, errors.Errorf("invalid deleteToken length (%v bytes)", n)
}
return &deleteToken, nil
func getDeleteTokenFromRequest(r *http.Request) string {
return r.URL.Query().Get("deleteToken")
}