Ejemplo n.º 1
0
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData)
{
  SecBufferDesc   OutBuffer, InBuffer;
  SecBuffer       InBuffers[2], OutBuffers;
  DWORD           dwSSPIFlags, dwSSPIOutFlags, cbData, cbIoBuffer;
  TimeStamp       tsExpiry;
  SECURITY_STATUS rc;
  PUCHAR          IoBuffer;
  BOOL            fDoRead;
  MARIADB_TLS     *ctls= pvio->ctls;
  SC_CTX          *sctx= (SC_CTX *)ctls->ssl;


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


  /* Allocate data buffer */
  if (!(IoBuffer = LocalAlloc(LMEM_FIXED, SC_IO_BUFFER_SIZE)))
    return SEC_E_INSUFFICIENT_MEMORY;

  cbIoBuffer = 0;
  fDoRead = InitialRead;

  /* handshake loop: We will leave a handshake is finished
     or an error occurs */

  rc = SEC_I_CONTINUE_NEEDED;

  while (rc == SEC_I_CONTINUE_NEEDED ||
         rc == SEC_E_INCOMPLETE_MESSAGE ||
         rc == SEC_I_INCOMPLETE_CREDENTIALS )
  {
    /* Read data */
    if (rc == SEC_E_INCOMPLETE_MESSAGE ||
        !cbIoBuffer)
    {
      if(fDoRead)
      {
        cbData = (DWORD)pvio->methods->read(pvio, IoBuffer + cbIoBuffer, (size_t)(SC_IO_BUFFER_SIZE - cbIoBuffer));
        if (cbData == SOCKET_ERROR || cbData == 0)
        {
          rc = SEC_E_INTERNAL_ERROR;
          break;
        }
        cbIoBuffer += cbData;
      }
      else
        fDoRead = TRUE;
    }

    /* input buffers
       First buffer stores data received from server. leftover data
       will be stored in second buffer with BufferType SECBUFFER_EXTRA */

    InBuffers[0].pvBuffer   = IoBuffer;
    InBuffers[0].cbBuffer   = cbIoBuffer;
    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;


    /* output buffer */
    OutBuffers.pvBuffer  = NULL;
    OutBuffers.BufferType= SECBUFFER_TOKEN;
    OutBuffers.cbBuffer  = 0;

    OutBuffer.cBuffers      = 1;
    OutBuffer.pBuffers      = &OutBuffers;
    OutBuffer.ulVersion     = SECBUFFER_VERSION;


    rc = InitializeSecurityContextA(&sctx->CredHdl,
                                    &sctx->ctxt,
                                    NULL,
                                    dwSSPIFlags,
                                    0,
                                    SECURITY_NATIVE_DREP,
                                    &InBuffer,
                                    0,
                                    NULL,
                                    &OutBuffer,
                                    &dwSSPIOutFlags,
                                    &tsExpiry );


    if (rc == SEC_E_OK  ||
        rc == SEC_I_CONTINUE_NEEDED ||
        FAILED(rc) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
    {
      if(OutBuffers.cbBuffer && OutBuffers.pvBuffer)
      {
        cbData= (DWORD)pvio->methods->write(pvio, (uchar *)OutBuffers.pvBuffer, (size_t)OutBuffers.cbBuffer);
        if(cbData == SOCKET_ERROR || cbData == 0)
        {
          FreeContextBuffer(OutBuffers.pvBuffer);
          DeleteSecurityContext(&sctx->ctxt);
          return SEC_E_INTERNAL_ERROR;
        }

        /* Free output context buffer */
        FreeContextBuffer(OutBuffers.pvBuffer);
        OutBuffers.pvBuffer = NULL;
      }
    }

    /* check if we need to read more data */
    switch (rc) {
    case SEC_E_INCOMPLETE_MESSAGE:
      /* we didn't receive all data, so just continue loop */
      continue;
      break;
    case SEC_E_OK:
      /* handshake completed, but we need to check if extra
         data was sent (which contains encrypted application data) */
      if (InBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        if (!(pExtraData->pvBuffer= LocalAlloc(0, InBuffers[1].cbBuffer)))
          return SEC_E_INSUFFICIENT_MEMORY;
        
        MoveMemory(pExtraData->pvBuffer, IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer );
        pExtraData->BufferType = SECBUFFER_TOKEN;
        pExtraData->cbBuffer   = InBuffers[1].cbBuffer;
      }
      else
      {
        pExtraData->BufferType= SECBUFFER_EMPTY;
        pExtraData->pvBuffer= NULL;
        pExtraData->cbBuffer= 0;
      }
    break;
 
    case SEC_I_INCOMPLETE_CREDENTIALS:
      /* Provided credentials didn't contain a valid client certificate.
         We will try to connect anonymously, using current credentials */
      fDoRead= FALSE;
      rc= SEC_I_CONTINUE_NEEDED;
      continue;
      break;
    default:
      if (FAILED(rc))
      {
        ma_schannel_set_sec_error(pvio, rc);
        goto loopend;
      }
      break;
    }

    if ( InBuffers[1].BufferType == SECBUFFER_EXTRA )
    {
      MoveMemory( IoBuffer, IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer );
      cbIoBuffer = InBuffers[1].cbBuffer;
    }

    cbIoBuffer = 0;
  }
loopend:
  if (FAILED(rc)) 
    DeleteSecurityContext(&sctx->ctxt);
  LocalFree(IoBuffer);

  return rc;
}
Ejemplo n.º 2
0
INT
auth_sspi_client_step(sspi_client_state* state, SEC_CHAR* challenge) {
    SecBufferDesc inbuf;
    SecBuffer inBufs[1];
    SecBufferDesc outbuf;
    SecBuffer outBufs[1];
    ULONG ignored;
    SECURITY_STATUS status = AUTH_GSS_CONTINUE;
    SIZE_T len;

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

    inbuf.ulVersion = SECBUFFER_VERSION;
    inbuf.cBuffers = 1;
    inbuf.pBuffers = inBufs;
    inBufs[0].pvBuffer = NULL;
    inBufs[0].cbBuffer = 0;
    inBufs[0].BufferType = SECBUFFER_TOKEN;
    if (state->haveCtx) {
        inBufs[0].pvBuffer = base64_decode(challenge, &len);
        inBufs[0].cbBuffer = (ULONG)len;
    }

    outbuf.ulVersion = SECBUFFER_VERSION;
    outbuf.cBuffers = 1;
    outbuf.pBuffers = outBufs;
    outBufs[0].pvBuffer = NULL;
    outBufs[0].cbBuffer = 0;
    outBufs[0].BufferType = SECBUFFER_TOKEN;

    Py_BEGIN_ALLOW_THREADS
    status = InitializeSecurityContextA(/* CredHandle */
                                        &state->cred,
                                        /* CtxtHandle (NULL on first call) */
                                        state->haveCtx ? &state->ctx : NULL,
                                        /* Service Principal Name */
                                        state->spn,
                                        /* Flags */
                                        ISC_REQ_ALLOCATE_MEMORY | state->flags,
                                        /* Always 0 */
                                        0,
                                        /* Target data representation */
                                        SECURITY_NETWORK_DREP,
                                        /* Challenge (NULL on first call) */
                                        state->haveCtx ? &inbuf : NULL,
                                        /* Always 0 */
                                        0,
                                        /* CtxtHandle (Set on first call) */
                                        &state->ctx,
                                        /* Output */
                                        &outbuf,
                                        /* Context attributes */
                                        &ignored,
                                        /* Expiry (We don't use this) */
                                        NULL);
    Py_END_ALLOW_THREADS
    if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
        set_krberror(status, "InitializeSecurityContext");
        status = AUTH_GSS_ERROR;
        goto done;
    }
    state->haveCtx = 1;
    if (outBufs[0].cbBuffer) {
        state->response = base64_encode(outBufs[0].pvBuffer,
                                        outBufs[0].cbBuffer);
    }
    if (status == SEC_E_OK) {
        /* Get authenticated username. */
        SecPkgContext_Names names;
        status = QueryContextAttributes(
            &state->ctx, SECPKG_ATTR_NAMES, &names);
        if (status != SEC_E_OK) {
            set_krberror(status, "QueryContextAttributes");
            status = AUTH_GSS_ERROR;
            goto done;
        }
        state->username = _strdup(names.sUserName);
        if (state->username == NULL) {
            PyErr_SetNone(PyExc_MemoryError);
            FreeContextBuffer(names.sUserName);
            status = AUTH_GSS_ERROR;
            goto done;
        }
        FreeContextBuffer(names.sUserName);
        status = AUTH_GSS_COMPLETE;
    } else {
        status = AUTH_GSS_CONTINUE;
    }
done:
    if (inBufs[0].pvBuffer) {
        free(inBufs[0].pvBuffer);
    }
    if (outBufs[0].pvBuffer) {
        FreeContextBuffer(outBufs[0].pvBuffer);
    }
    return status;
}
Ejemplo n.º 3
0
OM_uint32  gss_init_sec_context (
        OM_uint32 *minor_status,
        gss_cred_id_t claimant_cred_handle,
        gss_ctx_id_t *context_handle,
        gss_name_t target_name,
        gss_OID mech_type,
        int req_flags,
        int time_req,
        gss_channel_bindings_t input_channel_bindings,
        gss_buffer_t input_token,
        gss_OID *actual_mech_types,
        gss_buffer_t output_token,
        int *ret_flags,
        OM_int32 *time_rec)
{
	SecPkgInfoA *secPackInfo = NULL;
	gss_cred_id_t credhandle={0};
	gss_ctx_id_t *pctx;

	// SECBUFFER_TOKEN
	// This buffer type is used to indicate the security token portion of the message. 
	// This is read-only for input parameters or read/write for output parameters.
	SecBuffer InputBuf[1] = {input_token?input_token->length:0,SECBUFFER_TOKEN,input_token?input_token->value:0};
	SecBuffer OutputBuf[1] = {0,SECBUFFER_TOKEN,NULL};
	SecBufferDesc InBuffer[1] = {SECBUFFER_VERSION, 1, InputBuf};
	SecBufferDesc OutBuffer[1] = {SECBUFFER_VERSION, 1, OutputBuf};
	OM_uint32 ret;
	TimeStamp tr;
	unsigned long rf;
	SECURITY_STATUS retq;

	//
	// Previously gserver passed ISC_REQ_ALLOCATE_MEMORY to InitializeSecurityContext
	// but it returns SEC_E_BUFFER_TOO_SMALL - I think this is because
	// only Digest and Schannel will allocate output buffers for you, even though the documentation
	// doesn't make that clear for InitializeSecurityContext (see AcquireCredentialsHandle doco).
	//
	if((retq=QuerySecurityPackageInfoA( "Kerberos", &secPackInfo )) != SEC_E_OK)
		return 0;

	OutputBuf->BufferType = SECBUFFER_TOKEN; // preping a token here
	OutputBuf->cbBuffer = secPackInfo->cbMaxToken;
	OutputBuf->pvBuffer = malloc(secPackInfo->cbMaxToken);

	if(claimant_cred_handle.dwLower==0 && claimant_cred_handle.dwUpper==0)
	{
		static gss_cred_id_t global_client_cred={0};
		if(global_client_cred.dwLower==0 || global_client_cred.dwUpper==0)
		{
			ret = AcquireCredentialsHandleA(NULL,"Kerberos",SECPKG_CRED_OUTBOUND,NULL,NULL,NULL,NULL,&global_client_cred,NULL);
			if(ret)
				return ret;
		}
		credhandle = global_client_cred;
	}
	else
		credhandle = claimant_cred_handle;

	if(context_handle->dwLower==0 && context_handle->dwUpper==0)
		pctx = NULL;
	else
		pctx = context_handle;

	// note - only Digest and Schannel will allocate output buffers for you. 
	// so kerberos and other security contexts should not use ISC_REQ_ALLOCATE_MEMORY
	// and also should not free them by calling the FreeContextBuffer function.
	ret = InitializeSecurityContextA(
		&credhandle, pctx, target_name, req_flags, 0, SECURITY_NETWORK_DREP,
		input_token?InBuffer:NULL,0, pctx?NULL:context_handle, OutBuffer, &rf, &tr); 

	// really need to return if that didn't work...
	if (ret != SEC_E_OK /*GSS_S_COMPLETE*/ && ret != SEC_I_CONTINUE_NEEDED /*GSS_S_CONTINUE_NEEDED*/ )
	{
		free(OutputBuf->pvBuffer);
		OutputBuf->pvBuffer = NULL;
		return ret;
	}

	output_token->length = OutputBuf[0].cbBuffer;
	output_token->value = malloc((OutputBuf[0].cbBuffer)+100);
	if (output_token->value!=NULL)
		memcpy(output_token->value,OutputBuf[0].pvBuffer,output_token->length);
	
	// only call this if InitializeSecurityContext successfully created the buffers for us
	// FreeContextBuffer(OutBuffer);

	// manually made the memory, so manually release it...
	free(OutputBuf->pvBuffer);
	OutputBuf->pvBuffer = NULL;

	*minor_status = 0;
	if(time_rec)
		*time_rec=tr.LowPart;
	if(ret_flags)
		*ret_flags=rf;
	return ret;
}
Ejemplo n.º 4
0
bool CSSPIHandler::ClientStep(bool& more, const char *inputBuffer, size_t inputSize)
{
	SECURITY_STATUS rcISC;
	DWORD ctxAttr;
	// input and output buffers
	TimeStamp useBefore;
	SecBufferDesc obd,ibd;
	SecBuffer ob[1], ib[2];

	m_outputBuffer.resize(m_secPackInfo->cbMaxToken);

	obd.ulVersion = SECBUFFER_VERSION;
	obd.cBuffers = 1;
	obd.pBuffers = ob; // just one buffer
	ob[0].cbBuffer = m_secPackInfo->cbMaxToken;
	ob[0].pvBuffer = (void*)m_outputBuffer.data();
	ob[0].BufferType = SECBUFFER_TOKEN; // preping a token here

	if(inputBuffer)
	{
		// prepare to get the server's response
		ibd.ulVersion = SECBUFFER_VERSION;
		ibd.cBuffers = 1;
		ibd.pBuffers = ib; // just one buffer

		ib[0].cbBuffer=(DWORD)inputSize;
		ib[0].pvBuffer =(void*)inputBuffer;
		ib[0].BufferType = SECBUFFER_TOKEN; // preping a token here
	}

	rcISC = InitializeSecurityContextA( &m_credHandle, m_haveContext? &m_contextHandle:NULL,
		(char*)m_tokenSource, m_ctxReq, 0, SECURITY_NATIVE_DREP, m_haveContext?&ibd:NULL,
		0, &m_contextHandle, &obd, &ctxAttr, &useBefore );

	if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE || rcISC == SEC_I_COMPLETE_NEEDED )
	{
		CompleteAuthToken( &m_contextHandle, &obd );
		if ( rcISC == SEC_I_COMPLETE_NEEDED )
			rcISC = SEC_E_OK;
		else if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE )
			rcISC = SEC_I_CONTINUE_NEEDED;
	}

	if(rcISC<0)
	{
		m_rc = rcISC;
		more=false;
		return false;
	}

	m_outputBuffer.resize(ob[0].cbBuffer);

	if ( rcISC != SEC_I_CONTINUE_NEEDED )
	{
		m_rc = rcISC;
		if ( rcISC != SEC_E_OK )
			m_haveContext = false;
		else
		{
			QueryContextAttributes(&m_contextHandle,SECPKG_ATTR_SIZES,&m_secSizes);
			m_haveContext = true;
		}

		more=false;
		return m_haveContext;
	}

	m_haveContext = true;
	more=true;
	return true;
}
Ejemplo n.º 5
-1
BOOL GenClientContext (BYTE *pIn, DWORD cbIn, BYTE *pOut, DWORD *pcbOut, BOOL *pfDone, SEC_CHAR *pszTarget, CredHandle *hCred, struct _SecHandle *hCtxt)
{
	SECURITY_STATUS   ss;
	TimeStamp         Lifetime;
	SecBufferDesc     OutBuffDesc;
	SecBuffer         OutSecBuff;
	SecBufferDesc     InBuffDesc;
	SecBuffer         InSecBuff;
	ULONG             ContextAttributes;
	SEC_CHAR	      lpPackageName[1024];
	_SEC_WINNT_AUTH_IDENTITY	auth_data;
	PCHAR pUserName = NULL;
	DWORD cbUserName = 0;
	DWORD dw;


	if( NULL == pIn )  
	{   
		GetUserNameExA(NameSamCompatible, pUserName, &cbUserName);
		pUserName = (PCHAR) malloc (cbUserName);
		GetUserNameExA(NameSamCompatible, pUserName, &cbUserName);

		cbUserName = (DWORD)((int)strchr(pUserName,'\\'));
		*(char *)cbUserName = 0;
		auth_data.Domain = (unsigned char *)pUserName;
		auth_data.User = (unsigned char *)((int)cbUserName+1);
		printf("%s@%s\n",(char *)auth_data.User,(char *)auth_data.Domain);

		auth_data.UserLength = strlen((char *)auth_data.User);
		auth_data.DomainLength = strlen((char *)auth_data.Domain);
		auth_data.Password = NULL;
		auth_data.PasswordLength = 0;
		auth_data.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

	   	lstrcpynA (lpPackageName, "NTLM", 5);
	   	ss = AcquireCredentialsHandleA (NULL, lpPackageName, SECPKG_CRED_OUTBOUND, NULL, &auth_data, NULL, NULL, hCred, &Lifetime);
	   	if (!(SEC_SUCCESS (ss))) MyHandleError("AcquireCreds failed ");
	}

	OutBuffDesc.ulVersion = 0;
	OutBuffDesc.cBuffers  = 1;
	OutBuffDesc.pBuffers  = &OutSecBuff;

	OutSecBuff.cbBuffer   = *pcbOut;
	OutSecBuff.BufferType = SECBUFFER_TOKEN;
	OutSecBuff.pvBuffer   = pOut;

	if (pIn)
	{
		 InBuffDesc.ulVersion = 0;
		 InBuffDesc.cBuffers  = 1;
		 InBuffDesc.pBuffers  = &InSecBuff;

		 InSecBuff.cbBuffer   = cbIn;
		 InSecBuff.BufferType = SECBUFFER_TOKEN;
		 InSecBuff.pvBuffer   = pIn;
		ss = InitializeSecurityContextA (hCred,	hCtxt,	pszTarget,	ISC_REQ_CONFIDENTIALITY, 0,	SECURITY_NATIVE_DREP,	&InBuffDesc,	0, 	hCtxt,	&OutBuffDesc, &ContextAttributes,	&Lifetime);
	}
	else
	{
		 ss = InitializeSecurityContextA (hCred, NULL, pszTarget, ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP, NULL, 0, hCtxt, &OutBuffDesc, &ContextAttributes, &Lifetime);
	}

	if (!SEC_SUCCESS (ss)) MyHandleError ("InitializeSecurityContext failed " );

	*pcbOut = OutSecBuff.cbBuffer;
	*pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||(SEC_I_COMPLETE_AND_CONTINUE == ss));
	return TRUE;
}