• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include "src/core/tsi/local_transport_security.h"
20 
21 #include <grpc/support/alloc.h>
22 #include <grpc/support/port_platform.h>
23 #include <grpc/support/string_util.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "absl/log/log.h"
29 #include "src/core/lib/iomgr/exec_ctx.h"
30 #include "src/core/tsi/transport_security_grpc.h"
31 #include "src/core/util/crash.h"
32 
33 namespace {
34 
35 // Main struct for local TSI zero-copy frame protector.
36 typedef struct local_zero_copy_grpc_protector {
37   tsi_zero_copy_grpc_protector base;
38 } local_zero_copy_grpc_protector;
39 
40 // Main struct for local TSI handshaker result.
41 typedef struct local_tsi_handshaker_result {
42   tsi_handshaker_result base;
43   unsigned char* unused_bytes;
44   size_t unused_bytes_size;
45 } local_tsi_handshaker_result;
46 
47 // Main struct for local TSI handshaker.
48 typedef struct local_tsi_handshaker {
49   tsi_handshaker base;
50 } local_tsi_handshaker;
51 
52 // --- tsi_handshaker_result methods implementation. ---
53 
handshaker_result_extract_peer(const tsi_handshaker_result *,tsi_peer *)54 tsi_result handshaker_result_extract_peer(const tsi_handshaker_result* /*self*/,
55                                           tsi_peer* /*peer*/) {
56   return TSI_OK;
57 }
58 
handshaker_result_get_frame_protector_type(const tsi_handshaker_result *,tsi_frame_protector_type * frame_protector_type)59 tsi_result handshaker_result_get_frame_protector_type(
60     const tsi_handshaker_result* /*self*/,
61     tsi_frame_protector_type* frame_protector_type) {
62   *frame_protector_type = TSI_FRAME_PROTECTOR_NONE;
63   return TSI_OK;
64 }
65 
handshaker_result_get_unused_bytes(const tsi_handshaker_result * self,const unsigned char ** bytes,size_t * bytes_size)66 tsi_result handshaker_result_get_unused_bytes(const tsi_handshaker_result* self,
67                                               const unsigned char** bytes,
68                                               size_t* bytes_size) {
69   if (self == nullptr || bytes == nullptr || bytes_size == nullptr) {
70     LOG(ERROR) << "Invalid arguments to get_unused_bytes()";
71     return TSI_INVALID_ARGUMENT;
72   }
73   auto* result = reinterpret_cast<local_tsi_handshaker_result*>(
74       const_cast<tsi_handshaker_result*>(self));
75   *bytes_size = result->unused_bytes_size;
76   *bytes = result->unused_bytes;
77   return TSI_OK;
78 }
79 
handshaker_result_destroy(tsi_handshaker_result * self)80 void handshaker_result_destroy(tsi_handshaker_result* self) {
81   if (self == nullptr) {
82     return;
83   }
84   local_tsi_handshaker_result* result =
85       reinterpret_cast<local_tsi_handshaker_result*>(
86           const_cast<tsi_handshaker_result*>(self));
87   gpr_free(result->unused_bytes);
88   gpr_free(result);
89 }
90 
91 const tsi_handshaker_result_vtable result_vtable = {
92     handshaker_result_extract_peer,
93     handshaker_result_get_frame_protector_type,
94     nullptr,  // handshaker_result_create_zero_copy_grpc_protector
95     nullptr,  // handshaker_result_create_frame_protector
96     handshaker_result_get_unused_bytes,
97     handshaker_result_destroy};
98 
create_handshaker_result(const unsigned char * received_bytes,size_t received_bytes_size,tsi_handshaker_result ** self)99 tsi_result create_handshaker_result(const unsigned char* received_bytes,
100                                     size_t received_bytes_size,
101                                     tsi_handshaker_result** self) {
102   if (self == nullptr) {
103     LOG(ERROR) << "Invalid arguments to create_handshaker_result()";
104     return TSI_INVALID_ARGUMENT;
105   }
106   local_tsi_handshaker_result* result =
107       grpc_core::Zalloc<local_tsi_handshaker_result>();
108   if (received_bytes_size > 0) {
109     result->unused_bytes =
110         static_cast<unsigned char*>(gpr_malloc(received_bytes_size));
111     memcpy(result->unused_bytes, received_bytes, received_bytes_size);
112   }
113   result->unused_bytes_size = received_bytes_size;
114   result->base.vtable = &result_vtable;
115   *self = &result->base;
116   return TSI_OK;
117 }
118 
119 // --- tsi_handshaker methods implementation. ---
120 
handshaker_next(tsi_handshaker * self,const unsigned char * received_bytes,size_t received_bytes_size,const unsigned char **,size_t * bytes_to_send_size,tsi_handshaker_result ** result,tsi_handshaker_on_next_done_cb,void *,std::string * error)121 tsi_result handshaker_next(tsi_handshaker* self,
122                            const unsigned char* received_bytes,
123                            size_t received_bytes_size,
124                            const unsigned char** /*bytes_to_send*/,
125                            size_t* bytes_to_send_size,
126                            tsi_handshaker_result** result,
127                            tsi_handshaker_on_next_done_cb /*cb*/,
128                            void* /*user_data*/, std::string* error) {
129   if (self == nullptr) {
130     LOG(ERROR) << "Invalid arguments to handshaker_next()";
131     if (error != nullptr) *error = "invalid argument";
132     return TSI_INVALID_ARGUMENT;
133   }
134   // Note that there is no interaction between TSI peers, and all operations are
135   // local.
136   //
137   *bytes_to_send_size = 0;
138   create_handshaker_result(received_bytes, received_bytes_size, result);
139   return TSI_OK;
140 }
141 
handshaker_destroy(tsi_handshaker * self)142 void handshaker_destroy(tsi_handshaker* self) {
143   if (self == nullptr) {
144     return;
145   }
146   local_tsi_handshaker* handshaker =
147       reinterpret_cast<local_tsi_handshaker*>(self);
148   gpr_free(handshaker);
149 }
150 
151 const tsi_handshaker_vtable handshaker_vtable = {
152     nullptr,  // get_bytes_to_send_to_peer -- deprecated
153     nullptr,  // process_bytes_from_peer   -- deprecated
154     nullptr,  // get_result                -- deprecated
155     nullptr,  // extract_peer              -- deprecated
156     nullptr,  // create_frame_protector    -- deprecated
157     handshaker_destroy,
158     handshaker_next,
159     nullptr,  // shutdown
160 };
161 
162 }  // namespace
163 
tsi_local_handshaker_create(tsi_handshaker ** self)164 tsi_result tsi_local_handshaker_create(tsi_handshaker** self) {
165   if (self == nullptr) {
166     LOG(ERROR) << "Invalid arguments to local_tsi_handshaker_create()";
167     return TSI_INVALID_ARGUMENT;
168   }
169   local_tsi_handshaker* handshaker = grpc_core::Zalloc<local_tsi_handshaker>();
170   handshaker->base.vtable = &handshaker_vtable;
171   *self = &handshaker->base;
172   return TSI_OK;
173 }
174