1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ using NtApiDotNet . Win32 . SafeHandles ;
1516using NtApiDotNet . Win32 . Security . Authentication ;
1617using System ;
1718
@@ -22,9 +23,68 @@ namespace NtApiDotNet.Win32.Rpc.Transport
2223 /// </summary>
2324 public struct RpcTransportSecurity
2425 {
26+ #region Private Members
2527 private readonly Func < RpcTransportSecurity , IClientAuthenticationContext > _auth_factory ;
2628 private RpcAuthenticationType _auth_type ;
2729
30+ private string GetAuthPackageName ( )
31+ {
32+ switch ( _auth_type )
33+ {
34+ case RpcAuthenticationType . Negotiate :
35+ return AuthenticationPackage . NEGOSSP_NAME ;
36+ case RpcAuthenticationType . Kerberos :
37+ return AuthenticationPackage . KERBEROS_NAME ;
38+ case RpcAuthenticationType . WinNT :
39+ return AuthenticationPackage . NTLM_NAME ;
40+ case RpcAuthenticationType . None :
41+ throw new ArgumentException ( "Must specify an authentication type to authenticate an RPC connection." ) ;
42+ default :
43+ throw new ArgumentException ( $ "Unknown authentication type: { _auth_type } ") ;
44+ }
45+ }
46+
47+ private InitializeContextReqFlags GetContextRequestFlags ( )
48+ {
49+ InitializeContextReqFlags flags = InitializeContextReqFlags . Connection | InitializeContextReqFlags . UseDCEStyle ;
50+ if ( SecurityQualityOfService != null )
51+ {
52+ switch ( SecurityQualityOfService . ImpersonationLevel )
53+ {
54+ case SecurityImpersonationLevel . Identification :
55+ flags |= InitializeContextReqFlags . Identify ;
56+ break ;
57+ case SecurityImpersonationLevel . Delegation :
58+ flags |= InitializeContextReqFlags . Delegate | InitializeContextReqFlags . MutualAuth ;
59+ break ;
60+ }
61+ }
62+
63+ switch ( AuthenticationLevel )
64+ {
65+ case RpcAuthenticationLevel . PacketIntegrity :
66+ flags |= InitializeContextReqFlags . Integrity | InitializeContextReqFlags . ReplayDetect | InitializeContextReqFlags . SequenceDetect ;
67+ break ;
68+ case RpcAuthenticationLevel . PacketPrivacy :
69+ flags |= InitializeContextReqFlags . Confidentiality | InitializeContextReqFlags . Integrity | InitializeContextReqFlags . ReplayDetect | InitializeContextReqFlags . SequenceDetect ;
70+ break ;
71+ }
72+
73+ if ( AuthenticationCapabilities . HasFlagSet ( RpcAuthenticationCapabilities . MutualAuthentication ) )
74+ {
75+ flags |= InitializeContextReqFlags . MutualAuth ;
76+ }
77+ if ( AuthenticationCapabilities . HasFlagSet ( RpcAuthenticationCapabilities . NullSession ) )
78+ {
79+ flags |= InitializeContextReqFlags . NullSession ;
80+ }
81+
82+ return flags ;
83+ }
84+
85+ #endregion
86+
87+ #region Public Properties
2888 /// <summary>
2989 /// Security quality of service.
3090 /// </summary>
@@ -58,7 +118,9 @@ public RpcAuthenticationType AuthenticationType
58118 /// Authentication capabilities.
59119 /// </summary>
60120 public RpcAuthenticationCapabilities AuthenticationCapabilities { get ; set ; }
121+ #endregion
61122
123+ #region Constructors
62124 /// <summary>
63125 /// Constructor.
64126 /// </summary>
@@ -77,62 +139,49 @@ public RpcTransportSecurity(SecurityQualityOfService security_quality_of_service
77139 {
78140 SecurityQualityOfService = security_quality_of_service ;
79141 }
142+ #endregion
80143
81- private string GetAuthPackageName ( )
82- {
83- switch ( _auth_type )
84- {
85- case RpcAuthenticationType . Negotiate :
86- return AuthenticationPackage . NEGOSSP_NAME ;
87- case RpcAuthenticationType . Kerberos :
88- return AuthenticationPackage . KERBEROS_NAME ;
89- case RpcAuthenticationType . WinNT :
90- return AuthenticationPackage . NTLM_NAME ;
91- case RpcAuthenticationType . None :
92- throw new ArgumentException ( "Must specify an authentication type to authenticate an RPC connection." ) ;
93- default :
94- throw new ArgumentException ( $ "Unknown authentication type: { _auth_type } ") ;
95- }
96- }
97-
98- private InitializeContextReqFlags GetContextRequestFlags ( )
144+ #region Static Members
145+ /// <summary>
146+ /// Query the service principal name for the server.
147+ /// </summary>
148+ /// <param name="string_binding">The binding string for the server.</param>
149+ /// <param name="authn_svc">The authentication service to query.</param>
150+ /// <param name="throw_on_error">True to throw on error.</param>
151+ /// <returns>The service principal name.</returns>
152+ public static NtResult < string > QueryServicePrincipalName ( string string_binding , RpcAuthenticationType authn_svc , bool throw_on_error )
99153 {
100- InitializeContextReqFlags flags = InitializeContextReqFlags . Connection | InitializeContextReqFlags . UseDCEStyle ;
101- if ( SecurityQualityOfService != null )
154+ using ( var binding = SafeRpcBindingHandle . Create ( string_binding , false ) )
102155 {
103- switch ( SecurityQualityOfService . ImpersonationLevel )
156+ if ( ! binding . IsSuccess )
104157 {
105- case SecurityImpersonationLevel . Identification :
106- flags |= InitializeContextReqFlags . Identify ;
107- break ;
108- case SecurityImpersonationLevel . Delegation :
109- flags |= InitializeContextReqFlags . Delegate | InitializeContextReqFlags . MutualAuth ;
110- break ;
158+ return binding . Cast < string > ( ) ;
111159 }
112- }
113160
114- switch ( AuthenticationLevel )
115- {
116- case RpcAuthenticationLevel . PacketIntegrity :
117- flags |= InitializeContextReqFlags . Integrity | InitializeContextReqFlags . ReplayDetect | InitializeContextReqFlags . SequenceDetect ;
118- break ;
119- case RpcAuthenticationLevel . PacketPrivacy :
120- flags |= InitializeContextReqFlags . Confidentiality | InitializeContextReqFlags . Integrity | InitializeContextReqFlags . ReplayDetect | InitializeContextReqFlags . SequenceDetect ;
121- break ;
122- }
123-
124- if ( AuthenticationCapabilities . HasFlagSet ( RpcAuthenticationCapabilities . MutualAuthentication ) )
125- {
126- flags |= InitializeContextReqFlags . MutualAuth ;
127- }
128- if ( AuthenticationCapabilities . HasFlagSet ( RpcAuthenticationCapabilities . NullSession ) )
129- {
130- flags |= InitializeContextReqFlags . NullSession ;
161+ return Win32NativeMethods . RpcMgmtInqServerPrincName ( binding . Result , authn_svc ,
162+ out SafeRpcStringHandle spn ) . CreateWin32Result ( throw_on_error , ( ) => {
163+ using ( spn )
164+ {
165+ return spn . ToString ( ) ;
166+ }
167+ }
168+ ) ;
131169 }
170+ }
132171
133- return flags ;
172+ /// <summary>
173+ /// Query the service principal name for the server.
174+ /// </summary>
175+ /// <param name="string_binding">The binding string for the server.</param>
176+ /// <param name="authn_svc">The authentication service to query.</param>
177+ /// <returns>The service principal name.</returns>
178+ public static string QueryServicePrincipalName ( string string_binding , RpcAuthenticationType authn_svc )
179+ {
180+ return QueryServicePrincipalName ( string_binding , authn_svc , true ) . Result ;
134181 }
182+ #endregion
135183
184+ #region Internal Members
136185 internal IClientAuthenticationContext CreateClientContext ( )
137186 {
138187 if ( _auth_factory != null )
@@ -157,5 +206,6 @@ internal IClientAuthenticationContext CreateClientContext()
157206 ServicePrincipalName , SecDataRep . Native ) ;
158207 }
159208 }
209+ #endregion
160210 }
161211}
0 commit comments