Remote Call Framework 3.2
SspiFilter.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2020, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 3.2
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef INCLUDE_RCF_SSPIFILTER_HPP
20 #define INCLUDE_RCF_SSPIFILTER_HPP
21 
22 #include <functional>
23 #include <memory>
24 
25 #include <RCF/ByteBuffer.hpp>
26 #include <RCF/Enums.hpp>
27 #include <RCF/Filter.hpp>
28 #include <RCF/RcfFwd.hpp>
29 #include <RCF/RecursionLimiter.hpp>
30 #include <RCF/ThreadLibrary.hpp>
31 #include <RCF/Export.hpp>
32 
33 #include <RCF/Tchar.hpp>
34 
35 #ifndef SECURITY_WIN32
36 #define SECURITY_WIN32
37 #endif
38 
39 #include <windows.h>
40 #include <security.h>
41 #include <schannel.h>
42 #include <WinCrypt.h>
43 #include <tchar.h>
44 
45 namespace RCF {
46 
47  typedef RCF::tstring tstring;
48 
49  class SspiFilter;
50  class RcfSession;
51  class ClientStub;
52 
53  typedef std::shared_ptr<SspiFilter> SspiFilterPtr;
54 
56  class RCF_EXPORT SspiImpersonator
57  {
58  public:
59  SspiImpersonator(SspiFilterPtr sspiFilterPtr);
60 
62  SspiImpersonator(RcfSession & session);
63 
66 
67  bool impersonate();
68 
70  void revertToSelf() const;
71 
72  private:
73  SspiFilterPtr mSspiFilterPtr;
74  };
75 
76  static const ULONG DefaultSspiContextRequirements =
77  ISC_REQ_REPLAY_DETECT |
78  ISC_REQ_SEQUENCE_DETECT |
79  ISC_REQ_CONFIDENTIALITY |
80  ISC_REQ_INTEGRITY |
81  ISC_REQ_DELEGATE |
82  ISC_REQ_MUTUAL_AUTH;
83 
84  static const ULONG DefaultSchannelContextRequirements =
85  ASC_REQ_SEQUENCE_DETECT
86  | ASC_REQ_REPLAY_DETECT
87  | ASC_REQ_CONFIDENTIALITY
88  | ASC_REQ_EXTENDED_ERROR
89  | ASC_REQ_ALLOCATE_MEMORY
90  | ASC_REQ_STREAM;
91 
92 #if defined(SP_PROT_TLS1_3_SERVER) && defined(SP_PROT_TLS1_3_CLIENT)
93 
94  static const DWORD DefaultSchannelServerProtocols =
95  SP_PROT_TLS1_3_SERVER
96  | SP_PROT_TLS1_2_SERVER;
97 
98  static const DWORD DefaultSchannelClientProtocols =
99  SP_PROT_TLS1_3_CLIENT
100  | SP_PROT_TLS1_2_CLIENT
101  | SP_PROT_TLS1_1_CLIENT
102  | SP_PROT_TLS1_0_CLIENT;
103 
104 #else
105 
106  static const DWORD DefaultSchannelServerProtocols =
107  SP_PROT_TLS1_2_SERVER;
108 
109  static const DWORD DefaultSchannelClientProtocols =
110  SP_PROT_TLS1_2_CLIENT
111  | SP_PROT_TLS1_1_CLIENT
112  | SP_PROT_TLS1_0_CLIENT;
113 
114 #endif
115 
116  class SchannelClientFilter;
117  typedef SchannelClientFilter SchannelFilter;
118 
119  class SchannelFilterFactory;
120 
121  class Certificate;
122  class Win32Certificate;
123 
124  class SspiCredentials;
125  typedef std::shared_ptr<SspiCredentials> SspiCredentialsPtr;
126 
127  class RCF_EXPORT SspiFilter : public Filter
128  {
129  public:
130 
131  ~SspiFilter();
132 
133  SspiMessageProtection getQop();
134 
135  typedef SspiImpersonator Impersonator;
136 
137  Win32CertificatePtr getPeerCertificate();
138 
139  PCtxtHandle getSecurityContext() const;
140 
141  protected:
142 
143  friend class SspiImpersonator;
144 
145  SspiFilter(
146  SspiCredentialsPtr credentialsPtr,
147  ClientStub * pClientStub,
149  ULONG contextRequirements,
150  SspiRole clientOrServer,
151  SspiType sspiType,
152  const tstring & packageName = RCF_T(""),
153  const tstring & packageList = RCF_T(""));
154 
155  enum Event
156  {
157  ReadIssued,
158  WriteIssued,
159  ReadCompleted,
160  WriteCompleted
161  };
162 
163  enum ContextState
164  {
165  AuthContinue,
166  AuthOk,
167  AuthOkAck,
168  AuthFailed
169  };
170 
171  enum State
172  {
173  Ready,
174  Reading,
175  Writing
176  };
177 
178  void freeContext();
179 
180  void init();
181  void deinit();
182  void resetState();
183 
184  void createClientCredentials();
185 
186  void read(
187  const ByteBuffer &byteBuffer,
188  std::size_t bytesRequested);
189 
190  void write(const std::vector<ByteBuffer> &byteBuffers);
191 
192  void onReadCompleted(const ByteBuffer &byteBuffer);
193  void onWriteCompleted(std::size_t bytesTransferred);
194 
195  void handleEvent(Event event);
196  void readBuffer();
197  void writeBuffer();
198 
199  void encryptWriteBuffer();
200  bool decryptReadBuffer();
201 
202  void encryptWriteBufferSchannel();
203  bool decryptReadBufferSchannel();
204 
205  bool completeReadBlock();
206  bool completeWriteBlock();
207  bool completeBlock();
208  void resumeUserIo();
209  void resizeReadBuffer(std::size_t newSize);
210  void resizeWriteBuffer(std::size_t newSize);
211 
212  void shiftReadBuffer(bool shiftEntireBuffer = true);
213  void trimReadBuffer();
214 
215  bool shouldRetryWithExtraData(const SecBufferDesc& ibd, const SecBufferDesc& obd);
216 
217  virtual void handleHandshakeEvent() = 0;
218 
219  protected:
220 
221  ClientStub * mpClientStub;
222 
224  ULONG mContextRequirements;
225 
226  SspiCredentialsPtr mCredentialsPtr;
227  tstring mPackageName;
228  tstring mPackageList;
229 
230  bool mHaveContext;
231  CtxtHandle mContext;
232  ContextState mContextState;
233  State mPreState;
234  State mPostState;
235  Event mEvent;
236  const SspiRole mClientOrServer;
237 
238  ByteBuffer mReadByteBufferOrig;
239  ByteBuffer mWriteByteBufferOrig;
240  std::size_t mBytesRequestedOrig;
241 
242  ByteBuffer mReadByteBuffer;
243  ReallocBufferPtr mReadBufferVectorPtr;
244  char * mReadBuffer;
245  std::size_t mReadBufferPos;
246  std::size_t mReadBufferLen;
247 
248  ByteBuffer mWriteByteBuffer;
249  ReallocBufferPtr mWriteBufferVectorPtr;
250  char * mWriteBuffer;
251  std::size_t mWriteBufferPos;
252  std::size_t mWriteBufferLen;
253 
254  std::vector<ByteBuffer> mByteBuffers;
255  ByteBuffer mTempByteBuffer;
256 
257  // Are we doing Schannel or Kerberos/NTLM.
258  const SspiType mSspiType;
259 
260  std::size_t mMaxMessageLength;
261 
262  // Schannel-specific members.
263  Win32CertificatePtr mLocalCertPtr;
264  Win32CertificatePtr mRemoteCertPtr;
265  CertificateValidationCallback mCertValidationCallback;
266  tstring mAutoCertValidation;
267  tstring mTlsSniName;
268  const std::size_t mReadAheadChunkSize;
269  std::size_t mRemainingDataPos;
270 
271  std::vector<RCF::ByteBuffer> mMergeBufferList;
272  std::vector<char> mMergeBuffer;
273 
274  bool mProtocolChecked;
275 
276  bool mResumeUserIoAfterWrite = false;
277 
278  private:
279  bool mLimitRecursion;
280  RecursionState<ByteBuffer, int> mRecursionStateRead;
281  RecursionState<std::size_t, int> mRecursionStateWrite;
282 
283  void onReadCompleted_(const ByteBuffer &byteBuffer);
284  void onWriteCompleted_(std::size_t bytesTransferred);
285 
286  friend class SchannelFilterFactory;
287  };
288 
289 
290  // Server filters.
291 
292  class RCF_EXPORT SspiServerFilter : public SspiFilter
293  {
294  public:
295  SspiServerFilter(
296  SspiCredentialsPtr credentialsPtr,
297  SspiType sspiType);
298 
299  private:
300  bool doHandshakeSchannel();
301  bool doHandshake();
302  void handleHandshakeEvent();
303  };
304 
305  class NtlmServerFilter : public SspiServerFilter
306  {
307  public:
308  NtlmServerFilter(SspiCredentialsPtr credentialsPtr);
309  int getFilterId() const;
310  };
311 
312  class KerberosServerFilter : public SspiServerFilter
313  {
314  public:
315  KerberosServerFilter(SspiCredentialsPtr credentialsPtr);
316  int getFilterId() const;
317  };
318 
319  class NegotiateServerFilter : public SspiServerFilter
320  {
321  public:
322  NegotiateServerFilter(SspiCredentialsPtr credentialsPtr);
323  int getFilterId() const;
324  };
325 
326  // Server filter factories.
327 
328  class RCF_EXPORT NtlmFilterFactory : public FilterFactory
329  {
330  public:
331  NtlmFilterFactory();
332 
333  FilterPtr createFilter(RcfServer & server);
334  int getFilterId();
335 
336  private:
337 
338  Mutex mCredentialsMutex;
339  SspiCredentialsPtr mCredentialsPtr;
340  };
341 
342  class KerberosFilterFactory : public FilterFactory
343  {
344  public:
345  KerberosFilterFactory();
346 
347  FilterPtr createFilter(RcfServer & server);
348  int getFilterId();
349 
350  private:
351 
352  Mutex mCredentialsMutex;
353  SspiCredentialsPtr mCredentialsPtr;
354  };
355 
356  class NegotiateFilterFactory : public FilterFactory
357  {
358  public:
359  NegotiateFilterFactory(const tstring &packageList = RCF_T("Kerberos, NTLM"));
360 
361  FilterPtr createFilter(RcfServer & server);
362  int getFilterId();
363 
364  private:
365 
366  Mutex mCredentialsMutex;
367  tstring mPackageList;
368  SspiCredentialsPtr mCredentialsPtr;
369  };
370 
371  // Client filters.
372 
373  class SspiClientFilter : public SspiFilter
374  {
375  public:
376  SspiClientFilter(
377  SspiCredentialsPtr credentialsPtr,
378  ClientStub * pClientStub,
380  ULONG contextRequirements,
381  SspiType sspiType,
382  const tstring & packageName,
383  const tstring & packageList) :
384  SspiFilter(
385  credentialsPtr,
386  pClientStub,
387  qop,
388  contextRequirements,
389  Sr_Client,
390  sspiType,
391  packageName,
392  packageList)
393  {
394  }
395 
396  private:
397 
398  bool doHandshakeSchannel();
399  bool doHandshake();
400  void handleHandshakeEvent();
401  };
402 
403  class NtlmClientFilter : public SspiClientFilter
404  {
405  public:
406  NtlmClientFilter(
407  ClientStub * pClientStub,
408  SspiMessageProtection qop = Smp_Encryption,
409  ULONG contextRequirements = DefaultSspiContextRequirements);
410 
411  int getFilterId() const;
412  };
413 
414  class KerberosClientFilter : public SspiClientFilter
415  {
416  public:
417  KerberosClientFilter(
418  ClientStub * pClientStub,
419  SspiMessageProtection qop = Smp_Encryption,
420  ULONG contextRequirements = DefaultSspiContextRequirements);
421 
422  int getFilterId() const;
423  };
424 
425  class NegotiateClientFilter : public SspiClientFilter
426  {
427  public:
428 
429  NegotiateClientFilter(
430  ClientStub * pClientStub,
432  ULONG contextRequirements = DefaultSspiContextRequirements);
433 
434 
435  int getFilterId() const;
436  };
437 
438  typedef NtlmClientFilter NtlmFilter;
439  typedef KerberosClientFilter KerberosFilter;
440  typedef NegotiateClientFilter NegotiateFilter;
441 
442 
443  // These SSPI-prefixed typedefs make us compatible with code written for RCF 1.0.
444  typedef NtlmFilter SspiNtlmFilter;
445  typedef KerberosFilter SspiKerberosFilter;
446  typedef NegotiateFilter SspiNegotiateFilter;
447 
448  typedef NtlmServerFilter SspiNtlmServerFilter;
449  typedef KerberosServerFilter SspiKerberosServerFilter;
450  typedef NegotiateServerFilter SspiNegotiateServerFilter;
451  typedef NtlmFilterFactory SspiNtlmFilterFactory;
452  typedef KerberosFilterFactory SspiKerberosFilterFactory;
453  typedef NegotiateFilterFactory SspiNegotiateFilterFactory;
454  typedef NtlmClientFilter SspiNtlmClientFilter;
455  typedef KerberosClientFilter SspiKerberosClientFilter;
456  typedef NegotiateClientFilter SspiNegotiateClientFilter;
457 
458  typedef SspiFilter SspiFilterBase;
459  typedef SspiFilterPtr SspiFilterBasePtr;
460 
461 } // namespace RCF
462 
463 #endif // ! INCLUDE_RCF_SSPIFILTER_HPP
SspiMessageProtection
Definition: Enums.hpp:207
Allows the server side of a SSPI-based connection to impersonate the client. Only applicable to conne...
Definition: SspiFilter.hpp:56
Represents a server side session, associated with a client connection.
Definition: RcfSession.hpp:65
Controls the client side of a RCF connection.
Definition: ClientStub.hpp:83
std::shared_ptr< Win32Certificate > Win32CertificatePtr
Reference counted wrapper for RCF::Win32Certificate.
Definition: RcfFwd.hpp:258
std::function< bool(Certificate *)> CertificateValidationCallback
Describes user-provided callback functions for validating a certificate.
Definition: RcfFwd.hpp:115
RCF_EXPORT bool deinit()
Reference-counted deinitialization of RCF library. For actual deinitialization to take place...
Represents an in-memory certificate, either from a remote peer or loaded from a local certificate sto...
Definition: Win32Certificate.hpp:38
Provides RCF server-side functionality.
Definition: RcfServer.hpp:54
Definition: ByteBuffer.hpp:40
Definition: AmiIoHandler.hpp:24
Base class for all RCF certificate classes.
Definition: Certificate.hpp:30
RCF_EXPORT bool init(RcfConfigT *=nullptr)
Reference-counted initialization of RCF library. May be called multiple times (see deinit())...
Messages are sent in clear text.
Definition: Enums.hpp:210