Esempio n. 1
0
    int sspiValidateServerSecurityLayerOffering(SspiConnContext* pcctx,
                                                sasl_client_params_t* cparams,
                                                const char *serverin,
                                                unsigned serverinlen) {
        SecPkgContext_Sizes sizes;
        SECURITY_STATUS status = QueryContextAttributesW(&pcctx->ctx,
                                                         SECPKG_ATTR_SIZES,
                                                         &sizes);
        if (status != SEC_E_OK) {
            HandleLastError(cparams->utils, status, "QueryContextAttributes(sizes)");
            return SASL_FAIL;
        }
        
        unsigned bufferLength = sizes.cbMaxToken + sizes.cbMaxSignature + sizes.cbSecurityTrailer;
        boost::scoped_array<char> message(new char[bufferLength]);
        if (serverinlen > bufferLength) {
            cparams->utils->seterror(cparams->utils->conn, 0, "SSPI: server message is too long");
            return SASL_FAIL;
        }
        memcpy(message.get(), serverin, serverinlen);
        
        SecBuffer wrapBufs[4];
        SecBufferDesc wrapBufDesc;
        wrapBufDesc.cBuffers = 2;
        wrapBufDesc.pBuffers = wrapBufs;
        wrapBufDesc.ulVersion = SECBUFFER_VERSION;

        wrapBufs[0].cbBuffer = 0;
        wrapBufs[0].BufferType = SECBUFFER_DATA;
        wrapBufs[0].pvBuffer = message.get();

        wrapBufs[1].cbBuffer = serverinlen;
        wrapBufs[1].BufferType = SECBUFFER_STREAM;
        wrapBufs[1].pvBuffer = message.get();

        status = DecryptMessage(&pcctx->ctx,
                                &wrapBufDesc,
                                0,
                                NULL);
        if (status != SEC_E_OK) {
            HandleLastError(cparams->utils, status, "DecryptMessage");
            return SASL_FAIL;
        }

        // Validate the server's plaintext message.
        // Length (as per RFC 4752)
        if (wrapBufs[0].cbBuffer < 4) {
            cparams->utils->seterror(cparams->utils->conn, 0, "SSPI: server message is too short");
            return SASL_FAIL;
        }
        // First bit of first byte set, indicating that the client may elect to use no
        // security layer. As a client we are uninterested in any of the other features the
        // server offers and thus we ignore the other bits.
        if (!(static_cast<char*>(wrapBufs[0].pvBuffer)[0] & 1)) {
            cparams->utils->seterror(cparams->utils->conn, 0, 
                                     "SSPI: server does not support the required security layer");
            return SASL_BADAUTH;
        }
        return SASL_OK;
    }
Esempio n. 2
0
	BOOL Write(void *buf, size_t len)
	{
		BOOL write_ret = WriteFile(hCom, buf, len, 0, (OVERLAPPED*)&write_over);
		if(!write_ret && GetLastError() != ERROR_IO_PENDING) {
			HandleLastError("WriteFile");
			return FALSE;
		}

		return TRUE;
	}
Esempio n. 3
0
	void iocp_thread()
	{
		DWORD bytes_transferred;
		OVER *over;
		ULONG key;

		while(true) {
			bytes_transferred = 0;
			BOOL completed = GetQueuedCompletionStatus(hIOCP,&bytes_transferred,&key,(OVERLAPPED**)&over,timeout);

			if(key == KEY_STOP) {
				if(log_level) std::cerr << "KEY_STOP" << std::endl;
				break;
			}

			DWORD last_error = completed ? 0 : HandleLastError("GetQueuedCompletionStatus");
			if(log_level) fprintf(stderr,"completed[%i] bytes_transferred[%i] over.operation[%i]\n",completed,bytes_transferred,over ? over->operation : 0);			
			
			if((!completed && last_error == WAIT_TIMEOUT)) {
				fprintf(stderr,"WAIT_TIMEOUT\n");				
			}

			if(timeout.check()) {
				int i = CancelIo(hCom);
				fprintf(stderr,"CancelIo = %i\n",i);
				continue;
			}
			

			if(!completed || !over) {
				continue;
			}

			if(over->operation == OP_READ) {
				if(completed) {
					long packet_found = data_received(read_buf,bytes_transferred);
					if(!packet_found) {
						Read(read_buf,1);
					}
				}
			}

			if(over->operation == OP_WRITE) {
				if(data_sent(bytes_transferred,system::error_code(last_error,system::system_category())) == 0) {
					Read(read_buf,1);
				}
			}						
		}

		if(log_level) std::cerr << "iocp_thread stopped" << std::endl;
	}
Esempio n. 4
0
static HANDLE ComOpen(const char *path, uint32_t baud, uint8_t parity, uint32_t flags) {
	COMMTIMEOUTS		CommTimeouts;
	DCB					dcb;
		
	wchar_t baud_s[50];
	wsprintf(baud_s, L"baud=%d parity=%s data=8 stop=1",baud,
		parity == PARITY::EVEN ? "E" : (parity == PARITY::ODD ? "O" : "N" ) );

	// get a handle to the port
	HANDLE hCom = CreateFileA(path,					// communication port path
				     GENERIC_READ | GENERIC_WRITE,	// read/write types
				     0,								// comm devices must be opened with exclusive access
				     NULL,							// no security attributes
				     OPEN_EXISTING,					// comm devices must use OPEN_EXISTING
				     flags,    	                    // flags
				     0);							// template must be 0 for comm devices

	
	if (hCom == INVALID_HANDLE_VALUE) {
		HandleLastError("CreateFile");
		return hCom;
	}

	// set the timeout values
	CommTimeouts.ReadIntervalTimeout			= 1;
	CommTimeouts.ReadTotalTimeoutMultiplier		= 0;
	CommTimeouts.ReadTotalTimeoutConstant		= 0;
	CommTimeouts.WriteTotalTimeoutMultiplier	= 0;
	CommTimeouts.WriteTotalTimeoutConstant		= 0;

	// configure
	if (SetCommTimeouts(hCom, &CommTimeouts))
	{					   
		//if (GetCommState(hCom, &dcb))
		//{
			//dcb.fOutxCtsFlow = FALSE;
			
			//dcb.fRtsControl = RTS_CONTROL_ENABLE;
			
			if (BuildCommDCB(baud_s, &dcb))
			{
				
				
				SetCommState(hCom, &dcb);			// normal operation... continue
			}
		//}
	}

	return hCom;
}
Esempio n. 5
0
	BlockwiseImpl(const char* path,uint32_t baud, uint8_t parity)
	:read_over(OP_READ),write_over(OP_WRITE),read_size(1) {
		uint32_t flags = FILE_FLAG_OVERLAPPED;
		hCom = ComOpen(path, baud, parity, flags);
		if(INVALID_HANDLE_VALUE == hCom) throw -1;
		
		hIOCP = CreateIoCompletionPort(hCom,0,0,0);
		if(!hIOCP) {
			HandleLastError("CreateIoCompletionPort");
			throw -2;
		};
	
		io_thread = thread(boost::bind(&BlockwiseImpl::iocp_thread,this));		
	}
Esempio n. 6
0
	bool Read(void *buf, size_t len)
	{
		//ReadFile
		//If the function succeeds, the return value is nonzero (TRUE).
		//If the function fails, or is completing asynchronously, the return value is zero (FALSE). To get extended error information, call the GetLastError function.
		//Note  The GetLastError code ERROR_IO_PENDING is not a failure; it designates the read operation is pending completion asynchronously. For more information, see Remarks.
		//Comments:
		//On Windows XP (at least) we have ReadFile returning TRUE and still initiating async iocp operation.

		if(log_level) std::cerr << "BlockwiseImpl::Read " << timeout.time_left()<< std::endl;
		BOOL read_ret = ReadFile(hCom, buf, len, 0, (OVERLAPPED*)&read_over);
		if(!read_ret && GetLastError() != ERROR_IO_PENDING) {
			HandleLastError("ReadFile");
			return true;
		} 
		return false;;
	}
Esempio n. 7
0
    int sspiClientMechStep(void *conn_context,
                           sasl_client_params_t *cparams,
                           const char *serverin,
                           unsigned serverinlen,
                           sasl_interact_t **prompt_need,
                           const char **clientout,
                           unsigned *clientoutlen,
                           sasl_out_params_t *oparams) {
        SspiConnContext* pcctx = static_cast<SspiConnContext*>(conn_context);
        *clientout = NULL;
        *clientoutlen = 0;

        if (pcctx->authComplete) {
            return sspiSendClientAuthzId(pcctx, cparams, 
                                         serverin, serverinlen, 
                                         clientout, clientoutlen, 
                                         oparams);
        }

        SecBufferDesc inbuf;
        SecBuffer inBufs[1];
        SecBufferDesc outbuf;
        SecBuffer outBufs[1];

        if (pcctx->haveCtxt) {
            // If we already have a context, we now have data to send.
            // Put this data in an inbuf.
            inbuf.ulVersion = SECBUFFER_VERSION;
            inbuf.cBuffers = 1;
            inbuf.pBuffers = inBufs;
            inBufs[0].pvBuffer = const_cast<char*>(serverin);
            inBufs[0].cbBuffer = serverinlen;
            inBufs[0].BufferType = SECBUFFER_TOKEN;
        }

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

        ULONG contextAttr = 0;
        SECURITY_STATUS status = InitializeSecurityContextW(&pcctx->cred,
                                                            pcctx->haveCtxt ? &pcctx->ctx : NULL,
                                                            const_cast<wchar_t*>(
                                                                pcctx->nameToken.c_str()),
                                                            ISC_REQ_ALLOCATE_MEMORY |
                                                            ISC_REQ_MUTUAL_AUTH,
                                                            0,
                                                            SECURITY_NETWORK_DREP,
                                                            (pcctx->haveCtxt ? &inbuf : NULL),
                                                            0,
                                                            &pcctx->ctx,
                                                            &outbuf,
                                                            &contextAttr,
                                                            NULL);

        if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
            HandleLastError(cparams->utils, status, "InitializeSecurityContext");
            return SASL_FAIL;
        }

        ON_BLOCK_EXIT(FreeContextBuffer, outbuf.pBuffers[0].pvBuffer);
        pcctx->haveCtxt = true;

        if (status == SEC_E_OK) {
            // Send back nothing and wait for the server to reply with the security capabilities
            *clientout = NULL;
            *clientoutlen = 0;
            pcctx->authComplete = true;
            return SASL_CONTINUE;
        }

        char *newoutbuf = static_cast<char*>(cparams->utils->malloc(outBufs[0].cbBuffer));
        *clientoutlen = outBufs[0].cbBuffer;
        memcpy(newoutbuf, outBufs[0].pvBuffer, *clientoutlen);
        *clientout = newoutbuf;
        return SASL_CONTINUE;
    }
Esempio n. 8
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;
    }