• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "libidn2_sapi.h"  // NOLINT(build/include)
16 
17 #include <cstdlib>
18 #include <fstream>
19 #include <iostream>
20 
21 #include "absl/log/log.h"
22 #include "sandboxed_api/util/fileops.h"
23 
24 static constexpr std::size_t kMaxDomainNameLength = 256;
25 static constexpr int kMinPossibleKnownError = -10000;
26 
ProcessErrors(const absl::StatusOr<int> & untrusted_res,sapi::v::GenericPtr & ptr)27 absl::StatusOr<std::string> IDN2Lib::ProcessErrors(
28     const absl::StatusOr<int>& untrusted_res, sapi::v::GenericPtr& ptr) {
29   SAPI_RETURN_IF_ERROR(untrusted_res.status());
30   int res = untrusted_res.value();
31   if (res < 0) {
32     if (res == IDN2_MALLOC) {
33       return absl::ResourceExhaustedError("malloc() failed in libidn2");
34     }
35     if (res > kMinPossibleKnownError) {
36       return absl::InvalidArgumentError(idn2_strerror(res));
37     }
38     return absl::InvalidArgumentError("Unexpected error");
39   }
40   sapi::v::RemotePtr p(reinterpret_cast<void*>(ptr.GetValue()));
41   auto maybe_untrusted_name = sandbox_->GetCString(p, kMaxDomainNameLength);
42   SAPI_RETURN_IF_ERROR(sandbox_->Free(&p));
43   if (!maybe_untrusted_name.ok()) {
44     return maybe_untrusted_name.status();
45   }
46   // FIXME: sanitize the result by checking that the return value is
47   // valid ASCII (for a-labels) or UTF-8 (for u-labels) and doesn't
48   // contain potentially malicious characters.
49   return *maybe_untrusted_name;
50 }
51 
idn2_register_u8(const char * ulabel,const char * alabel)52 absl::StatusOr<std::string> IDN2Lib::idn2_register_u8(const char* ulabel,
53                                                       const char* alabel) {
54   std::optional<sapi::v::ConstCStr> alabel_ptr;
55   std::optional<sapi::v::ConstCStr> ulabel_ptr;
56   if (ulabel) {
57     ulabel_ptr.emplace(ulabel);
58   }
59   if (alabel) {
60     alabel_ptr.emplace(alabel);
61   }
62   sapi::v::GenericPtr ptr;
63   const auto untrusted_res = api_.idn2_register_u8(
64       ulabel ? ulabel_ptr->PtrBefore() : nullptr,
65       alabel ? alabel_ptr->PtrBefore() : nullptr, ptr.PtrAfter(),
66       IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
67   return this->ProcessErrors(untrusted_res, ptr);
68 }
69 
SapiGeneric(const char * data,absl::StatusOr<int> (IDN2Api::* cb)(sapi::v::Ptr * input,sapi::v::Ptr * output,int flags))70 absl::StatusOr<std::string> IDN2Lib::SapiGeneric(
71     const char* data,
72     absl::StatusOr<int> (IDN2Api::*cb)(sapi::v::Ptr* input,
73                                        sapi::v::Ptr* output, int flags)) {
74   sapi::v::ConstCStr src(data);
75   sapi::v::GenericPtr ptr;
76 
77   absl::StatusOr<int> untrusted_res = ((api_).*(cb))(
78       src.PtrBefore(), ptr.PtrAfter(), IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
79   return this->ProcessErrors(untrusted_res, ptr);
80 }
81 
idn2_to_unicode_8z8z(const char * data)82 absl::StatusOr<std::string> IDN2Lib::idn2_to_unicode_8z8z(const char* data) {
83   return IDN2Lib::SapiGeneric(data, &IDN2Api::idn2_to_unicode_8z8z);
84 }
85 
idn2_to_ascii_8z(const char * data)86 absl::StatusOr<std::string> IDN2Lib::idn2_to_ascii_8z(const char* data) {
87   return IDN2Lib::SapiGeneric(data, &IDN2Api::idn2_to_ascii_8z);
88 }
89 
idn2_lookup_u8(const char * data)90 absl::StatusOr<std::string> IDN2Lib::idn2_lookup_u8(const char* data) {
91   return IDN2Lib::SapiGeneric(data, &IDN2Api::idn2_lookup_u8);
92 }
93