Пример #1
0
/** Destroy a DSNINFO struct, freeing all memory associated with it */
static void
free_dsninfo(DSNINFO * di)
{				/* the DSNINFO struct to be freed */
	tds_free_login(di->login);
	tds_dstr_free(&di->origdsn);
	tds_dstr_free(&di->dsn);
	free(di);
}
Пример #2
0
static int
tds_read_conf_sections(FILE * in, const char *server, TDSLOGIN * login)
{
	DSTR default_instance;
	int default_port;

	int found;

	tds_read_conf_section(in, "global", tds_parse_conf_section, login);

	if (!server[0])
		return 0;
	rewind(in);

	tds_dstr_init(&default_instance);
	tds_dstr_dup(&default_instance, &login->instance_name);
	default_port = login->port;

	found = tds_read_conf_section(in, server, tds_parse_conf_section, login);

	/* 
	 * If both instance and port are specified and neither one came from the default, it's an error 
	 * TODO: If port/instance is specified in the non-default, it has priority over the default setting. 
	 * TODO: test this. 
	 */
	if (!tds_dstr_isempty(&login->instance_name) && login->port &&
	    !(!tds_dstr_isempty(&default_instance) || default_port)) {
		tdsdump_log(TDS_DBG_ERROR, "error: cannot specify both port %d and instance %s.\n", 
						login->port, tds_dstr_cstr(&login->instance_name));
		/* tdserror(tds_get_ctx(tds), tds, TDSEPORTINSTANCE, 0); */
	}
	tds_dstr_free(&default_instance);
	return found;
}
Пример #3
0
/** 
 * Parse connection string and fill connect_info according
 * @param connect_string     connect string
 * @param connect_string_end connect string end (pointer to char past last)
 * @param connect_info       where to store connection info
 * @return 1 if success 0 otherwhise
 */
int
odbc_parse_connect_string(const char *connect_string, const char *connect_string_end, TDSCONNECTINFO * connect_info)
{
	const char *p, *end;
	DSTR *dest_s, value;
	int reparse = 0;	/* flag for indicate second parse of string */
	char option[16];
	char tmp[256];

	tds_dstr_init(&value);
	for (p = connect_string; p && *p;) {
		dest_s = NULL;

		/* parse option */
		end = (const char *) memchr(p, '=', connect_string_end - p);
		if (!end)
			break;

		/* account for spaces between ;'s. */
		while (p < end && *p == ' ')
			++p;

		if ((end - p) >= (int) sizeof(option))
			option[0] = 0;
		else {
			memcpy(option, p, end - p);
			option[end - p] = 0;
		}

		/* parse value */
		p = end + 1;
		if (*p == '{') {
			++p;
			/* search "};" */
			end = p;
			while ((end = (const char *) memchr(end, '}', connect_string_end - end)) != NULL) {
				if ((end + 1) != connect_string_end && end[1] == ';')
					break;
				++end;
			}
		} else {
			end = (const char *) memchr(p, ';', connect_string_end - p);
		}
		if (!end)
			end = connect_string_end;

		if (!tds_dstr_copyn(&value, p, end - p))
			return 0;

		if (strcasecmp(option, "SERVER") == 0) {
			/* ignore if servername specified */
			if (!reparse) {
				dest_s = &connect_info->server_name;
				tds_lookup_host(tds_dstr_cstr(&value), tmp);
				if (!tds_dstr_copy(&connect_info->ip_addr, tmp)) {
					tds_dstr_free(&value);
					return 0;
				}
			}
		} else if (strcasecmp(option, "SERVERNAME") == 0) {
			if (!reparse) {
				tds_read_conf_file(connect_info, tds_dstr_cstr(&value));
				reparse = 1;
				p = connect_string;
				continue;
			}
		} else if (strcasecmp(option, "DSN") == 0) {
			if (!reparse) {
				odbc_get_dsn_info(tds_dstr_cstr(&value), connect_info);
				reparse = 1;
				p = connect_string;
				continue;
			}
		} else if (strcasecmp(option, "DATABASE") == 0) {
			dest_s = &connect_info->database;
		} else if (strcasecmp(option, "UID") == 0) {
			dest_s = &connect_info->user_name;
		} else if (strcasecmp(option, "PWD") == 0) {
			dest_s = &connect_info->password;
		} else if (strcasecmp(option, "APP") == 0) {
			dest_s = &connect_info->app_name;
		} else if (strcasecmp(option, "WSID") == 0) {
			dest_s = &connect_info->host_name;
		} else if (strcasecmp(option, "LANGUAGE") == 0) {
			dest_s = &connect_info->language;
		} else if (strcasecmp(option, "Port") == 0) {
			connect_info->port = atoi(tds_dstr_cstr(&value));
		} else if (strcasecmp(option, "TDS_Version") == 0) {
			tds_config_verstr(tds_dstr_cstr(&value), connect_info);
		} else if (strcasecmp(option, "Domain") == 0) {
			dest_s = &connect_info->default_domain;
		} else if (strcasecmp(option, "TextSize") == 0) {
			connect_info->text_size = atoi(tds_dstr_cstr(&value));
		} else if (strcasecmp(option, "PacketSize") == 0) {
			connect_info->block_size = atoi(tds_dstr_cstr(&value));
			/* TODO "Address" field */
		}

		/* copy to destination */
		if (dest_s) {
			tds_dstr_set(dest_s, tds_dstr_cstr(&value));
			tds_dstr_init(&value);
		}

		p = end;
		/* handle "" ";.." "};.." cases */
		if (p >= connect_string_end)
			break;
		if (*p == '}')
			++p;
		++p;
	}

	tds_dstr_free(&value);
	return p != NULL;
}
Пример #4
0
/** 
 * Parse connection string and fill login according
 * @param connect_string     connect string
 * @param connect_string_end connect string end (pointer to char past last)
 * @param login         where to store connection info
 * @return 1 if success 0 otherwhise
 */
int
odbc_parse_connect_string(TDS_ERRS *errs, const char *connect_string, const char *connect_string_end, TDSLOGIN * login,
			  TDS_PARSED_PARAM *parsed_params)
{
	const char *p, *end;
	DSTR *dest_s, value = DSTR_INITIALIZER;
	enum { CFG_DSN = 1, CFG_SERVER = 2, CFG_SERVERNAME = 4 };
	unsigned int cfgs = 0;	/* flags for indicate second parse of string */
	char option[24];
	int trusted = 0;

	if (parsed_params)
		memset(parsed_params, 0, sizeof(*parsed_params)*ODBC_PARAM_SIZE);

	for (p = connect_string; p < connect_string_end && *p;) {
		int num_param = -1;

		dest_s = NULL;

		/* handle empty options */
		while (p < connect_string_end && *p == ';')
			++p;

		/* parse option */
		end = (const char *) memchr(p, '=', connect_string_end - p);
		if (!end)
			break;

		/* account for spaces between ;'s. */
		while (p < end && *p == ' ')
			++p;

		if ((end - p) >= (int) sizeof(option))
			option[0] = 0;
		else {
			memcpy(option, p, end - p);
			option[end - p] = 0;
		}

		/* parse value */
		p = end + 1;
		if (*p == '{') {
			++p;
			/* search "};" */
			end = p;
			while ((end = (const char *) memchr(end, '}', connect_string_end - end)) != NULL) {
				if ((end + 1) != connect_string_end && end[1] == ';')
					break;
				++end;
			}
		} else {
			end = (const char *) memchr(p, ';', connect_string_end - p);
		}
		if (!end)
			end = connect_string_end;

		if (!tds_dstr_copyn(&value, p, end - p)) {
			odbc_errs_add(errs, "HY001", NULL);
			return 0;
		}

#define CHK_PARAM(p) (strcasecmp(option, odbc_param_##p) == 0 && (num_param=ODBC_PARAM_##p) >= 0)
		if (CHK_PARAM(Server)) {
			/* error if servername or DSN specified */
			if ((cfgs & (CFG_DSN|CFG_SERVERNAME)) != 0) {
				tds_dstr_free(&value);
				odbc_errs_add(errs, "HY000", "Only one between SERVER, SERVERNAME and DSN can be specified");
				return 0;
			}
			if (!cfgs) {
				dest_s = &login->server_name;
				/* not that safe cast but works -- freddy77 */
				if (!parse_server(errs, (char *) tds_dstr_cstr(&value), login)) {
					tds_dstr_free(&value);
					return 0;
				}
				cfgs = CFG_SERVER;
			}
		} else if (CHK_PARAM(Servername)) {
			if ((cfgs & (CFG_DSN|CFG_SERVER)) != 0) {
				tds_dstr_free(&value);
				odbc_errs_add(errs, "HY000", "Only one between SERVER, SERVERNAME and DSN can be specified");
				return 0;
			}
			if (!cfgs) {
				odbc_dstr_swap(&login->server_name, &value);
				tds_read_conf_file(login, tds_dstr_cstr(&login->server_name));
				cfgs = CFG_SERVERNAME;
				p = connect_string;
				continue;
			}
		} else if (CHK_PARAM(DSN)) {
			if ((cfgs & (CFG_SERVER|CFG_SERVERNAME)) != 0) {
				tds_dstr_free(&value);
				odbc_errs_add(errs, "HY000", "Only one between SERVER, SERVERNAME and DSN can be specified");
				return 0;
			}
			if (!cfgs) {
				if (!odbc_get_dsn_info(errs, tds_dstr_cstr(&value), login)) {
					tds_dstr_free(&value);
					return 0;
				}
				cfgs = CFG_DSN;
				p = connect_string;
				continue;
			}
		} else if (CHK_PARAM(Database)) {
			dest_s = &login->database;
		} else if (CHK_PARAM(UID)) {
			dest_s = &login->user_name;
		} else if (CHK_PARAM(PWD)) {
			dest_s = &login->password;
		} else if (CHK_PARAM(APP)) {
			dest_s = &login->app_name;
		} else if (CHK_PARAM(WSID)) {
			dest_s = &login->client_host_name;
		} else if (CHK_PARAM(Language)) {
			tds_parse_conf_section(TDS_STR_LANGUAGE, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(Port)) {
			tds_parse_conf_section(TDS_STR_PORT, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(TDS_Version)) {
			tds_parse_conf_section(TDS_STR_VERSION, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(TextSize)) {
			tds_parse_conf_section(TDS_STR_TEXTSZ, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(PacketSize)) {
			tds_parse_conf_section(TDS_STR_BLKSZ, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(ClientCharset)) {
			tds_parse_conf_section(TDS_STR_CLCHARSET, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(DumpFile)) {
			tds_parse_conf_section(TDS_STR_DUMPFILE, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(DumpFileAppend)) {
			tds_parse_conf_section(TDS_STR_APPENDMODE, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(DebugFlags)) {
			tds_parse_conf_section(TDS_STR_DEBUGFLAGS, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(Encryption)) {
			tds_parse_conf_section(TDS_STR_ENCRYPTION, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(UseNTLMv2)) {
			tds_parse_conf_section(TDS_STR_USENTLMV2, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(REALM)) {
			tds_parse_conf_section(TDS_STR_REALM, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(ServerSPN)) {
			tds_parse_conf_section(TDS_STR_SPN, tds_dstr_cstr(&value), login);
		} else if (CHK_PARAM(Trusted_Connection)) {
			trusted = tds_config_boolean(option, tds_dstr_cstr(&value), login);
			tdsdump_log(TDS_DBG_INFO1, "trusted %s -> %d\n", tds_dstr_cstr(&value), trusted);
			num_param = -1;
			/* TODO odbc_param_Address field */
		} else if (CHK_PARAM(MARS_Connection)) {
			if (tds_config_boolean(option, tds_dstr_cstr(&value), login))
				login->mars = 1;
		} else if (CHK_PARAM(AttachDbFilename)) {
			dest_s = &login->db_filename;
		} else if (CHK_PARAM(ApplicationIntent)) {
			const char *readonly_intent;

			if (strcasecmp(tds_dstr_cstr(&value), "ReadOnly") == 0) {
				readonly_intent = "yes";
			} else if (strcasecmp(tds_dstr_cstr(&value), "ReadWrite") == 0) {
				readonly_intent = "no";
			} else {
				tdsdump_log(TDS_DBG_ERROR, "Invalid ApplicationIntent %s\n", tds_dstr_cstr(&value));
				return 0;
			}

			tds_parse_conf_section(TDS_STR_READONLY_INTENT, readonly_intent, login);
			tdsdump_log(TDS_DBG_INFO1, "Application Intent %s\n", readonly_intent);
		}

		if (num_param >= 0 && parsed_params) {
			parsed_params[num_param].p = p;
			parsed_params[num_param].len = end - p;
		}

		/* copy to destination */
		if (dest_s)
			odbc_dstr_swap(dest_s, &value);

		p = end;
		/* handle "" ";.." "};.." cases */
		if (p >= connect_string_end)
			break;
		if (*p == '}')
			++p;
		++p;
	}

	if (trusted) {
		if (parsed_params) {
			parsed_params[ODBC_PARAM_Trusted_Connection].p = "Yes";
			parsed_params[ODBC_PARAM_Trusted_Connection].len = 3;
			parsed_params[ODBC_PARAM_UID].p = NULL;
			parsed_params[ODBC_PARAM_PWD].p = NULL;
		}
		tds_dstr_empty(&login->user_name);
		tds_dstr_empty(&login->password);
	}

	tds_dstr_free(&value);
	return 1;
}