gnunet-gns-registrar

GNU Name System registrar
Log | Files | Refs | README

commit 42c2a6856591e5dca5d9dde8a150b13070394fd5
parent b155150004b3ae3bef58f6d3096f8c4d91d6a72e
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Mon, 18 Mar 2024 21:32:09 +0100

Sanitize user inputs.

Diffstat:
Mpkg/rest/gnsregistrar.go | 63++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 34 insertions(+), 29 deletions(-)

diff --git a/pkg/rest/gnsregistrar.go b/pkg/rest/gnsregistrar.go @@ -27,6 +27,7 @@ import ( "html/template" "io" "net/http" + "net/url" "os" "os/exec" "strings" @@ -275,7 +276,7 @@ func (t *Registrar) searchPage(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, fmt.Sprintf("/?error=%s", err), http.StatusSeeOther) return } - http.Redirect(w, r, "/name/" + label, http.StatusSeeOther) + http.Redirect(w, r, "/name/" + url.QueryEscape(label), http.StatusSeeOther) return } @@ -389,9 +390,10 @@ func (t *Registrar) updateRegistration(w http.ResponseWriter, r *http.Request) { zkey string ) vars := mux.Vars(r) + sanitizedLabel := url.QueryEscape(vars["label"]) w.Header().Set("Content-Type", "text/html; charset=utf-8") client = &http.Client{} - req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + vars["label"] + "?include_maintenance=yes", nil) + req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + sanitizedLabel + "?include_maintenance=yes", nil) if t.GnunetBasicAuthEnabled { req.SetBasicAuth(t.GnunetUsername, t.GnunetPassword) } @@ -422,23 +424,23 @@ func (t *Registrar) updateRegistration(w http.ResponseWriter, r *http.Request) { return } } else if http.StatusNotFound != resp.StatusCode { - http.Redirect(w, r, "/name/" + vars["label"] + "?error=Error determining zone status", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Error determining zone status", http.StatusSeeOther) return } if nil == regMetadata { - http.Redirect(w, r, "/name/"+vars["label"], http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel, http.StatusSeeOther) return } err = r.ParseForm() if nil != err { fmt.Printf("Unable to parse form: " + err.Error()) - http.Redirect(w, r, "/name/"+vars["label"] + "?error=Form invalid", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Form invalid", http.StatusSeeOther) return } token = r.Form.Get("token") zkey = r.Form.Get("zkey") if regMetadata.RegistrationID != token { - http.Redirect(w, r, "/name/"+vars["label"] + "?error=Unauthorized", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Unauthorized", http.StatusSeeOther) return } for _, record := range namestoreResponse.Records { @@ -454,10 +456,10 @@ func (t *Registrar) updateRegistration(w http.ResponseWriter, r *http.Request) { err = t.createOrUpdateRegistration(&namestoreResponse) if nil != err { fmt.Println(err) - http.Redirect(w, r, "/name/"+vars["label"] + "?error=Update: Internal error", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Update: Internal error", http.StatusSeeOther) return } - http.Redirect(w, r, "/name/"+vars["label"] + "/edit?token=" + token, http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "/edit?token=" + token, http.StatusSeeOther) return } @@ -469,9 +471,10 @@ func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) { client *http.Client ) vars := mux.Vars(r) + sanitizedLabel := url.QueryEscape(vars["label"]) w.Header().Set("Content-Type", "text/html; charset=utf-8") client = &http.Client{} - req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + vars["label"] + "?include_maintenance=yes", nil) + req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + sanitizedLabel + "?include_maintenance=yes", nil) if t.GnunetBasicAuthEnabled { req.SetBasicAuth(t.GnunetUsername, t.GnunetPassword) } @@ -502,15 +505,15 @@ func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) { return } } else if http.StatusNotFound != resp.StatusCode { - http.Redirect(w, r, "/name/" + vars["label"] + "?error=Error determining zone status", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Error determining zone status", http.StatusSeeOther) return } if nil == regMetadata { - http.Redirect(w, r, "/name/"+vars["label"], http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel, http.StatusSeeOther) return } if regMetadata.RegistrationID != r.URL.Query().Get("token") { - http.Redirect(w, r, "/name/"+vars["label"] + "?error=Unauthorized", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Unauthorized", http.StatusSeeOther) return } for _, record := range namestoreResponse.Records { @@ -555,12 +558,13 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") client = &http.Client{} label = vars["label"] + sanitizedLabel := url.QueryEscape(vars["label"]) err := t.isNameValid(label) if nil != err { http.Redirect(w, r, fmt.Sprintf("/?error=%s", err), http.StatusSeeOther) return } - req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + label + "?include_maintenance=yes", nil) + req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + sanitizedLabel + "?include_maintenance=yes", nil) if t.GnunetBasicAuthEnabled { req.SetBasicAuth(t.GnunetUsername, t.GnunetPassword) } @@ -584,19 +588,19 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) { fmt.Printf("Failed to get zone contents" + err.Error()) return } - regMetadata, err = t.getCurrentRegistrationMetadata(label, &namestoreResponse) + regMetadata, err = t.getCurrentRegistrationMetadata(sanitizedLabel, &namestoreResponse) if err != nil { http.Redirect(w, r, "/" + "?error=Registration failed: Failed to get registration metadata", http.StatusSeeOther) fmt.Printf("Failed to get registration metadata" + err.Error()) return } } else if http.StatusNotFound != resp.StatusCode { - http.Redirect(w, r, "/name/" + label + "?error=Registration failed: Error determining zone status", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Error determining zone status", http.StatusSeeOther) return } if nil != regMetadata { if regMetadata.Paid == false { - http.Redirect(w, r, "/name/"+ label + "?error=Registration failed: Pending buy order", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Pending buy order", http.StatusSeeOther) return } regMetadata.Paid = false @@ -605,20 +609,20 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) { regId = generateRegistrationId() } summaryMsg := strings.Replace(t.SummaryTemplateString, "${NAME}", label, 1) - orderID, newOrderErr := t.Merchant.AddNewOrder(*t.RegistrationCost, summaryMsg, t.BaseUrl + "/name/" + label + "/edit?token=" + regId) + orderID, newOrderErr := t.Merchant.AddNewOrder(*t.RegistrationCost, summaryMsg, t.BaseUrl + "/name/" + sanitizedLabel + "/edit?token=" + regId) if newOrderErr != nil { fmt.Println(newOrderErr) - http.Redirect(w, r, "/name/" + label + "?error=Registration failed: Unable to create order", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Unable to create order", http.StatusSeeOther) return } _, payto, paytoErr := t.Merchant.IsOrderPaid(orderID) if paytoErr != nil { - http.Redirect(w, r, "/name/" + label + "?error=Registration failed: Error getting payment data", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Error getting payment data", http.StatusSeeOther) return } qrPng, qrErr := qrcode.Encode(payto, qrcode.Medium, 256) if qrErr != nil { - http.Redirect(w, r, "/name/" + label + "?error=Registration failed: Error generating QR code", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Error generating QR code", http.StatusSeeOther) return } paymentUntil := time.Now().Add(t.PaymentExpiration) @@ -638,7 +642,7 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) { metadataRecordValue, err := json.Marshal(regMetadata) if nil != err { fmt.Println(err) - http.Redirect(w, r, "/name/" + label + "?error=Registration failed: Internal error", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Internal error", http.StatusSeeOther) return } metaRecord.Value = string(metadataRecordValue) @@ -646,14 +650,14 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) { err = t.createOrUpdateRegistration(&namestoreResponse) if nil != err { fmt.Println(err) - http.Redirect(w, r, "/name/" + label + "?error=Registration failed: Internal error", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Internal error", http.StatusSeeOther) return } } else { - err = t.setupRegistrationMetadataBeforePayment(label, r.URL.Query().Get("zkey"), orderID, paymentUntil, regId) + err = t.setupRegistrationMetadataBeforePayment(sanitizedLabel, r.URL.Query().Get("zkey"), orderID, paymentUntil, regId) if err != nil { fmt.Println(err) - http.Redirect(w, r, "/name/" + label + "?error=Registration failed: Internal error", http.StatusSeeOther) + http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Internal error", http.StatusSeeOther) return } } @@ -662,9 +666,9 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) { fullData := map[string]interface{}{ "qrCode": template.URL("data:image/png;base64," + encodedPng), "payto": template.URL(payto), - "fulfillmentUrl": template.URL(t.BaseUrl + "/name/" + label + "/edit?token=" + regId), + "fulfillmentUrl": template.URL(t.BaseUrl + "/name/" + sanitizedLabel + "/edit?token=" + regId), "registrationId": regId, - "label": label, + "label": sanitizedLabel, "error": errorMsg, "cost": cost, "suffixHint": t.SuffixHint, @@ -795,12 +799,13 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") label := vars["label"] err := t.isNameValid(label) + sanitizedLabel := url.QueryEscape(vars["label"]) if nil != err { http.Redirect(w, r, fmt.Sprintf("/?error=%s", err), http.StatusSeeOther) return } client = &http.Client{} - req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + label + "?include_maintenance=yes", nil) + req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + sanitizedLabel + "?include_maintenance=yes", nil) if t.GnunetBasicAuthEnabled { req.SetBasicAuth(t.GnunetUsername, t.GnunetPassword) } @@ -824,7 +829,7 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/" + "?error=Failed to get zone contents.", http.StatusSeeOther) return } - regMetadata, err = t.getCurrentRegistrationMetadata(label, &namestoreResponse) + regMetadata, err = t.getCurrentRegistrationMetadata(sanitizedLabel, &namestoreResponse) if err != nil { fmt.Println("Failed to get registration metadata: " + err.Error()) http.Redirect(w, r, "/" + "?error=Failed to get registration metadata.", http.StatusSeeOther) @@ -848,7 +853,7 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) { } cost, _ := t.RegistrationCost.FormatWithCurrencySpecification(t.CurrencySpec) fullData := map[string]interface{}{ - "label": label, + "label": sanitizedLabel, "error": r.URL.Query().Get("error"), "cost": cost, "available": regMetadata == nil,