github.com/adacta-ru/mattermost-server@v5.11.1+incompatible/app/plugin_requests.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "net/http" 8 "path" 9 "strings" 10 11 "bytes" 12 "io/ioutil" 13 14 "github.com/gorilla/mux" 15 "github.com/mattermost/mattermost-server/mlog" 16 "github.com/mattermost/mattermost-server/model" 17 "github.com/mattermost/mattermost-server/plugin" 18 "github.com/mattermost/mattermost-server/utils" 19 ) 20 21 func (a *App) ServePluginRequest(w http.ResponseWriter, r *http.Request) { 22 pluginsEnvironment := a.GetPluginsEnvironment() 23 if pluginsEnvironment == nil { 24 err := model.NewAppError("ServePluginRequest", "app.plugin.disabled.app_error", nil, "Enable plugins to serve plugin requests", http.StatusNotImplemented) 25 a.Log.Error(err.Error()) 26 w.WriteHeader(err.StatusCode) 27 w.Header().Set("Content-Type", "application/json") 28 w.Write([]byte(err.ToJson())) 29 return 30 } 31 32 params := mux.Vars(r) 33 hooks, err := pluginsEnvironment.HooksForPlugin(params["plugin_id"]) 34 if err != nil { 35 a.Log.Error("Access to route for non-existent plugin", mlog.String("missing_plugin_id", params["plugin_id"]), mlog.Err(err)) 36 http.NotFound(w, r) 37 return 38 } 39 40 a.servePluginRequest(w, r, hooks.ServeHTTP) 41 } 42 43 func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler func(*plugin.Context, http.ResponseWriter, *http.Request)) { 44 token := "" 45 context := &plugin.Context{ 46 RequestId: model.NewId(), 47 IpAddress: utils.GetIpAddress(r), 48 AcceptLanguage: r.Header.Get("Accept-Language"), 49 UserAgent: r.UserAgent(), 50 } 51 cookieAuth := false 52 53 authHeader := r.Header.Get(model.HEADER_AUTH) 54 if strings.HasPrefix(strings.ToUpper(authHeader), model.HEADER_BEARER+" ") { 55 token = authHeader[len(model.HEADER_BEARER)+1:] 56 } else if strings.HasPrefix(strings.ToLower(authHeader), model.HEADER_TOKEN+" ") { 57 token = authHeader[len(model.HEADER_TOKEN)+1:] 58 } else if cookie, _ := r.Cookie(model.SESSION_COOKIE_TOKEN); cookie != nil { 59 token = cookie.Value 60 cookieAuth = true 61 } else { 62 token = r.URL.Query().Get("access_token") 63 } 64 65 r.Header.Del("Mattermost-User-Id") 66 if token != "" { 67 session, err := a.GetSession(token) 68 csrfCheckPassed := false 69 70 if err == nil && cookieAuth && r.Method != "GET" { 71 sentToken := "" 72 73 if r.Header.Get(model.HEADER_CSRF_TOKEN) == "" { 74 bodyBytes, _ := ioutil.ReadAll(r.Body) 75 r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) 76 r.ParseForm() 77 sentToken = r.FormValue("csrf") 78 r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) 79 } else { 80 sentToken = r.Header.Get(model.HEADER_CSRF_TOKEN) 81 } 82 83 expectedToken := session.GetCSRF() 84 85 if sentToken == expectedToken { 86 csrfCheckPassed = true 87 } 88 89 // ToDo(DSchalla) 2019/01/04: Remove after deprecation period and only allow CSRF Header (MM-13657) 90 if r.Header.Get(model.HEADER_REQUESTED_WITH) == model.HEADER_REQUESTED_WITH_XML && !csrfCheckPassed { 91 csrfErrorMessage := "CSRF Check failed for request - Please migrate your plugin to either send a CSRF Header or Form Field, XMLHttpRequest is deprecated" 92 if *a.Config().ServiceSettings.ExperimentalStrictCSRFEnforcement { 93 a.Log.Warn(csrfErrorMessage) 94 } else { 95 a.Log.Debug(csrfErrorMessage) 96 csrfCheckPassed = true 97 } 98 } 99 } else { 100 csrfCheckPassed = true 101 } 102 103 if session != nil && err == nil && csrfCheckPassed { 104 r.Header.Set("Mattermost-User-Id", session.UserId) 105 context.SessionId = session.Id 106 } 107 } 108 109 cookies := r.Cookies() 110 r.Header.Del("Cookie") 111 for _, c := range cookies { 112 if c.Name != model.SESSION_COOKIE_TOKEN { 113 r.AddCookie(c) 114 } 115 } 116 r.Header.Del(model.HEADER_AUTH) 117 r.Header.Del("Referer") 118 119 params := mux.Vars(r) 120 121 subpath, _ := utils.GetSubpathFromConfig(a.Config()) 122 123 newQuery := r.URL.Query() 124 newQuery.Del("access_token") 125 r.URL.RawQuery = newQuery.Encode() 126 r.URL.Path = strings.TrimPrefix(r.URL.Path, path.Join(subpath, "plugins", params["plugin_id"])) 127 128 handler(context, w, r) 129 }