// HandleLoginFunc is uniq handler for Authorization and create new session only func (router *Router) HandleLoginFunc(path string, f func(http.ResponseWriter, *http.Request, *sessions.Sessions)) *mux.Route { routerFunc := func(w http.ResponseWriter, r *http.Request) { /* Set headers */ setHeaderNoCache(w) /* Defered run and catch panics */ defer func() { // Catch all panics from handler if rec := recover(); rec != nil { switch rec := rec.(type) { // Panicerr catched case panicerr.Error: logger.Info(fmt.Sprintf("%v [ %v ] Error catched: Code '%v' Text '%v'", strings.Split(r.RemoteAddr, ":")[0], r.RequestURI, rec.Code, rec.Err)) //Send response with json error description w.WriteHeader(500) w.Write([]byte(rec.ToJSONString())) // Unknown panic default: raven.CaptureError(fmt.Errorf("%v", rec), nil) logger.Error(fmt.Sprintf("%v [ %v ] Unknown Error catched: '%v'", strings.Split(r.RemoteAddr, ":")[0], r.RequestURI, rec)) http.Error(w, http.StatusText(500), 500) panic(rec) } } }() /* Run handler's function */ f(w, r, sessions.SessionsStorage) /* Make api trigger call */ plugins.DefaultManager.Trigger(w, r, nil) } // Insert func to gorilla/mux router return router.HandleFunc(path, routerFunc) }
// HandleInternalFunc is a gorilla Router's wrapper function. // This handles standart modules functions. func (router *Router) HandleInternalFunc(path string, f func(http.ResponseWriter, *http.Request, *sessions.Sessions)) *mux.Route { routerFunc := func(w http.ResponseWriter, r *http.Request) { // Trigger starting of new process if !isIgnored(r.RequestURI) { if err := shutdown.DefaultWatcher.Start(); err != nil { http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable) return } defer shutdown.DefaultWatcher.Finish() } /* # Pre run */ // 1. Clean expired sessions sessions.SessionsStorage.CleanExpired() // 2. Define empty handler var handler rhandler // 3. Set headers setHeaderNoCache(w) // 4. Defered run and catch panics defer func() { // Remove handler from running list router.mutex.Lock() router.deleteHandler(handler.id) router.mutex.Unlock() // Catch all panics from handler if rec := recover(); rec != nil { switch rec := rec.(type) { // Panicerr catched case panicerr.Error: logger.Info(fmt.Sprintf("%v [ %v ] Error catched: Code '%v' Text '%v'", strings.Split(r.RemoteAddr, ":")[0], r.RequestURI, rec.Code, rec.Err)) //Send response with json error description w.Header().Set("Content-Type", "application/json") w.WriteHeader(500) w.Write([]byte(rec.ToJSONString())) // Unknown panic default: raven.CaptureError(fmt.Errorf("%v", rec), nil) logger.Error(fmt.Sprintf("%v [ %v ] Unknown Error catched: '%v'", strings.Split(r.RemoteAddr, ":")[0], r.RequestURI, rec)) http.Error(w, http.StatusText(500), 500) panic(rec) } } }() /* # Permissions checks */ // 1. Prevent bruteforce of sessionID ok, duration := bruteforce.Check(strings.Split(r.RemoteAddr, ":")[0]) if !ok { logger.Warning("IP " + strings.Split(r.RemoteAddr, ":")[0] + " banned by bruteforce (no session) for " + strconv.FormatInt(duration, 10) + " sec.") http.Error(w, http.StatusText(429), 429) return } // 2. Check if session started and getting session info sess, err := sessions.SessionsStorage.Get(r) if err != nil { logger.Warning(err.Error()) http.Error(w, http.StatusText(401), 401) return } // 3. Clear IP in bruteforce check bruteforce.Clean(strings.Split(r.RemoteAddr, ":")[0]) // 4. Check for timeout before actions for particular handlers if err := bruteforce.CheckTimeout(r, sessions.SessionsStorage); err != nil { http.Error(w, http.StatusText(429), 429) log.Println("Timeout error: ", err) return } // 5. Register session activity for sessions timeout sessions.SessionsStorage.RegisterActivity(r) // 6. Check module access permisions if sess.Username != "root" { userInfo := users.Get(sess.Username) if userInfo == nil { panicerr.Core.Auth("Can't get template" + sess.Username) } allowedModules := userInfo.GetTemplate().Modules if err != nil || !hasPermissions(r.RequestURI, allowedModules) { http.Error(w, http.StatusText(403), 403) logger.Warning(fmt.Sprintf("Permission denied to access '%v' for %v as user %v", r.RequestURI, strings.Split(r.RemoteAddr, ":")[0], sess.Username)) return } } // 7. Check for simultaneous connections from a single user router.CheckNumConnection(sess.Username) /* # Append handler to running list for tracking */ func() { // Make it atomic router.mutex.Lock() defer router.mutex.Unlock() // Increment handler ID router.curID++ // create handler struct handler = rhandler{ id: router.curID, URI: r.RequestURI, Username: sess.Username, IP: r.RemoteAddr, StartTime: time.Now().Format(time.StampMilli), SessionID: sess.ID, } // Append new handler to list router.handlers[router.curID] = handler }() /* # Add action to journal */ journal.Add(journal.Operation{ SessionID: sess.ID, Date: time.Now().Format(journal.TimeLayout), Username: sess.Username, Operation: moduleutils.GetCurrentModule(r.RequestURI), Content: r.RequestURI, //Extra: }) /* # Run handler's function */ f(w, r, sessions.SessionsStorage) /* # Make api trigger call */ plugins.DefaultManager.Trigger(w, r, sess) } // Insert func to gorilla/mux router return router.HandleFunc(path, routerFunc) }