Exemplo n.º 1
0
OM_uint32 gss_wrap (
		OM_uint32 *minor_status,
		gss_ctx_id_t context_handle,
		int conf_req_flag,
		gss_qop_t qop_req,
		gss_buffer_t input_message_buffer,
		int *conf_state,
		gss_buffer_t output_message_buffer)
{
	*minor_status = 0;
	SecPkgContext_Sizes sizes={0};
	BOOL b = QueryContextAttributes(&context_handle,SECPKG_ATTR_SIZES,&sizes);
	char *buffer = (char*)malloc(sizes.cbSecurityTrailer+input_message_buffer->length+sizes.cbBlockSize);
	SecBuffer InputBuffer[3] = { { sizes.cbSecurityTrailer,SECBUFFER_TOKEN,buffer },
								 { input_message_buffer->length,SECBUFFER_DATA,buffer+sizes.cbSecurityTrailer },
							     { sizes.cbBlockSize,SECBUFFER_PADDING,buffer+sizes.cbSecurityTrailer+input_message_buffer->length }
							   };
	SecBufferDesc InputBufferDesc = {SECBUFFER_VERSION, 3, InputBuffer};
	OM_uint32 ret;
	memcpy(InputBuffer[1].pvBuffer,input_message_buffer->value,input_message_buffer->length);
	ret = EncryptMessage(&context_handle, conf_req_flag? 0:KERB_WRAP_NO_ENCRYPT, &InputBufferDesc, 0);
	output_message_buffer->value=buffer;
	memmove(buffer+InputBuffer[0].cbBuffer,InputBuffer[1].pvBuffer,InputBuffer[1].cbBuffer);
	memmove(buffer+InputBuffer[0].cbBuffer+InputBuffer[1].cbBuffer,InputBuffer[2].pvBuffer,InputBuffer[2].cbBuffer);
	output_message_buffer->length=InputBuffer[0].cbBuffer+InputBuffer[1].cbBuffer+InputBuffer[2].cbBuffer;
	return ret;
}
Exemplo n.º 2
0
/* {{{ ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version) */
my_bool ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version)
{
  SC_CTX *sctx;
  SecPkgContext_ConnectionInfo ConnectionInfo;
  if (!ctls->ssl)
    return 1;

  sctx= (SC_CTX *)ctls->ssl;

  if (QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_CONNECTION_INFO, &ConnectionInfo) != SEC_E_OK)
    return 1;

  switch(ConnectionInfo.dwProtocol)
  {
  case SP_PROT_SSL3_CLIENT:
    version->iversion= 1;
    break;
  case SP_PROT_TLS1_CLIENT:
    version->iversion= 2;
    break;
  case SP_PROT_TLS1_1_CLIENT:
    version->iversion= 3;
    break;
  case SP_PROT_TLS1_2_CLIENT:
    version->iversion= 4;
    break;
  default:
    version->iversion= 0;
    break;
  }
  version->cversion= ssl_protocol_version[version->iversion];
  return 0;
}
Exemplo n.º 3
0
static int tls_write(URLContext *h, const uint8_t *buf, int len)
{
    TLSContext *c = h->priv_data;
    TLSShared *s = &c->tls_shared;
    SECURITY_STATUS sspi_ret;
    int ret = 0, data_size;
    uint8_t *data = NULL;
    SecBuffer outbuf[4];
    SecBufferDesc outbuf_desc;

    if (c->sizes.cbMaximumMessage == 0) {
        sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes);
        if (sspi_ret != SEC_E_OK)
            return AVERROR_UNKNOWN;
    }

    /* limit how much data we can consume */
    len = FFMIN(len, c->sizes.cbMaximumMessage);

    data_size = c->sizes.cbHeader + len + c->sizes.cbTrailer;
    data = av_malloc(data_size);
    if (data == NULL)
        return AVERROR(ENOMEM);

    init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
                  data, c->sizes.cbHeader);
    init_sec_buffer(&outbuf[1], SECBUFFER_DATA,
                  data + c->sizes.cbHeader, len);
    init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
                  data + c->sizes.cbHeader + len,
                  c->sizes.cbTrailer);
    init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
    init_sec_buffer_desc(&outbuf_desc, outbuf, 4);

    memcpy(outbuf[1].pvBuffer, buf, len);

    sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0);
    if (sspi_ret == SEC_E_OK)  {
        len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
        ret = ffurl_write(s->tcp, data, len);
        if (ret < 0 || ret != len) {
            ret = AVERROR(EIO);
            av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n");
            goto done;
        }
    } else {
        av_log(h, AV_LOG_ERROR, "Encrypting data failed\n");
        if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
            ret = AVERROR(ENOMEM);
        else
            ret = AVERROR(EIO);
        goto done;
    }

done:
    av_freep(&data);
    return ret < 0 ? ret : outbuf[1].cbBuffer;
}
Exemplo n.º 4
0
my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
{
  SECURITY_STATUS sRet;
  DWORD flags;
  MARIADB_PVIO *pvio= sctx->mysql->net.pvio;
  PCCERT_CONTEXT pServerCert= NULL;

  if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    return 0;
  }

  flags= CERT_STORE_SIGNATURE_FLAG |
         CERT_STORE_TIME_VALIDITY_FLAG;


    
  if (sctx->client_ca_ctx)
  {
 	  if (!(sRet= CertVerifySubjectCertificateContext(pServerCert,
                                                    sctx->client_ca_ctx,
                                                    &flags)))
    {
      ma_schannel_set_win_error(pvio);
      return 0;
    }

    if (flags)
    {
      if ((flags & CERT_STORE_SIGNATURE_FLAG) != 0)
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Certificate signature check failed");
      else if ((flags & CERT_STORE_REVOCATION_FLAG) != 0)
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "certificate was revoked");
      else if ((flags & CERT_STORE_TIME_VALIDITY_FLAG) != 0)
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "certificate has expired");
      else
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown error during certificate validation");
      return 0;
    }
  }

  /* Check if none of the certificates in the certificate chain have been revoked. */
  if (sctx->client_crl_ctx)
  {
    PCRL_INFO Info[1];

    Info[0]= sctx->client_crl_ctx->pCrlInfo;
    if (!(CertVerifyCRLRevocation(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                  pServerCert->pCertInfo,
                                  1, Info))                               )
    {
      pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CRL Revocation failed");
      return 0;
    }
  }
  return 1;
}
Exemplo n.º 5
0
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, unsigned char *fp, unsigned int len)
{
  SC_CTX *sctx= (SC_CTX *)ctls->ssl;
  PCCERT_CONTEXT pRemoteCertContext = NULL;
  if (QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext) != SEC_E_OK)
    return 0;
  CertGetCertificateContextProperty(pRemoteCertContext, CERT_HASH_PROP_ID, fp, (DWORD *)&len);
  return len;
}
Exemplo n.º 6
0
OM_uint32 gss_wrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
		    int conf_req_flag,gss_qop_t qop_req,
		    gss_buffer_t input_message_buffer,int *conf_state,
		    gss_buffer_t output_message_buffer)
{
  OM_uint32 major_status;
  SecBuffer buf[3];
  SecBufferDesc bufs;
  SecPkgContext_Sizes sizes;
  *minor_status = NIL;		/* never any minor status */
  *conf_state = conf_req_flag;	/* same as requested */
  if ((major_status =		/* get trailer and padding sizes */
       QueryContextAttributes (context_handle,SECPKG_ATTR_SIZES,&sizes)) ==
      SEC_E_OK) {
				/* create big enough output buffer */
    output_message_buffer->value =
      fs_get (sizes.cbSecurityTrailer + input_message_buffer->length +
	      sizes.cbBlockSize);
    /* MSDN claims that for EncryptMessage() in Kerberos, you need an
     * uninitialized SECBUFFER_STREAM_HEADER; a SECBUFFER_DATA that "contains
     * the message to be encrypted.  The message is encrypted in place,
     * overwirting the original contents of its buffer"; an uninitialized
     * SECBUFFER_STREAM_TRAILER, and an uninitialized SECBUFFER_EMPTY.  I've
     * never been able to get it to work that way.
     */
    bufs.cBuffers = 3;		/* set up buffer descriptor */
    bufs.pBuffers = buf;
    bufs.ulVersion = SECBUFFER_VERSION;
    buf[0].BufferType = SECBUFFER_TOKEN;
    buf[0].pvBuffer = output_message_buffer->value;
    buf[0].cbBuffer = sizes.cbSecurityTrailer;
				/* I/O buffer */
    buf[1].BufferType = SECBUFFER_DATA;
    buf[1].pvBuffer = ((char *) buf[0].pvBuffer) + buf[0].cbBuffer;
    buf[1].cbBuffer = input_message_buffer->length;
    memcpy (buf[1].pvBuffer,input_message_buffer->value,buf[1].cbBuffer);
    buf[2].BufferType = SECBUFFER_PADDING;
    buf[2].pvBuffer = ((char *) buf[1].pvBuffer) + buf[1].cbBuffer;
    buf[2].cbBuffer = sizes.cbBlockSize;
    if ((major_status = EncryptMessage (context_handle,qop_req,&bufs,0)) ==
	GSS_S_COMPLETE) {
				/* slide data as necessary (how annoying!) */
      unsigned long i = sizes.cbSecurityTrailer - buf[0].cbBuffer;
      if (i) buf[1].pvBuffer =
	       memmove (((char *) buf[0].pvBuffer) + buf[0].cbBuffer,
			buf[1].pvBuffer,buf[1].cbBuffer);
      if (i += (input_message_buffer->length - buf[1].cbBuffer))
	buf[1].pvBuffer = memmove (((char *)buf[1].pvBuffer) + buf[1].cbBuffer,
		   buf[2].pvBuffer,buf[2].cbBuffer);
      output_message_buffer->length = buf[0].cbBuffer + buf[1].cbBuffer +
	buf[2].cbBuffer;
    }
    else fs_give (&output_message_buffer->value);
  }
  return major_status;		/* return status */
}
Exemplo n.º 7
0
SECURITY_STATUS SSL_SOCKET :: VerifySessionCertificate()
	{
	PCCERT_CONTEXT pRemoteCertContext = NULL;
	SECURITY_STATUS Status = QueryContextAttributes(&hCtx,SECPKG_ATTR_REMOTE_CERT_CONTEXT,(PVOID)&pRemoteCertContext);
	if (Status != SEC_E_OK) 
		return Status;
	Status = Verify(pRemoteCertContext);
	CertFreeCertificateContext(pRemoteCertContext);
	return Status;
	}
/* sqExtractPeerName: Extract the name from the cert of the remote peer. */
static int sqExtractPeerName(sqSSL *ssl) {
	SECURITY_STATUS ret;
	PCCERT_CONTEXT certHandle = NULL;
	PCERT_NAME_INFO certInfo = NULL;
	PCERT_RDN_ATTR certAttr = NULL;
	DWORD dwSize = 0;
	char tmpBuf[1024];

	if(ssl->peerName) {
		free(ssl->peerName);
		ssl->peerName = NULL;
	}
	ret = QueryContextAttributes(&ssl->sslCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&certHandle);
	/* No credentials were provided; can't extract peer name */
	if(ret == SEC_E_NO_CREDENTIALS) return 1;

	if(ret != SEC_E_OK) {
		if(ssl->loglevel) printf("sqExtractPeerName: QueryContextAttributes failed (code = %x)\n", ret);
		return 0;
	}

	/* Figure out the size of the blob */
	if(!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_NAME,
		certHandle->pCertInfo->Subject.pbData,
		certHandle->pCertInfo->Subject.cbData,
		0, NULL, &dwSize)) {
			if(ssl->loglevel) printf("sqExtractPeerName: CryptDecodeObject failed\n");
			return 0;
	}
	
	/* Get the contents */
	certInfo = alloca(dwSize);
	if(!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_NAME, 
		certHandle->pCertInfo->Subject.pbData,
		certHandle->pCertInfo->Subject.cbData,
		0, certInfo, &dwSize)) {
			if(ssl->loglevel) printf("sqExtractPeerName: CryptDecodeObject failed\n");
			return 0;
	}

	/* Fetch the CN from the cert */
	certAttr = CertFindRDNAttr(szOID_COMMON_NAME, certInfo);
	if(certAttr == NULL) return 0;

	/* Translate from RDN to string */
	if(CertRDNValueToStr(CERT_RDN_PRINTABLE_STRING, &certAttr->Value, tmpBuf, sizeof(tmpBuf)) == 0) return 0;
	ssl->peerName = _strdup(tmpBuf);
	if(ssl->loglevel) printf("sqExtractPeerName: Peer name is %s\n", ssl->peerName);

	CertFreeCertificateContext(certHandle);

	return 1;
}
Exemplo n.º 9
0
Certificate::ref SchannelContext::getPeerCertificate() const 
{
	SchannelCertificate::ref pCertificate;

	ScopedCertContext pServerCert;
	SECURITY_STATUS status = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset());
	if (status != SEC_E_OK)
		return pCertificate;

	pCertificate.reset( new SchannelCertificate(pServerCert) );
	return pCertificate;
}
Exemplo n.º 10
0
void SSL_SOCKET :: GetCertificateInfoString(TCHAR* s)
	{
	PCCERT_CONTEXT pRemoteCertContext = NULL;
	SECURITY_STATUS Status = QueryContextAttributes(&hCtx,SECPKG_ATTR_REMOTE_CERT_CONTEXT,(PVOID)&pRemoteCertContext);
	if (Status != SEC_E_OK) 
		return;

	CertGetNameString(   
		pRemoteCertContext,   
		CERT_NAME_FRIENDLY_DISPLAY_TYPE,   
		0,
		NULL,   
		s,   
		1000);
	CertFreeCertificateContext(pRemoteCertContext);
	}
Exemplo n.º 11
0
AUTH_RESULT GSSAPISession::authenticate()
{
#ifdef Q_OS_WIN
    SECURITY_STATUS status;
    _inSecBuf.cbBuffer = static_cast<unsigned long>(inBuffer.length());
    _inSecBuf.BufferType = SECBUFFER_TOKEN;
    _inSecBuf.pvBuffer = inBuffer.data();
    _outSecBuf.cbBuffer = _info->cbMaxToken;

    CtxtHandle* contextPtr = &_context;
    if(_first)
    {
        contextPtr = NULL;
        _first = false;
    }
    status = AcceptSecurityContext (
                    &_serverHandle,
                    contextPtr,
                    &_inSecBufDesc,
                    0,
                    SECURITY_NATIVE_DREP,
                    &_context,
                    &_outSecBufDesc,
                    &_attrs,
                    &_serviceLifetime
                    );


    outBuffer = QByteArray((const char *)_outSecBuf.pvBuffer, _outSecBuf.cbBuffer);
    if(status == SEC_I_CONTINUE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) return AUTH_RESULT::CONTINUE;
    if(status == 0)
    {

        status = QuerySecurityContextToken(&_context, &_secToken);
        status  = QueryContextAttributes(&_context, SECPKG_ATTR_NAMES, &_names);
        return AUTH_RESULT::ACCEPTED;
    }

    return AUTH_RESULT::REJECTED;
#endif
#ifdef Q_OS_LINUX
    throw "not implemented";
    return AUTH_RESULT::REJECTED;
#endif
}
Exemplo n.º 12
0
void RPC_ENTRY kull_m_rpc_drsr_RpcSecurityCallback(void *Context)
{
	RPC_STATUS rpcStatus;
	SECURITY_STATUS secStatus;
	PCtxtHandle data = NULL;

	rpcStatus = I_RpcBindingInqSecurityContext(Context, (LPVOID *) &data);
	if(rpcStatus == RPC_S_OK)
	{
		if(kull_m_rpc_drsr_g_sKey.SessionKey)
		{
			FreeContextBuffer(kull_m_rpc_drsr_g_sKey.SessionKey);
			kull_m_rpc_drsr_g_sKey.SessionKeyLength = 0;
			kull_m_rpc_drsr_g_sKey.SessionKey = NULL;
		}
		secStatus = QueryContextAttributes(data, SECPKG_ATTR_SESSION_KEY, (LPVOID) &kull_m_rpc_drsr_g_sKey);
		if(secStatus != SEC_E_OK)
			PRINT_ERROR(L"QueryContextAttributes %08x\n", secStatus);
	}
	else PRINT_ERROR(L"I_RpcBindingInqSecurityContext %08x\n", rpcStatus);
}
Exemplo n.º 13
0
OM_uint32 gss_unwrap (
		OM_uint32 * minor_status,
		gss_ctx_id_t context_handle,
		gss_buffer_t input_message_buffer,
		gss_buffer_t output_message_buffer,
		int * conf_state,
		gss_qop_t * qop_state)
{
	SecPkgContext_Sizes sizes={0};
	BOOL b = QueryContextAttributes(&context_handle,SECPKG_ATTR_SIZES,&sizes);
	SecBuffer InputBuffer[2] = { { input_message_buffer->length,SECBUFFER_STREAM,input_message_buffer->value },
								 { 0,SECBUFFER_DATA,NULL },
							   };
	SecBufferDesc InputBufferDesc = {SECBUFFER_VERSION, 2, InputBuffer};
	OM_uint32 ret;
	ret = DecryptMessage(&context_handle, &InputBufferDesc, 0, (unsigned long*)qop_state);
	output_message_buffer->value=InputBuffer[1].pvBuffer;
	output_message_buffer->length=InputBuffer[1].cbBuffer;
	*minor_status = 0;
	return ret;
}
Exemplo n.º 14
0
const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
{
  SecPkgContext_ConnectionInfo cinfo;
  SECURITY_STATUS sRet;
  SC_CTX *sctx;
  DWORD i= 0;

  if (!ctls || !ctls->ssl)
    return NULL;

  sctx= (SC_CTX *)ctls->ssl;

  sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_CONNECTION_INFO, (PVOID)&cinfo);
  if (sRet != SEC_E_OK)
    return NULL;

  while (valid_ciphers[i].cipher)
  {
    if (valid_ciphers[i].aid == cinfo.aiCipher)
      return valid_ciphers[i].cipher;
    i++;
  }
  return NULL;
}
Exemplo n.º 15
0
int sserver_connect(const struct protocol_interface *protocol, int verify_only)
{
	char crypt_password[64];
	char server_version[128];
	char tmp_keyname[256];
	const char *begin_request = "BEGIN SSL AUTH REQUEST";
	const char *end_request = "END SSL AUTH REQUEST";
	const char *username = NULL;
	const char *cert = current_server()->current_root->optional_3;
	int l;
	int sserver_version = 0;
	int strict = 0;
	CScramble scramble;
	bool send_client_version = false;

	if(current_server()->current_root->optional_1)
	{
	  sserver_version = atoi(current_server()->current_root->optional_1);
	  if(sserver_version != 0 && sserver_version != 1)
	  {
	    server_error(0,"version must be one of:");
	    server_error(0,"0 - All CVSNT-type servers");
	    server_error(0,"1 - Unix server using Corey Minards' sserver patches");
	    server_error(1,"Please specify a valid value");
	  }
	}

	if(!CGlobalSettings::GetUserValue("cvsnt","sserver","StrictChecking",server_version,sizeof(server_version)))
	{
	  strict = atoi(server_version);
	}

	if(!cert && !CGlobalSettings::GetUserValue("cvsnt","sserver","ClientCert",tmp_keyname,sizeof(tmp_keyname)))
	{
	  cert = tmp_keyname;
	}

	if(current_server()->current_root->optional_2)
		strict = atoi(current_server()->current_root->optional_2);

	if(sserver_version == 1) /* Old sserver */
	{
	  begin_request = verify_only?"BEGIN SSL VERIFICATION REQUEST":"BEGIN SSL REQUEST";
	  end_request = verify_only?"END SSL VERIFICATION REQUEST":"END SSL REQUEST";
	}
	else if(verify_only)
	{
		begin_request = "BEGIN SSL VERIFICATION REQUEST";
		end_request = "END SSL VERIFICATION REQUEST";
	}
	username = get_username(current_server()->current_root);

	if(!username || !current_server()->current_root->hostname || !current_server()->current_root->directory)
		return CVSPROTO_BADPARMS;

	if(tcp_connect(current_server()->current_root))
		return CVSPROTO_FAIL;
	if(current_server()->current_root->password)
		strncpy(crypt_password,scramble.Scramble(current_server()->current_root->password),sizeof(crypt_password));
	else
	{
		if(sserver_get_user_password(username,current_server()->current_root->hostname,current_server()->current_root->port,current_server()->current_root->directory,crypt_password,sizeof(crypt_password)))
		{
			/* Using null password - trace something out here */
			server_error(0,"Using an empty password; you may need to do 'cvs login' with a real password\n");
			strncpy(crypt_password,scramble.Scramble(""),sizeof(crypt_password));
		}
	}

	if(sserver_version == 0) /* Pre-CVSNT had no version check */
	{
	  if(tcp_printf("%s\n",begin_request)<0)
		return CVSPROTO_FAIL;
	  for(;;)
	  {
		*server_version='\0';
		if((l=tcp_readline(server_version,sizeof(server_version))<0))
			return CVSPROTO_FAIL;
		if(*server_version)
			break;
#ifdef _WIN32
		Sleep(10);
#else
		usleep(10);
#endif
	  }
	  if(strncmp(server_version,"SSERVER ",8))
	  {
	  	  server_error(0,"%s\n",server_version);
		  return CVSPROTO_FAIL;
	  }
	  if(strncmp(server_version+8,"1.0 ",4))
		  send_client_version = true;
	}

	if(!ClientAuthenticate(cert,current_server()->current_root->hostname))
		return CVSPROTO_AUTHFAIL;

	QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes);

	PCERT_CONTEXT sc;
	PCCERT_CHAIN_CONTEXT pcc;
	CERT_SIMPLE_CHAIN  *psc;
	CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) };
	DWORD trust,rc;
	
	rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc);
	if(rc)
		server_error(1,"Couldn't get server certificate");

	if(!CertGetCertificateChain(NULL, sc, NULL, NULL, &para, 0, NULL, &pcc))
		server_error(1,"Couldn't get server certificate chain");

    psc = pcc->rgpChain[0];
	trust = psc->TrustStatus.dwErrorStatus;
 
    if (trust)
    {
        if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT))
            ; // Seld signed
        else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID))
			server_error(1,"Server certificate expired");
        else
			server_error(1,"Server certificate verification failed - %08x",trust);
    }

	if(strict)
	{
		char certname[256];

		CertGetNameString(sc, CERT_NAME_DNS_TYPE, 0, NULL, certname, sizeof(certname));
		  if(strcasecmp(certname,current_server()->current_root->hostname))
			server_error(1, "Certificate CommonName '%s' does not match server name '%s'\n",certname,current_server()->current_root->hostname);
	}

	CertFreeCertificateChain(pcc);
	FreeContextBuffer(sc);
 
	g_sslBufferInPos=g_sslBufferOutPos=0;
	g_sslBufferInLen=g_sslBufferOutLen=0;

	if(sserver_version == 1)
	{
	  if(sserver_printf("%s\n",begin_request)<0)
		return CVSPROTO_FAIL;
	}

    // For server versions 1.1+ send CLIENT_VERSION_STRING
	if(send_client_version && sserver_printf(SSERVER_CLIENT_VERSION_STRING)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n%s\n",current_server()->current_root->directory,username)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n",crypt_password)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n",end_request)<0)
		return CVSPROTO_FAIL;
	return CVSPROTO_SUCCESS;
}
Exemplo n.º 16
0
int
_mongoc_sspi_auth_sspi_client_wrap (mongoc_sspi_client_state_t *state,
                                    SEC_CHAR *data,
                                    SEC_CHAR *user,
                                    ULONG ulen,
                                    int protect)
{
   SECURITY_STATUS status;
   SecPkgContext_Sizes sizes;
   SecBuffer wrapBufs[3];
   SecBufferDesc wrapBufDesc;
   SEC_CHAR *decodedData = NULL;
   SEC_CHAR *inbuf;
   SIZE_T inbufSize;
   SEC_CHAR *outbuf;
   DWORD outbufSize;
   SEC_CHAR *plaintextMessage;
   ULONG plaintextMessageSize;

   if (state->response != NULL) {
      free (state->response);
      state->response = NULL;
   }

   if (!state->haveCtx) {
      return MONGOC_SSPI_AUTH_GSS_ERROR;
   }

   status = QueryContextAttributes (&state->ctx, SECPKG_ATTR_SIZES, &sizes);
   if (status != SEC_E_OK) {
      _mongoc_sspi_set_gsserror (status, "QueryContextAttributes");
      return MONGOC_SSPI_AUTH_GSS_ERROR;
   }

   if (user) {
      /* Length of user + 4 bytes for security layer (see below). */
      plaintextMessageSize = ulen + 4;
   } else {
      decodedData = _mongoc_sspi_base64_decode (data, &plaintextMessageSize);
      if (!decodedData) {
         return MONGOC_SSPI_AUTH_GSS_ERROR;
      }
   }

   inbufSize =
      sizes.cbSecurityTrailer + plaintextMessageSize + sizes.cbBlockSize;
   inbuf = (SEC_CHAR *) malloc (inbufSize);
   if (inbuf == NULL) {
      free (decodedData);
      return MONGOC_SSPI_AUTH_GSS_ERROR;
   }

   plaintextMessage = inbuf + sizes.cbSecurityTrailer;
   if (user) {
      /* Authenticate the provided user. Unlike pykerberos, we don't
       * need any information from "data" to do that.
       * */
      plaintextMessage[0] = 1; /* No security layer */
      plaintextMessage[1] = 0;
      plaintextMessage[2] = 0;
      plaintextMessage[3] = 0;
      memcpy_s (plaintextMessage + 4,
                inbufSize - sizes.cbSecurityTrailer - 4,
                user,
                strlen (user));
   } else {
      /* No user provided. Just rewrap data. */
      memcpy_s (plaintextMessage,
                inbufSize - sizes.cbSecurityTrailer,
                decodedData,
                plaintextMessageSize);
      free (decodedData);
   }

   wrapBufDesc.cBuffers = 3;
   wrapBufDesc.pBuffers = wrapBufs;
   wrapBufDesc.ulVersion = SECBUFFER_VERSION;

   wrapBufs[0].cbBuffer = sizes.cbSecurityTrailer;
   wrapBufs[0].BufferType = SECBUFFER_TOKEN;
   wrapBufs[0].pvBuffer = inbuf;

   wrapBufs[1].cbBuffer = (ULONG) plaintextMessageSize;
   wrapBufs[1].BufferType = SECBUFFER_DATA;
   wrapBufs[1].pvBuffer = inbuf + sizes.cbSecurityTrailer;

   wrapBufs[2].cbBuffer = sizes.cbBlockSize;
   wrapBufs[2].BufferType = SECBUFFER_PADDING;
   wrapBufs[2].pvBuffer =
      inbuf + (sizes.cbSecurityTrailer + plaintextMessageSize);

   status = EncryptMessage (
      &state->ctx, protect ? 0 : SECQOP_WRAP_NO_ENCRYPT, &wrapBufDesc, 0);
   if (status != SEC_E_OK) {
      free (inbuf);
      _mongoc_sspi_set_gsserror (status, "EncryptMessage");
      return MONGOC_SSPI_AUTH_GSS_ERROR;
   }

   outbufSize =
      wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer + wrapBufs[2].cbBuffer;
   outbuf = (SEC_CHAR *) malloc (sizeof (SEC_CHAR) * outbufSize);
   memcpy_s (outbuf, outbufSize, wrapBufs[0].pvBuffer, wrapBufs[0].cbBuffer);
   memcpy_s (outbuf + wrapBufs[0].cbBuffer,
             outbufSize - wrapBufs[0].cbBuffer,
             wrapBufs[1].pvBuffer,
             wrapBufs[1].cbBuffer);
   memcpy_s (outbuf + wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer,
             outbufSize - wrapBufs[0].cbBuffer - wrapBufs[1].cbBuffer,
             wrapBufs[2].pvBuffer,
             wrapBufs[2].cbBuffer);
   state->response = _mongoc_sspi_base64_encode (outbuf, outbufSize);
   if (!state->response) {
      status = MONGOC_SSPI_AUTH_GSS_ERROR;
   } else {
      status = MONGOC_SSPI_AUTH_GSS_COMPLETE;
   }
   free (inbuf);
   free (outbuf);
   return status;
}
Exemplo n.º 17
0
    int sspiSendClientAuthzId(SspiConnContext* pcctx,
                              sasl_client_params_t* cparams,
                              const char *serverin,
                              unsigned serverinlen,
                              const char **clientout,
                              unsigned *clientoutlen,
                              sasl_out_params_t* oparams) {

        // Ensure server response is decryptable.
        int decryptStatus = sspiValidateServerSecurityLayerOffering(pcctx, 
                                                                    cparams, 
                                                                    serverin, 
                                                                    serverinlen);
        if (decryptStatus != SASL_OK) {
            return decryptStatus;
        }

        // Fill in AUTHID and AUTHZID fields in oparams.
        int ret = cparams->canon_user(cparams->utils->conn,
                                      pcctx->userPlusRealm.c_str(), 
                                      0,
                                      SASL_CU_AUTHID | SASL_CU_AUTHZID,
                                      oparams);
        
        // Reply to server with security capability and authz name.
        SecPkgContext_Sizes sizes;
        SECURITY_STATUS status = QueryContextAttributes(&pcctx->ctx,
                                                        SECPKG_ATTR_SIZES,
                                                        &sizes);
        if (status != SEC_E_OK) {
            HandleLastError(cparams->utils, status, "QueryContextAttributes(sizes)");
            return SASL_FAIL;
        }
        
        // See RFC4752.
        int plaintextMessageSize = 4 + pcctx->userPlusRealm.size();
        boost::scoped_array<char> message(new char[sizes.cbSecurityTrailer +
                                                   plaintextMessageSize +
                                                   sizes.cbBlockSize]);
        char* plaintextMessage = message.get() + sizes.cbSecurityTrailer;
        plaintextMessage[0] = 1; // LAYER_NONE
        plaintextMessage[1] = 0;
        plaintextMessage[2] = 0;
        plaintextMessage[3] = 0;
        memcpy(&plaintextMessage[4], pcctx->userPlusRealm.c_str(), pcctx->userPlusRealm.size());
        
        SecBuffer wrapBufs[3];
        SecBufferDesc wrapBufDesc;
        wrapBufDesc.cBuffers = 3;
        wrapBufDesc.pBuffers = wrapBufs;
        wrapBufDesc.ulVersion = SECBUFFER_VERSION;
        
        wrapBufs[0].cbBuffer = sizes.cbSecurityTrailer;
        wrapBufs[0].BufferType = SECBUFFER_TOKEN;
        wrapBufs[0].pvBuffer = message.get();
        
        wrapBufs[1].cbBuffer = plaintextMessageSize;
        wrapBufs[1].BufferType = SECBUFFER_DATA;
        wrapBufs[1].pvBuffer = message.get() + sizes.cbSecurityTrailer;
        
        wrapBufs[2].cbBuffer = sizes.cbBlockSize;
        wrapBufs[2].BufferType = SECBUFFER_PADDING;
        wrapBufs[2].pvBuffer = message.get() + sizes.cbSecurityTrailer + plaintextMessageSize;

        status = EncryptMessage(&pcctx->ctx,
                                SECQOP_WRAP_NO_ENCRYPT,
                                &wrapBufDesc,
                                0);

        if (status != SEC_E_OK) {
            HandleLastError(cparams->utils, status, "EncryptMessage");
            return SASL_FAIL;
        }
        
        // Create the message to send to server.
        *clientoutlen = wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer + wrapBufs[2].cbBuffer;
        char *newoutbuf = static_cast<char*>(cparams->utils->malloc(*clientoutlen));
        memcpy(newoutbuf, 
               wrapBufs[0].pvBuffer, 
               wrapBufs[0].cbBuffer);
        memcpy(newoutbuf + wrapBufs[0].cbBuffer, 
               wrapBufs[1].pvBuffer, 
               wrapBufs[1].cbBuffer);
        memcpy(newoutbuf + wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer, 
               wrapBufs[2].pvBuffer, 
               wrapBufs[2].cbBuffer);
        *clientout = newoutbuf;
        
        return SASL_OK;
    }
Exemplo n.º 18
0
void main()
{

	SOCKET            Client_Socket;
	BYTE              Data[BIG_BUFF];
	PCHAR             pMessage;
	WSADATA           wsaData;
	CredHandle        hCred;
	struct _SecHandle hCtxt;
	SECURITY_STATUS   ss;
	DWORD             cbRead;
	ULONG             cbMaxSignature;
	ULONG             cbSecurityTrailer;
	SecPkgContext_Sizes            SecPkgContextSizes;
	SecPkgContext_NegotiationInfo  SecPkgNegInfo;
	BOOL DoAuthentication (SOCKET s);

	//-------------------------------------------------------------------
	//  Initialize the socket and the SSP security package.

	if(WSAStartup (0x0101, &wsaData))
	{
		MyHandleError("Could not initialize winsock ");
	}

	//--------------------------------------------------------------------
	//  Connect to a server.

	if (!ConnectAuthSocket (
				&Client_Socket,
				&hCred,
				&hCtxt))
	{
		MyHandleError("Authenticated server connection ");
	}

	//--------------------------------------------------------------------
	//   An authenticated session with a server has been established.
	//   Receive and manage a message from the server.
	//   First, find and display the name of the negotiated
	//   SSP and the size of the signature and the encryption 
	//   trailer blocks for this SSP.

	ss = QueryContextAttributes(
	&hCtxt,
	SECPKG_ATTR_NEGOTIATION_INFO,
	&SecPkgNegInfo );

	if (!SEC_SUCCESS(ss))  
	{
		MyHandleError("QueryContextAttributes failed ");
	}
	else
	{
		printf("Package Name: %s\n", SecPkgNegInfo.PackageInfo->Name);
	}

	ss = QueryContextAttributes(
	&hCtxt,
	SECPKG_ATTR_SIZES,
	&SecPkgContextSizes );

	if (!SEC_SUCCESS(ss))  
	{
		MyHandleError("Query context ");
	}

	cbMaxSignature = SecPkgContextSizes.cbMaxSignature;
	cbSecurityTrailer = SecPkgContextSizes.cbSecurityTrailer;

	printf("InitializeSecurityContext result = 0x%08x\n", ss);

	//--------------------------------------------------------------------
	//   Decrypt and display the message from the server.

	if (!ReceiveBytes(
				Client_Socket, 
				Data, 
				BIG_BUFF, 
				&cbRead))
	{
		MyHandleError("No response from server ");
	}

	if (0 == cbRead)
	{
		MyHandleError("Zero bytes received ");
	}

	pMessage = (PCHAR) DecryptThis(
	Data, 
	&cbRead,
	&hCtxt,
	cbSecurityTrailer);

	printf ("The message from the server is \n ->  %.*s \n",
	cbRead, pMessage);

	//--------------------------------------------------------------------
	//  Terminate socket and security package.

	DeleteSecurityContext (&hCtxt);
	FreeCredentialHandle (&hCred); 
	shutdown (Client_Socket, 2);
	closesocket (Client_Socket);
	if (SOCKET_ERROR == WSACleanup ())
	{
		MyHandleError("Problem with socket cleanup ");
	}

	exit (EXIT_SUCCESS);
}  // end main
Exemplo n.º 19
0
/*
 * '_sspiAccept()' - Accept an SSL/TLS connection
 */
BOOL					/* O - 1 on success, 0 on failure */
_sspiAccept(_sspi_struct_t *conn)	/* I  - Client connection */
{
  DWORD			dwSSPIFlags;	/* SSL connection attributes we want */
  DWORD			dwSSPIOutFlags;	/* SSL connection attributes we got */
  TimeStamp		tsExpiry;	/* Time stamp */
  SECURITY_STATUS	scRet;		/* SSPI Status */
  SecBufferDesc		inBuffer;	/* Array of SecBuffer structs */
  SecBuffer		inBuffers[2];	/* Security package buffer */
  SecBufferDesc		outBuffer;	/* Array of SecBuffer structs */
  SecBuffer		outBuffers[1];	/* Security package buffer */
  DWORD			num = 0;	/* 32 bit status value */
  BOOL			fInitContext = TRUE;
					/* Has the context been init'd? */
  BOOL			ok = TRUE;	/* Return value */

  if (!conn)
    return (FALSE);

  dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT  |
                ASC_REQ_REPLAY_DETECT    |
                ASC_REQ_CONFIDENTIALITY  |
                ASC_REQ_EXTENDED_ERROR   |
                ASC_REQ_ALLOCATE_MEMORY  |
                ASC_REQ_STREAM;

  conn->decryptBufferUsed = 0;

 /*
  * Set OutBuffer for AcceptSecurityContext call
  */
  outBuffer.cBuffers = 1;
  outBuffer.pBuffers = outBuffers;
  outBuffer.ulVersion = SECBUFFER_VERSION;

  scRet = SEC_I_CONTINUE_NEEDED;

  while (scRet == SEC_I_CONTINUE_NEEDED    ||
         scRet == SEC_E_INCOMPLETE_MESSAGE ||
         scRet == SEC_I_INCOMPLETE_CREDENTIALS)
  {
    if ((conn->decryptBufferUsed == 0) || (scRet == SEC_E_INCOMPLETE_MESSAGE))
    {
      if (conn->decryptBufferLength <= conn->decryptBufferUsed)
      {
        conn->decryptBufferLength += 4096;
        conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer,
                                              conn->decryptBufferLength);

        if (!conn->decryptBuffer)
        {
          DEBUG_printf(("_sspiAccept: unable to allocate %d byte decrypt buffer",
                        conn->decryptBufferLength));
          ok = FALSE;
          goto cleanup;
        }
      }

      for (;;)
      {
        num = recv(conn->sock,
                   conn->decryptBuffer + conn->decryptBufferUsed,
                   (int)(conn->decryptBufferLength - conn->decryptBufferUsed),
                   0);

        if ((num == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
          Sleep(1);
        else
          break;
      }

      if (num == SOCKET_ERROR)
      {
        DEBUG_printf(("_sspiAccept: recv failed: %d", WSAGetLastError()));
        ok = FALSE;
        goto cleanup;
      }
      else if (num == 0)
      {
        DEBUG_printf(("_sspiAccept: client disconnected"));
        ok = FALSE;
        goto cleanup;
      }

      DEBUG_printf(("_sspiAccept: received %d (handshake) bytes from client",
                    num));
      conn->decryptBufferUsed += num;
    }

   /*
    * InBuffers[1] is for getting extra data that
    * SSPI/SCHANNEL doesn't proccess on this
    * run around the loop.
    */
    inBuffers[0].pvBuffer   = conn->decryptBuffer;
    inBuffers[0].cbBuffer   = (unsigned long) conn->decryptBufferUsed;
    inBuffers[0].BufferType = SECBUFFER_TOKEN;

    inBuffers[1].pvBuffer   = NULL;
    inBuffers[1].cbBuffer   = 0;
    inBuffers[1].BufferType = SECBUFFER_EMPTY;

    inBuffer.cBuffers       = 2;
    inBuffer.pBuffers       = inBuffers;
    inBuffer.ulVersion      = SECBUFFER_VERSION;

   /*
    * Initialize these so if we fail, pvBuffer contains NULL,
    * so we don't try to free random garbage at the quit
    */
    outBuffers[0].pvBuffer   = NULL;
    outBuffers[0].BufferType = SECBUFFER_TOKEN;
    outBuffers[0].cbBuffer   = 0;

    scRet = AcceptSecurityContext(&conn->creds, (fInitContext?NULL:&conn->context),
                                  &inBuffer, dwSSPIFlags, SECURITY_NATIVE_DREP,
                                  (fInitContext?&conn->context:NULL), &outBuffer,
                                  &dwSSPIOutFlags, &tsExpiry);

    fInitContext = FALSE;

    if (scRet == SEC_E_OK              ||
        scRet == SEC_I_CONTINUE_NEEDED ||
        (FAILED(scRet) && ((dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR) != 0)))
    {
      if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
      {
       /*
        * Send response to server if there is one
        */
        num = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);

        if ((num == SOCKET_ERROR) || (num == 0))
        {
          DEBUG_printf(("_sspiAccept: handshake send failed: %d", WSAGetLastError()));
          ok = FALSE;
          goto cleanup;
        }

        DEBUG_printf(("_sspiAccept: send %d handshake bytes to client",
                     outBuffers[0].cbBuffer));

        FreeContextBuffer(outBuffers[0].pvBuffer);
        outBuffers[0].pvBuffer = NULL;
      }
    }

    if (scRet == SEC_E_OK)
    {
     /*
      * If there's extra data then save it for
      * next time we go to decrypt
      */
      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        memcpy(conn->decryptBuffer,
               (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)),
               inBuffers[1].cbBuffer);
        conn->decryptBufferUsed = inBuffers[1].cbBuffer;
      }
      else
      {
        conn->decryptBufferUsed = 0;
      }

      ok = TRUE;
      break;
    }
    else if (FAILED(scRet) && (scRet != SEC_E_INCOMPLETE_MESSAGE))
    {
      DEBUG_printf(("_sspiAccept: AcceptSecurityContext failed: %x", scRet));
      ok = FALSE;
      break;
    }

    if (scRet != SEC_E_INCOMPLETE_MESSAGE &&
        scRet != SEC_I_INCOMPLETE_CREDENTIALS)
    {
      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        memcpy(conn->decryptBuffer,
               (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)),
               inBuffers[1].cbBuffer);
        conn->decryptBufferUsed = inBuffers[1].cbBuffer;
      }
      else
      {
        conn->decryptBufferUsed = 0;
      }
    }
  }

  if (ok)
  {
    conn->contextInitialized = TRUE;

   /*
    * Find out how big the header will be:
    */
    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->streamSizes);

    if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiAccept: QueryContextAttributes failed: %x", scRet));
      ok = FALSE;
    }
  }

cleanup:

  return (ok);
}
Exemplo n.º 20
0
/*
 * '_sspiConnect()' - Make an SSL connection. This function
 *                    assumes a TCP/IP connection has already
 *                    been successfully made
 */
BOOL					/* O - 1 on success, 0 on failure */
_sspiConnect(_sspi_struct_t *conn,	/* I - Client connection */
             const CHAR *hostname)	/* I - Server hostname */
{
  PCCERT_CONTEXT	serverCert;	/* Server certificate */
  DWORD			dwSSPIFlags;	/* SSL connection attributes we want */
  DWORD			dwSSPIOutFlags;	/* SSL connection attributes we got */
  TimeStamp		tsExpiry;	/* Time stamp */
  SECURITY_STATUS	scRet;		/* Status */
  DWORD			cbData;		/* Data count */
  SecBufferDesc		inBuffer;	/* Array of SecBuffer structs */
  SecBuffer		inBuffers[2];	/* Security package buffer */
  SecBufferDesc		outBuffer;	/* Array of SecBuffer structs */
  SecBuffer		outBuffers[1];	/* Security package buffer */
  BOOL			ok = TRUE;	/* Return value */

  serverCert  = NULL;

  dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT   |
                ISC_REQ_REPLAY_DETECT     |
                ISC_REQ_CONFIDENTIALITY   |
                ISC_RET_EXTENDED_ERROR    |
                ISC_REQ_ALLOCATE_MEMORY   |
                ISC_REQ_STREAM;

 /*
  * Initiate a ClientHello message and generate a token.
  */
  outBuffers[0].pvBuffer   = NULL;
  outBuffers[0].BufferType = SECBUFFER_TOKEN;
  outBuffers[0].cbBuffer   = 0;

  outBuffer.cBuffers = 1;
  outBuffer.pBuffers = outBuffers;
  outBuffer.ulVersion = SECBUFFER_VERSION;

  scRet = InitializeSecurityContext(&conn->creds, NULL, TEXT(""), dwSSPIFlags,
                                    0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
                                    &outBuffer, &dwSSPIOutFlags, &tsExpiry);

  if (scRet != SEC_I_CONTINUE_NEEDED)
  {
    DEBUG_printf(("_sspiConnect: InitializeSecurityContext(1) failed: %x", scRet));
    ok = FALSE;
    goto cleanup;
  }

 /*
  * Send response to server if there is one.
  */
  if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
  {
    cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);

    if ((cbData == SOCKET_ERROR) || !cbData)
    {
      DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError()));
      FreeContextBuffer(outBuffers[0].pvBuffer);
      DeleteSecurityContext(&conn->context);
      ok = FALSE;
      goto cleanup;
    }

    DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData));

   /*
    * Free output buffer.
    */
    FreeContextBuffer(outBuffers[0].pvBuffer);
    outBuffers[0].pvBuffer = NULL;
  }

  dwSSPIFlags = ISC_REQ_MANUAL_CRED_VALIDATION |
	            ISC_REQ_SEQUENCE_DETECT        |
                ISC_REQ_REPLAY_DETECT          |
                ISC_REQ_CONFIDENTIALITY        |
                ISC_RET_EXTENDED_ERROR         |
                ISC_REQ_ALLOCATE_MEMORY        |
                ISC_REQ_STREAM;

  conn->decryptBufferUsed = 0;

 /*
  * Loop until the handshake is finished or an error occurs.
  */
  scRet = SEC_I_CONTINUE_NEEDED;

  while(scRet == SEC_I_CONTINUE_NEEDED        ||
        scRet == SEC_E_INCOMPLETE_MESSAGE     ||
        scRet == SEC_I_INCOMPLETE_CREDENTIALS)
  {
    if ((conn->decryptBufferUsed == 0) || (scRet == SEC_E_INCOMPLETE_MESSAGE))
    {
      if (conn->decryptBufferLength <= conn->decryptBufferUsed)
      {
        conn->decryptBufferLength += 4096;
        conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer, conn->decryptBufferLength);

        if (!conn->decryptBuffer)
        {
          DEBUG_printf(("_sspiConnect: unable to allocate %d byte decrypt buffer",
                        conn->decryptBufferLength));
          SetLastError(E_OUTOFMEMORY);
          ok = FALSE;
          goto cleanup;
        }
      }

      cbData = recv(conn->sock, conn->decryptBuffer + conn->decryptBufferUsed,
                    (int) (conn->decryptBufferLength - conn->decryptBufferUsed), 0);

      if (cbData == SOCKET_ERROR)
      {
        DEBUG_printf(("_sspiConnect: recv failed: %d", WSAGetLastError()));
        ok = FALSE;
        goto cleanup;
      }
      else if (cbData == 0)
      {
        DEBUG_printf(("_sspiConnect: server unexpectedly disconnected"));
        ok = FALSE;
        goto cleanup;
      }

      DEBUG_printf(("_sspiConnect: %d bytes of handshake data received",
                    cbData));

      conn->decryptBufferUsed += cbData;
    }

   /*
    * Set up the input buffers. Buffer 0 is used to pass in data
    * received from the server. Schannel will consume some or all
    * of this. Leftover data (if any) will be placed in buffer 1 and
    * given a buffer type of SECBUFFER_EXTRA.
    */
    inBuffers[0].pvBuffer   = conn->decryptBuffer;
    inBuffers[0].cbBuffer   = (unsigned long) conn->decryptBufferUsed;
    inBuffers[0].BufferType = SECBUFFER_TOKEN;

    inBuffers[1].pvBuffer   = NULL;
    inBuffers[1].cbBuffer   = 0;
    inBuffers[1].BufferType = SECBUFFER_EMPTY;

    inBuffer.cBuffers       = 2;
    inBuffer.pBuffers       = inBuffers;
    inBuffer.ulVersion      = SECBUFFER_VERSION;

   /*
    * Set up the output buffers. These are initialized to NULL
    * so as to make it less likely we'll attempt to free random
    * garbage later.
    */
    outBuffers[0].pvBuffer  = NULL;
    outBuffers[0].BufferType= SECBUFFER_TOKEN;
    outBuffers[0].cbBuffer  = 0;

    outBuffer.cBuffers      = 1;
    outBuffer.pBuffers      = outBuffers;
    outBuffer.ulVersion     = SECBUFFER_VERSION;

   /*
    * Call InitializeSecurityContext.
    */
    scRet = InitializeSecurityContext(&conn->creds, &conn->context, NULL, dwSSPIFlags,
                                      0, SECURITY_NATIVE_DREP, &inBuffer, 0, NULL,
                                      &outBuffer, &dwSSPIOutFlags, &tsExpiry);

   /*
    * If InitializeSecurityContext was successful (or if the error was
    * one of the special extended ones), send the contends of the output
    * buffer to the server.
    */
    if (scRet == SEC_E_OK                ||
        scRet == SEC_I_CONTINUE_NEEDED   ||
        FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
    {
      if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
      {
        cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);

        if ((cbData == SOCKET_ERROR) || !cbData)
        {
          DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError()));
          FreeContextBuffer(outBuffers[0].pvBuffer);
          DeleteSecurityContext(&conn->context);
          ok = FALSE;
          goto cleanup;
        }

        DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData));

       /*
        * Free output buffer.
        */
        FreeContextBuffer(outBuffers[0].pvBuffer);
        outBuffers[0].pvBuffer = NULL;
      }
    }

   /*
    * If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE,
    * then we need to read more data from the server and try again.
    */
    if (scRet == SEC_E_INCOMPLETE_MESSAGE)
      continue;

   /*
    * If InitializeSecurityContext returned SEC_E_OK, then the
    * handshake completed successfully.
    */
    if (scRet == SEC_E_OK)
    {
     /*
      * If the "extra" buffer contains data, this is encrypted application
      * protocol layer stuff. It needs to be saved. The application layer
      * will later decrypt it with DecryptMessage.
      */
      DEBUG_printf(("_sspiConnect: Handshake was successful"));

      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        if (conn->decryptBufferLength < inBuffers[1].cbBuffer)
        {
          conn->decryptBuffer = realloc(conn->decryptBuffer, inBuffers[1].cbBuffer);

          if (!conn->decryptBuffer)
          {
            DEBUG_printf(("_sspiConnect: unable to allocate %d bytes for decrypt buffer",
                          inBuffers[1].cbBuffer));
            SetLastError(E_OUTOFMEMORY);
            ok = FALSE;
            goto cleanup;
          }
        }

        memmove(conn->decryptBuffer,
                conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer),
                inBuffers[1].cbBuffer);

        conn->decryptBufferUsed = inBuffers[1].cbBuffer;

        DEBUG_printf(("_sspiConnect: %d bytes of app data was bundled with handshake data",
                      conn->decryptBufferUsed));
      }
      else
        conn->decryptBufferUsed = 0;

     /*
      * Bail out to quit
      */
      break;
    }

   /*
    * Check for fatal error.
    */
    if (FAILED(scRet))
    {
      DEBUG_printf(("_sspiConnect: InitializeSecurityContext(2) failed: %x", scRet));
      ok = FALSE;
      break;
    }

   /*
    * If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS,
    * then the server just requested client authentication.
    */
    if (scRet == SEC_I_INCOMPLETE_CREDENTIALS)
    {
     /*
      * Unimplemented
      */
      DEBUG_printf(("_sspiConnect: server requested client credentials"));
      ok = FALSE;
      break;
    }

   /*
    * Copy any leftover data from the "extra" buffer, and go around
    * again.
    */
    if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
    {
      memmove(conn->decryptBuffer,
              conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer),
              inBuffers[1].cbBuffer);

      conn->decryptBufferUsed = inBuffers[1].cbBuffer;
    }
    else
    {
      conn->decryptBufferUsed = 0;
    }
  }

  if (ok)
  {
    conn->contextInitialized = TRUE;

   /*
    * Get the server cert
    */
    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (VOID*) &serverCert );

    if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_REMOTE_CERT_CONTEXT): %x", scRet));
      ok = FALSE;
      goto cleanup;
    }

    scRet = sspi_verify_certificate(serverCert, hostname, conn->certFlags);

    if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiConnect: sspi_verify_certificate failed: %x", scRet));
      ok = FALSE;
      goto cleanup;
    }

   /*
    * Find out how big the header/trailer will be:
    */
    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->streamSizes);

    if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_STREAM_SIZES): %x", scRet));
      ok = FALSE;
    }
  }

cleanup:

  if (serverCert)
    CertFreeCertificateContext(serverCert);

  return (ok);
}
Exemplo n.º 21
0
static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags)
{
  SECURITY_STATUS e;
  ULONG a;
  TimeStamp t;
  SecBuffer ibuf[2],obuf[1];
  SecBufferDesc ibufs,obufs;
  SCHANNEL_CRED tlscred;
  CERT_CONTEXT *cert;
  CERT_CHAIN_PARA chparam;
  CERT_CHAIN_CONTEXT *chain;
  SSL_EXTRA_CERT_CHAIN_POLICY_PARA policy;
  CERT_CHAIN_POLICY_PARA polparam;
  CERT_CHAIN_POLICY_STATUS status;
  char tmp[MAILTMPLEN],certname[256];
  char *reason = NIL;
  ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
    ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY |
      ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR |
	ISC_REQ_MANUAL_CRED_VALIDATION;
  LPSTR usage[] = {
    szOID_PKIX_KP_SERVER_AUTH,
    szOID_SERVER_GATED_CRYPTO,
    szOID_SGC_NETSCAPE
  };
  PWSTR whost = NIL;
  char *buf = (char *) fs_get (ssltsz);
  unsigned long size = 0;
  sslcertificatequery_t scq =
    (sslcertificatequery_t) mail_parameters (NIL,GET_SSLCERTIFICATEQUERY,NIL);
  sslfailure_t sf = (sslfailure_t) mail_parameters (NIL,GET_SSLFAILURE,NIL);
  SSLSTREAM *stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0,
					    sizeof (SSLSTREAM));
  stream->tcpstream = tstream;	/* bind TCP stream */
				/* initialize TLS credential */
  memset (&tlscred,0,sizeof (SCHANNEL_CRED));
  tlscred.dwVersion = SCHANNEL_CRED_VERSION;
  tlscred.grbitEnabledProtocols = SP_PROT_TLS1;

				/* acquire credentials */
  if (AcquireCredentialsHandle
      (NIL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NIL,(flags & NET_TLSCLIENT) ?
       &tlscred : NIL,NIL,NIL,&stream->cred,&t)
      != SEC_E_OK) reason = "Acquire credentials handle failed";
  else while (!reason) {	/* negotiate security context */
				/* initialize buffers */
    ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = buf;
    ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NIL;
    obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL;
    ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
    ibuf[1].BufferType = SECBUFFER_EMPTY;
				/* initialize buffer descriptors */
    ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
    ibufs.cBuffers = 2; obufs.cBuffers = 1;
    ibufs.pBuffers = ibuf; obufs.pBuffers = obuf;
				/* negotiate security */
    e = InitializeSecurityContext
      (&stream->cred,size ? &stream->context : NIL,host,req,0,
       SECURITY_NETWORK_DREP,size? &ibufs:NIL,0,&stream->context,&obufs,&a,&t);
				/* have an output buffer we need to send? */
    if (obuf[0].pvBuffer && obuf[0].cbBuffer) {
      if (!tcp_sout (stream->tcpstream,obuf[0].pvBuffer,obuf[0].cbBuffer))
	reason = "Unexpected TCP output disconnect";
				/* free the buffer */
      FreeContextBuffer (obuf[0].pvBuffer);
    }
    if (!reason) switch (e) {	/* negotiation state */
    case SEC_I_INCOMPLETE_CREDENTIALS:
      break;			/* server wants client auth */
    case SEC_I_CONTINUE_NEEDED:
      if (size) {		/* continue, read any data? */
				/* yes, anything regurgiated back to us? */
	if (ibuf[1].BufferType == SECBUFFER_EXTRA) {
				/* yes, set this as the new data */
	  memmove (buf,buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);
	  size = ibuf[1].cbBuffer;
	  break;
	}
	size = 0;		/* otherwise, read more stuff from server */
      }
    case SEC_E_INCOMPLETE_MESSAGE:
				/* need to read more data from server */
      if (!tcp_getdata (stream->tcpstream))
	reason = "Unexpected TCP input disconnect";
      else {
	memcpy (buf+size,stream->tcpstream->iptr,stream->tcpstream->ictr);
	size += stream->tcpstream->ictr;
				/* empty it from TCP's buffers */
	stream->tcpstream->iptr += stream->tcpstream->ictr;
	stream->tcpstream->ictr = 0;
      }
      break;

    case SEC_E_OK:		/* success, any data to be regurgitated? */
      if (ibuf[1].BufferType == SECBUFFER_EXTRA) {
				/* yes, set this as the new data */
	memmove (stream->tcpstream->iptr = stream->tcpstream->ibuf,
		 buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);
	stream->tcpstream->ictr = ibuf[1].cbBuffer;
      }
      if (!(flags & NET_NOVALIDATECERT)) {
				/* need validation, make wchar of host */
	if (!((size = MultiByteToWideChar (CP_ACP,0,host,-1,NIL,0)) &&
	      (whost = (PWSTR) fs_get (size*sizeof (WCHAR))) &&
	      MultiByteToWideChar (CP_ACP,0,host,-1,whost,size)))
	  fatal ("Can't make wchar of host name!");
				/* get certificate */
	if ((QueryContextAttributes
	     (&stream->context,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&cert) !=
	     SEC_E_OK) || !cert) {
	  reason = "*Unable to get certificate";
	  strcpy (certname,"<no certificate>");
	}
	else {			/* get certificate subject name */
	  CertNameToStr (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
			 &cert->pCertInfo->Subject,CERT_X500_NAME_STR,
			 certname,255);
				/* build certificate chain */
	  memset (&chparam,0,sizeof (chparam));
	  chparam.cbSize = sizeof (chparam);
	  chparam.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
	  chparam.RequestedUsage.Usage.rgpszUsageIdentifier = usage;
	  chparam.RequestedUsage.Usage.cUsageIdentifier =
	    sizeof (usage) / sizeof (LPSTR);
	  if (!CertGetCertificateChain
	      (NIL,cert,NIL,cert->hCertStore,&chparam,NIL,NIL,&chain))
	    reason = ssl_analyze_status (GetLastError (),tmp);
	  else {		/* validate certificate chain */
	    memset (&policy,0,sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA));
	    policy.cbStruct = sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA);
	    policy.dwAuthType = AUTHTYPE_SERVER;
	    policy.fdwChecks = NIL;
	    policy.pwszServerName = whost;
	    memset (&polparam,0,sizeof (polparam));
	    polparam.cbSize = sizeof (polparam);
	    polparam.pvExtraPolicyPara = &policy;
	    memset (&status,0,sizeof (status));
	    status.cbSize = sizeof (status);
	    if (!CertVerifyCertificateChainPolicy
		(CERT_CHAIN_POLICY_SSL,chain,&polparam,&status))
	      reason = ssl_analyze_status (GetLastError (),tmp);
	    else if (status.dwError)
	      reason = ssl_analyze_status (status.dwError,tmp);
	    CertFreeCertificateChain (chain);
	  }
	}
	if (whost) fs_give ((void **) &whost);

	if (reason) {		/* got an error? */
				/* application callback */
	  if (scq) reason = (*scq) ((*reason == '*') ? reason + 1 : reason,
				    host,certname) ? NIL : "";
	  else if (*certname) {	/* error message to return via mm_log() */
	    sprintf (buf,"*%.128s: %.255s",
		     (*reason == '*') ? reason + 1 : reason,certname);
	    reason = buf;
	  }
	}
      }
      if (reason ||
	  (reason = ssl_analyze_status
	   (QueryContextAttributes
	    (&stream->context,SECPKG_ATTR_STREAM_SIZES,&stream->sizes),buf)))
	break;			/* error in certificate or getting sizes */
      fs_give ((void **) &buf);	/* flush temporary buffer */
				/* make maximum-sized buffers */
      stream->bufsize = stream->sizes.cbHeader +
	stream->sizes.cbMaximumMessage + stream->sizes.cbTrailer;
      if (stream->sizes.cbMaximumMessage < SSLBUFLEN)
	fatal ("cbMaximumMessage is less than SSLBUFLEN!");
      else if (stream->sizes.cbMaximumMessage < 16384) {
	sprintf (tmp,"WINDOWS BUG: cbMaximumMessage = %ld, should be 16384",
		 (long) stream->sizes.cbMaximumMessage);
	mm_log (tmp,NIL);
      }
      stream->ibuf = (char *) fs_get (stream->bufsize);
      stream->obuf = (char *) fs_get (stream->bufsize);
      return stream;
    default:
      reason = ssl_analyze_status (e,buf);
    }
  }
  ssl_close (stream);		/* failed to do SSL */
  stream = NIL;			/* no stream returned */
  switch (*reason) {		/* analyze reason */
  case '*':			/* certificate failure */
    ++reason;			/* skip over certificate failure indication */
				/* pass to error callback */
    if (sf) (*sf) (host,reason,flags);
    else {			/* no error callback, build error message */
      sprintf (tmp,"Certificate failure for %.80s: %.512s",host,reason);
      mm_log (tmp,ERROR);
    }
  case '\0':			/* user answered no to certificate callback */
    if (flags & NET_TRYSSL)	/* return dummy stream to stop tryssl */
      stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0,
				     sizeof (SSLSTREAM));
    break;
  default:			/* non-certificate failure */
    if (flags & NET_TRYSSL);	/* no error output if tryssl */
				/* pass to error callback */
    else if (sf) (*sf) (host,reason,flags);
    else {			/* no error callback, build error message */
      sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason);
      mm_log (tmp,ERROR);
    }
    break;
  }
  fs_give ((void **) &buf);	/* flush temporary buffer */
  return stream;
}
Exemplo n.º 22
0
int SSL_SOCKET :: s_ssend(char* b,int sz)
	{
	// QueryContextAttributes
	// Encrypt Message
	// ssend

	SecPkgContext_StreamSizes Sizes;
	SECURITY_STATUS ss = 0;
	ss = QueryContextAttributes(&hCtx,SECPKG_ATTR_STREAM_SIZES,&Sizes);
	if (FAILED(ss))
		return -1;

	Z<SecBuffer> Buffers(100);
	int mPos = 0;
	for(;;)
		{
		Z<char> mmsg(Sizes.cbMaximumMessage*2);
		Z<char> mhdr(Sizes.cbHeader*2);
		Z<char> mtrl(Sizes.cbTrailer*2);

		unsigned int dwMessage = sz - mPos;
		if (dwMessage == 0)
			break; // all ok!

		if (dwMessage > Sizes.cbMaximumMessage)
			{
			dwMessage = Sizes.cbMaximumMessage;
			}
		memcpy(mmsg,b + mPos,dwMessage);
		mPos += dwMessage;


		Buffers[0].pvBuffer     = mhdr;
		Buffers[0].cbBuffer     = Sizes.cbHeader;
		Buffers[0].BufferType   = SECBUFFER_STREAM_HEADER;
		Buffers[2].pvBuffer     = mtrl;
		Buffers[2].cbBuffer     = Sizes.cbTrailer;
		Buffers[2].BufferType   = SECBUFFER_STREAM_TRAILER;
		Buffers[3].pvBuffer     = 0;
		Buffers[3].cbBuffer     = 0;
		Buffers[3].BufferType   = SECBUFFER_EMPTY;
		Buffers[1].pvBuffer     = mmsg;
		Buffers[1].cbBuffer     = dwMessage;
		Buffers[1].BufferType   = SECBUFFER_DATA;

		sbin.ulVersion = SECBUFFER_VERSION;
		sbin.pBuffers = Buffers;
		sbin.cBuffers = 4;

		ss = EncryptMessage(&hCtx,0,&sbin,0);
		if (FAILED(ss))
			return -1;


		// Send this message
		int rval;
		rval = ssend_p((char*)Buffers[0].pvBuffer,Buffers[0].cbBuffer);
		if (rval != Buffers[0].cbBuffer)
			return rval;
		rval = ssend_p((char*)Buffers[1].pvBuffer,Buffers[1].cbBuffer);
		if (rval != Buffers[1].cbBuffer)
			return rval;
		rval = ssend_p((char*)Buffers[2].pvBuffer,Buffers[2].cbBuffer);
		if (rval != Buffers[2].cbBuffer)
			return rval;
		}

	return sz;
	}
Exemplo n.º 23
0
my_bool ma_tls_connect(MARIADB_TLS *ctls)
{
  my_bool blocking;
  MYSQL *mysql;
  SCHANNEL_CRED Cred;
  MARIADB_PVIO *pvio;
  my_bool rc= 1;
  SC_CTX *sctx;
  SECURITY_STATUS sRet;
  PCCERT_CONTEXT pRemoteCertContext = NULL,
                 pLocalCertContext= NULL;
  ALG_ID AlgId[MAX_ALG_ID]= {0};
  
  if (!ctls || !ctls->pvio)
    return 1;;
  
  pvio= ctls->pvio;
  sctx= (SC_CTX *)ctls->ssl;

  /* Set socket to blocking if not already set */
  if (!(blocking= pvio->methods->is_blocking(pvio)))
    pvio->methods->blocking(pvio, TRUE, 0);

  mysql= pvio->mysql;
 
  if (ma_tls_set_client_certs(ctls))
    goto end;

  ZeroMemory(&Cred, sizeof(SCHANNEL_CRED));

  /* Set cipher */
  if (mysql->options.ssl_cipher)
  {
    WORD validTokens = 0;
    char *token = strtok(mysql->options.ssl_cipher, ":");
    while (token)
    {
      struct st_cipher_suite *valid;
      for (valid = valid_ciphers; valid && valid->aid; valid++)
      {
        if (!strcmp(token, valid->cipher))
        {
          AlgId[validTokens++] = valid->aid;
          break;
        }
      }
      token = strtok(NULL, ":");
    }
  }
  Cred.palgSupportedAlgs = (ALG_ID *)&AlgId;
  
  Cred.dwVersion= SCHANNEL_CRED_VERSION;
  if (mysql->options.extension)
    Cred.dwMinimumCipherStrength = MAX(128, mysql->options.extension->tls_cipher_strength);
  else
    Cred.dwMinimumCipherStrength = 128;
  Cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK | SCH_SEND_ROOT_CERT |
    SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION;
  if (sctx->client_cert_ctx)
  {
    Cred.cCreds = 1;
    Cred.paCred = &sctx->client_cert_ctx;
  }
  if (mysql->options.extension && mysql->options.extension->tls_version)
  {
    Cred.grbitEnabledProtocols= 0;
    if (strstr("TLSv1.0", mysql->options.extension->tls_version))
      Cred.grbitEnabledProtocols|= SP_PROT_TLS1_0;
    if (strstr("TLSv1.1", mysql->options.extension->tls_version))
      Cred.grbitEnabledProtocols|= SP_PROT_TLS1_1;
    if (strstr("TLSv1.2", mysql->options.extension->tls_version))
      Cred.grbitEnabledProtocols|= SP_PROT_TLS1_2;
  }
  else
    Cred.grbitEnabledProtocols = SP_PROT_TLS1_0 |
                                 SP_PROT_TLS1_1 |
                                 SP_PROT_TLS1_2;

  if ((sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
                                       NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL)) != SEC_E_OK)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    goto end;
  }
  sctx->FreeCredHdl= 1;

  if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
    goto end;

  sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext);
  if (sRet != SEC_E_OK)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    goto end;
  }
  
  if (!ma_schannel_verify_certs(sctx, 0))
    goto end;
 
  return 0;

end:
  if (pRemoteCertContext)
    CertFreeCertificateContext(pRemoteCertContext);
  if (rc && sctx->IoBufferSize)
    LocalFree(sctx->IoBuffer);
  sctx->IoBufferSize= 0;
  if (sctx->client_cert_ctx)
    CertFreeCertificateContext(sctx->client_cert_ctx);
  sctx->client_cert_ctx= 0;
  return 1;
}
Exemplo n.º 24
0
int SSL_SOCKET :: s_recv(char* b,int sz)
	{
	SecPkgContext_StreamSizes Sizes;
	SECURITY_STATUS ss = 0;
	ss = QueryContextAttributes(&hCtx,SECPKG_ATTR_STREAM_SIZES,&Sizes);
	if (FAILED(ss))
		return -1;

	int TotalR = 0;
	int pI = 0;
	SecBuffer Buffers[5] = {0};
	SecBuffer *     pDataBuffer;
	SecBuffer *     pExtraBuffer;
	Z<char> mmsg(Sizes.cbMaximumMessage*10);


	if (PendingRecvDataSize)
		{
		if (sz <= PendingRecvDataSize)
			{
			memcpy(b,PendingRecvData,sz);
			
			// 
			Z<char> dj(PendingRecvDataSize);
			memcpy(dj,PendingRecvData,PendingRecvDataSize);
			memcpy(PendingRecvData,dj + sz,PendingRecvDataSize - sz);
			PendingRecvDataSize -= sz;
			return sz;
			}
		// else , occupied already
		memcpy(b,PendingRecvData,PendingRecvDataSize);
		sz = PendingRecvDataSize;
		PendingRecvDataSize = 0;
		return sz;
		}

	for(;;)
		{
		unsigned int dwMessage = Sizes.cbMaximumMessage;
		
		if (dwMessage > Sizes.cbMaximumMessage)
			dwMessage = Sizes.cbMaximumMessage;

		int rval = 0;
		if (ExtraDataSize)
			{
			memcpy(mmsg + pI,ExtraData,ExtraDataSize);
			pI += ExtraDataSize;
			ExtraDataSize = 0;
			}
		else
			{
			rval = recv_p(mmsg + pI,dwMessage);
			if (rval == 0 || rval == -1)
				return rval;
			pI += rval;
			}


		Buffers[0].pvBuffer     = mmsg;
		Buffers[0].cbBuffer     = pI;
		Buffers[0].BufferType   = SECBUFFER_DATA;

		Buffers[1].BufferType   = SECBUFFER_EMPTY;
		Buffers[2].BufferType   = SECBUFFER_EMPTY;
		Buffers[3].BufferType   = SECBUFFER_EMPTY;

		sbin.ulVersion = SECBUFFER_VERSION;
		sbin.pBuffers = Buffers;
		sbin.cBuffers = 4;

		ss = DecryptMessage(&hCtx,&sbin,0,NULL);
		if (ss == SEC_E_INCOMPLETE_MESSAGE)
			continue;
		if (ss != SEC_E_OK && ss != SEC_I_RENEGOTIATE && ss != SEC_I_CONTEXT_EXPIRED)
			return -1;

		pDataBuffer  = NULL;
		pExtraBuffer = NULL;
		for (int i = 0; i < 4; i++) 
			{
			if (pDataBuffer == NULL && Buffers[i].BufferType == SECBUFFER_DATA) 
				{
				pDataBuffer = &Buffers[i];
				}
			if (pExtraBuffer == NULL && Buffers[i].BufferType == SECBUFFER_EXTRA) 
				{
				pExtraBuffer = &Buffers[i];
				}
			}
		if (pExtraBuffer)
			{
			ExtraDataSize = pExtraBuffer->cbBuffer;
			ExtraData.Resize(ExtraDataSize + 10);
			memcpy(ExtraData,pExtraBuffer->pvBuffer,ExtraDataSize);
			pI = 0;
			}

		if (ss == SEC_I_RENEGOTIATE)
			{
			ss = ClientLoop();
			if (FAILED(ss))
				return -1;
			}

	

		if (pDataBuffer == 0)
			break;

		TotalR = pDataBuffer->cbBuffer;
		if (TotalR <= sz)
			{
			memcpy(b,pDataBuffer->pvBuffer,TotalR);
			}
		else
			{
			TotalR = sz;
			memcpy(b,pDataBuffer->pvBuffer,TotalR);
			PendingRecvDataSize = pDataBuffer->cbBuffer - TotalR;
			PendingRecvData.Resize(PendingRecvDataSize + 100);
			PendingRecvData.clear();
			memcpy(PendingRecvData,(char*)pDataBuffer->pvBuffer + TotalR,PendingRecvDataSize);
			}


		break;
		}



	return TotalR;
	}
Exemplo n.º 25
0
static
DWORD
SignServer(
    IN INT nSocket,
    IN CredHandle *pServerCreds,
    IN ULONG AscFlags
    )
{
    DWORD dwError = ERROR_SUCCESS;
    ULONG ulQop = 0;
    INT nContextAcquired = 0;
    ULONG nIndex = 0;
    SecBuffer TransmitBuffer;
    SecBuffer MsgBuffer;
    SecBuffer WrapBuffers[2] = {0};
    SecBufferDesc WrapBufferDesc;
    CtxtHandle Context;
    SecPkgContext_Names Names;
    SecPkgContext_Sizes Sizes;
    SecPkgContext_SessionKey SessionKey;

    memset(&TransmitBuffer, 0, sizeof(SecBuffer));
    memset(&MsgBuffer, 0, sizeof(SecBuffer));
    memset(&WrapBufferDesc, 0, sizeof(SecBufferDesc));
    memset(&Context, 0, sizeof(CtxtHandle));
    memset(&Names, 0, sizeof(SecPkgContext_Names));
    memset(&Sizes, 0, sizeof(SecPkgContext_Sizes));
    memset(&SessionKey, 0, sizeof(SecPkgContext_SessionKey));

    /* Establish a context with the client */
    dwError = ServerEstablishContext(
        nSocket,
        pServerCreds,
        &Context,
        AscFlags
        );

    BAIL_ON_ERROR(dwError);

    dwError = QueryContextAttributes(
        &Context,
        SECPKG_ATTR_NAMES,
        &Names
        );

    if (dwError)
    {
        printf("Unable to query context: %d\n", dwError);
    }
    else
    {
        printf("Context is for user: %s\n", Names.sUserName);
    }

    dwError = QueryContextAttributes(
        &Context,
        SECPKG_ATTR_SESSION_KEY,
        &SessionKey
        );

    if (dwError)
    {
        printf("Unable to query context: %X\n", dwError);
    }
    else
    {
        printf("Session Key: ");
        for(nIndex = 0; nIndex < SessionKey.SessionKeyLength; nIndex++)
        {
            printf("%02X ", SessionKey.SessionKey[nIndex]);
        }
        printf("\n\n");
    }

    printf("Server accepted context successfully!\n");

    // for clean up... once we've established a context, we must clean it up on
    // future failures.
    nContextAcquired = 1;

    dwError = QueryContextAttributes
        (
        &Context,
        SECPKG_ATTR_SIZES,
        &Sizes
        );

    BAIL_ON_ERROR(dwError);

    /* Receive the sealed message token */
    dwError = RecvToken(nSocket, &TransmitBuffer);
    BAIL_ON_ERROR(dwError);

    printf("RECEIVED:\n");
    DumpBuffer(TransmitBuffer.pvBuffer, TransmitBuffer.cbBuffer);
    printf("\n");

    WrapBufferDesc.cBuffers = 2;
    WrapBufferDesc.pBuffers = WrapBuffers;
    WrapBufferDesc.ulVersion = SECBUFFER_VERSION;

    WrapBuffers[0].BufferType = SECBUFFER_TOKEN;
    WrapBuffers[0].pvBuffer = TransmitBuffer.pvBuffer;
    WrapBuffers[0].cbBuffer = Sizes.cbMaxSignature;

    WrapBuffers[1].BufferType = SECBUFFER_DATA;
    WrapBuffers[1].cbBuffer = TransmitBuffer.cbBuffer - Sizes.cbMaxSignature;
    WrapBuffers[1].pvBuffer = (PBYTE)TransmitBuffer.pvBuffer + Sizes.cbMaxSignature;

    dwError = DecryptMessage(
        &Context,
        &WrapBufferDesc,
        0,                  // no sequence number
        &ulQop
        );

    if (dwError)
    {
        // When we bail, this var will try to be freed which is a bad thing...
        // the memory will be freed when TransmitBuffer is freed, so it's ok
        // to set this buffer to NULL here.
        WrapBuffers[1].pvBuffer = NULL;
        printf("Unable to decrypt message\n");
    }

    BAIL_ON_ERROR(dwError);

    MsgBuffer = WrapBuffers[1];

    printf("Received message '%.*s' from client\n", MsgBuffer.cbBuffer, MsgBuffer.pvBuffer);

    /* Produce a signature block for the message */

    WrapBuffers[0] = MsgBuffer;

    WrapBuffers[1].BufferType = SECBUFFER_TOKEN;
    WrapBuffers[1].cbBuffer = Sizes.cbMaxSignature;
    WrapBuffers[1].pvBuffer = malloc(Sizes.cbMaxSignature);

    if (WrapBuffers[1].pvBuffer == NULL)
    {
        dwError = ERROR_NOT_ENOUGH_MEMORY;
        BAIL_ON_ERROR(dwError);
    }

    dwError = MakeSignature(
        &Context,
        0,
        &WrapBufferDesc,
        0
        );

    if (dwError)
    {
        printf("Unable to MakeSignature");
    }

    BAIL_ON_ERROR(dwError);

    free(TransmitBuffer.pvBuffer);

    TransmitBuffer = WrapBuffers[1];
    WrapBuffers[1].pvBuffer = NULL;
    WrapBuffers[1].cbBuffer = 0;

    /* Send the signature block to the client */

    dwError = SendToken(nSocket, &TransmitBuffer);
    BAIL_ON_ERROR(dwError);

    free(TransmitBuffer.pvBuffer);
    TransmitBuffer.pvBuffer = NULL;
    TransmitBuffer.cbBuffer = 0;

    /* Delete context */

    dwError = DeleteSecurityContext( &Context );
    BAIL_ON_ERROR(dwError);

finish:
    return dwError;
error:
    if (Names.sUserName)
    {
        FreeContextBuffer(Names.sUserName);
    }
    if (TransmitBuffer.pvBuffer)
    {
        free(TransmitBuffer.pvBuffer);
        TransmitBuffer.pvBuffer = NULL;
        TransmitBuffer.cbBuffer = 0;
    }
    if (WrapBuffers[1].pvBuffer)
    {
        free(WrapBuffers[1].pvBuffer);
        WrapBuffers[1].pvBuffer = NULL;
        WrapBuffers[1].cbBuffer = 0;
    }
    if (nContextAcquired)
    {
        DeleteSecurityContext(&Context);
    }
    goto finish;
}
Exemplo n.º 26
0
int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
{
  SC_CTX *sctx= (SC_CTX *)ctls->ssl;
  MARIADB_PVIO *pvio= ctls->pvio;
  int rc= 1;
  char *szName= NULL;
  char *pszServerName= pvio->mysql->host;

  /* check server name */
  if (pszServerName && (sctx->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
  {
    PCCERT_CONTEXT pServerCert;
    DWORD NameSize= 0;
    char *p1, *p2;
    SECURITY_STATUS sRet;

    if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
    {
      ma_schannel_set_sec_error(pvio, sRet);
      return 1;
    }

    if (!(NameSize= CertNameToStr(pServerCert->dwCertEncodingType,
      &pServerCert->pCertInfo->Subject,
      CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
      NULL, 0)))
    {
      pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Can't retrieve name of server certificate");
      return 1;
    }

    if (!(szName= (char *)LocalAlloc(0, NameSize + 1)))
    {
      pvio->set_error(sctx->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
      goto end;
    }

    if (!CertNameToStr(pServerCert->dwCertEncodingType,
      &pServerCert->pCertInfo->Subject,
      CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
      szName, NameSize))
    {
      pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Can't retrieve name of server certificate");
      goto end;
    }
    if ((p1 = strstr(szName, "CN=")))
    {
      p1+= 3;
      if ((p2= strstr(p1, ", ")))
        *p2= 0;
      if (!strcmp(pszServerName, p1))
      {
        rc= 0;
        goto end;
      }
      pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
                     "Name of server certificate didn't match");
    }
  }
end:
  if (szName)
    LocalFree(szName);
  return rc;
}
Exemplo n.º 27
0
int sserver_auth_protocol_connect(const struct protocol_interface *protocol, const char *auth_string)
{
	CScramble scramble;
	char *tmp;
	int certonly;
	char *client_version = NULL;
	char keyfile[256];
	const char *hostname = NULL;

    if (!strcmp (auth_string, "BEGIN SSL VERIFICATION REQUEST"))
		sserver_protocol_interface.verify_only = 1;
    else if (!strcmp (auth_string, "BEGIN SSL AUTH REQUEST"))
		sserver_protocol_interface.verify_only = 0;
	else
		return CVSPROTO_NOTME;

	write(current_server()->out_fd,SSERVER_INIT_STRING,sizeof(SSERVER_INIT_STRING)-1);

	if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CertificatesOnly",keyfile,sizeof(keyfile)))
		certonly = atoi(keyfile);
	if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","ServerDnsName",keyfile,sizeof(keyfile)))
		hostname = keyfile;

	if(!ServerAuthenticate(hostname))
		return CVSPROTO_AUTHFAIL;

	QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes);

	g_sslBufferInPos=g_sslBufferOutPos=0;
	g_sslBufferInLen=g_sslBufferOutLen=0;

    set_encrypted_channel(1); /* Error must go through us now */

	PCERT_CONTEXT sc;
	PCCERT_CHAIN_CONTEXT pcc;
	CERT_SIMPLE_CHAIN  *psc;
	CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) };
	DWORD trust,rc;
	BOOL cert = FALSE;
	
	rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc);
	if(rc && rc!=SEC_E_NO_CREDENTIALS)
		server_error(1,"Couldn't get client certificate");

	if(rc!=SEC_E_NO_CREDENTIALS) /* The client doesn't have to send us a cert. as cvs uses passwords normally */
	{
		if(!CertGetCertificateChain(NULL, sc, NULL, NULL, &para, 0, NULL, &pcc))
			server_error(1,"Couldn't get client certificate chain");

		psc = pcc->rgpChain[0];
		trust = psc->TrustStatus.dwErrorStatus;
	 
		if (trust)
		{
			if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT))
				server_error(1,"Client sent self signed certificate");
			else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID))
				server_error(1,"Client certificate expired");
			else
				server_error(1,"Client certificate verification failed - %08x",trust);
		}

		CertFreeCertificateChain(pcc);
		FreeContextBuffer(sc);

		cert = TRUE;
	}
 
    /* Get the three important pieces of information in order. */
    /* See above comment about error handling.  */

	/* get version, if sent.  1.0 clients didn't have this handshake so we have to handle that. */
	server_getline (protocol, &client_version, MAX_PATH);
	if(strncmp(client_version,"SSERVER-CLIENT ",15))
	{
		sserver_protocol_interface.auth_repository = client_version;
		client_version = NULL;
	}
	else
    	server_getline (protocol, &sserver_protocol_interface.auth_repository, MAX_PATH);
    server_getline (protocol, &sserver_protocol_interface.auth_username, MAX_PATH);
	server_getline (protocol, &sserver_protocol_interface.auth_password, MAX_PATH);

	if(client_version) free(client_version);
	client_version = NULL;

    /* ... and make sure the protocol ends on the right foot. */
    /* See above comment about error handling.  */
    server_getline(protocol, &tmp, MAX_PATH);
    if (strcmp (tmp,
		sserver_protocol_interface.verify_only ?
		"END SSL VERIFICATION REQUEST" : "END SSL AUTH REQUEST")
	!= 0)
    {
		server_printf ("bad auth protocol end: %s\n", tmp);
		free(tmp);
		return CVSPROTO_FAIL;
    }

	strcpy(sserver_protocol_interface.auth_password, scramble.Unscramble(sserver_protocol_interface.auth_password));

	free(tmp);

	switch(certonly)
	{
	case 0:
		break;
	case 1:
		if(!cert)
		{
			server_error(0,"E Login requires a valid client certificate.\n");
			return CVSPROTO_AUTHFAIL;
		}
		free(sserver_protocol_interface.auth_password);
		sserver_protocol_interface.auth_password = NULL;
		break;
	case 2:
		if(!cert)
		{
			server_error(0,"E Login requires a valid client certificate.\n");
			return CVSPROTO_AUTHFAIL;
		}
		break;
	};

	return CVSPROTO_SUCCESS;
}
Exemplo n.º 28
0
char* CompleteGssapi(HANDLE hSecurity, unsigned char *szChallenge, unsigned chlsz)
{
	if (!szChallenge || !szChallenge[0]) return NULL;

	NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity;
	unsigned char inDataBuffer[1024];

	SecBuffer inBuffers[2] =
	{
		{ sizeof(inDataBuffer), SECBUFFER_DATA, inDataBuffer },
		{ chlsz, SECBUFFER_STREAM, szChallenge }
	};

	SecBufferDesc inBuffersDesc = { SECBUFFER_VERSION, 2, inBuffers };

	unsigned long qop = 0;
	SECURITY_STATUS sc = DecryptMessage(&hNtlm->hClientContext, &inBuffersDesc, 0, &qop);
	if (sc != SEC_E_OK) {
		ReportSecError(sc, __LINE__);
		return NULL;
	}

	// unsigned char LayerMask = inDataBuffer[0];
	// unsigned int MaxMessageSize = htonl(*(unsigned*)&inDataBuffer[1]);

	SecPkgContext_Sizes sizes;
	sc = QueryContextAttributes(&hNtlm->hClientContext, SECPKG_ATTR_SIZES, &sizes);
	if (sc != SEC_E_OK) {
		ReportSecError(sc, __LINE__);
		return NULL;
	}

	unsigned char *tokenBuffer = (unsigned char*)alloca(sizes.cbSecurityTrailer);
	unsigned char *paddingBuffer = (unsigned char*)alloca(sizes.cbBlockSize);

	unsigned char outDataBuffer[4] = { 1, 0, 16, 0 };

	SecBuffer outBuffers[3] =
	{
		{ sizes.cbSecurityTrailer, SECBUFFER_TOKEN, tokenBuffer },
		{ sizeof(outDataBuffer), SECBUFFER_DATA, outDataBuffer },
		{ sizes.cbBlockSize, SECBUFFER_PADDING, paddingBuffer }
	};
	SecBufferDesc outBuffersDesc = { SECBUFFER_VERSION, 3, outBuffers };

	sc = EncryptMessage(&hNtlm->hClientContext, SECQOP_WRAP_NO_ENCRYPT, &outBuffersDesc, 0);
	if (sc != SEC_E_OK) {
		ReportSecError(sc, __LINE__);
		return NULL;
	}

	unsigned i, ressz = 0;
	for (i = 0; i < outBuffersDesc.cBuffers; i++)
		ressz += outBuffersDesc.pBuffers[i].cbBuffer;

	unsigned char *response = (unsigned char*)alloca(ressz), *p = response;
	for (i = 0; i < outBuffersDesc.cBuffers; i++) {
		memcpy(p, outBuffersDesc.pBuffers[i].pvBuffer, outBuffersDesc.pBuffers[i].cbBuffer);
		p += outBuffersDesc.pBuffers[i].cbBuffer;
	}

	return mir_base64_encode(response, ressz);
}
Exemplo n.º 29
0
static int send_chunk(CONCRETE_IO_HANDLE tls_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
{
    int result;

    if ((tls_io == NULL) ||
        (buffer == NULL) ||
        (size == 0))
    {
        /* Invalid arguments */
        result = __LINE__;
    }
    else
    {
        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
        if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
        {
            result = __LINE__;
        }
        else
        {
            SecPkgContext_StreamSizes  sizes;
            SECURITY_STATUS status = QueryContextAttributes(&tls_io_instance->security_context, SECPKG_ATTR_STREAM_SIZES, &sizes);
            if (status != SEC_E_OK)
            {
                result = __LINE__;
            }
            else
            {
                SecBuffer security_buffers[4];
                SecBufferDesc security_buffers_desc;
                size_t needed_buffer = sizes.cbHeader + size + sizes.cbTrailer;
                unsigned char* out_buffer = (unsigned char*)malloc(needed_buffer);
                if (out_buffer == NULL)
                {
                    result = __LINE__;
                }
                else
                {
                    memcpy(out_buffer + sizes.cbHeader, buffer, size);

                    security_buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
                    security_buffers[0].cbBuffer = sizes.cbHeader;
                    security_buffers[0].pvBuffer = out_buffer;
                    security_buffers[1].BufferType = SECBUFFER_DATA;
                    security_buffers[1].cbBuffer = size;
                    security_buffers[1].pvBuffer = out_buffer + sizes.cbHeader;
                    security_buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
                    security_buffers[2].cbBuffer = sizes.cbTrailer;
                    security_buffers[2].pvBuffer = out_buffer + sizes.cbHeader + size;
                    security_buffers[3].cbBuffer = 0;
                    security_buffers[3].BufferType = SECBUFFER_EMPTY;
                    security_buffers[3].pvBuffer = 0;

                    security_buffers_desc.cBuffers = sizeof(security_buffers) / sizeof(security_buffers[0]);
                    security_buffers_desc.pBuffers = security_buffers;
                    security_buffers_desc.ulVersion = SECBUFFER_VERSION;

                    status = EncryptMessage(&tls_io_instance->security_context, 0, &security_buffers_desc, 0);
                    if (FAILED(status))
                    {
                        result = __LINE__;
                    }
                    else
                    {
                        if (xio_send(tls_io_instance->socket_io, out_buffer, security_buffers[0].cbBuffer + security_buffers[1].cbBuffer + security_buffers[2].cbBuffer, on_send_complete, callback_context) != 0)
                        {
                            result = __LINE__;
                        }
                        else
                        {
                            size_t i;
                            for (i = 0; i < size; i++)
                            {
                                LOG(tls_io_instance->logger_log, 0, "%02x-> ", ((unsigned char*)buffer)[i]);
                            }
                            LOG(tls_io_instance->logger_log, LOG_LINE, "");

                            result = 0;
                        }
                    }

                    free(out_buffer);
                }
            }
        }
    }

    return result;
}
Exemplo n.º 30
0
SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls)
{
  MARIADB_PVIO *pvio;
  SECURITY_STATUS sRet;
  DWORD OutFlags;
  DWORD r;
  SC_CTX *sctx;
  SecBuffer ExtraData;
  DWORD SFlags= ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
                ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | 
                ISC_REQ_USE_SUPPLIED_CREDS |
                ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM;
  
  SecBufferDesc	BufferOut;
  SecBuffer  BuffersOut;

  if (!ctls || !ctls->pvio)
    return 1;

  pvio= ctls->pvio;
  sctx= (SC_CTX *)ctls->ssl;

  /* Initialie securifty context */
  BuffersOut.BufferType= SECBUFFER_TOKEN;
  BuffersOut.cbBuffer= 0;
  BuffersOut.pvBuffer= NULL;


  BufferOut.cBuffers= 1;
  BufferOut.pBuffers= &BuffersOut;
  BufferOut.ulVersion= SECBUFFER_VERSION;

  sRet = InitializeSecurityContext(&sctx->CredHdl,
                                    NULL,
                                    pvio->mysql->host,
                                    SFlags,
                                    0,
                                    SECURITY_NATIVE_DREP,
                                    NULL,
                                    0,
                                    &sctx->ctxt,
                                    &BufferOut,
                                    &OutFlags,
                                    NULL);

  if(sRet != SEC_I_CONTINUE_NEEDED)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    return sRet;
  }

  /* send client hello packaet */
  if(BuffersOut.cbBuffer != 0 && BuffersOut.pvBuffer != NULL)
  {  
    r= (DWORD)pvio->methods->write(pvio, (uchar *)BuffersOut.pvBuffer, (size_t)BuffersOut.cbBuffer);
    if (r <= 0)
    {
      sRet= SEC_E_INTERNAL_ERROR;
      goto end;
    }
  }
  sRet= ma_schannel_handshake_loop(pvio, TRUE, &ExtraData);

  /* allocate IO-Buffer for write operations: After handshake
  was successfull, we are able now to calculate payload */
  if ((sRet = QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_STREAM_SIZES, &sctx->Sizes )))
    goto end;

  sctx->IoBufferSize= SCHANNEL_PAYLOAD(sctx->Sizes);
  if (!(sctx->IoBuffer= (PUCHAR)LocalAlloc(0, sctx->IoBufferSize)))
  {
    sRet= SEC_E_INSUFFICIENT_MEMORY;
    goto end;
  }
    
  return sRet;
end:
  LocalFree(sctx->IoBuffer);
  sctx->IoBufferSize= 0;
  FreeContextBuffer(BuffersOut.pvBuffer);
  DeleteSecurityContext(&sctx->ctxt);
  return sRet;
}