1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <IceSSL/SChannelTransceiverI.h>
6 
7 #include <IceUtil/StringUtil.h>
8 
9 #include <IceSSL/ConnectionInfo.h>
10 #include <IceSSL/Instance.h>
11 #include <IceSSL/SChannelEngine.h>
12 #include <IceSSL/Util.h>
13 #include <Ice/Communicator.h>
14 #include <Ice/LoggerUtil.h>
15 #include <Ice/Buffer.h>
16 #include <Ice/LocalException.h>
17 
18 using namespace std;
19 using namespace Ice;
20 using namespace IceSSL;
21 
22 namespace
23 {
24 
25 string
26 protocolName(DWORD protocol)
27 {
28     switch(protocol)
29     {
30         case SP_PROT_SSL2_CLIENT:
PluginI(const Ice::CommunicatorPtr & com)31         case SP_PROT_SSL2_SERVER:
32             return "SSL 2.0";
33         case SP_PROT_SSL3_CLIENT:
34         case SP_PROT_SSL3_SERVER:
35             return "SSL 3.0";
36         case SP_PROT_TLS1_CLIENT:
create(CERT_SIGNED_CONTENT_INFO * cert) const37         case SP_PROT_TLS1_SERVER:
38             return "TLS 1.0";
39         case SP_PROT_TLS1_1_CLIENT:
40         case SP_PROT_TLS1_1_SERVER:
41             return "TLS 1.1";
42         case SP_PROT_TLS1_2_CLIENT:
load(const std::string & file) const43         case SP_PROT_TLS1_2_SERVER:
44             return "TLS 1.2";
45         default:
46             return "Unknown";
47     }
48 }
decode(const std::string & encoding) const49 
50 string
51 trustStatusToString(DWORD status)
52 {
53     if(status & CERT_TRUST_NO_ERROR)
54     {
55         return "CERT_TRUST_NO_ERROR";
56     }
57 
58     if(status & CERT_TRUST_IS_NOT_TIME_VALID)
59     {
60         return "CERT_TRUST_IS_NOT_TIME_VALID";
61     }
62 
63     if(status & CERT_TRUST_IS_REVOKED)
64     {
65         return "CERT_TRUST_IS_REVOKED";
66     }
67 
68     if(status & CERT_TRUST_IS_NOT_SIGNATURE_VALID)
69     {
70         return "CERT_TRUST_IS_NOT_SIGNATURE_VALID";
71     }
72 
73     if(status & CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
74     {
75         return "CERT_TRUST_IS_NOT_VALID_FOR_USAGE";
76     }
77 
78     if(status & CERT_TRUST_IS_UNTRUSTED_ROOT)
79     {
80         return "CERT_TRUST_IS_UNTRUSTED_ROOT";
81     }
82 
83     if(status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN)
84     {
85         return "CERT_TRUST_REVOCATION_STATUS_UNKNOWN";
86     }
87 
88     if(status & CERT_TRUST_IS_CYCLIC)
89     {
90         return "CERT_TRUST_IS_CYCLIC";
91     }
92 
93     if(status & CERT_TRUST_INVALID_EXTENSION)
94     {
95         return "CERT_TRUST_INVALID_EXTENSION";
96     }
97 
98     if(status & CERT_TRUST_INVALID_POLICY_CONSTRAINTS)
99     {
100         return "CERT_TRUST_INVALID_POLICY_CONSTRAINTS";
101     }
102 
103     if(status & CERT_TRUST_INVALID_BASIC_CONSTRAINTS)
104     {
105         return "CERT_TRUST_INVALID_BASIC_CONSTRAINTS";
106     }
107 
108     if(status & CERT_TRUST_INVALID_NAME_CONSTRAINTS)
109     {
110         return "CERT_TRUST_INVALID_NAME_CONSTRAINTS";
111     }
112 
113     if(status & CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT)
114     {
115         return "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT";
116     }
117 
118     if(status & CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT)
119     {
120         return "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT";
121     }
122 
123     if(status & CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT)
124     {
125         return "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT";
126     }
127 
128     if(status & CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT)
129     {
130         return "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT";
131     }
132 
133     if(status & CERT_TRUST_IS_OFFLINE_REVOCATION)
134     {
135         return "CERT_TRUST_IS_OFFLINE_REVOCATION";
136     }
137 
138     if(status & CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY)
139     {
140         return "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY";
141     }
142 
143     if(status & CERT_TRUST_IS_EXPLICIT_DISTRUST)
144     {
145         return "CERT_TRUST_IS_EXPLICIT_DISTRUST";
146     }
147 
148     if(status & CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT)
149     {
150         return "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT";
151     }
152 
153     //
154     // New in Windows 8
155     //
156     //if(status & CERT_TRUST_HAS_WEAK_SIGNATURE)
157     //{
158     //    return "CERT_TRUST_HAS_WEAK_SIGNATURE";
159     //}
160 
161     if(status & CERT_TRUST_IS_PARTIAL_CHAIN)
162     {
163         return "CERT_TRUST_IS_PARTIAL_CHAIN";
164     }
165 
166     if(status & CERT_TRUST_CTL_IS_NOT_TIME_VALID)
167     {
168         return "CERT_TRUST_CTL_IS_NOT_TIME_VALID";
169     }
170 
171     if(status & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID)
172     {
173         return "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID";
174     }
175 
176     if(status & CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE)
177     {
178         return "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE";
179     }
180 
181     ostringstream os;
182     os << "UNKNOWN TRUST FAILURE: " << status;
183     return os.str();
184 }
185 
186 SecBuffer*
187 getSecBufferWithType(const SecBufferDesc& desc, ULONG bufferType)
188 {
189     for(ULONG i = 0; i < desc.cBuffers; ++i)
190     {
191         if(desc.pBuffers[i].BufferType == bufferType)
192         {
193             return &desc.pBuffers[i];
194         }
195     }
196     return 0;
197 }
198 
199 string
200 secStatusToString(SECURITY_STATUS status)
201 {
202     return IceUtilInternal::errorToString(status);
203 }
204 
205 }
206 
207 IceInternal::NativeInfoPtr
208 SChannel::TransceiverI::getNativeInfo()
209 {
210     return _delegate->getNativeInfo();
211 }
212 
213 IceInternal::SocketOperation
214 SChannel::TransceiverI::sslHandshake()
215 {
216     DWORD flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY |
217         ASC_REQ_STREAM;
218     if(_incoming)
219     {
220         flags |= ASC_REQ_EXTENDED_ERROR;
221         if(_engine->getVerifyPeer() > 0)
222         {
223             flags |= ASC_REQ_MUTUAL_AUTH;
224         }
225     }
226     else
227     {
228         flags |= ISC_REQ_USE_SUPPLIED_CREDS | ISC_REQ_MANUAL_CRED_VALIDATION | ISC_RET_EXTENDED_ERROR;
229     }
230 
231     SECURITY_STATUS err = SEC_E_OK;
232     if(_state == StateHandshakeNotStarted)
233     {
234         _ctxFlags = 0;
235         _readBuffer.b.resize(2048);
236         _readBuffer.i = _readBuffer.b.begin();
237         _credentials = _engine->newCredentialsHandle(_incoming);
238         _credentialsInitialized = true;
239 
240         if(!_incoming)
241         {
242             SecBuffer outBuffer = { 0, SECBUFFER_TOKEN, 0 };
243             SecBufferDesc outBufferDesc = { SECBUFFER_VERSION, 1, &outBuffer };
244 
245             err = InitializeSecurityContext(&_credentials, 0, const_cast<char *>(_host.c_str()), flags, 0, 0, 0, 0,
246                                             &_ssl, &outBufferDesc, &_ctxFlags, 0);
247             if(err != SEC_E_OK && err != SEC_I_CONTINUE_NEEDED)
248             {
249                 throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + secStatusToString(err));
250             }
251             _sslInitialized = true;
252 
253             //
254             // Copy the data to the write buffer
255             //
256             _writeBuffer.b.resize(outBuffer.cbBuffer);
257             _writeBuffer.i = _writeBuffer.b.begin();
258             memcpy(_writeBuffer.i, outBuffer.pvBuffer, outBuffer.cbBuffer);
259             FreeContextBuffer(outBuffer.pvBuffer);
260 
261             _state = StateHandshakeWriteContinue;
262         }
263         else
264         {
265             _state = StateHandshakeReadContinue;
266         }
267     }
268 
269     while(true)
270     {
271         if(_state == StateHandshakeReadContinue)
272         {
273             // If read buffer is empty, try to read some data.
274             if(_readBuffer.i == _readBuffer.b.begin() && !readRaw(_readBuffer))
275             {
276                 return IceInternal::SocketOperationRead;
277             }
278 
279             SecBuffer inBuffers[2] = {
280                 { static_cast<DWORD>(_readBuffer.i - _readBuffer.b.begin()), SECBUFFER_TOKEN, _readBuffer.b.begin() },
281                 { 0, SECBUFFER_EMPTY, 0 }
282             };
283             SecBufferDesc inBufferDesc = { SECBUFFER_VERSION, 2, inBuffers };
284 
285             SecBuffer outBuffers[2] = {
286                 { 0, SECBUFFER_TOKEN, 0 },
287                 { 0, SECBUFFER_ALERT, 0 }
288             };
289             SecBufferDesc outBufferDesc = { SECBUFFER_VERSION, 2, outBuffers };
290 
291             if(_incoming)
292             {
293                 err = AcceptSecurityContext(&_credentials, (_sslInitialized ? &_ssl : 0), &inBufferDesc, flags, 0,
294                                             &_ssl, &outBufferDesc, &_ctxFlags, 0);
295                 if(err == SEC_I_CONTINUE_NEEDED || err == SEC_E_OK)
296                 {
297                     _sslInitialized = true;
298                 }
299             }
300             else
301             {
302                 err = InitializeSecurityContext(&_credentials, &_ssl, const_cast<char*>(_host.c_str()), flags, 0, 0,
303                                                 &inBufferDesc, 0, 0, &outBufferDesc, &_ctxFlags, 0);
304             }
305 
306             //
307             // If the message is incomplete we need to read more data.
308             //
309             if(err == SEC_E_INCOMPLETE_MESSAGE)
310             {
311                 SecBuffer* missing = getSecBufferWithType(inBufferDesc, SECBUFFER_MISSING);
312                 size_t pos = _readBuffer.i - _readBuffer.b.begin();
313                 _readBuffer.b.resize((missing && missing->cbBuffer > 0) ? (pos + missing->cbBuffer) : (pos * 2));
314                 _readBuffer.i = _readBuffer.b.begin() + pos;
315                 return IceInternal::SocketOperationRead;
316             }
317             else if(err != SEC_I_CONTINUE_NEEDED && err != SEC_E_OK)
318             {
319                 throw SecurityException(__FILE__, __LINE__, "SSL handshake failure:\n" + secStatusToString(err));
320             }
321 
322             //
323             // Copy out security tokens to the write buffer if any.
324             //
325             SecBuffer* token = getSecBufferWithType(outBufferDesc, SECBUFFER_TOKEN);
326             assert(token);
327             if(token->cbBuffer)
328             {
329                 _writeBuffer.b.resize(static_cast<size_t>(token->cbBuffer));
330                 _writeBuffer.i = _writeBuffer.b.begin();
331                 memcpy(_writeBuffer.i, token->pvBuffer, token->cbBuffer);
332                 FreeContextBuffer(token->pvBuffer);
333             }
334 
335             //
336             // Check for remaining data in the input buffer.
337             //
338             SecBuffer* extra = getSecBufferWithType(inBufferDesc, SECBUFFER_EXTRA);
339             if(extra)
340             {
341                 // Shift the extra data to the start of the input buffer
342                 memmove(_readBuffer.b.begin(), _readBuffer.i - extra->cbBuffer, extra->cbBuffer);
343                 _readBuffer.i = _readBuffer.b.begin() + extra->cbBuffer;
344             }
345             else
346             {
347                 _readBuffer.i = _readBuffer.b.begin();
348             }
349 
350             if(token->cbBuffer)
351             {
352                 if(err == SEC_E_OK)
353                 {
354                     _state = StateHandshakeWriteNoContinue; // Write and don't continue.
355                 }
356                 else
357                 {
358                     _state = StateHandshakeWriteContinue; // Continue writing if we have a token.
359                 }
360             }
361             else if(err == SEC_E_OK)
362             {
363                 break; // We're done.
364             }
365 
366             // Otherwise continue either reading credentials
367         }
368 
369         if(_state == StateHandshakeWriteContinue || _state == StateHandshakeWriteNoContinue)
370         {
371             //
372             // Write any pending data.
373             //
374             if(!writeRaw(_writeBuffer))
375             {
376                 return IceInternal::SocketOperationWrite;
377             }
378             if(_state == StateHandshakeWriteNoContinue)
379             {
380                 break; // Token is written and we weren't told to continue, so we're done!
381             }
382             _state = StateHandshakeReadContinue;
383         }
384     }
385 
386     //
387     // Check if the requested capabilities are met.
388     //
389     // NOTE: it's important for _ctxFlags to be a data member. The context flags might not be checked immediately
390     // if the last write can't complete without blocking above. In such a case, the context flags are checked here
391     // only once the sslHandshake is called again after the write completes.
392     //
393     if(flags != _ctxFlags)
394     {
395         if(_incoming)
396         {
397             if(!(_ctxFlags & ASC_REQ_SEQUENCE_DETECT))
398             {
399                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup sequence detect");
400             }
401 
402             if(!(_ctxFlags & ASC_REQ_REPLAY_DETECT))
403             {
404                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup replay detect");
405             }
406 
407             if(!(_ctxFlags & ASC_REQ_CONFIDENTIALITY))
408             {
409                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup confidentiality");
410             }
411 
412             if(!(_ctxFlags & ASC_REQ_EXTENDED_ERROR))
413             {
414                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup extended error");
415             }
416 
417             if(!(_ctxFlags & ASC_REQ_ALLOCATE_MEMORY))
418             {
419                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup memory allocation");
420             }
421 
422             if(!(_ctxFlags & ASC_REQ_STREAM))
423             {
424                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup stream");
425             }
426         }
427         else
428         {
429             if(!(_ctxFlags & ISC_REQ_SEQUENCE_DETECT))
430             {
431                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup sequence detect");
432             }
433 
434             if(!(_ctxFlags & ISC_REQ_REPLAY_DETECT))
435             {
436                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup replay detect");
437             }
438 
439             if(!(_ctxFlags & ISC_REQ_CONFIDENTIALITY))
440             {
441                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup confidentiality");
442             }
443 
444             if(!(_ctxFlags & ISC_REQ_EXTENDED_ERROR))
445             {
446                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup extended error");
447             }
448 
449             if(!(_ctxFlags & ISC_REQ_ALLOCATE_MEMORY))
450             {
451                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup memory allocation");
452             }
453 
454             if(!(_ctxFlags & ISC_REQ_STREAM))
455             {
456                 throw SecurityException(__FILE__, __LINE__, "IceSSL: SChannel failed to setup stream");
457             }
458         }
459     }
460 
461     err = QueryContextAttributes(&_ssl, SECPKG_ATTR_STREAM_SIZES, &_sizes);
462     if(err != SEC_E_OK)
463     {
464         throw SecurityException(__FILE__, __LINE__, "IceSSL: failure to query stream sizes attributes:\n" +
465                                 secStatusToString(err));
466     }
467 
468     size_t pos = _readBuffer.i - _readBuffer.b.begin();
469     if(pos <= (_sizes.cbHeader + _sizes.cbMaximumMessage + _sizes.cbTrailer))
470     {
471         _readBuffer.b.resize(_sizes.cbHeader + _sizes.cbMaximumMessage + _sizes.cbTrailer);
472         _readBuffer.i = _readBuffer.b.begin() + pos;
473     }
474 
475     _writeBuffer.b.reset();
476     _writeBuffer.i = _writeBuffer.b.begin();
477 
478     return IceInternal::SocketOperationNone;
479 }
480 
481 //
482 // Try to decrypt a message and return the number of bytes decrypted, if the number of bytes
483 // decrypted is less than the size requested it means that the application needs to read more
484 // data before it can decrypt the complete message.
485 //
486 size_t
487 SChannel::TransceiverI::decryptMessage(IceInternal::Buffer& buffer)
488 {
489     assert(_readBuffer.i != _readBuffer.b.begin() || !_readUnprocessed.b.empty());
490 
491     //
492     // First check if there is data in the unprocessed buffer.
493     //
494     size_t length = std::min(static_cast<size_t>(buffer.b.end() - buffer.i), _readUnprocessed.b.size());
495     if(length > 0)
496     {
497         memcpy(buffer.i, _readUnprocessed.b.begin(), length);
498         memmove(_readUnprocessed.b.begin(), _readUnprocessed.b.begin() + length, _readUnprocessed.b.size() - length);
499         _readUnprocessed.b.resize(_readUnprocessed.b.size() - length);
500     }
501 
502     while(true)
503     {
504         //
505         // If we have filled the buffer or if nothing left to read from
506         // the read buffer, we're done.
507         //
508         Byte* i = buffer.i + length;
509         if(i == buffer.b.end() || _readBuffer.i == _readBuffer.b.begin())
510         {
511             break;
512         }
513 
514         //
515         // Try to decrypt the buffered data.
516         //
517         SecBuffer inBuffers[4] = {
518             { static_cast<DWORD>(_readBuffer.i - _readBuffer.b.begin()), SECBUFFER_DATA, _readBuffer.b.begin() },
519             { 0, SECBUFFER_EMPTY, 0 },
520             { 0, SECBUFFER_EMPTY, 0 },
521             { 0, SECBUFFER_EMPTY, 0 }
522         };
523         SecBufferDesc inBufferDesc = { SECBUFFER_VERSION, 4, inBuffers };
524 
525         SECURITY_STATUS err = DecryptMessage(&_ssl, &inBufferDesc, 0, 0);
526         if(err == SEC_E_INCOMPLETE_MESSAGE)
527         {
528             //
529             // There isn't enough data to decrypt the message. The input
530             // buffer is resized to the SSL max message size after the SSL
531             // handshake completes so an incomplete message can only occur
532             // if the read buffer is not full.
533             //
534             assert(_readBuffer.i != _readBuffer.b.end());
535             return length;
536         }
537         else if(err == SEC_I_CONTEXT_EXPIRED || err == SEC_I_RENEGOTIATE)
538         {
539             //
540             // The message sender has finished using the connection and
541             // has initiated a shutdown.
542             //
543             throw ConnectionLostException(__FILE__, __LINE__, 0);
544         }
545         else if(err != SEC_E_OK)
546         {
547             throw ProtocolException(__FILE__, __LINE__, "IceSSL: protocol error during read:\n" +
548                                     secStatusToString(err));
549         }
550 
551         SecBuffer* dataBuffer = getSecBufferWithType(inBufferDesc, SECBUFFER_DATA);
552         assert(dataBuffer);
553         DWORD remaining = min(static_cast<DWORD>(buffer.b.end() - i), dataBuffer->cbBuffer);
554         length += remaining;
555         if(remaining)
556         {
557             memcpy(i, dataBuffer->pvBuffer, remaining);
558 
559             //
560             // Copy remaining decrypted data to unprocessed buffer
561             //
562             if(dataBuffer->cbBuffer > remaining)
563             {
564                 _readUnprocessed.b.resize(dataBuffer->cbBuffer - remaining);
565                 memcpy(_readUnprocessed.b.begin(), reinterpret_cast<Byte*>(dataBuffer->pvBuffer) + remaining,
566                     dataBuffer->cbBuffer - remaining);
567             }
568         }
569 
570         //
571         // Move any remaining encrypted data to the begining of the input buffer
572         //
573         SecBuffer* extraBuffer = getSecBufferWithType(inBufferDesc, SECBUFFER_EXTRA);
574         if(extraBuffer && extraBuffer->cbBuffer > 0)
575         {
576             memmove(_readBuffer.b.begin(), _readBuffer.i - extraBuffer->cbBuffer, extraBuffer->cbBuffer);
577             _readBuffer.i = _readBuffer.b.begin() + extraBuffer->cbBuffer;
578         }
579         else
580         {
581             _readBuffer.i = _readBuffer.b.begin();
582         }
583     }
584     return length;
585 }
586 
587 //
588 // Encrypt a message and return the number of bytes that has been encrypted, if the
589 // number of bytes is less than the message size, the function must be called again.
590 //
591 size_t
592 SChannel::TransceiverI::encryptMessage(IceInternal::Buffer& buffer)
593 {
594     //
595     // Limit the message size to cbMaximumMessage which is the maximun size data that can be
596     // embeded in a SSL record.
597     //
598     DWORD length = std::min(static_cast<DWORD>(buffer.b.end() - buffer.i), _sizes.cbMaximumMessage);
599 
600     //
601     // Resize the buffer to hold the encrypted data
602     //
603     _writeBuffer.b.resize(_sizes.cbHeader + length + _sizes.cbTrailer);
604     _writeBuffer.i = _writeBuffer.b.begin();
605 
606     SecBuffer buffers[4] = {
607         { _sizes.cbHeader, SECBUFFER_STREAM_HEADER, _writeBuffer.i },
608         { length, SECBUFFER_DATA, _writeBuffer.i + _sizes.cbHeader },
609         { _sizes.cbTrailer, SECBUFFER_STREAM_TRAILER, _writeBuffer.i + _sizes.cbHeader + length },
610         { 0, SECBUFFER_EMPTY, 0 }
611     };
612     SecBufferDesc buffersDesc = { SECBUFFER_VERSION, 4, buffers };
613 
614     // Data is encrypted in place, copy the data to be encrypted to the data buffer.
615     memcpy(buffers[1].pvBuffer, buffer.i, length);
616 
617     SECURITY_STATUS err = EncryptMessage(&_ssl, 0, &buffersDesc, 0);
618     if(err != SEC_E_OK)
619     {
620         throw ProtocolException(__FILE__, __LINE__, "IceSSL: protocol error encrypting message:\n" +
621                                 secStatusToString(err));
622     }
623 
624     // EncryptMessage resizes the buffers, so resize the write buffer as well to reflect this.
625     _writeBuffer.b.resize(buffers[0].cbBuffer + buffers[1].cbBuffer + buffers[2].cbBuffer);
626     _writeBuffer.i = _writeBuffer.b.begin();
627 
628     return length;
629 }
630 
631 IceInternal::SocketOperation
632 SChannel::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
633 {
634     if(_state == StateNotInitialized)
635     {
636         IceInternal::SocketOperation op = _delegate->initialize(readBuffer, writeBuffer);
637         if(op != IceInternal::SocketOperationNone)
638         {
639             return op;
640         }
641         _state = StateHandshakeNotStarted;
642     }
643 
644     IceInternal::SocketOperation op = sslHandshake();
645     if(op != IceInternal::SocketOperationNone)
646     {
647         return op;
648     }
649 
650     //
651     // Build the peer certificate chain and verify it.
652     //
653     PCCERT_CONTEXT cert = 0;
654     SECURITY_STATUS err = QueryContextAttributes(&_ssl, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &cert);
655     if(err && err != SEC_E_NO_CREDENTIALS)
656     {
657         throw SecurityException(__FILE__, __LINE__, "IceSSL: certificate verification failure:\n" +
658                                 secStatusToString(err));
659     }
660 
661     if(!cert && ((!_incoming && _engine->getVerifyPeer() > 0) || (_incoming && _engine->getVerifyPeer() == 2)))
662     {
663         //
664         // Clients require server certificate if VerifyPeer > 0 and servers require client
665         // certificate if VerifyPeer == 2
666         //
667         throw SecurityException(__FILE__, __LINE__, "IceSSL: certificate required");
668     }
669     else if(cert) // Verify the remote certificate
670     {
671         CERT_CHAIN_PARA chainP;
672         memset(&chainP, 0, sizeof(chainP));
673         chainP.cbSize = sizeof(chainP);
674 
675         string trustError;
676         PCCERT_CHAIN_CONTEXT certChain;
677         if(!CertGetCertificateChain(_engine->chainEngine(), cert, 0, 0, &chainP,
678                                     CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, 0, &certChain))
679         {
680             CertFreeCertificateContext(cert);
681             trustError = IceUtilInternal::lastErrorToString();
682         }
683         else
684         {
685             if(certChain->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR)
686             {
687                 trustError = trustStatusToString(certChain->TrustStatus.dwErrorStatus);
688             }
689             else
690             {
691                 _verified = true;
692             }
693 
694             CERT_SIMPLE_CHAIN* simpleChain = certChain->rgpChain[0];
695             for(DWORD i = 0; i < simpleChain->cElement; ++i)
696             {
697                 PCCERT_CONTEXT c = simpleChain->rgpElement[i]->pCertContext;
698                 PCERT_SIGNED_CONTENT_INFO cc;
699 
700                 DWORD length = 0;
701                 if(!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_CERT, c->pbCertEncoded,
702                                         c->cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, 0, &cc, &length))
703                 {
704                     CertFreeCertificateChain(certChain);
705                     CertFreeCertificateContext(cert);
706                     throw SecurityException(__FILE__, __LINE__, "IceSSL: error decoding peer certificate chain:\n" +
707                                             IceUtilInternal::lastErrorToString());
708                 }
709                 _certs.push_back(SChannel::Certificate::create(cc));
710             }
711 
712             CertFreeCertificateChain(certChain);
713             CertFreeCertificateContext(cert);
714         }
715 
716         if(!trustError.empty())
717         {
718             if(_engine->getVerifyPeer() == 0)
719             {
720                 if(_instance->traceLevel() >= 1)
721                 {
722                     _instance->logger()->trace(_instance->traceCategory(),
723                                                "IceSSL: ignoring certificate verification failure:\n" + trustError);
724                 }
725             }
726             else
727             {
728                 string msg = "IceSSL: certificate verification failure:\n" + trustError;
729                 if(_instance->traceLevel() >= 1)
730                 {
731                     _instance->logger()->trace(_instance->traceCategory(), msg);
732                 }
733                 throw SecurityException(__FILE__, __LINE__, msg);
734             }
735         }
736     }
737 
738     SecPkgContext_ConnectionInfo connInfo;
739     err = QueryContextAttributes(&_ssl, SECPKG_ATTR_CONNECTION_INFO, &connInfo);
740     if(err == SEC_E_OK)
741     {
742         _cipher = _engine->getCipherName(connInfo.aiCipher);
743     }
744     else
745     {
746         throw SecurityException(__FILE__, __LINE__, "IceSSL: error reading cipher info:\n" + secStatusToString(err));
747     }
748 
749     _engine->verifyPeer(_host, ICE_DYNAMIC_CAST(ConnectionInfo, getInfo()), toString());
750     _state = StateHandshakeComplete;
751 
752     if(_instance->engine()->securityTraceLevel() >= 1)
753     {
754         string sslCipherName;
755         string sslKeyExchangeAlgorithm;
756         string sslProtocolName;
757         SecPkgContext_ConnectionInfo info;
758         if(QueryContextAttributes(&_ssl, SECPKG_ATTR_CONNECTION_INFO, &info) == SEC_E_OK)
759         {
760             sslCipherName = _engine->getCipherName(info.aiCipher);
761             sslKeyExchangeAlgorithm = _engine->getCipherName(info.aiExch);
762             sslProtocolName = protocolName(info.dwProtocol);
763         }
764 
765         Trace out(_instance->logger(), _instance->traceCategory());
766         out << "SSL summary for " << (_incoming ? "incoming" : "outgoing") << " connection\n";
767 
768         if(sslCipherName.empty())
769         {
770             out << "unknown cipher\n";
771         }
772         else
773         {
774             out << "cipher = " << sslCipherName
775                 << "\nkey exchange = " << sslKeyExchangeAlgorithm
776                 << "\nprotocol = " << sslProtocolName << "\n";
777         }
778         out << toString();
779     }
780     _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead,
781                                       !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin());
782     return IceInternal::SocketOperationNone;
783 }
784 
785 IceInternal::SocketOperation
786 SChannel::TransceiverI::closing(bool initiator, const Ice::LocalException&)
787 {
788     // If we are initiating the connection closure, wait for the peer
789     // to close the TCP/IP connection. Otherwise, close immediately.
790     return initiator ? IceInternal::SocketOperationRead : IceInternal::SocketOperationNone;
791 }
792 
793 void
794 SChannel::TransceiverI::close()
795 {
796     if(_sslInitialized)
797     {
798         DeleteSecurityContext(&_ssl);
799         _sslInitialized = false;
800     }
801 
802     if(_credentialsInitialized)
803     {
804         FreeCredentialsHandle(&_credentials);
805         _credentialsInitialized = false;
806     }
807 
808     _delegate->close();
809 
810     //
811     // Clear the buffers now instead of waiting for destruction.
812     //
813     _writeBuffer.b.clear();
814     _readBuffer.b.clear();
815     _readUnprocessed.b.clear();
816 }
817 
818 IceInternal::SocketOperation
819 SChannel::TransceiverI::write(IceInternal::Buffer& buf)
820 {
821     if(_state == StateNotInitialized)
822     {
823         return _delegate->write(buf);
824     }
825 
826     if(buf.i == buf.b.end())
827     {
828         return IceInternal::SocketOperationNone;
829     }
830     assert(_state == StateHandshakeComplete);
831 
832     while(buf.i != buf.b.end())
833     {
834         if(_bufferedW == 0)
835         {
836             assert(_writeBuffer.i == _writeBuffer.b.end());
837             _bufferedW = encryptMessage(buf);
838         }
839 
840         if(!writeRaw(_writeBuffer))
841         {
842             return IceInternal::SocketOperationWrite;
843         }
844 
845         assert(_writeBuffer.i == _writeBuffer.b.end()); // Finished writing the encrypted data
846 
847         buf.i += _bufferedW;
848         _bufferedW = 0;
849     }
850     return IceInternal::SocketOperationNone;
851 }
852 
853 IceInternal::SocketOperation
854 SChannel::TransceiverI::read(IceInternal::Buffer& buf)
855 {
856     if(_state == StateNotInitialized)
857     {
858         return _delegate->read(buf);
859     }
860 
861     if(buf.i == buf.b.end())
862     {
863         return IceInternal::SocketOperationNone;
864     }
865     assert(_state == StateHandshakeComplete);
866 
867     _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, false);
868     while(buf.i != buf.b.end())
869     {
870         if(_readUnprocessed.b.empty() && _readBuffer.i == _readBuffer.b.begin() && !readRaw(_readBuffer))
871         {
872             return IceInternal::SocketOperationRead;
873         }
874 
875         size_t decrypted = decryptMessage(buf);
876         if(decrypted == 0)
877         {
878             if(!readRaw(_readBuffer))
879             {
880                 return IceInternal::SocketOperationRead;
881             }
882             continue;
883         }
884 
885         buf.i += decrypted;
886     }
887     _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead,
888                                       !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin());
889     return IceInternal::SocketOperationNone;
890 }
891 
892 #ifdef ICE_USE_IOCP
893 
894 bool
895 SChannel::TransceiverI::startWrite(IceInternal::Buffer& buffer)
896 {
897     if(_state == StateNotInitialized)
898     {
899         return _delegate->startWrite(buffer);
900     }
901 
902     if(_state == StateHandshakeComplete && _bufferedW == 0)
903     {
904         assert(_writeBuffer.i == _writeBuffer.b.end());
905         _bufferedW = encryptMessage(buffer);
906     }
907 
908     return _delegate->startWrite(_writeBuffer) && _bufferedW == static_cast<size_t>((buffer.b.end() - buffer.i));
909 }
910 
911 void
912 SChannel::TransceiverI::finishWrite(IceInternal::Buffer& buf)
913 {
914     if(_state == StateNotInitialized)
915     {
916         _delegate->finishWrite(buf);
917         return;
918     }
919 
920     _delegate->finishWrite(_writeBuffer);
921     if(_writeBuffer.i != _writeBuffer.b.end())
922     {
923         return; // We're not finished yet with writing the write buffer.
924     }
925 
926     if(_state == StateHandshakeComplete)
927     {
928         buf.i += _bufferedW;
929         _bufferedW = 0;
930     }
931 }
932 
933 void
934 SChannel::TransceiverI::startRead(IceInternal::Buffer& buffer)
935 {
936     if(_state == StateNotInitialized)
937     {
938         _delegate->startRead(buffer);
939         return;
940     }
941     _delegate->startRead(_readBuffer);
942 }
943 
944 void
945 SChannel::TransceiverI::finishRead(IceInternal::Buffer& buf)
946 {
947     if(_state == StateNotInitialized)
948     {
949         _delegate->finishRead(buf);
950         return;
951     }
952 
953     _delegate->finishRead(_readBuffer);
954     if(_state == StateHandshakeComplete)
955     {
956         size_t decrypted = decryptMessage(buf);
957         if(decrypted > 0)
958         {
959             buf.i += decrypted;
960             _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead,
961                                               !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin());
962         }
963         else
964         {
965             _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, false);
966         }
967     }
968 }
969 #endif
970 
971 string
972 SChannel::TransceiverI::protocol() const
973 {
974     return _instance->protocol();
975 }
976 
977 string
978 SChannel::TransceiverI::toString() const
979 {
980     return _delegate->toString();
981 }
982 
983 string
984 SChannel::TransceiverI::toDetailedString() const
985 {
986     return toString();
987 }
988 
989 Ice::ConnectionInfoPtr
990 SChannel::TransceiverI::getInfo() const
991 {
992     ConnectionInfoPtr info = ICE_MAKE_SHARED(ConnectionInfo);
993     info->underlying = _delegate->getInfo();
994     info->incoming = _incoming;
995     info->adapterName = _adapterName;
996     info->cipher = _cipher;
997     info->certs = _certs;
998     info->verified = _verified;
999     return info;
1000 }
1001 
1002 void
1003 SChannel::TransceiverI::checkSendSize(const IceInternal::Buffer&)
1004 {
1005 }
1006 
1007 void
1008 SChannel::TransceiverI::setBufferSize(int rcvSize, int sndSize)
1009 {
1010     _delegate->setBufferSize(rcvSize, sndSize);
1011 }
1012 
1013 SChannel::TransceiverI::TransceiverI(const InstancePtr& instance,
1014                                    const IceInternal::TransceiverPtr& delegate,
1015                                    const string& hostOrAdapterName,
1016                                    bool incoming) :
1017     _instance(instance),
1018     _engine(SChannel::SSLEnginePtr::dynamicCast(instance->engine())),
1019     _host(incoming ? "" : hostOrAdapterName),
1020     _adapterName(incoming ? hostOrAdapterName : ""),
1021     _incoming(incoming),
1022     _delegate(delegate),
1023     _state(StateNotInitialized),
1024     _bufferedW(0),
1025     _sslInitialized(false),
1026     _credentialsInitialized(false),
1027     _verified(false)
1028 {
1029 }
1030 
1031 SChannel::TransceiverI::~TransceiverI()
1032 {
1033 }
1034 
1035 bool
1036 SChannel::TransceiverI::writeRaw(IceInternal::Buffer& buf)
1037 {
1038     _delegate->write(buf);
1039     return buf.i == buf.b.end();
1040 }
1041 
1042 bool
1043 SChannel::TransceiverI::readRaw(IceInternal::Buffer& buf)
1044 {
1045     IceInternal::Buffer::Container::iterator p = buf.i;
1046     _delegate->read(buf);
1047     return buf.i != p;
1048 }
1049