Rev 1189 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1189 | Rev 1282 | ||
---|---|---|---|
1 | <?php |
1 | <?php |
2 | 2 | ||
3 | /* |
3 | /* |
4 | * OIDplus 2.0 RDAP |
4 | * OIDplus 2.0 RDAP |
5 | * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
5 | * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
6 | * Authors Daniel Marschall, ViaThinkSoft |
6 | * Authors Daniel Marschall, ViaThinkSoft |
7 | * Till Wehowski, Frdlweb |
7 | * Till Wehowski, Frdlweb |
8 | * |
8 | * |
9 | * Licensed under the Apache License, Version 2.0 (the "License"); |
9 | * Licensed under the Apache License, Version 2.0 (the "License"); |
10 | * you may not use this file except in compliance with the License. |
10 | * you may not use this file except in compliance with the License. |
11 | * You may obtain a copy of the License at |
11 | * You may obtain a copy of the License at |
12 | * |
12 | * |
13 | * http://www.apache.org/licenses/LICENSE-2.0 |
13 | * http://www.apache.org/licenses/LICENSE-2.0 |
14 | * |
14 | * |
15 | * Unless required by applicable law or agreed to in writing, software |
15 | * Unless required by applicable law or agreed to in writing, software |
16 | * distributed under the License is distributed on an "AS IS" BASIS, |
16 | * distributed under the License is distributed on an "AS IS" BASIS, |
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
18 | * See the License for the specific language governing permissions and |
18 | * See the License for the specific language governing permissions and |
19 | * limitations under the License. |
19 | * limitations under the License. |
20 | */ |
20 | */ |
21 | 21 | ||
22 | namespace Frdlweb\OIDplus; |
22 | namespace Frdlweb\OIDplus; |
23 | 23 | ||
24 | use ViaThinkSoft\OIDplus\OIDplus; |
24 | use ViaThinkSoft\OIDplus\OIDplus; |
25 | use ViaThinkSoft\OIDplus\OIDplusBaseClass; |
25 | use ViaThinkSoft\OIDplus\OIDplusBaseClass; |
26 | use ViaThinkSoft\OIDplus\OIDplusObject; |
26 | use ViaThinkSoft\OIDplus\OIDplusObject; |
27 | use ViaThinkSoft\OIDplus\OIDplusOIDIP; |
27 | use ViaThinkSoft\OIDplus\OIDplusOIDIP; |
28 | use ViaThinkSoft\OIDplus\OIDplusPagePublicObjects; |
28 | use ViaThinkSoft\OIDplus\OIDplusPagePublicObjects; |
29 | 29 | ||
30 | // phpcs:disable PSR1.Files.SideEffects |
30 | // phpcs:disable PSR1.Files.SideEffects |
31 | \defined('INSIDE_OIDPLUS') or die; |
31 | \defined('INSIDE_OIDPLUS') or die; |
32 | // phpcs:enable PSR1.Files.SideEffects |
32 | // phpcs:enable PSR1.Files.SideEffects |
33 | 33 | ||
34 | class OIDplusRDAP extends OIDplusBaseClass { |
34 | class OIDplusRDAP extends OIDplusBaseClass { |
35 | 35 | ||
36 | /** |
36 | /** |
37 | * @var string |
37 | * @var string |
38 | */ |
38 | */ |
39 | protected $rdapBaseUri; |
39 | protected $rdapBaseUri; |
40 | 40 | ||
41 | /** |
41 | /** |
42 | * @var bool |
42 | * @var bool |
43 | */ |
43 | */ |
44 | protected $useCache; |
44 | protected $useCache; |
45 | 45 | ||
46 | /** |
46 | /** |
47 | * @var string |
47 | * @var string |
48 | */ |
48 | */ |
49 | protected $rdapCacheDir; |
49 | protected $rdapCacheDir; |
50 | 50 | ||
51 | /** |
51 | /** |
52 | * @var int |
52 | * @var int |
53 | */ |
53 | */ |
54 | protected $rdapCacheExpires; |
54 | protected $rdapCacheExpires; |
55 | 55 | ||
56 | /** |
56 | /** |
57 | * @throws \ViaThinkSoft\OIDplus\OIDplusException |
57 | * @throws \ViaThinkSoft\OIDplus\OIDplusException |
58 | */ |
58 | */ |
59 | public function __construct() { |
59 | public function __construct() { |
60 | $this->rdapBaseUri = OIDplus::baseConfig()->getValue('RDAP_BASE_URI', OIDplus::webpath() ); |
60 | $this->rdapBaseUri = OIDplus::baseConfig()->getValue('RDAP_BASE_URI', OIDplus::webpath() ); |
61 | $this->useCache = OIDplus::baseConfig()->getValue('RDAP_CACHE_ENABLED', false ); |
61 | $this->useCache = OIDplus::baseConfig()->getValue('RDAP_CACHE_ENABLED', false ); |
62 | $this->rdapCacheDir = OIDplus::baseConfig()->getValue('RDAP_CACHE_DIRECTORY', OIDplus::localpath().'userdata/cache/' ); |
62 | $this->rdapCacheDir = OIDplus::baseConfig()->getValue('RDAP_CACHE_DIRECTORY', OIDplus::localpath().'userdata/cache/' ); |
63 | $this->rdapCacheExpires = OIDplus::baseConfig()->getValue('RDAP_CACHE_EXPIRES', 60 * 3 ); |
63 | $this->rdapCacheExpires = OIDplus::baseConfig()->getValue('RDAP_CACHE_EXPIRES', 60 * 3 ); |
64 | } |
64 | } |
65 | 65 | ||
66 | /** |
66 | /** |
67 | * @param string $query |
67 | * @param string $query |
68 | * @return array |
68 | * @return array |
69 | * @throws \ViaThinkSoft\OIDplus\OIDplusException |
69 | * @throws \ViaThinkSoft\OIDplus\OIDplusException |
70 | */ |
70 | */ |
71 | public function rdapQuery(string $query): array { |
71 | public function rdapQuery(string $query): array { |
72 | $query = str_replace('oid:.', 'oid:', $query); |
72 | $query = str_replace('oid:.', 'oid:', $query); |
73 | $n = explode(':', $query); |
73 | $n = explode(':', $query); |
74 | if(2>count($n)){ |
74 | if(2>count($n)){ |
75 | array_unshift($n, 'oid'); |
75 | array_unshift($n, 'oid'); |
76 | $query = 'oid:'.$query; |
76 | $query = 'oid:'.$query; |
77 | } |
77 | } |
78 | $ns = $n[0]; |
78 | $ns = $n[0]; |
79 | 79 | ||
80 | if(true === $this->useCache){ |
80 | if(true === $this->useCache){ |
81 | $cacheFile = $this->rdapCacheDir. 'rdap_' |
81 | $cacheFile = $this->rdapCacheDir. 'rdap_' |
82 | .sha1(\get_current_user() |
82 | .sha1(\get_current_user() |
83 | . $this->rdapBaseUri.__FILE__.$query |
83 | . $this->rdapBaseUri.__FILE__.$query |
84 | .OIDplus::baseConfig()->getValue('SERVER_SECRET', sha1(__FILE__.\get_current_user()) ) |
84 | .OIDplus::authUtils()->makeSecret('cee75760-f4f8-11ed-b67e-3c4a92df8582') |
85 | ) |
85 | ) |
86 | .'.' |
86 | .'.' |
87 | .strlen( $this->rdapBaseUri.$query ) |
87 | .strlen( $this->rdapBaseUri.$query ) |
88 | .'.ser' |
88 | .'.ser' |
89 | ; |
89 | ; |
90 | 90 | ||
91 | $tmp = $this->rdap_read_cache($cacheFile, $this->rdapCacheExpires); |
91 | $tmp = $this->rdap_read_cache($cacheFile, $this->rdapCacheExpires); |
92 | if ($tmp) return $tmp; |
92 | if ($tmp) return $tmp; |
93 | }else{ |
93 | }else{ |
94 | $cacheFile = false; |
94 | $cacheFile = false; |
95 | } |
95 | } |
96 | 96 | ||
97 | $out = []; |
97 | $out = []; |
98 | 98 | ||
99 | $obj = OIDplusObject::findFitting($query); |
99 | $obj = OIDplusObject::findFitting($query); |
100 | 100 | ||
101 | if(!$obj){ |
101 | if(!$obj){ |
102 | // If object was not found, try if it is an alternative identifier of another object |
102 | // If object was not found, try if it is an alternative identifier of another object |
103 | $alts = OIDplusPagePublicObjects::getAlternativesForQuery($query); |
103 | $alts = OIDplusPagePublicObjects::getAlternativesForQuery($query); |
104 | foreach ($alts as $alt) { |
104 | foreach ($alts as $alt) { |
105 | if ($obj = OIDplusObject::findFitting($alt)) { |
105 | if ($obj = OIDplusObject::findFitting($alt)) { |
106 | $query = $obj->nodeId(); |
106 | $query = $obj->nodeId(); |
107 | break; |
107 | break; |
108 | } |
108 | } |
109 | } |
109 | } |
110 | 110 | ||
111 | // Still nothing found? |
111 | // Still nothing found? |
112 | if(!$obj){ |
112 | if(!$obj){ |
113 | $out['error'] = 'Not found'; |
113 | $out['error'] = 'Not found'; |
114 | if(true === $this->useCache){ |
114 | if(true === $this->useCache){ |
115 | $this->rdap_write_cache($out, $cacheFile); |
115 | $this->rdap_write_cache($out, $cacheFile); |
116 | } |
116 | } |
117 | return $this->rdap_out($out); |
117 | return $this->rdap_out($out); |
118 | } |
118 | } |
119 | } else { |
119 | } else { |
120 | $query = $obj->nodeId(); |
120 | $query = $obj->nodeId(); |
121 | } |
121 | } |
122 | 122 | ||
123 | $whois_server = ''; |
123 | $whois_server = ''; |
124 | if (OIDplus::config()->getValue('individual_whois_server', '') != '') { |
124 | if (OIDplus::config()->getValue('individual_whois_server', '') != '') { |
125 | $whois_server = OIDplus::config()->getValue('individual_whois_server', ''); |
125 | $whois_server = OIDplus::config()->getValue('individual_whois_server', ''); |
126 | } |
126 | } |
127 | else if (OIDplus::config()->getValue('vts_whois', '') != '') { |
127 | else if (OIDplus::config()->getValue('vts_whois', '') != '') { |
128 | $whois_server = OIDplus::config()->getValue('vts_whois', ''); |
128 | $whois_server = OIDplus::config()->getValue('vts_whois', ''); |
129 | } |
129 | } |
130 | if (!empty($whois_server)) { |
130 | if (!empty($whois_server)) { |
131 | list($whois_host, $whois_port) = explode(':',"$whois_server:43"); |
131 | list($whois_host, $whois_port) = explode(':',"$whois_server:43"); |
132 | if ($whois_port === '43') $out['port43'] = $whois_host; |
132 | if ($whois_port === '43') $out['port43'] = $whois_host; |
133 | } |
133 | } |
134 | 134 | ||
135 | $parentHandle=$obj->one_up(); |
135 | $parentHandle=$obj->one_up(); |
136 | 136 | ||
137 | $out['name'] = $obj->nodeId(true); |
137 | $out['name'] = $obj->nodeId(true); |
138 | $out['objectClassName'] = $ns; |
138 | $out['objectClassName'] = $ns; |
139 | $out['handle'] = $ns.':'.$n[1]; |
139 | $out['handle'] = $ns.':'.$n[1]; |
140 | $out['parentHandle'] = (null !== $parentHandle && is_callable([$parentHandle, 'nodeId']) ) |
140 | $out['parentHandle'] = (null !== $parentHandle && is_callable([$parentHandle, 'nodeId']) ) |
141 | ? $parentHandle->nodeId(true) |
141 | ? $parentHandle->nodeId(true) |
142 | : null; |
142 | : null; |
143 | 143 | ||
144 | $out['rdapConformance'] = [ |
144 | $out['rdapConformance'] = [ |
145 | "rdap_level_0", //https://datatracker.ietf.org/doc/html/rfc9083 |
145 | "rdap_level_0", //https://datatracker.ietf.org/doc/html/rfc9083 |
146 | ]; |
146 | ]; |
147 | $out['links'] = [ |
147 | $out['links'] = [ |
148 | [ |
148 | [ |
149 | "href"=> 'https://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'], |
149 | "href"=> 'https://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'], |
150 | "type"=> "application/rdap+json", |
150 | "type"=> "application/rdap+json", |
151 | "title"=> sprintf("Information about the %s %s", $ns, $n[1]), |
151 | "title"=> sprintf("Information about the %s %s", $ns, $n[1]), |
152 | "value"=> $this->rdapBaseUri.$ns.'/'.$n[1], |
152 | "value"=> $this->rdapBaseUri.$ns.'/'.$n[1], |
153 | "rel"=> "self" |
153 | "rel"=> "self" |
154 | ], |
154 | ], |
155 | [ |
155 | [ |
156 | "href"=> OIDplus::webpath()."?goto=".urlencode($query), |
156 | "href"=> OIDplus::webpath()."?goto=".urlencode($query), |
157 | "type"=> "text/html", |
157 | "type"=> "text/html", |
158 | "title"=> sprintf("Information about the %s %s in the online repository", $ns, $n[1]), |
158 | "title"=> sprintf("Information about the %s %s in the online repository", $ns, $n[1]), |
159 | "value"=> OIDplus::webpath()."?goto=".urlencode($query), |
159 | "value"=> OIDplus::webpath()."?goto=".urlencode($query), |
160 | "rel"=> "alternate" |
160 | "rel"=> "alternate" |
161 | ] |
161 | ] |
162 | ]; |
162 | ]; |
163 | $out['remarks'] = [ |
163 | $out['remarks'] = [ |
164 | [ |
164 | [ |
165 | "title"=>"Availability", |
165 | "title"=>"Availability", |
166 | "description"=> [ |
166 | "description"=> [ |
167 | sprintf("The %s %s is known.", strtoupper($ns), $n[1]), |
167 | sprintf("The %s %s is known.", strtoupper($ns), $n[1]), |
168 | ], |
168 | ], |
169 | "links"=> [] |
169 | "links"=> [] |
170 | ], |
170 | ], |
171 | [ |
171 | [ |
172 | "title"=>"Description", |
172 | "title"=>"Description", |
173 | "description"=> [ |
173 | "description"=> [ |
174 | ($obj->isConfidential()) ? 'REDACTED FOR PRIVACY' : $obj->getDescription(), |
174 | ($obj->isConfidential()) ? 'REDACTED FOR PRIVACY' : $obj->getDescription(), |
175 | ], |
175 | ], |
176 | "links"=> [ |
176 | "links"=> [ |
177 | [ |
177 | [ |
178 | "href"=> OIDplus::webpath()."?goto=".urlencode($query), |
178 | "href"=> OIDplus::webpath()."?goto=".urlencode($query), |
179 | "type"=> "text/html", |
179 | "type"=> "text/html", |
180 | "title"=> sprintf("Information about the %s %s in the online repository", $ns, $n[1]), |
180 | "title"=> sprintf("Information about the %s %s in the online repository", $ns, $n[1]), |
181 | "value"=> OIDplus::webpath()."?goto=".urlencode($query), |
181 | "value"=> OIDplus::webpath()."?goto=".urlencode($query), |
182 | "rel"=> "alternate" |
182 | "rel"=> "alternate" |
183 | ] |
183 | ] |
184 | ] |
184 | ] |
185 | ], |
185 | ], |
186 | 186 | ||
187 | ]; |
187 | ]; |
188 | 188 | ||
189 | if (!is_null(OIDplus::getPluginByOid("1.3.6.1.4.1.37476.2.5.2.4.1.100"))) { // OIDplusPagePublicWhois |
189 | if (!is_null(OIDplus::getPluginByOid("1.3.6.1.4.1.37476.2.5.2.4.1.100"))) { // OIDplusPagePublicWhois |
190 | $oidIPUrl = OIDplus::webpath().'plugins/viathinksoft/publicPages/100_whois/whois/webwhois.php?query='.urlencode($query); |
190 | $oidIPUrl = OIDplus::webpath().'plugins/viathinksoft/publicPages/100_whois/whois/webwhois.php?query='.urlencode($query); |
191 | 191 | ||
192 | $oidip_generator = new OIDplusOIDIP(); |
192 | $oidip_generator = new OIDplusOIDIP(); |
193 | 193 | ||
194 | list($oidIP, $dummy_content_type) = $oidip_generator->oidipQuery($query); |
194 | list($oidIP, $dummy_content_type) = $oidip_generator->oidipQuery($query); |
195 | 195 | ||
196 | $out['remarks'][] = [ |
196 | $out['remarks'][] = [ |
197 | "title" => "OID-IP Result", |
197 | "title" => "OID-IP Result", |
198 | "description" => $oidIP, |
198 | "description" => $oidIP, |
199 | "links" => [ |
199 | "links" => [ |
200 | [ |
200 | [ |
201 | "href"=> $oidIPUrl, |
201 | "href"=> $oidIPUrl, |
202 | "type"=> "text/plain", |
202 | "type"=> "text/plain", |
203 | "title"=> sprintf("OIDIP Result for the %s %s (Plaintext)", $ns, $n[1]), |
203 | "title"=> sprintf("OIDIP Result for the %s %s (Plaintext)", $ns, $n[1]), |
204 | "value"=> $oidIPUrl, |
204 | "value"=> $oidIPUrl, |
205 | "rel"=> "alternate" |
205 | "rel"=> "alternate" |
206 | ], |
206 | ], |
207 | [ |
207 | [ |
208 | "href"=> "$oidIPUrl\$format=json", |
208 | "href"=> "$oidIPUrl\$format=json", |
209 | "type"=> "application/json", |
209 | "type"=> "application/json", |
210 | "title"=> sprintf("OIDIP Result for the %s %s (JSON)", $ns, $n[1]), |
210 | "title"=> sprintf("OIDIP Result for the %s %s (JSON)", $ns, $n[1]), |
211 | "value"=> "$oidIPUrl\$format=json", |
211 | "value"=> "$oidIPUrl\$format=json", |
212 | "rel"=> "alternate" |
212 | "rel"=> "alternate" |
213 | ], |
213 | ], |
214 | [ |
214 | [ |
215 | "href"=> "$oidIPUrl\$format=xml", |
215 | "href"=> "$oidIPUrl\$format=xml", |
216 | "type"=> "application/xml", |
216 | "type"=> "application/xml", |
217 | "title"=> sprintf("OIDIP Result for the %s %s (XML)", $ns, $n[1]), |
217 | "title"=> sprintf("OIDIP Result for the %s %s (XML)", $ns, $n[1]), |
218 | "value"=> "$oidIPUrl\$format=xml", |
218 | "value"=> "$oidIPUrl\$format=xml", |
219 | "rel"=> "alternate" |
219 | "rel"=> "alternate" |
220 | ] |
220 | ] |
221 | ] |
221 | ] |
222 | ]; |
222 | ]; |
223 | 223 | ||
224 | list($oidIPJSON, $dummy_content_type) = $oidip_generator->oidipQuery("$query\$format=json"); |
224 | list($oidIPJSON, $dummy_content_type) = $oidip_generator->oidipQuery("$query\$format=json"); |
225 | $out['oidplus_oidip'] = json_decode($oidIPJSON); |
225 | $out['oidplus_oidip'] = json_decode($oidIPJSON); |
226 | } |
226 | } |
227 | 227 | ||
228 | $out['notices']=[ |
228 | $out['notices']=[ |
229 | [ |
229 | [ |
230 | "title" => "Authentication Policy", |
230 | "title" => "Authentication Policy", |
231 | "description" => |
231 | "description" => |
232 | [ |
232 | [ |
233 | "Access to sensitive data for users with proper credentials." |
233 | "Access to sensitive data for users with proper credentials." |
234 | ], |
234 | ], |
235 | "links" => |
235 | "links" => |
236 | [ |
236 | [ |
237 | [ |
237 | [ |
238 | "value" => $this->rdapBaseUri."help", |
238 | "value" => $this->rdapBaseUri."help", |
239 | "rel" => "alternate", |
239 | "rel" => "alternate", |
240 | "type" => "text/html", |
240 | "type" => "text/html", |
241 | "href" => OIDplus::webpath()."?goto=oidplus%3Aresources%24OIDplus%2Fprivacy_documentation.html" |
241 | "href" => OIDplus::webpath()."?goto=oidplus%3Aresources%24OIDplus%2Fprivacy_documentation.html" |
242 | ] |
242 | ] |
243 | ] |
243 | ] |
244 | ] |
244 | ] |
245 | ]; |
245 | ]; |
246 | 246 | ||
247 | if($obj->isConfidential()){ |
247 | if($obj->isConfidential()){ |
248 | $out['remarks'][1]['type'] = "result set truncated due to authorization"; |
248 | $out['remarks'][1]['type'] = "result set truncated due to authorization"; |
249 | } |
249 | } |
250 | 250 | ||
251 | $out['statuses']=[ |
251 | $out['statuses']=[ |
252 | 'active', |
252 | 'active', |
253 | ]; |
253 | ]; |
254 | 254 | ||
255 | 255 | ||
256 | if(true === $this->useCache){ |
256 | if(true === $this->useCache){ |
257 | $this->rdap_write_cache($out, $cacheFile); |
257 | $this->rdap_write_cache($out, $cacheFile); |
258 | } |
258 | } |
259 | return $this->rdap_out($out); |
259 | return $this->rdap_out($out); |
260 | } |
260 | } |
261 | 261 | ||
262 | /** |
262 | /** |
263 | * @param array $out |
263 | * @param array $out |
264 | * @param string $cacheFile |
264 | * @param string $cacheFile |
265 | * @return void |
265 | * @return void |
266 | */ |
266 | */ |
267 | protected function rdap_write_cache(array $out, string $cacheFile){ |
267 | protected function rdap_write_cache(array $out, string $cacheFile){ |
268 | @file_put_contents($cacheFile, serialize($out)); |
268 | @file_put_contents($cacheFile, serialize($out)); |
269 | } |
269 | } |
270 | 270 | ||
271 | /** |
271 | /** |
272 | * @param string $cacheFile |
272 | * @param string $cacheFile |
273 | * @param int $rdapCacheExpires |
273 | * @param int $rdapCacheExpires |
274 | * @return array|null |
274 | * @return array|null |
275 | */ |
275 | */ |
276 | protected function rdap_read_cache(string $cacheFile, int $rdapCacheExpires){ |
276 | protected function rdap_read_cache(string $cacheFile, int $rdapCacheExpires){ |
277 | if (file_exists($cacheFile) && filemtime($cacheFile) >= time() - $rdapCacheExpires) { |
277 | if (file_exists($cacheFile) && filemtime($cacheFile) >= time() - $rdapCacheExpires) { |
278 | $out = unserialize(file_get_contents($cacheFile)); |
278 | $out = unserialize(file_get_contents($cacheFile)); |
279 | if(is_array($out) || is_object($out)){ |
279 | if(is_array($out) || is_object($out)){ |
280 | return $this->rdap_out($out); |
280 | return $this->rdap_out($out); |
281 | } |
281 | } |
282 | } |
282 | } |
283 | return null; |
283 | return null; |
284 | } |
284 | } |
285 | 285 | ||
286 | /** |
286 | /** |
287 | * @param array $out |
287 | * @param array $out |
288 | * @return array |
288 | * @return array |
289 | */ |
289 | */ |
290 | protected function rdap_out(array $out): array { |
290 | protected function rdap_out(array $out): array { |
291 | $out_content = json_encode($out); |
291 | $out_content = json_encode($out); |
292 | $out_type = 'application/rdap+json'; |
292 | $out_type = 'application/rdap+json'; |
293 | return array($out_content, $out_type); |
293 | return array($out_content, $out_type); |
294 | } |
294 | } |
295 | 295 | ||
296 | } |
296 | } |
297 | 297 |