From 94eab548c583491912335d58f6442eb952cec5ab Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sat, 19 Dec 2015 23:07:08 +0100 Subject: fetcher now checks for permissions improved error handling for fetcher diff --git a/src/helsinki.at/rhimport/fetcher.go b/src/helsinki.at/rhimport/fetcher.go index fed51bf..300abef 100644 --- a/src/helsinki.at/rhimport/fetcher.go +++ b/src/helsinki.at/rhimport/fetcher.go @@ -29,6 +29,7 @@ import ( "github.com/golang-basic/go-curl" "io/ioutil" "mime" + "net/http" "net/url" "os" "path" @@ -36,6 +37,11 @@ import ( "strings" ) +type FetchResult struct { + ResponseCode int + ErrorString string +} + type FetcherCurlCBData struct { basepath string filename string @@ -83,7 +89,7 @@ func curlWriteCallback(ptr []byte, userdata interface{}) bool { return true } -func FetchFileCurl(ctx *ImportContext, uri *url.URL) (err error) { +func FetchFileCurl(ctx *ImportContext, res *FetchResult, uri *url.URL) (err error) { rhl.Printf("curl-based fetcher called for '%s'", ctx.SourceUri) easy := curl.EasyInit() @@ -116,7 +122,7 @@ func FetchFileCurl(ctx *ImportContext, uri *url.URL) (err error) { easy.Setopt(curl.OPT_PROGRESSDATA, ctx) if err = easy.Perform(); err != nil { - err = fmt.Errorf("fetcher('%s'): %s", ctx.SourceUri, err) + err = fmt.Errorf("curl-fetcher('%s'): %s", ctx.SourceUri, err) return } @@ -130,7 +136,7 @@ func FetchFileCurl(ctx *ImportContext, uri *url.URL) (err error) { return } -func FetchFileLocal(ctx *ImportContext, uri *url.URL) (err error) { +func FetchFileLocal(ctx *ImportContext, res *FetchResult, uri *url.URL) (err error) { rhl.Printf("Local fetcher called for '%s'", ctx.SourceUri) if ctx.ProgressCallBack != nil { ctx.ProgressCallBack(1, "fetching", 1.0, ctx.ProgressCallBackData) @@ -139,15 +145,17 @@ func FetchFileLocal(ctx *ImportContext, uri *url.URL) (err error) { ctx.SourceFile = filepath.Join(ctx.Config.LocalFetchDir, path.Clean("/"+uri.Path)) var src *os.File if src, err = os.Open(ctx.SourceFile); err != nil { - return + res.ResponseCode = http.StatusBadRequest + res.ErrorString = fmt.Sprintf("local-file open(): %s", err) + return nil } - defer src.Close() + src.Close() ctx.DeleteSourceFile = false ctx.DeleteSourceDir = false return } -type FetchFunc func(*ImportContext, *url.URL) (err error) +type FetchFunc func(*ImportContext, *FetchResult, *url.URL) (err error) // TODO: implement fetchers for: // archiv:// @@ -182,15 +190,52 @@ func fetcher_init() { } } -func FetchFile(ctx *ImportContext) (err error) { +func checkPassword(ctx *ImportContext, result *FetchResult) (err error) { + cached := true + + for { + req := getPasswordRequest{} + req.username = ctx.UserName + req.cached = cached + req.response = make(chan getPasswordResult) + ctx.RdDb.getPasswordChan <- req + + res := <-req.response + if res.err != nil { + return res.err + } + if ctx.Password == res.password { + return nil + } + if cached { + cached = false + } else { + break + } + } + result.ResponseCode = http.StatusUnauthorized + result.ErrorString = "invalid username and/or password" + return +} + +func FetchFile(ctx *ImportContext) (res *FetchResult, err error) { + res = &FetchResult{ResponseCode: http.StatusOK} var uri *url.URL if uri, err = url.Parse(ctx.SourceUri); err != nil { - return + res.ResponseCode = http.StatusBadRequest + res.ErrorString = fmt.Sprintf("parsing uri: %s", err) + return res, nil + } + + if !ctx.Trusted { + if err = checkPassword(ctx, res); err != nil || res.ResponseCode != http.StatusOK { + return + } } if fetcher, ok := fetchers[uri.Scheme]; ok { - err = fetcher(ctx, uri) + err = fetcher(ctx, res, uri) } else { err = fmt.Errorf("No fetcher for uri scheme '%s' found.", uri.Scheme) } diff --git a/src/helsinki.at/rhimportd/ctrlTelnet.go b/src/helsinki.at/rhimportd/ctrlTelnet.go index eb3c607..65504f4 100644 --- a/src/helsinki.at/rhimportd/ctrlTelnet.go +++ b/src/helsinki.at/rhimportd/ctrlTelnet.go @@ -152,11 +152,23 @@ func (c *TelnetClient) handle_cmd_set(args []string) { } switch strings.ToLower(args[0]) { case "username": - c.ctx.UserName = args[1] + if args[1] == "\"\"" || args[1] == "''" { + c.ctx.UserName = "" + } else { + c.ctx.UserName = args[1] + } case "password": - c.ctx.Password = args[1] + if args[1] == "\"\"" || args[1] == "''" { + c.ctx.Password = "" + } else { + c.ctx.Password = args[1] + } case "sourceuri": - c.ctx.SourceUri = args[1] + if args[1] == "\"\"" || args[1] == "''" { + c.ctx.SourceUri = "" + } else { + c.ctx.SourceUri = args[1] + } case "showid": if id, err := strconv.ParseUint(args[1], 10, 32); err != nil { c.say("invalid value (must be an positive integer)") @@ -170,7 +182,11 @@ func (c *TelnetClient) handle_cmd_set(args []string) { c.ctx.ClearShowCarts = val } case "groupname": - c.ctx.GroupName = args[1] + if args[1] == "\"\"" || args[1] == "''" { + c.ctx.GroupName = "" + } else { + c.ctx.GroupName = args[1] + } case "cart": if cart, err := strconv.ParseUint(args[1], 10, 32); err != nil { c.say("invalid value (must be an positive integer)") @@ -263,22 +279,25 @@ func (c *TelnetClient) handle_cmd_run(args []string) { } c.say("fetching file from '%s'", ctx.SourceUri) - if err := rhimport.FetchFile(&ctx); err != nil { + if fres, err := rhimport.FetchFile(&ctx); err != nil { c.say("fetch file error: %s", err) return + } else if fres.ResponseCode != http.StatusOK { + c.say("fetch file error: %s", fres.ErrorString) + return } c.say("importing file '%s'", ctx.SourceFile) - if result, err := rhimport.ImportFile(&ctx); err != nil { + if ires, err := rhimport.ImportFile(&ctx); err != nil { c.say("import file error: %s", err) return } else { - if result.ResponseCode == http.StatusOK { - c.say("File got succesfully imported into Cart/Cut %d/%d", result.Cart, result.Cut) - rhl.Printf("File got succesfully imported into Cart/Cut %d/%d", result.Cart, result.Cut) + if ires.ResponseCode == http.StatusOK { + c.say("File got succesfully imported into Cart/Cut %d/%d", ires.Cart, ires.Cut) + rhl.Printf("File got succesfully imported into Cart/Cut %d/%d", ires.Cart, ires.Cut) } else { - c.say("Fileimport has failed (Cart/Cut %d/%d): %s", result.Cart, result.Cut, result.ErrorString) - rhl.Printf("Fileimport has failed (Cart/Cut %d/%d): %s", result.Cart, result.Cut, result.ErrorString) + c.say("Fileimport has failed (Cart/Cut %d/%d): %s", ires.Cart, ires.Cut, ires.ErrorString) + rhl.Printf("Fileimport has failed (Cart/Cut %d/%d): %s", ires.Cart, ires.Cut, ires.ErrorString) } } } diff --git a/src/helsinki.at/rhimportd/ctrlWebSimple.go b/src/helsinki.at/rhimportd/ctrlWebSimple.go index 2de324f..c5b81ce 100644 --- a/src/helsinki.at/rhimportd/ctrlWebSimple.go +++ b/src/helsinki.at/rhimportd/ctrlWebSimple.go @@ -141,22 +141,26 @@ func webSimpleHandler(conf *rhimport.Config, rddb *rhimport.RdDb, trusted bool, return } - if err = rhimport.FetchFile(ctx); err != nil { + var fres *rhimport.FetchResult + if fres, err = rhimport.FetchFile(ctx); err != nil { webSimpleErrorResponse(w, http.StatusInternalServerError, err.Error()) return } + if fres.ResponseCode != http.StatusOK { + webSimpleErrorResponse(w, fres.ResponseCode, fres.ErrorString) + } - var result *rhimport.ImportResult - if result, err = rhimport.ImportFile(ctx); err != nil { + var ires *rhimport.ImportResult + if ires, err = rhimport.ImportFile(ctx); err != nil { webSimpleErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - if result.ResponseCode == http.StatusOK { + if ires.ResponseCode == http.StatusOK { rhl.Println("ImportFile succesfully imported", ctx.SourceFile) } else { rhl.Println("ImportFile import of", ctx.SourceFile, "was unsuccesful") } - webSimpleResponse(w, result) + webSimpleResponse(w, ires) return } -- cgit v0.10.2