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  }