1 /** @file 2 3 URL rewriting. 4 5 @section license License 6 7 Licensed to the Apache Software Foundation (ASF) under one 8 or more contributor license agreements. See the NOTICE file 9 distributed with this work for additional information 10 regarding copyright ownership. The ASF licenses this file 11 to you under the Apache License, Version 2.0 (the 12 "License"); you may not use this file except in compliance 13 with the License. You may obtain a copy of the License at 14 15 http://www.apache.org/licenses/LICENSE-2.0 16 17 Unless required by applicable law or agreed to in writing, software 18 distributed under the License is distributed on an "AS IS" BASIS, 19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 See the License for the specific language governing permissions and 21 limitations under the License. 22 23 */ 24 25 #pragma once 26 27 #include "tscore/ink_config.h" 28 #include "UrlMapping.h" 29 #include "UrlMappingPathIndex.h" 30 #include "HttpTransact.h" 31 #include "tscore/Regex.h" 32 #include "PluginFactory.h" 33 #include "NextHopStrategyFactory.h" 34 35 #include <memory> 36 37 #define URL_REMAP_FILTER_NONE 0x00000000 38 #define URL_REMAP_FILTER_REFERER 0x00000001 /* enable "referer" header validation */ 39 #define URL_REMAP_FILTER_REDIRECT_FMT 0x00010000 /* enable redirect URL formatting */ 40 41 struct BUILD_TABLE_INFO; 42 43 /** 44 * used for redirection, mapping, and reverse mapping 45 **/ 46 enum mapping_type { 47 FORWARD_MAP, 48 REVERSE_MAP, 49 PERMANENT_REDIRECT, 50 TEMPORARY_REDIRECT, 51 FORWARD_MAP_REFERER, 52 FORWARD_MAP_WITH_RECV_PORT, 53 NONE 54 }; 55 56 /** 57 * 58 **/ 59 class UrlRewrite : public RefCountObj 60 { 61 public: 62 using URLTable = std::unordered_map<std::string, UrlMappingPathIndex *>; 63 UrlRewrite() = default; 64 ~UrlRewrite() override; 65 66 /** Load the configuration. 67 * 68 * This access data in librecords to obtain the information needed for loading the configuration. 69 * 70 * @return @c true if the instance state is valid, @c false if not. 71 */ 72 bool load(); 73 74 /** Build the internal url write tables. 75 * 76 * @param path Path to configuration file. 77 * @return 0 on success, non-zero error code on failure. 78 */ 79 int BuildTable(const char *path); 80 81 mapping_type Remap_redirect(HTTPHdr *request_header, URL *redirect_url); 82 bool ReverseMap(HTTPHdr *response_header); 83 void SetReverseFlag(int flag); 84 void Print() const; 85 86 // The UrlRewrite object is-a RefCountObj, but this is a convenience to make it clear that we 87 // don't delete() these objects directly, but via the release() method only. 88 UrlRewrite * acquire()89 acquire() 90 { 91 this->refcount_inc(); 92 return this; 93 } 94 95 void release()96 release() 97 { 98 if (0 == this->refcount_dec()) { 99 // Delete this on an ET_TASK thread, which avoids doing potentially slow things on an ET_NET thread. 100 Debug("url_rewrite", "Deleting old configuration immediately"); 101 new_Deleter(this, 0); 102 } 103 } 104 105 bool is_valid()106 is_valid() const 107 { 108 return _valid; 109 }; 110 111 static constexpr int MAX_REGEX_SUBS = 10; 112 113 struct RegexMapping { 114 url_mapping *url_map; 115 Regex regular_expression; 116 117 // we store the host-string-to-substitute here; if a match is found, 118 // the substitutions are made and the resulting url is stored 119 // directly in toURL's host field 120 char *to_url_host_template; 121 int to_url_host_template_len; 122 123 // stores the number of substitutions 124 int n_substitutions; 125 126 // these two together point to template string places where 127 // substitutions need to be made and the matching substring 128 // to use 129 int substitution_markers[MAX_REGEX_SUBS]; 130 int substitution_ids[MAX_REGEX_SUBS]; 131 132 LINK(RegexMapping, link); 133 }; 134 135 typedef Queue<RegexMapping> RegexMappingList; 136 137 struct MappingsStore { 138 std::unique_ptr<URLTable> hash_lookup; 139 RegexMappingList regex_list; 140 bool emptyMappingsStore141 empty() 142 { 143 return ((hash_lookup == nullptr) && regex_list.empty()); 144 } 145 }; 146 147 void PerformACLFiltering(HttpTransact::State *s, url_mapping *mapping); 148 void PrintStore(const MappingsStore &store) const; 149 150 void DestroyStore(MappingsStore & store)151 DestroyStore(MappingsStore &store) 152 { 153 _destroyTable(store.hash_lookup); 154 _destroyList(store.regex_list); 155 } 156 157 bool InsertForwardMapping(mapping_type maptype, url_mapping *mapping, const char *src_host); 158 bool InsertMapping(mapping_type maptype, url_mapping *new_mapping, RegexMapping *reg_map, const char *src_host, 159 bool is_cur_mapping_regex); 160 161 bool TableInsert(std::unique_ptr<URLTable> &h_table, url_mapping *mapping, const char *src_host); 162 163 MappingsStore forward_mappings; 164 MappingsStore reverse_mappings; 165 MappingsStore permanent_redirects; 166 MappingsStore temporary_redirects; 167 MappingsStore forward_mappings_with_recv_port; 168 169 bool forwardMappingLookup(URL * request_url,int request_port,const char * request_host,int request_host_len,UrlMappingContainer & mapping_container)170 forwardMappingLookup(URL *request_url, int request_port, const char *request_host, int request_host_len, 171 UrlMappingContainer &mapping_container) 172 { 173 return _mappingLookup(forward_mappings, request_url, request_port, request_host, request_host_len, mapping_container); 174 } 175 bool reverseMappingLookup(URL * request_url,int request_port,const char * request_host,int request_host_len,UrlMappingContainer & mapping_container)176 reverseMappingLookup(URL *request_url, int request_port, const char *request_host, int request_host_len, 177 UrlMappingContainer &mapping_container) 178 { 179 return _mappingLookup(reverse_mappings, request_url, request_port, request_host, request_host_len, mapping_container); 180 } 181 bool permanentRedirectLookup(URL * request_url,int request_port,const char * request_host,int request_host_len,UrlMappingContainer & mapping_container)182 permanentRedirectLookup(URL *request_url, int request_port, const char *request_host, int request_host_len, 183 UrlMappingContainer &mapping_container) 184 { 185 return _mappingLookup(permanent_redirects, request_url, request_port, request_host, request_host_len, mapping_container); 186 } 187 bool temporaryRedirectLookup(URL * request_url,int request_port,const char * request_host,int request_host_len,UrlMappingContainer & mapping_container)188 temporaryRedirectLookup(URL *request_url, int request_port, const char *request_host, int request_host_len, 189 UrlMappingContainer &mapping_container) 190 { 191 return _mappingLookup(temporary_redirects, request_url, request_port, request_host, request_host_len, mapping_container); 192 } 193 bool forwardMappingWithRecvPortLookup(URL * request_url,int recv_port,const char * request_host,int request_host_len,UrlMappingContainer & mapping_container)194 forwardMappingWithRecvPortLookup(URL *request_url, int recv_port, const char *request_host, int request_host_len, 195 UrlMappingContainer &mapping_container) 196 { 197 return _mappingLookup(forward_mappings_with_recv_port, request_url, recv_port, request_host, request_host_len, 198 mapping_container); 199 } 200 201 int nohost_rules = 0; 202 int reverse_proxy = 0; 203 204 char *ts_name = nullptr; // Used to send redirects when no host info 205 206 char *http_default_redirect_url = nullptr; // Used if redirect in "referer" filtering was not defined properly 207 int num_rules_forward = 0; 208 int num_rules_reverse = 0; 209 int num_rules_redirect_permanent = 0; 210 int num_rules_redirect_temporary = 0; 211 int num_rules_forward_with_recv_port = 0; 212 213 PluginFactory pluginFactory; 214 NextHopStrategyFactory *strategyFactory = nullptr; 215 216 private: 217 bool _valid = false; 218 219 bool _mappingLookup(MappingsStore &mappings, URL *request_url, int request_port, const char *request_host, int request_host_len, 220 UrlMappingContainer &mapping_container); 221 url_mapping *_tableLookup(std::unique_ptr<URLTable> &h_table, URL *request_url, int request_port, char *request_host, 222 int request_host_len); 223 bool _regexMappingLookup(RegexMappingList ®ex_mappings, URL *request_url, int request_port, const char *request_host, 224 int request_host_len, int rank_ceiling, UrlMappingContainer &mapping_container); 225 int _expandSubstitutions(int *matches_info, const RegexMapping *reg_map, const char *matched_string, char *dest_buf, 226 int dest_buf_size); 227 void _destroyTable(std::unique_ptr<URLTable> &h_table); 228 void _destroyList(RegexMappingList ®exes); 229 inline bool _addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping *reg_map, const char *src_host, 230 bool is_cur_mapping_regex, int &count); 231 }; 232 233 void url_rewrite_remap_request(const UrlMappingContainer &mapping_container, URL *request_url, int scheme = -1); 234