Remote Call Framework 3.4
SspiFilter.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2023, Delta V Software. All rights reserved.
6 // https://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 under GPL terms.
12 //
13 // Version: 3.4
14 // Contact: support <at> deltavsoft.com
15 //
16 //******************************************************************************
17 
18 #ifndef INCLUDE_RCF_SSPIFILTER_HPP
19 #define INCLUDE_RCF_SSPIFILTER_HPP
20 
21 #include <functional>
22 #include <memory>
23 
24 #include <RCF/ByteBuffer.hpp>
25 #include <RCF/Enums.hpp>
26 #include <RCF/Filter.hpp>
27 #include <RCF/RcfFwd.hpp>
28 #include <RCF/RecursionLimiter.hpp>
29 #include <RCF/ThreadLibrary.hpp>
30 #include <RCF/Export.hpp>
31 
32 #include <RCF/Tchar.hpp>
33 
34 #ifndef SECURITY_WIN32
35 #define SECURITY_WIN32
36 #endif
37 
38 #include <windows.h>
39 #include <security.h>
40 #include <schannel.h>
41 #include <WinCrypt.h>
42 #include <tchar.h>
43 
44 namespace RCF {
45 
46  typedef RCF::tstring tstring;
47 
48  class SspiFilter;
49  class RcfSession;
50  class ClientStub;
51 
52  typedef std::shared_ptr<SspiFilter> SspiFilterPtr;
53 
55  class RCF_EXPORT SspiImpersonator
56  {
57  public:
58  SspiImpersonator(SspiFilterPtr sspiFilterPtr);
59 
61  SspiImpersonator(RcfSession & session);
62 
65 
66  bool impersonate();
67 
69  void revertToSelf() const;
70 
71  private:
72  SspiFilterPtr mSspiFilterPtr;
73  };
74 
75  static const ULONG DefaultSspiContextRequirements =
76  ISC_REQ_REPLAY_DETECT |
77  ISC_REQ_SEQUENCE_DETECT |
78  ISC_REQ_CONFIDENTIALITY |
79  ISC_REQ_INTEGRITY |
80  ISC_REQ_DELEGATE |
81  ISC_REQ_MUTUAL_AUTH;
82 
83  static const ULONG DefaultSchannelContextRequirements =
84  ASC_REQ_SEQUENCE_DETECT
85  | ASC_REQ_REPLAY_DETECT
86  | ASC_REQ_CONFIDENTIALITY
87  | ASC_REQ_EXTENDED_ERROR
88  | ASC_REQ_ALLOCATE_MEMORY
89  | ASC_REQ_STREAM;
90 
91 #if defined(SP_PROT_TLS1_3_SERVER) && defined(SP_PROT_TLS1_3_CLIENT)
92 
93  static const DWORD DefaultSchannelServerProtocols =
94  SP_PROT_TLS1_3_SERVER
95  | SP_PROT_TLS1_2_SERVER;
96 
97  static const DWORD DefaultSchannelClientProtocols =
98  SP_PROT_TLS1_3_CLIENT
99  | SP_PROT_TLS1_2_CLIENT
100  | SP_PROT_TLS1_1_CLIENT
101  | SP_PROT_TLS1_0_CLIENT;
102 
103 #else
104 
105  static const DWORD DefaultSchannelServerProtocols =
106  SP_PROT_TLS1_2_SERVER;
107 
108  static const DWORD DefaultSchannelClientProtocols =
109  SP_PROT_TLS1_2_CLIENT
110  | SP_PROT_TLS1_1_CLIENT
111  | SP_PROT_TLS1_0_CLIENT;
112 
113 #endif
114 
115  class SchannelClientFilter;
116  typedef SchannelClientFilter SchannelFilter;
117 
118  class SchannelFilterFactory;
119 
120  class Certificate;
121  class Win32Certificate;
122 
123  class SspiCredentials;
124  typedef std::shared_ptr<SspiCredentials> SspiCredentialsPtr;
125 
126  class RCF_EXPORT SspiFilter : public Filter
127  {
128  public:
129 
130  ~SspiFilter();
131 
132  SspiMessageProtection getQop();
133 
134  typedef SspiImpersonator Impersonator;
135 
136  Win32CertificatePtr getPeerCertificate();
137 
138  PCtxtHandle getSecurityContext() const;
139 
140  protected:
141 
142  friend class SspiImpersonator;
143 
144  SspiFilter(
145  SspiCredentialsPtr credentialsPtr,
146  ClientStub * pClientStub,
148  ULONG contextRequirements,
149  SspiRole clientOrServer,
150  SspiType sspiType,
151  const tstring & packageName = RCF_T(""),
152  const tstring & packageList = RCF_T(""));
153 
154  enum Event
155  {
156  ReadIssued,
157  WriteIssued,
158  ReadCompleted,
159  WriteCompleted
160  };
161 
162  enum ContextState
163  {
164  AuthContinue,
165  AuthOk,
166  AuthOkAck,
167  AuthFailed
168  };
169 
170  enum State
171  {
172  Ready,
173  Reading,
174  Writing
175  };
176 
177  void freeContext();
178 
179  void init();
180  void deinit();
181  void resetState();
182 
183  void createClientCredentials();
184 
185  void read(
186  const ByteBuffer &byteBuffer,
187  std::size_t bytesRequested);
188 
189  void write(const std::vector<ByteBuffer> &byteBuffers);
190 
191  void onReadCompleted(const ByteBuffer &byteBuffer);
192  void onWriteCompleted(std::size_t bytesTransferred);
193 
194  void handleEvent(Event event);
195  void readBuffer();
196  void writeBuffer();
197 
198  void encryptWriteBuffer();
199  bool decryptReadBuffer();
200 
201  void encryptWriteBufferSchannel();
202  bool decryptReadBufferSchannel();
203 
204  bool completeReadBlock();
205  bool completeWriteBlock();
206  bool completeBlock();
207  void resumeUserIo();
208  void resizeReadBuffer(std::size_t newSize);
209  void resizeWriteBuffer(std::size_t newSize);
210 
211  void shiftReadBuffer(bool shiftEntireBuffer = true);
212  void trimReadBuffer();
213 
214  bool shouldRetryWithExtraData(const SecBufferDesc& ibd, const SecBufferDesc& obd);
215 
216  virtual void handleHandshakeEvent() = 0;
217 
218  protected:
219 
220  ClientStub * mpClientStub;
221 
223  ULONG mContextRequirements;
224 
225  SspiCredentialsPtr mCredentialsPtr;
226  tstring mPackageName;
227  tstring mPackageList;
228 
229  bool mHaveContext;
230  CtxtHandle mContext;
231  ContextState mContextState;
232  State mPreState;
233  State mPostState;
234  Event mEvent;
235  const SspiRole mClientOrServer;
236 
237  ByteBuffer mReadByteBufferOrig;
238  ByteBuffer mWriteByteBufferOrig;
239  std::size_t mBytesRequestedOrig;
240 
241  ByteBuffer mReadByteBuffer;
242  ReallocBufferPtr mReadBufferVectorPtr;
243  char * mReadBuffer;
244  std::size_t mReadBufferPos;
245  std::size_t mReadBufferLen;
246 
247  ByteBuffer mWriteByteBuffer;
248  ReallocBufferPtr mWriteBufferVectorPtr;
249  char * mWriteBuffer;
250  std::size_t mWriteBufferPos;
251  std::size_t mWriteBufferLen;
252 
253  std::vector<ByteBuffer> mByteBuffers;
254  ByteBuffer mTempByteBuffer;
255 
256  // Are we doing Schannel or Kerberos/NTLM.
257  const SspiType mSspiType;
258 
259  std::size_t mMaxMessageLength;
260 
261  // Schannel-specific members.
262  Win32CertificatePtr mLocalCertPtr;
263  Win32CertificatePtr mRemoteCertPtr;
264  CertificateValidationCallback mCertValidationCallback;
265  tstring mAutoCertValidation;
266  tstring mTlsSniName;
267  const std::size_t mReadAheadChunkSize;
268  std::size_t mRemainingDataPos;
269  bool mRemainingDataAlreadyShifted;
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:206
Allows the server side of a SSPI-based connection to impersonate the client. Only applicable to conne...
Definition: SspiFilter.hpp:55
Represents a server side session, associated with a client connection.
Definition: RcfSession.hpp:64
Controls the client side of a RCF connection.
Definition: ClientStub.hpp:82
std::shared_ptr< Win32Certificate > Win32CertificatePtr
Reference counted wrapper for RCF::Win32Certificate.
Definition: RcfFwd.hpp:257
std::function< bool(Certificate *)> CertificateValidationCallback
Describes user-provided callback functions for validating a certificate.
Definition: RcfFwd.hpp:114
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:37
Provides RCF server-side functionality.
Definition: RcfServer.hpp:53
Definition: ByteBuffer.hpp:39
Definition: AmiIoHandler.hpp:23
Base class for all RCF certificate classes.
Definition: Certificate.hpp:29
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:209