github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/services/httpservice/httpservice.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package httpservice 5 6 import ( 7 "net" 8 "net/http" 9 "strings" 10 "time" 11 "unicode" 12 13 "github.com/mattermost/mattermost-server/v5/services/configservice" 14 ) 15 16 // HTTPService wraps the functionality for making http requests to provide some improvements to the default client 17 // behaviour. 18 type HTTPService interface { 19 // MakeClient returns an http client constructed with a RoundTripper as returned by MakeTransport. 20 MakeClient(trustURLs bool) *http.Client 21 22 // MakeTransport returns a RoundTripper that is suitable for making requests to external resources. The default 23 // implementation provides: 24 // - A shorter timeout for dial and TLS handshake (defined as constant "ConnectTimeout") 25 // - A timeout for end-to-end requests 26 // - A Mattermost-specific user agent header 27 // - Additional security for untrusted and insecure connections 28 MakeTransport(trustURLs bool) *MattermostTransport 29 } 30 31 type HTTPServiceImpl struct { 32 configService configservice.ConfigService 33 34 RequestTimeout time.Duration 35 } 36 37 func splitFields(c rune) bool { 38 return unicode.IsSpace(c) || c == ',' 39 } 40 41 func MakeHTTPService(configService configservice.ConfigService) HTTPService { 42 return &HTTPServiceImpl{ 43 configService, 44 RequestTimeout, 45 } 46 } 47 48 func (h *HTTPServiceImpl) MakeClient(trustURLs bool) *http.Client { 49 return &http.Client{ 50 Transport: h.MakeTransport(trustURLs), 51 Timeout: h.RequestTimeout, 52 } 53 } 54 55 func (h *HTTPServiceImpl) MakeTransport(trustURLs bool) *MattermostTransport { 56 insecure := h.configService.Config().ServiceSettings.EnableInsecureOutgoingConnections != nil && *h.configService.Config().ServiceSettings.EnableInsecureOutgoingConnections 57 58 if trustURLs { 59 return NewTransport(insecure, nil, nil) 60 } 61 62 allowHost := func(host string) bool { 63 if h.configService.Config().ServiceSettings.AllowedUntrustedInternalConnections == nil { 64 return false 65 } 66 for _, allowed := range strings.FieldsFunc(*h.configService.Config().ServiceSettings.AllowedUntrustedInternalConnections, splitFields) { 67 if host == allowed { 68 return true 69 } 70 } 71 return false 72 } 73 74 allowIP := func(ip net.IP) bool { 75 reservedIP := IsReservedIP(ip) 76 ownIP, err := IsOwnIP(ip) 77 78 // If there is an error getting the self-assigned IPs, default to the secure option 79 if err != nil { 80 return false 81 } 82 83 // If it's not a reserved IP and it's not self-assigned IP, accept the IP 84 if !reservedIP && !ownIP { 85 return true 86 } 87 88 if h.configService.Config().ServiceSettings.AllowedUntrustedInternalConnections == nil { 89 return false 90 } 91 92 // In the case it's the self-assigned IP, enforce that it needs to be explicitly added to the AllowedUntrustedInternalConnections 93 for _, allowed := range strings.FieldsFunc(*h.configService.Config().ServiceSettings.AllowedUntrustedInternalConnections, splitFields) { 94 if _, ipRange, err := net.ParseCIDR(allowed); err == nil && ipRange.Contains(ip) { 95 return true 96 } 97 } 98 return false 99 } 100 101 return NewTransport(insecure, allowHost, allowIP) 102 }