Skip to main content

libgssapi/
name.rs

1#[cfg(feature = "localname")]
2use crate::oid::NO_OID;
3use crate::{
4    error::{Error, MajorFlags},
5    oid::Oid,
6    util::{Buf, BufRef},
7};
8#[cfg(feature = "localname")]
9use libgssapi_sys::gss_localname;
10use libgssapi_sys::{
11    GSS_S_COMPLETE, OM_uint32, gss_OID, gss_OID_desc, gss_canonicalize_name,
12    gss_display_name, gss_duplicate_name, gss_export_name, gss_import_name, gss_name_t,
13    gss_release_name,
14};
15use std::{fmt, ptr};
16
17pub struct Name(gss_name_t);
18
19unsafe impl Send for Name {}
20unsafe impl Sync for Name {}
21
22impl Drop for Name {
23    fn drop(&mut self) {
24        if !self.0.is_null() {
25            let mut _minor = GSS_S_COMPLETE;
26            let _major = unsafe {
27                gss_release_name(
28                    &mut _minor as *mut OM_uint32,
29                    &mut self.0 as *mut gss_name_t,
30                )
31            };
32        }
33    }
34}
35
36impl fmt::Debug for Name {
37    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
38        if let Ok(buf) = self.display_name() {
39            if let Ok(s) = std::str::from_utf8(&buf) {
40                write!(f, "{}", s)
41            } else {
42                write!(f, "<name can't be decoded>")
43            }
44        } else {
45            write!(f, "<name can't be displayed>")
46        }
47    }
48}
49
50impl fmt::Display for Name {
51    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
52        fmt::Debug::fmt(self, f)
53    }
54}
55
56impl Name {
57    pub(crate) unsafe fn to_c(&self) -> gss_name_t {
58        self.0
59    }
60
61    #[allow(dead_code)]
62    pub(crate) unsafe fn from_c(ptr: gss_name_t) -> Self {
63        Name(ptr)
64    }
65
66    /// parse the specified bytes as a gssapi name, with optional
67    /// `kind` e.g. `GSS_NT_HOSTBASED_SERVICE` or
68    /// `GSS_NT_KRB5_PRINCIPAL`.
69    pub fn new(s: &[u8], kind: Option<Oid<'_>>) -> Result<Self, Error> {
70        let mut buf = BufRef::from(s);
71        let mut minor = GSS_S_COMPLETE;
72        let mut name: gss_name_t = ptr::null_mut();
73        let major = unsafe {
74            gss_import_name(
75                &mut minor as *mut OM_uint32,
76                buf.to_c(),
77                match &kind {
78                    None => ptr::null_mut::<gss_OID_desc>(),
79                    Some(kind) => kind.to_c(),
80                },
81                &mut name as *mut gss_name_t,
82            )
83        };
84        if major == GSS_S_COMPLETE {
85            Ok(Name(name))
86        } else {
87            Err(Error {
88                major: MajorFlags::from_bits_retain(major),
89                minor,
90            })
91        }
92    }
93
94    /// canonicalize a name for the specified mechanism (or the
95    /// default mechanism if not specified). This makes a copy of the
96    /// name.
97    pub fn canonicalize(&self, mech: Option<Oid<'_>>) -> Result<Self, Error> {
98        let mut out: gss_name_t = ptr::null_mut();
99        let mut minor = GSS_S_COMPLETE;
100        let major = unsafe {
101            gss_canonicalize_name(
102                &mut minor as *mut OM_uint32,
103                self.to_c(),
104                match &mech {
105                    None => ptr::null_mut::<gss_OID_desc>(),
106                    Some(id) => id.to_c(),
107                },
108                &mut out as *mut gss_name_t,
109            )
110        };
111        if major == GSS_S_COMPLETE {
112            Ok(Name(out))
113        } else {
114            Err(Error {
115                major: MajorFlags::from_bits_retain(major),
116                minor,
117            })
118        }
119    }
120
121    /// Produce a contiguous string representation of a canonicalized
122    /// name suitable for direct comparison. You must either use a
123    /// canonical name, or call canonicalize before using this method.
124    pub fn export(&self) -> Result<Buf, Error> {
125        let mut out = Buf::empty();
126        let mut minor = GSS_S_COMPLETE;
127        let major =
128            unsafe { gss_export_name(&mut minor as *mut OM_uint32, self.0, out.to_c()) };
129        if major == GSS_S_COMPLETE {
130            Ok(out)
131        } else {
132            Err(Error {
133                major: MajorFlags::from_bits_retain(major),
134                minor,
135            })
136        }
137    }
138
139    /// Return the raw textual representation of the internal GSS
140    /// name. Usually this will be utf8, or at least ascii, but that
141    /// isn't guaranteed.
142    pub fn display_name(&self) -> Result<Buf, Error> {
143        let mut out = Buf::empty();
144        let mut minor = GSS_S_COMPLETE;
145        let mut oid = ptr::null_mut::<gss_OID_desc>();
146        let major = unsafe {
147            gss_display_name(
148                &mut minor as *mut OM_uint32,
149                self.to_c(),
150                out.to_c(),
151                &mut oid as *mut gss_OID,
152            )
153        };
154        if major == GSS_S_COMPLETE {
155            Ok(out)
156        } else {
157            Err(Error {
158                major: MajorFlags::from_bits_retain(major),
159                minor,
160            })
161        }
162    }
163
164    /// Return the raw textual representation of the internal GSS name
165    /// as interpreted by the specified mechanism. If no mechanism is
166    /// specified then it will be assumed to be NO_OID.
167    #[cfg(feature = "localname")]
168    pub fn local_name(&self, mechs: Option<Oid<'_>>) -> Result<Buf, Error> {
169        let mut out = Buf::empty();
170        let mut minor = GSS_S_COMPLETE;
171        let major = unsafe {
172            gss_localname(
173                &mut minor as *mut OM_uint32,
174                self.0,
175                mechs.as_ref().map_or(NO_OID, |o| o.to_c()),
176                out.to_c(),
177            )
178        };
179        if major == GSS_S_COMPLETE {
180            Ok(out)
181        } else {
182            Err(Error {
183                major: MajorFlags::from_bits_retain(major),
184                minor,
185            })
186        }
187    }
188
189    /// Duplicate the name.
190    pub fn duplicate(&self) -> Result<Self, Error> {
191        let mut copy: gss_name_t = ptr::null_mut();
192        let mut minor = GSS_S_COMPLETE;
193        let major = unsafe {
194            gss_duplicate_name(
195                &mut minor as *mut OM_uint32,
196                self.to_c(),
197                &mut copy as *mut gss_name_t,
198            )
199        };
200        if major == GSS_S_COMPLETE {
201            Ok(Name(copy))
202        } else {
203            Err(Error {
204                major: MajorFlags::from_bits_retain(major),
205                minor,
206            })
207        }
208    }
209}