Пример #1
0
int tango_test_connection(tango_connection_t *connection) {
	if(connection->session_status <= kTangoSessionStatusProtocolNegotiated) {
		_tango_set_error(connection, kTangoErrorGeneralSystemError, "Not connected yet.");
		error("tango_test_connection(): No tango_connect() has been successfully called yet.");	
		return -1;
	}
	
	return _tango_ECHO(connection, 2, 'F');
}
Пример #2
0
int tango_connect(tango_connection_t *connection) {
	// Connect
	int result = connect(connection->socket, (struct sockaddr *)&connection->sock_addr, sizeof(struct sockaddr_in));
	if(result < 0) {
		_tango_set_error(connection, kTangoErrorConnectionProblem, "Failed to connect");
		error("tango_connect(): Failed to connect(); %s.\n", strerror( errno ));	
		return -1;
	}
	
	if (_tango_NEGOTIATE_PROTOCOL(connection) < 0) return 0;	
	if (_tango_SESSION_SETUP(connection) < 0) return 0;
	if (_tango_TREE_CONNECT(connection) < 0) return 0;
	
	return 1;
}
Пример #3
0
tango_connection_t *tango_create(const char *share, const char* username, const char *password) {
	static unsigned short next_mid = 0;
	
	tango_connection_t *tango_connection_ptr = malloc(sizeof(tango_connection_t));
	if (tango_connection_ptr == NULL) {
		_tango_set_error(tango_connection_ptr, kTangoErrorGeneralSystemError, "tango_create(): Unable to malloc mem.\n");
		error("tango_create(): Unable to malloc mem.\n");
		return NULL;
	}
	
	// Null it
	memset(tango_connection_ptr, 0, sizeof(tango_connection_t));
	
	// Create a socket
	int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock < 0) {
		_tango_set_error(tango_connection_ptr, kTangoErrorGeneralSystemError, "tango_create(): Failed to create socket().\n");
		debug("tango_create(): Failed to create socket().\n");
		goto bailout;
	}
		
	tango_connection_ptr->socket = sock;
	struct sockaddr_in sock_addr;
	
	// Parse share-string
	if (strncmp(share, "\\\\", 2) != 0 || strlen(share) < 3) {
		_tango_set_error(tango_connection_ptr, kTangoErrorParameterInvalid, "tango_create(): Passed parameter not a valid share.\n");
		debug("tango_create(): Passed parameter not a valid share.\n");
		goto bailout;
	}
	
	const char *begin_ptr = share + 2;
	char *end_ptr = strchr(begin_ptr, '\\');
	

	// Form: \\hostname\share
	char hostname[64];
	assert(strlen(begin_ptr) < 64 && "Hostname longer than 64 bytes");
	strncpy(hostname, begin_ptr, end_ptr - begin_ptr);
	hostname[end_ptr - begin_ptr] = '\0';
    sock_addr.sin_addr = address_for_host(hostname);
	int sin_addr_set = sock_addr.sin_addr.s_addr != INADDR_NONE;
	
	if (!sin_addr_set) {
		_tango_set_error(tango_connection_ptr, kTangoErrorParameterInvalid, "tango_create(): Invalid share.\n");
		error("tango_create(): Passed parameter not a valid share or contains no valid hostname/IP.\n");
		goto bailout;
	}

	
	char *slash_ptr = strchr(share + 2, '\\');
	slash_ptr = strchr(slash_ptr + 1, '\\');
	if (slash_ptr != NULL) {
		// Format: \\hostname\share\subfolder
		unsigned int slash_idx = slash_ptr - share;
		strncpy(tango_connection_ptr->share, share, slash_idx);
		tango_connection_ptr->share[slash_idx + 1] = '\0';	
	}
	else {
		// Format: \\hostname\share
		slash_ptr = strchr(share + 2, '\\');
		strcpy(tango_connection_ptr->share, slash_ptr+1);
	}

	// Configure port and connection-type
	sock_addr.sin_family = AF_INET;
	sock_addr.sin_port = htons(445); // Default-port for SMB over TCP/IP without NetBios

	tango_connection_ptr->sock_addr = sock_addr;
	
	// Set our Ids
	tango_connection_ptr->pid = 0x1234;
	tango_connection_ptr->mid = next_mid++;
	
	// Store username and password
	strcpy(tango_connection_ptr->user_name, username);
	strcpy(tango_connection_ptr->user_password, password);

	return tango_connection_ptr;
	
bailout:
	free(tango_connection_ptr);
	return NULL;
}
Пример #4
0
int _tango_TREE_CONNECT(tango_connection_t *connection) {
	
	unsigned int operation_successful = -1;
	
	/**
	 * 1. Define Request
	 */
	
	tango_smb_t *smb = _tango_create_smb();
	
	// Header
	_tango_populate_request_header(connection, smb, SMB_COM_TREE_CONNECT_ANDX);
	
	// Parameters
	unsigned char *parameters_ptr = _tango_smb_getParametersPointer(smb);
	unsigned int parameters_offset = 0;
	
	// AndX Command
	*((unsigned char *)(parameters_ptr + parameters_offset)) = SMB_COM_NONE;
	parameters_offset+=2; // 1 byte reserved
	
	// AndX Offset
	*((unsigned short *)(parameters_ptr + parameters_offset)) = 0;
	parameters_offset+=2;
	
	// Flags
	*((unsigned short *)(parameters_ptr + parameters_offset)) = 0x00;
	parameters_offset+=2;
	
	// PasswordLength;
	*((unsigned short *)(parameters_ptr + parameters_offset)) = 1;
	parameters_offset+=2;
	
	_tango_smb_setParametersSize(smb, parameters_offset);
	
	// Data
	unsigned char *data_ptr = _tango_smb_getDataPointer(smb);
	unsigned int data_offset = 0;

	//msg_data.byte_count = 1 + strlen(connection->share) + 1 + 6;
	
	// Password
	strcpy((char *)(data_ptr + data_offset), "");
	data_offset += strlen((char *)(data_ptr + data_offset)) + 1;
	
	// Path
	strcpy((char *)(data_ptr + data_offset), connection->share);
	data_offset += strlen((char *)(data_ptr + data_offset)) + 1;
	
	// Service
	strcpy((char *)(data_ptr + data_offset), "?????");
	data_offset += strlen((char *)(data_ptr + data_offset)) + 1;
	
	_tango_smb_setDataSize(smb, data_offset);
	
	/**
	 * 2. Send Request and receive Response
	 */
	
#ifdef VERY_VERBOSE
	printf("_tango_TREE_CONNECT_ANDX(): Sending TREE_CONNECT_ANDX:\n");
	printf("-----------------------------------------------------------------------------\n");
	_tango_print_message(smb);
	printf("-----------------------------------------------------------------------------\n");
#endif
	
	if (!_tango_send_and_receive(connection, smb, NULL)) {
		goto bailout;
	}

	debug("_tango_TREE_CONNECT_ANDX(): Received response\n");
	
	/**
	 * 3. Evaluate Response
	 */
	
	if (!_tango_evaluate_response_header(connection, smb)) {
		goto bailout;
	}
	
	if (_tango_smb_getParametersSize(smb) != 6) {
		_tango_set_error(connection, kTangoErrorInvalidResponseMessage, "Unable to connect to share");
		error("_tango_TREE_CONNECT_ANDX(): Parameters-block length %d (!= 6).\n", (int)_tango_smb_getParametersSize(smb));
		goto bailout;
	}
	
#ifdef VERY_VERBOSE
	printf("_tango_TREE_CONNECT_ANDX(): Received response:\n");
	printf("-----------------------------------------------------------------------------\n");
	_tango_print_message(smb);
	printf("-----------------------------------------------------------------------------\n");
#endif
	
	connection->session_status = kTangoSessionStatusConnectedToShare;
	operation_successful = 1;
	
bailout:
	_tango_release_smb(smb);
	return operation_successful;
}
Пример #5
0
int _tango_NEGOTIATE_PROTOCOL(tango_connection_t *connection) {

    int operation_successful = -1;

    /**
     * 1. Define Request
     */

    tango_smb_t *smb = _tango_create_smb();

    // Header
    _tango_populate_request_header(connection, smb, SMB_COM_NEGOTIATE);

    // Parameters
    unsigned char *parameters_ptr = _tango_smb_getParametersPointer(smb);
    _tango_smb_setParametersSize(smb, 0);

    // Data
    unsigned char *data_ptr = _tango_smb_getDataPointer(smb);
    unsigned int data_offset = 0;
    // Set to LanManager 0.12 for NT

    data_ptr[0] = 0x02;
    data_offset++;

    strcpy((char *)(data_ptr + data_offset), SMB_NEGOTIATE_PROTOCOL_DIALECT_LM012);
    data_offset += strlen(SMB_NEGOTIATE_PROTOCOL_DIALECT_LM012) + 1;
    _tango_smb_setDataSize(smb, data_offset);

    /**
     * 2. Send Request and receive Response
     */

#ifdef VERY_VERBOSE
    printf("_tango_NEGOTIATE_PROTOCOL(): Sending NEGOTIATE_PROTOCOL request:\n");
    printf("-----------------------------------------------------------------------------\n");
    _tango_print_message(smb);
    printf("-----------------------------------------------------------------------------\n");
#endif

    if (!_tango_send_and_receive(connection, smb, NULL)) {
        goto bailout;
    }

    debug("_tango_NEGOTIATE_PROTOCOL(): Received response\n");

    /**
     * 3. Evaluate Response
     */

    if (!_tango_evaluate_response_header(connection, smb)) {
        goto bailout;
    }

    // Read Parameters
    if (_tango_smb_getParametersSize(smb) != 34) {
        _tango_set_error(connection, kTangoErrorInvalidResponseMessage, "Invalid response.\n");
        debug("_tango_NEGOTIATE_PROTOCOL(): Parameters-block length %d (!= 34).\n", (int)_tango_smb_getParametersSize(smb));
        goto bailout;
    }

    /** TODO if no index is supported!
     Server Response ================
     UCHAR WordCount; USHORT DialectIndex; USHORT ByteCount;
     Description ============
     Count of parameter words = 1 Index of selected dialect Count of data bytes = 0
     */

#ifdef VERY_VERBOSE
    printf("_tango_NEGOTIATE_PROTOCOL(): Received response for NEGOTIATE_PROTOCOL_REQUEST:\n");
    printf("-----------------------------------------------------------------------------\n");
    _tango_print_NEGOTIATE_PROTOCOL_RESPONSE(smb);
    printf("-----------------------------------------------------------------------------\n");
#endif

    parameters_ptr = _tango_smb_getParametersPointer(smb);

    // params->DialectIndex
    // We assume he is Ok with our dialect as the NT_STATUS Level was set to SUCCESS

    // params->SecurityMode
    // TODO: Handle Sec mode

    // params->MaxMpxCount
    // Don't care for now

    // params->MaxNumberVCs
    // Don't care for now

    //connection->max_buffer_size = params->MaxBufferSize;

    // params->MaxRawSize
    // We don't support raw-mode to keep it easy

    // params->SessionKey
    connection->session_key = *(unsigned int *)(parameters_ptr + SMB_NEGOTIATE_PROTOCOL_RSP_PARAMETERS_SESSION_KEY_INT);

    // params->Capabilities
    unsigned int capabilities = *(unsigned int *)(parameters_ptr + SMB_NEGOTIATE_PROTOCOL_RSP_PARAMETERS_CAPABILITIES_INT);

    connection->extended_security = capabilities & CAP_EXTENDED_SECURITY;
    if (connection->extended_security) {
        error("_tango_NEGOTIATE_PROTOCOL(): Extended Security unsupported.\n");
        _tango_set_error(connection, kTangoErrorUnsupported, "Unsupported security mode");
        goto bailout;
    }

    debug("_tango_NEGOTIATE_PROTOCOL(): Server Capabilities 0x%x\n", capabilities);
    connection->server_capabilities = capabilities;
    if (capabilities & CAP_LARGE_READX) {
        debug("_tango_NEGOTIATE_PROTOCOL(): - CAP_LARGE_READX\n");
    }

    //time_t time = (time_t)((((((unsigned long)params->SystemTimeLow) << 32) | params->SystemTimeHigh)/10000000) - 11644473600);

    // params->ServerTimeZone
    // Too late... don't care for it now

    // params->EncryptionKeyLength
    unsigned char encryption_key_length = *(unsigned char *)(parameters_ptr + SMB_NEGOTIATE_PROTOCOL_RSP_PARAMETERS_ENCRYPTION_KEY_LENGTH_BYTE);



    // Store challange (no extended security)
    if (encryption_key_length == 0) {
        debug("_tango_NEGOTIATE_PROTOCOL(): No encryption (key-length == 0)\n");
    }
    else if (encryption_key_length == 8) {
        // Ok
    }
    else {
        error("_tango_NEGOTIATE_PROTOCOL(): Unsupported key-length (key-length = %u)\n", encryption_key_length);
        _tango_set_error(connection, kTangoErrorUnsupported, "Unsupported encryption.\n");
    }

    // Read Data

    data_ptr = _tango_smb_getDataPointer(smb);

    if (encryption_key_length == 8) {
        memcpy(&connection->sec_challenge, data_ptr, 8);

    }

    operation_successful = 1;
    connection->session_status = kTangoSessionStatusProtocolNegotiated;

bailout:
    _tango_release_smb(smb);
    return operation_successful;
}
Пример #6
0
int _tango_ECHO(tango_connection_t *connection, unsigned short number_of_echoes, char echoPayload) {
	
	unsigned int operation_successful = -1;
	
	/**
	 * 1. Define Request
	 */
	
	tango_smb_t *smb = _tango_create_smb();
	
	_tango_populate_request_header(connection, smb, SMB_COM_ECHO);
	
	// Parameters
	unsigned char *parameters_ptr = _tango_smb_getParametersPointer(smb);
	unsigned int parameters_offset = 0;
	
	// Echo count
	*((unsigned short *)(parameters_ptr + parameters_offset)) = number_of_echoes;
	parameters_offset+=2;
		
	_tango_smb_setParametersSize(smb, parameters_offset);
	
	// Data
	unsigned char *data_ptr = _tango_smb_getDataPointer(smb);
	unsigned int data_offset = 0;
	
	*((unsigned char *)(data_ptr + data_offset)) = echoPayload;
	data_offset+=1;
	
	_tango_smb_setDataSize(smb, data_offset);
	
	/**
	 * 2. Send Request and receive Response
	 */
	
#ifdef VERY_VERBOSE
	printf("_tango_ECHO(): Sending ECHO:\n");
	printf("-----------------------------------------------------------------------------\n");
	_tango_print_message(smb);
	printf("-----------------------------------------------------------------------------\n");
#endif
	
	if (!_tango_send(connection, smb)) {
		goto bailout;
	}
	
	for (int i=1; i<=number_of_echoes; i++) {
		if (!_tango_receive(connection, smb)) {
			goto bailout;
		}
		
		debug("_tango_ECHO(): Received response %d of %d\n", i, number_of_echoes);
		
		/**
		 * 3. Evaluate Response
		 */
		
		if (!_tango_evaluate_response_header(connection, smb)) {
			goto bailout;
		}
		
		if (_tango_smb_getParametersSize(smb) != 2) {
			_tango_set_error(connection, kTangoErrorInvalidResponseMessage, "Operation failed");
			error("_tango_ECHO(): Parameters-block length %d (!= 2).\n", (int)_tango_smb_getParametersSize(smb));
			goto bailout;
		}
		
		
#ifdef VERY_VERBOSE
		printf("_tango_ECHO(): Received response:\n");
		printf("-----------------------------------------------------------------------------\n");
		_tango_print_message(smb);
		printf("-----------------------------------------------------------------------------\n");
#endif
		
		data_ptr = _tango_smb_getDataPointer(smb);
		data_offset = 0;
		
		char echo = *((unsigned char *)(data_ptr + data_offset));
		
		if (echoPayload != echo) {
			_tango_set_error(connection, kTangoErrorInvalidResponseMessage, "Invalid response");
			error("_tango_ECHO(): Echo does not echo (%02x) the payload of request (%02x).\n", echo, echoPayload);
			goto bailout;
		}
	}

	operation_successful = 1;
	
bailout:
	_tango_release_smb(smb);
	return operation_successful;
}