1use bytes;
2use libgssapi_sys::{
3 gss_buffer_desc, gss_buffer_desc_struct, gss_buffer_t, gss_release_buffer, OM_uint32,
4 GSS_S_COMPLETE,
5};
6#[cfg(feature = "s4u")]
7use libgssapi_sys::{gss_buffer_set_t, gss_release_buffer_set};
8use std::{
9 ffi,
10 marker::PhantomData,
11 ops::{Deref, DerefMut, Drop},
12 ptr, slice,
13};
14
15#[cfg(feature = "iov")]
16mod iov {
17 use super::*;
18 use libgssapi_sys::{
19 gss_iov_buffer_desc, GSS_IOV_BUFFER_FLAG_ALLOCATE, GSS_IOV_BUFFER_FLAG_ALLOCATED,
20 GSS_IOV_BUFFER_TYPE_DATA, GSS_IOV_BUFFER_TYPE_EMPTY, GSS_IOV_BUFFER_TYPE_HEADER,
21 GSS_IOV_BUFFER_TYPE_MECH_PARAMS, GSS_IOV_BUFFER_TYPE_PADDING,
22 GSS_IOV_BUFFER_TYPE_SIGN_ONLY, GSS_IOV_BUFFER_TYPE_STREAM,
23 GSS_IOV_BUFFER_TYPE_TRAILER,
24 };
25 const GSS_IOV_BUFFER_FLAG_MASK: u32 = 0xFFFF0000;
26 #[derive(Debug, Clone, Copy)]
27 pub enum GssIovType {
28 Empty,
29 Data,
30 Header,
31 MechParams,
32 Trailer,
33 Padding,
34 Stream,
35 SignOnly,
36 }
37
38 impl GssIovType {
39 fn to_c(&self) -> u32 {
40 match self {
41 GssIovType::Empty => GSS_IOV_BUFFER_TYPE_EMPTY,
42 GssIovType::Data => GSS_IOV_BUFFER_TYPE_DATA,
43 GssIovType::Header => GSS_IOV_BUFFER_TYPE_HEADER,
44 GssIovType::MechParams => GSS_IOV_BUFFER_TYPE_MECH_PARAMS,
45 GssIovType::Trailer => GSS_IOV_BUFFER_TYPE_TRAILER,
46 GssIovType::Padding => GSS_IOV_BUFFER_TYPE_PADDING,
47 GssIovType::Stream => GSS_IOV_BUFFER_TYPE_STREAM,
48 GssIovType::SignOnly => GSS_IOV_BUFFER_TYPE_SIGN_ONLY,
49 }
50 }
51
52 fn from_c(t: u32) -> Option<Self> {
53 match t & !GSS_IOV_BUFFER_FLAG_MASK {
54 GSS_IOV_BUFFER_TYPE_EMPTY => Some(GssIovType::Empty),
55 GSS_IOV_BUFFER_TYPE_DATA => Some(GssIovType::Data),
56 GSS_IOV_BUFFER_TYPE_HEADER => Some(GssIovType::Header),
57 GSS_IOV_BUFFER_TYPE_MECH_PARAMS => Some(GssIovType::MechParams),
58 GSS_IOV_BUFFER_TYPE_TRAILER => Some(GssIovType::Trailer),
59 GSS_IOV_BUFFER_TYPE_PADDING => Some(GssIovType::Padding),
60 GSS_IOV_BUFFER_TYPE_STREAM => Some(GssIovType::Stream),
61 GSS_IOV_BUFFER_TYPE_SIGN_ONLY => Some(GssIovType::SignOnly),
62 _ => None,
63 }
64 }
65 }
66
67 #[repr(transparent)]
70 #[derive(Debug)]
71 pub struct GssIovFake(gss_iov_buffer_desc);
72
73 impl GssIovFake {
74 pub fn new(typ: GssIovType) -> GssIovFake {
76 let gss_iov = gss_iov_buffer_desc {
77 type_: typ.to_c(),
78 buffer: gss_buffer_desc_struct {
79 length: 0,
80 value: ptr::null_mut(),
81 },
82 };
83 GssIovFake(gss_iov)
84 }
85
86 pub fn len(&self) -> usize {
87 self.0.buffer.length as usize
88 }
89 }
90
91 #[repr(transparent)]
92 #[derive(Debug)]
93 pub struct GssIov<'a>(gss_iov_buffer_desc, PhantomData<&'a [u8]>);
94
95 unsafe impl<'a> Send for GssIov<'a> {}
96 unsafe impl<'a> Sync for GssIov<'a> {}
97
98 impl<'a> Drop for GssIov<'a> {
99 fn drop(&mut self) {
100 if self.0.type_ & GSS_IOV_BUFFER_FLAG_MASK & GSS_IOV_BUFFER_FLAG_ALLOCATED > 0
102 {
103 let mut minor = GSS_S_COMPLETE;
104 let _major = unsafe {
105 gss_release_buffer(
106 &mut minor as *mut OM_uint32,
107 &mut self.0.buffer as gss_buffer_t,
108 )
109 };
110 }
111 }
112 }
113
114 impl<'a> Deref for GssIov<'a> {
115 type Target = [u8];
116
117 fn deref(&self) -> &Self::Target {
118 let buf = self.0.buffer;
119 if buf.value.is_null() && buf.length == 0 {
120 &[]
121 } else {
122 unsafe { slice::from_raw_parts(buf.value.cast(), buf.length as usize) }
123 }
124 }
125 }
126
127 impl<'a> DerefMut for GssIov<'a> {
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 let buf = self.0.buffer;
130 unsafe {
131 if buf.value.is_null() && buf.length == 0 {
132 &mut []
133 } else {
134 slice::from_raw_parts_mut(buf.value.cast(), buf.length as usize)
135 }
136 }
137 }
138 }
139
140 impl<'a> GssIov<'a> {
141 pub fn new(typ: GssIovType, data: &'a mut [u8]) -> GssIov<'a> {
143 let gss_iov = gss_iov_buffer_desc {
144 type_: typ.to_c(),
145 buffer: gss_buffer_desc_struct {
146 length: data.len(),
147 value: data.as_mut_ptr().cast(),
148 },
149 };
150 GssIov(gss_iov, PhantomData)
151 }
152
153 pub fn new_alloc(typ: GssIovType) -> GssIov<'a> {
156 let gss_iov = gss_iov_buffer_desc {
157 type_: typ.to_c() | GSS_IOV_BUFFER_FLAG_ALLOCATE,
158 buffer: gss_buffer_desc_struct {
159 length: 0,
160 value: ptr::null_mut(),
161 },
162 };
163 GssIov(gss_iov, PhantomData)
164 }
165
166 pub fn typ(&self) -> Option<GssIovType> {
167 GssIovType::from_c(self.0.type_)
168 }
169
170 pub fn as_fake(self) -> GssIovFake {
173 GssIovFake(self.0)
174 }
175
176 pub fn header_length(&self, data: &GssIov<'a>) -> Option<usize> {
183 match GssIovType::from_c(self.0.type_) {
184 Some(GssIovType::Stream) => {
185 Some(data.0.buffer.value as usize - self.0.buffer.value as usize)
186 }
187 _ => None,
188 }
189 }
190
191 pub fn len(&self) -> usize {
192 self.0.buffer.length as usize
193 }
194 }
195}
196
197#[cfg(feature = "iov")]
198pub use iov::*;
199
200#[repr(transparent)]
205#[derive(Debug)]
206pub(crate) struct BufRef<'a>(gss_buffer_desc_struct, PhantomData<&'a [u8]>);
207
208unsafe impl<'a> Send for BufRef<'a> {}
209unsafe impl<'a> Sync for BufRef<'a> {}
210
211impl<'a> Deref for BufRef<'a> {
212 type Target = [u8];
213
214 fn deref(&self) -> &Self::Target {
215 if self.0.value.is_null() && self.0.length == 0 {
216 &[]
217 } else {
218 unsafe { slice::from_raw_parts(self.0.value.cast(), self.0.length as usize) }
219 }
220 }
221}
222
223impl<'a> From<&'a [u8]> for BufRef<'a> {
224 fn from(s: &[u8]) -> Self {
225 let gss_buf = gss_buffer_desc_struct {
226 length: s.len(),
227 value: s.as_ptr() as *mut ffi::c_void,
228 };
229 BufRef(gss_buf, PhantomData)
230 }
231}
232
233impl<'a> BufRef<'a> {
234 pub(crate) unsafe fn to_c(&mut self) -> gss_buffer_t {
235 &mut self.0 as gss_buffer_t
236 }
237}
238
239#[repr(transparent)]
242#[allow(dead_code)]
243#[derive(Debug)]
244pub struct Buf(gss_buffer_desc);
245
246unsafe impl Send for Buf {}
247unsafe impl Sync for Buf {}
248
249impl Deref for Buf {
250 type Target = [u8];
251
252 fn deref(&self) -> &Self::Target {
253 unsafe {
254 if self.0.value.is_null() && self.0.length == 0 {
255 &[]
256 } else {
257 slice::from_raw_parts(self.0.value.cast(), self.0.length as usize)
258 }
259 }
260 }
261}
262
263impl DerefMut for Buf {
264 fn deref_mut(&mut self) -> &mut Self::Target {
265 unsafe {
266 if self.0.value.is_null() && self.0.length == 0 {
267 &mut []
268 } else {
269 slice::from_raw_parts_mut(self.0.value.cast(), self.0.length as usize)
270 }
271 }
272 }
273}
274
275impl Drop for Buf {
276 fn drop(&mut self) {
277 if !self.0.value.is_null() {
278 let mut minor = GSS_S_COMPLETE;
279 let _major = unsafe {
280 gss_release_buffer(
281 &mut minor as *mut OM_uint32,
282 &mut self.0 as gss_buffer_t,
283 )
284 };
285 }
286 }
287}
288
289impl Buf {
290 pub(crate) fn empty() -> Buf {
291 Buf(gss_buffer_desc {
292 length: 0,
293 value: ptr::null_mut(),
294 })
295 }
296
297 pub(crate) unsafe fn to_c(&mut self) -> gss_buffer_t {
298 &mut self.0 as gss_buffer_t
299 }
300
301 pub fn to_bytes(self) -> GssBytes {
303 GssBytes { pos: 0, buf: self }
304 }
305}
306
307#[derive(Debug)]
308pub struct GssBytes {
309 pos: usize,
310 buf: Buf,
311}
312
313impl bytes::Buf for GssBytes {
314 fn remaining(&self) -> usize {
315 self.buf.0.length as usize - self.pos
316 }
317
318 fn chunk(&self) -> &[u8] {
319 &((*self.buf)[self.pos..])
320 }
321
322 fn advance(&mut self, cnt: usize) {
323 let rem = self.remaining();
324 if cnt > rem {
325 panic!(
326 "advancing {} would overrun the remaining buffer {}",
327 cnt, rem
328 );
329 } else {
330 self.pos += cnt;
331 }
332 }
333}
334
335impl GssBytes {
336 pub fn into_inner(self) -> Buf {
338 self.buf
339 }
340}
341
342#[cfg(feature = "s4u")]
343mod s4u {
344 use super::*;
345
346 #[repr(transparent)]
349 #[allow(dead_code)]
350 #[derive(Debug)]
351 pub(crate) struct BufSet<'a>(gss_buffer_set_t, PhantomData<&'a [BufRef<'a>]>);
352
353 unsafe impl Send for BufSet<'_> {}
354 unsafe impl Sync for BufSet<'_> {}
355
356 impl<'a> Deref for BufSet<'a> {
357 type Target = [BufRef<'a>];
358
359 fn deref(&self) -> &'a Self::Target {
360 if self.0.is_null()
361 || unsafe { (*self.0).elements.is_null() && (*self.0).count == 0 }
362 {
363 &[]
364 } else {
365 unsafe {
366 slice::from_raw_parts(
367 (*self.0).elements.cast(),
368 (*self.0).count as usize,
369 )
370 }
371 }
372 }
373 }
374
375 impl<'a> DerefMut for BufSet<'a> {
376 fn deref_mut(&mut self) -> &'a mut Self::Target {
377 if self.0.is_null()
378 || unsafe { (*self.0).elements.is_null() && (*self.0).count == 0 }
379 {
380 &mut []
381 } else {
382 unsafe {
383 slice::from_raw_parts_mut(
384 (*self.0).elements.cast(),
385 (*self.0).count as usize,
386 )
387 }
388 }
389 }
390 }
391
392 impl Drop for BufSet<'_> {
393 fn drop(&mut self) {
394 if !self.0.is_null() {
395 let mut minor = GSS_S_COMPLETE;
396 let _major = unsafe {
397 gss_release_buffer_set(&mut minor as *mut OM_uint32, &mut self.0)
398 };
399 }
400 }
401 }
402
403 impl BufSet<'_> {
404 pub(crate) fn empty() -> Self {
405 Self(ptr::null_mut(), PhantomData)
406 }
407
408 pub(crate) unsafe fn to_c(&mut self) -> &mut gss_buffer_set_t {
409 &mut self.0
410 }
411 }
412}
413
414#[cfg(feature = "s4u")]
415pub(crate) use s4u::*;