| 1108 | } |
| 1109 | |
| 1110 | static void client_handshake( pn_transport_t* transport) { |
| 1111 | pni_ssl_t *ssl = transport->ssl; |
| 1112 | // Feed SChannel ongoing responses from the server until the handshake is complete. |
| 1113 | SEC_CHAR *host = (SEC_CHAR *)(ssl->peer_hostname); |
| 1114 | ULONG ctxt_requested = ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS; |
| 1115 | ULONG ctxt_attrs; |
| 1116 | size_t max = 0; |
| 1117 | |
| 1118 | // token_buffs describe the buffer that's coming in. It should have |
| 1119 | // a token from the SSL server, or empty if sending final shutdown alert. |
| 1120 | bool shutdown = ssl->state == SHUTTING_DOWN; |
| 1121 | SecBuffer token_buffs[2]; |
| 1122 | token_buffs[0].cbBuffer = shutdown ? 0 : ssl->sc_in_count; |
| 1123 | token_buffs[0].BufferType = SECBUFFER_TOKEN; |
| 1124 | token_buffs[0].pvBuffer = shutdown ? 0 : ssl->sc_inbuf; |
| 1125 | token_buffs[1].cbBuffer = 0; |
| 1126 | token_buffs[1].BufferType = SECBUFFER_EMPTY; |
| 1127 | token_buffs[1].pvBuffer = 0; |
| 1128 | SecBufferDesc token_buff_desc; |
| 1129 | token_buff_desc.ulVersion = SECBUFFER_VERSION; |
| 1130 | token_buff_desc.cBuffers = 2; |
| 1131 | token_buff_desc.pBuffers = token_buffs; |
| 1132 | |
| 1133 | // send_buffs will hold information to forward to the peer. |
| 1134 | SecBuffer send_buffs[2]; |
| 1135 | send_buffs[0].cbBuffer = ssl->sc_out_size; |
| 1136 | send_buffs[0].BufferType = SECBUFFER_TOKEN; |
| 1137 | send_buffs[0].pvBuffer = ssl->sc_outbuf; |
| 1138 | send_buffs[1].cbBuffer = 0; |
| 1139 | send_buffs[1].BufferType = SECBUFFER_EMPTY; |
| 1140 | send_buffs[1].pvBuffer = 0; |
| 1141 | SecBufferDesc send_buff_desc; |
| 1142 | send_buff_desc.ulVersion = SECBUFFER_VERSION; |
| 1143 | send_buff_desc.cBuffers = 2; |
| 1144 | send_buff_desc.pBuffers = send_buffs; |
| 1145 | |
| 1146 | SECURITY_STATUS status; |
| 1147 | { |
| 1148 | csguard g(&ssl->cred->cslock); |
| 1149 | status = InitializeSecurityContext(&ssl->cred_handle, |
| 1150 | &ssl->ctxt_handle, host, ctxt_requested, 0, 0, |
| 1151 | &token_buff_desc, 0, NULL, &send_buff_desc, |
| 1152 | &ctxt_attrs, NULL); |
| 1153 | } |
| 1154 | |
| 1155 | switch (status) { |
| 1156 | case SEC_E_INCOMPLETE_MESSAGE: |
| 1157 | // Not enough - get more data from the server then try again. |
| 1158 | // Leave input buffers untouched. |
| 1159 | ssl_log(transport, PN_LEVEL_TRACE, "client handshake: incomplete record"); |
| 1160 | ssl->sc_in_incomplete = true; |
| 1161 | return; |
| 1162 | |
| 1163 | case SEC_I_CONTINUE_NEEDED: |
| 1164 | // Successful handshake step, requiring data to be sent to peer. |
| 1165 | ssl->sc_out_count = send_buffs[0].cbBuffer; |
| 1166 | // the token is the whole quantity to send |
| 1167 | ssl->network_out_pending = ssl->sc_out_count; |
no test coverage detected