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 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 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 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 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 #[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 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}