Beispiel #1
0
static SSL_RET
tds_pull_func_login(SSL_PULL_ARGS)
{
	TDSSOCKET *tds = (TDSSOCKET *) SSL_PTR;
	int have;

	tdsdump_log(TDS_DBG_INFO1, "in tds_pull_func_login\n");
	
	/* here we are initializing (crypted inside TDS packets) */

	/* if we have some data send it */
	/* here MARS is not already initialized so test is correct */
	/* TODO test even after initializing ?? */
	if (tds->out_pos > 8)
		tds_flush_packet(tds);

	for(;;) {
		have = tds->in_len - tds->in_pos;
		tdsdump_log(TDS_DBG_INFO1, "have %d\n", have);
		assert(have >= 0);
		if (have > 0)
			break;
		tdsdump_log(TDS_DBG_INFO1, "before read\n");
		if (tds_read_packet(tds) < 0)
			return -1;
		tdsdump_log(TDS_DBG_INFO1, "after read\n");
	}
	if (len > have)
		len = have;
	tdsdump_log(TDS_DBG_INFO1, "read %lu bytes\n", (unsigned long int) len);
	memcpy(data, tds->in_buf + tds->in_pos, len);
	tds->in_pos += len;
	return len;
}
Beispiel #2
0
static void
unfinished_query_test(TDSSOCKET *tds)
{
	int char_len;
	char *buf, *p;
	int i, len;
	union {
		TDS_USMALLINT si;
		TDS_UINT i;
		TDS_INT8 i8;
		char buf[8];
	} conv;

	if (IS_TDS72_PLUS(tds->conn))
		return;

	tds_init_write_buf(tds);

	/* try to build an invalid (unfinished) query split in two packets */
	char_len = IS_TDS7_PLUS(tds->conn) ? 2 : 1;
	buf = calloc(1, tds->out_buf_max + 200);
	memset(buf, '-', tds->out_buf_max + 200);
	strcpy(buf + (tds->out_buf_max - 8) / char_len - strlen(select_query) + 1, select_query);
	memset(strchr(buf, 0), 0, 16);

	/* convert if needed */
	len = strlen(buf);
	for (i = len; --i >= 0; ) {
		char c = buf[i];
		buf[i * char_len + 0] = c;
		if (IS_TDS7_PLUS(tds->conn))
			buf[i * char_len + 1] = 0;
	}
	len *= char_len;

	/* send the query using tds_put_int8, non allineati */
	tds->out_flag = TDS_QUERY;
	if (tds_set_state(tds, TDS_WRITING) != TDS_WRITING)
		exit(1);
	p = buf;
	memcpy(conv.buf, p, 2);
	tds_put_smallint(tds, conv.si);
	p += 2;
	for (; p < buf + len; p += 8) {
		CHECK_TDS_EXTRA(tds);
		memcpy(conv.buf, p, 8);
		tds_put_int8(tds, conv.i8);
	}
	tds_flush_packet(tds);
	tds_set_state(tds, TDS_PENDING);

	/* check result was fine */
	if (TDS_FAILED(tds_process_simple_query(tds))) {
		fprintf(stderr, "Error in prepared query\n");
		exit(1);
	}
	free(buf);
}
main(int argc, char **argv)
{
	TDSSOCKET *tds;
	TDSLOGIN login;
	TDSRESULTINFO *resinfo;

	tds = tds_listen(atoi(argv[1]));
	/* get_incoming(tds->s); */
	tds_read_login(tds, &login);
	dump_login(&login);
	if (!strcmp(login.user_name, "guest") && !strcmp(login.password, "sybase")) {
		tds->out_flag = 4;
		tds_env_change(tds, 1, "master", "pubs2");
		tds_send_msg(tds, 5701, 2, 10, "Changed database context to 'pubs2'.", "JDBC", "ZZZZZ", 1);
		if (!login.suppress_language) {
			tds_env_change(tds, 2, NULL, "us_english");
			tds_send_msg(tds, 5703, 1, 10, "Changed language setting to 'us_english'.", "JDBC", "ZZZZZ", 1);
		}
		tds_env_change(tds, 4, NULL, "512");
		tds_send_login_ack(tds, "sql server");
		tds_send_capabilities_token(tds);
		tds_send_253_token(tds, 0, 1);
	} else {
		/* send nack before exiting */
		exit(1);
	}
	tds_flush_packet(tds);
	/* printf("incoming packet %d\n", tds_read_packet(tds)); */
	printf("query : %s\n", tds_get_query(tds));
	tds->out_flag = 4;
	resinfo = tds_alloc_results(1);
	resinfo->columns[0]->column_type = SYBVARCHAR;
	resinfo->columns[0]->column_size = 30;
	strcpy(resinfo->columns[0]->column_name, "name");
	resinfo->columns[0]->column_namelen = 4;
	resinfo->current_row = "pubs2";
	tds_send_result(tds, resinfo);
	tds_send_174_token(tds, 1);
	tds_send_row(tds, resinfo);
	tds_send_253_token(tds, 16, 1);
	tds_flush_packet(tds);
	sleep(30);
}
Beispiel #4
0
static long
tds_ssl_ctrl_login(BIO *b, int cmd, long num, void *ptr)
{
	TDSSOCKET *tds = (TDSSOCKET *) b->ptr;

	switch (cmd) {
	case BIO_CTRL_FLUSH:
		if (tds->out_pos > 8)
			tds_flush_packet(tds);
		return 1;
	}
	return 0;
}
Beispiel #5
0
static int
tds_sspi_handle_next(TDSSOCKET * tds, struct tds_authentication * tds_auth, size_t len)
{
	SecBuffer in_buf, out_buf;
	SecBufferDesc in_desc, out_desc;
	SECURITY_STATUS status;
	ULONG attrs;
	TimeStamp ts;
	TDS_UCHAR *auth_buf;

	TDSSSPIAUTH *auth = (TDSSSPIAUTH *) tds_auth;

	if (len < 32 || len > NTLMBUF_LEN)
		return TDS_FAIL;

	auth_buf = (TDS_UCHAR *) malloc(len);
	if (!auth_buf)
		return TDS_FAIL;
	tds_get_n(tds, auth_buf, (int)len);

	in_desc.ulVersion  = out_desc.ulVersion  = SECBUFFER_VERSION;
	in_desc.cBuffers   = out_desc.cBuffers   = 1;
	in_desc.pBuffers   = &in_buf;
	out_desc.pBuffers   = &out_buf;

	in_buf.BufferType = SECBUFFER_TOKEN;
	in_buf.pvBuffer   = auth_buf;
	in_buf.cbBuffer   = (ULONG)len;

	out_buf.BufferType = SECBUFFER_TOKEN;
	out_buf.pvBuffer   = auth->tds_auth.packet;
	out_buf.cbBuffer   = NTLMBUF_LEN;

	status = sec_fn->InitializeSecurityContextA(&auth->cred, &auth->cred_ctx, auth->sname,
		ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION,
		0, SECURITY_NETWORK_DREP, &in_desc,
		0, &auth->cred_ctx, &out_desc,
		&attrs, &ts);

	free(auth_buf);

	if (status != SEC_E_OK)
		return TDS_FAIL;
	if (out_buf.cbBuffer == 0)
		return TDS_SUCCEED;

	tds_put_n(tds, auth->tds_auth.packet, out_buf.cbBuffer);

	return tds_flush_packet(tds);
}
Beispiel #6
0
/*
 * if a dead connection on the client side left this member in a questionable
 * state, let's bring in a correct one
 * We are not sure what the client did so we must try to clean as much as
 * possible.
 * Use pool_free_member if the state is really broken.
 */
void
pool_reset_member(TDS_POOL_MEMBER * pmbr)
{
	// FIXME not wait for server !!! asyncronous
	TDSSOCKET *tds = pmbr->tds;

	if (pmbr->current_user) {
		pmbr->current_user->assigned_member = NULL;
		pool_free_user(pmbr->current_user);
		pmbr->current_user = NULL;
	}

	/* cancel whatever pending */
	tds->state = TDS_IDLE;
	tds_init_write_buf(tds);
	tds->out_flag = TDS_CANCEL;
	tds_flush_packet(tds);
	tds->state = TDS_PENDING;

	if (tds_read_packet(tds) < 0) {
		pool_free_member(pmbr);
		return;
	}

	if (IS_TDS71_PLUS(tds->conn)) {
		/* this 0x9 final reset the state from mssql 2000 */
		tds_init_write_buf(tds);
		tds->out_flag = TDS_QUERY;
		tds_write_packet(tds, 0x9);
		tds->state = TDS_PENDING;

		if (tds_read_packet(tds) < 0) {
			pool_free_member(pmbr);
			return;
		}
	}

	pmbr->state = TDS_IDLE;
}
Beispiel #7
0
static TDSRET
tds_gss_handle_next(TDSSOCKET * tds, struct tds_authentication * auth, size_t len)
{
	TDSRET res;
	gss_buffer_desc recv_tok;

	if (((struct tds_gss_auth *) auth)->last_stat != GSS_S_CONTINUE_NEEDED)
		return TDS_FAIL;

	if (auth->packet) {
		OM_uint32 min_stat;
		gss_buffer_desc send_tok;

		send_tok.value = (void *) auth->packet;
		send_tok.length = auth->packet_len;
		gss_release_buffer(&min_stat, &send_tok);
		auth->packet = NULL;
	}

	recv_tok.length = len;
	recv_tok.value = (char* ) malloc(len);
	if (!recv_tok.value)
		return TDS_FAIL;
	tds_get_n(tds, recv_tok.value, len);

	res = tds_gss_continue(tds, (struct tds_gss_auth *) auth, &recv_tok);
	free(recv_tok.value);
	if (TDS_FAILED(res))
		return res;

	if (auth->packet_len) {
		tds->out_flag = TDS7_AUTH;
		tds_put_n(tds, auth->packet, auth->packet_len);
		return tds_flush_packet(tds);
	}
	return TDS_SUCCESS;
}
Beispiel #8
0
bool
pool_user_send_login_ack(TDS_POOL * pool, TDS_POOL_USER * puser)
{
	char msg[256];
	char block[32];
	TDSSOCKET *tds = puser->sock.tds, *mtds = puser->assigned_member->sock.tds;
	TDSLOGIN *login = puser->login;
	const char *database;
	const char *server = mtds->conn->server ? mtds->conn->server : "JDBC";
	bool dbname_mismatch, odbc_mismatch;

	pool->user_logins++;

	/* copy a bit of information, resize socket with block */
	tds->conn->tds_version = mtds->conn->tds_version;
	tds->conn->product_version = mtds->conn->product_version;
	memcpy(tds->conn->collation, mtds->conn->collation, sizeof(tds->conn->collation));
	tds->conn->tds71rev1 = mtds->conn->tds71rev1;
	free(tds->conn->product_name);
	tds->conn->product_name = strdup(mtds->conn->product_name);
	tds_realloc_socket(tds, mtds->conn->env.block_size);
	tds->conn->env.block_size = mtds->conn->env.block_size;
	tds->conn->client_spid = mtds->conn->spid;

	/* if database is different use USE statement */
	database = pool->database;
	dbname_mismatch = !tds_dstr_isempty(&login->database)
			  && strcasecmp(tds_dstr_cstr(&login->database), database) != 0;
	odbc_mismatch = (login->option_flag2 & TDS_ODBC_ON) == 0;
	if (dbname_mismatch || odbc_mismatch) {
		char *str;
		int len = 128 + tds_quote_id(mtds, NULL, tds_dstr_cstr(&login->database),-1);
		TDSRET ret;

		if ((str = (char *) malloc(len)) == NULL)
			return false;

		str[0] = 0;
		/* swicth to dblib options */
		if (odbc_mismatch)
			strcat(str, "SET ANSI_DEFAULTS OFF\nSET CONCAT_NULL_YIELDS_NULL OFF\n");
		if (dbname_mismatch) {
			strcat(str, "USE ");
			tds_quote_id(mtds, strchr(str, 0), tds_dstr_cstr(&login->database), -1);
		}
		ret = tds_submit_query(mtds, str);
		free(str);
		if (TDS_FAILED(ret) || TDS_FAILED(tds_process_simple_query(mtds)))
			return false;
		if (dbname_mismatch)
			database = tds_dstr_cstr(&login->database);
		else
			database = mtds->conn->env.database;
	}

	// 7.0
	// env database
	// database change message (with server name correct)
	// env language
	// language change message
	// env 0x3 charset ("iso_1")
	// env 0x5 lcid ("1033")
	// env 0x6 ("196609" ?? 0x30001)
	// loginack
	// env 0x4 packet size
	// done
	//
	// 7.1/7.2/7.3
	// env database
	// database change message (with server name correct)
	// env 0x7 collation
	// env language
	// language change message
	// loginack
	// env 0x4 packet size
	// done
	tds->out_flag = TDS_REPLY;
	tds_env_change(tds, TDS_ENV_DATABASE, "master", database);
	sprintf(msg, "Changed database context to '%s'.", database);
	tds_send_msg(tds, 5701, 2, 0, msg, server, NULL, 1);
	if (!login->suppress_language) {
		tds_env_change(tds, TDS_ENV_LANG, NULL, "us_english");
		tds_send_msg(tds, 5703, 1, 0, "Changed language setting to 'us_english'.", server, NULL, 1);
	}

	if (IS_TDS71_PLUS(tds->conn)) {
		tds_put_byte(tds, TDS_ENVCHANGE_TOKEN);
		tds_put_smallint(tds, 8);
		tds_put_byte(tds, TDS_ENV_SQLCOLLATION);
		tds_put_byte(tds, 5);
		tds_put_n(tds, tds->conn->collation, 5);
		tds_put_byte(tds, 0);
	}

	tds_send_login_ack(tds, mtds->conn->product_name);
	sprintf(block, "%d", tds->conn->env.block_size);
	tds_env_change(tds, TDS_ENV_PACKSIZE, block, block);
	/* tds_send_capabilities_token(tds); */
	tds_send_done_token(tds, 0, 0);

	/* send it! */
	tds_flush_packet(tds);

	tds_free_login(login);
	puser->login = NULL;
	return true;
}
Beispiel #9
0
/*
 * pool_user_login
 * Reads clients login packet and forges a login acknowledgement sequence 
 */
static bool
pool_user_login(TDS_POOL * pool, TDS_POOL_USER * puser)
{
	TDSSOCKET *tds;
	TDSLOGIN *login;

	tds = puser->sock.tds;
	while (tds->in_len <= tds->in_pos)
		if (tds_read_packet(tds) < 0)
			return false;

	tdsdump_log(TDS_DBG_NETWORK, "got packet type %d\n", tds->in_flag);
	if (tds->in_flag == TDS71_PRELOGIN) {
		if (!tds->conn->tds_version)
			tds->conn->tds_version = 0x701;
		tds->out_flag = TDS_REPLY;
		// TODO proper one !!
		// TODO detect TDS version here ??
		tds_put_n(tds,  "\x00\x00\x1a\x00\x06" /* version */
				"\x01\x00\x20\x00\x01" /* encryption */
				"\x02\x00\x21\x00\x01" /* instance ?? */
				"\x03\x00\x22\x00\x00" /* process id ?? */
				"\x04\x00\x22\x00\x01" /* MARS */
				"\xff"
				"\x0a\x00\x06\x40\x00\x00"
				"\x02"
				"\x01"
				""
				"\x00", 0x23);
		tds_flush_packet(tds);

		/* read another packet */
		tds->in_pos = tds->in_len;
		while (tds->in_len <= tds->in_pos)
			if (tds_read_packet(tds) < 0)
				return false;
	}

	puser->login = login = tds_alloc_login(1);
	if (tds->in_flag == TDS_LOGIN) {
		if (!tds->conn->tds_version)
			tds->conn->tds_version = 0x500;
		tds_read_login(tds, login);
	} else if (tds->in_flag == TDS7_LOGIN) {
		if (!tds->conn->tds_version)
			tds->conn->tds_version = 0x700;
		if (!tds7_read_login(tds, login))
			return false;
	} else {
		return false;
	}

	/* check we support version required */
	// TODO function to check it
	if (!IS_TDS71_PLUS(login))
		return false;

	tds->in_len = tds->in_pos = 0;

	dump_login(login);
	if (strcmp(tds_dstr_cstr(&login->user_name), pool->user) != 0
	    || strcmp(tds_dstr_cstr(&login->password), pool->password) != 0)
		/* TODO send nack before exiting */
		return false;

	return true;
}
Beispiel #10
0
static TDSRET
tds5_negotiate_handle_next(TDSSOCKET * tds, TDSAUTHENTICATION * tds_auth, size_t len)
{
	TDS5NEGOTIATE *auth = (TDS5NEGOTIATE *) tds_auth;
	TDSPARAMINFO *info;
	void *rsa, *nonce = NULL;
	size_t rsa_len, nonce_len = 0;
	void *em;
	size_t em_size;
	TDSRET rc = TDS_FAIL;

	/* send next data for authentication */

	if (!tds->login)
		goto error;

	/* we only support RSA authentication, we should have send 2/3 parameters:
	 * 1- integer.. unknown actually 1 TODO
	 * 2- binary, rsa public key in PEM format
	 * 3- binary, nonce (optional)
	 */

	/* message not supported */
	if (auth->msg_type != 0x1e)
		goto error;

	info = tds->param_info;
	if (!info || info->num_cols < 2)
		goto error;

	if (info->columns[1]->column_type != SYBLONGBINARY)
		goto error;
	if (info->num_cols >= 3 && info->columns[2]->column_type != SYBLONGBINARY)
		goto error;
	rsa = ((TDSBLOB*) info->columns[1]->column_data)->textvalue;
	rsa_len = info->columns[1]->column_size;
	if (info->num_cols >= 3) {
		nonce = ((TDSBLOB*) info->columns[2]->column_data)->textvalue;
		nonce_len = info->columns[2]->column_size;
	}

	em = tds5_rsa_encrypt(rsa, rsa_len, nonce, nonce_len, tds_dstr_cstr(&tds->login->password), &em_size);
	if (!em)
		goto error;

	tds->out_flag = TDS_NORMAL;

	/* password */
	tds5_send_msg(tds, 0x1f);
	tds_put_n(tds, "\xec\x0e\x00\x01\x00\x00\x00\x00\x00\x00\x00\xe1\xff\xff\xff\x7f\x00", 0x11);
	tds_put_byte(tds, TDS5_PARAMS_TOKEN);
	tds_put_int(tds, em_size);
	tds_put_n(tds, em, em_size);

	/* remote password */
	tds5_send_msg(tds, 0x20);
	tds_put_n(tds, "\xec\x17\x00\x02\x00\x00\x00\x00\x00\x00\x00\x27\xff\x00\x00\x00\x00\x00\x00\x00\xe1\xff\xff\xff\x7f\x00", 0x1a);
	tds_put_byte(tds, TDS5_PARAMS_TOKEN);
	tds_put_byte(tds, 0);
	tds_put_int(tds, em_size);
	tds_put_n(tds, em, em_size);

	free(em);

	rc = tds_flush_packet(tds);

error:
	tds5_negotiate_free(tds->conn, tds_auth);
	tds->conn->authentication = NULL;

	return rc;
}
Beispiel #11
0
int
main(int argc, char **argv)
{
    TDSCONTEXT *ctx;
    TDSSOCKET *tds;
    TDSLOGIN *login;
    TDSRESULTINFO *resinfo;

    if (argc < 2 || atoi(argv[1]) <= 0) {
        fprintf(stderr, "syntax: %s <port>\n", argv[0]);
        return 1;
    }

    ctx = tds_alloc_context(NULL);
    tds = tds_listen(ctx, atoi(argv[1]));
    if (!tds)
        return 1;
    /* get_incoming(tds->s); */
    login = tds_alloc_read_login(tds);
    if (!login) {
        fprintf(stderr, "Error reading login\n");
        exit(1);
    }
    dump_login(login);
    if (!strcmp(tds_dstr_cstr(&login->user_name), "guest") && !strcmp(tds_dstr_cstr(&login->password), "sybase")) {
        tds->out_flag = TDS_REPLY;
        tds_env_change(tds, TDS_ENV_DATABASE, "master", "pubs2");
        tds_send_msg(tds, 5701, 2, 10, "Changed database context to 'pubs2'.", "JDBC", "ZZZZZ", 1);
        if (!login->suppress_language) {
            tds_env_change(tds, TDS_ENV_LANG, NULL, "us_english");
            tds_send_msg(tds, 5703, 1, 10, "Changed language setting to 'us_english'.", "JDBC", "ZZZZZ", 1);
        }
        tds_env_change(tds, TDS_ENV_PACKSIZE, NULL, "512");
        /* TODO set mssql if tds7+ */
        tds_send_login_ack(tds, "sql server");
        if (IS_TDS50(tds))
            tds_send_capabilities_token(tds);
        tds_send_done_token(tds, 0, 1);
    } else {
        /* send nack before exiting */
        exit(1);
    }
    tds_flush_packet(tds);
    tds_free_login(login);
    login = NULL;
    /* printf("incoming packet %d\n", tds_read_packet(tds)); */
    printf("query : %s\n", tds_get_generic_query(tds));
    tds->out_flag = TDS_REPLY;
    resinfo = tds_alloc_results(1);
    resinfo->columns[0]->column_type = SYBVARCHAR;
    resinfo->columns[0]->column_size = 30;
    strcpy(resinfo->columns[0]->column_name, "name");
    resinfo->columns[0]->column_namelen = 4;
    resinfo->current_row = (TDS_UCHAR*) "pubs2";
    resinfo->columns[0]->column_data = resinfo->current_row;
    tds_send_result(tds, resinfo);
    tds_send_control_token(tds, 1);
    tds_send_row(tds, resinfo);
    tds_send_done_token(tds, 16, 1);
    tds_flush_packet(tds);
    sleep(30);

    tds_free_results(resinfo);
    tds_free_socket(tds);
    tds_free_context(ctx);

    return 0;
}