/* Also used to scan ODBC.INI entries */ void tds_parse_conf_section(const char *option, const char *value, void *param) { TDSLOGIN *login = (TDSLOGIN *) param; void *s = param; tdsdump_log(TDS_DBG_INFO1, "\t%s = '%s'\n", option, value); if (!strcmp(option, TDS_STR_VERSION)) { tds_config_verstr(value, login); } else if (!strcmp(option, TDS_STR_BLKSZ)) { int val = atoi(value); if (val >= 512 && val < 65536) login->block_size = val; } else if (!strcmp(option, TDS_STR_SWAPDT)) { /* this option is deprecated, just check value for compatibility */ tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_GSSAPI_DELEGATION)) { /* gssapi flag addition */ login->gssapi_use_delegation = tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_STR_DUMPFILE)) { s = tds_dstr_copy(&login->dump_file, value); } else if (!strcmp(option, TDS_STR_DEBUGFLAGS)) { char *end; long flags; flags = strtol(value, &end, 0); if (*value != '\0' && *end == '\0' && flags != LONG_MIN && flags != LONG_MAX) login->debug_flags = flags; } else if (!strcmp(option, TDS_STR_TIMEOUT) || !strcmp(option, TDS_STR_QUERY_TIMEOUT)) { if (atoi(value)) login->query_timeout = atoi(value); } else if (!strcmp(option, TDS_STR_CONNTIMEOUT)) { if (atoi(value)) login->connect_timeout = atoi(value); } else if (!strcmp(option, TDS_STR_HOST)) { char tmp[128]; struct addrinfo *addrs; if (TDS_FAILED(tds_lookup_host_set(value, &login->ip_addrs))) { tdsdump_log(TDS_DBG_WARN, "Found host entry %s however name resolution failed. \n", value); return; } tdsdump_log(TDS_DBG_INFO1, "Found host entry %s \n", value); s = tds_dstr_copy(&login->server_host_name, value); for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) tdsdump_log(TDS_DBG_INFO1, "IP addr is %s.\n", tds_addrinfo2str(addrs, tmp, sizeof(tmp))); } else if (!strcmp(option, TDS_STR_PORT)) { if (atoi(value)) login->port = atoi(value); } else if (!strcmp(option, TDS_STR_EMUL_LE)) { login->emul_little_endian = tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_STR_TEXTSZ)) { if (atoi(value)) login->text_size = atoi(value); } else if (!strcmp(option, TDS_STR_CHARSET)) { s = tds_dstr_copy(&login->server_charset, value); tdsdump_log(TDS_DBG_INFO1, "%s is %s.\n", option, tds_dstr_cstr(&login->server_charset)); } else if (!strcmp(option, TDS_STR_CLCHARSET)) { s = tds_dstr_copy(&login->client_charset, value); tdsdump_log(TDS_DBG_INFO1, "tds_parse_conf_section: %s is %s.\n", option, tds_dstr_cstr(&login->client_charset)); } else if (!strcmp(option, TDS_STR_USE_UTF_16)) { login->use_utf16 = tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_STR_LANGUAGE)) { s = tds_dstr_copy(&login->language, value); } else if (!strcmp(option, TDS_STR_APPENDMODE)) { tds_g_append_mode = tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_STR_INSTANCE)) { s = tds_dstr_copy(&login->instance_name, value); } else if (!strcmp(option, TDS_STR_ENCRYPTION)) { tds_config_encryption(value, login); } else if (!strcmp(option, TDS_STR_ASA_DATABASE)) { s = tds_dstr_copy(&login->server_name, value); } else if (!strcmp(option, TDS_STR_USENTLMV2)) { login->use_ntlmv2 = tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_STR_USELANMAN)) { login->use_lanman = tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_STR_REALM)) { s = tds_dstr_copy(&login->server_realm_name, value); } else if (!strcmp(option, TDS_STR_SPN)) { s = tds_dstr_copy(&login->server_spn, value); } else if (!strcmp(option, TDS_STR_CAFILE)) { s = tds_dstr_copy(&login->cafile, value); } else if (!strcmp(option, TDS_STR_CRLFILE)) { s = tds_dstr_copy(&login->crlfile, value); } else if (!strcmp(option, TDS_STR_CHECKSSLHOSTNAME)) { login->check_ssl_hostname = tds_config_boolean(option, value, login); } else if (!strcmp(option, TDS_STR_DBFILENAME)) { s = tds_dstr_copy(&login->db_filename, value); } else if (!strcmp(option, TDS_STR_DATABASE)) { s = tds_dstr_copy(&login->database, value); } else if (!strcmp(option, TDS_STR_READONLY_INTENT)) { login->readonly_intent = tds_config_boolean(option, value, login); tdsdump_log(TDS_DBG_FUNC, "Setting ReadOnly Intent to '%s'.\n", value); } else { tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s' ... ignoring.\n", option); } if (!s) login->valid_configuration = 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; }
static void tds_parse_conf_section(const char *option, const char *value, void *param) { TDSCONNECTINFO *connect_info = (TDSCONNECTINFO *) param; char tmp[256]; tdsdump_log(TDS_DBG_INFO1, "%L option = '%s' value = '%s'.\n", option, value); if (!strcmp(option, TDS_STR_VERSION)) { tds_config_verstr(value, connect_info); } else if (!strcmp(option, TDS_STR_BLKSZ)) { if (atoi(value)) connect_info->block_size = atoi(value); } else if (!strcmp(option, TDS_STR_SWAPDT)) { connect_info->broken_dates = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_SWAPMNY)) { connect_info->broken_money = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_TRYSVR)) { connect_info->try_server_login = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_TRYDOM)) { connect_info->try_domain_login = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_DOMAIN)) { tds_dstr_copy(&connect_info->default_domain, value); } else if (!strcmp(option, TDS_STR_XDOMAUTH)) { connect_info->xdomain_auth = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_DUMPFILE)) { tds_dstr_copy(&connect_info->dump_file, value); } else if (!strcmp(option, TDS_STR_DEBUGLVL)) { if (atoi(value)) connect_info->debug_level = atoi(value); } else if (!strcmp(option, TDS_STR_TIMEOUT)) { if (atoi(value)) connect_info->timeout = atoi(value); } else if (!strcmp(option, TDS_STR_CONNTMOUT)) { if (atoi(value)) connect_info->connect_timeout = atoi(value); } else if (!strcmp(option, TDS_STR_HOST)) { tdsdump_log(TDS_DBG_INFO1, "%L Found host entry %s.\n", value); tds_lookup_host(value, tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); tdsdump_log(TDS_DBG_INFO1, "%L IP addr is %s.\n", connect_info->ip_addr); } else if (!strcmp(option, TDS_STR_PORT)) { if (atoi(value)) connect_info->port = atoi(value); } else if (!strcmp(option, TDS_STR_EMUL_LE)) { connect_info->emul_little_endian = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_TEXTSZ)) { if (atoi(value)) connect_info->text_size = atoi(value); } else if (!strcmp(option, TDS_STR_CHARSET)) { tds_dstr_copy(&connect_info->server_charset, value); tdsdump_log(TDS_DBG_INFO1, "%L %s is %s.\n", option, connect_info->server_charset); } else if (!strcmp(option, TDS_STR_CLCHARSET)) { tds_dstr_copy(&connect_info->client_charset, value); tdsdump_log(TDS_DBG_INFO1, "%L tds_config_login:%d: %s is %s.\n", __LINE__, option, connect_info->client_charset); } else if (!strcmp(option, TDS_STR_LANGUAGE)) { tds_dstr_copy(&connect_info->language, value); } else if (!strcmp(option, TDS_STR_APPENDMODE)) { tds_g_append_mode = tds_config_boolean(value); } else { tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s'...ignoring.\n", option); fprintf(stderr, "FreeTDS: %s:%d: ignoring unrecognized option '%s'\n", __FILE__, __LINE__, option); } }
/** * Read connection information from given DSN * @param DSN DSN name * @param login where to store connection info * @return 1 if success 0 otherwhise */ int odbc_get_dsn_info(TDS_ERRS *errs, const char *DSN, TDSLOGIN * login) { char tmp[FILENAME_MAX]; int freetds_conf_less = 1; /* use old servername */ if (myGetPrivateProfileString(DSN, odbc_param_Servername, tmp) > 0) { freetds_conf_less = 0; if (!tds_dstr_copy(&login->server_name, tmp)) { odbc_errs_add(errs, "HY001", NULL); return 0; } tds_read_conf_file(login, tmp); if (myGetPrivateProfileString(DSN, odbc_param_Server, tmp) > 0) { odbc_errs_add(errs, "HY000", "You cannot specify both SERVERNAME and SERVER"); return 0; } if (myGetPrivateProfileString(DSN, odbc_param_Address, tmp) > 0) { odbc_errs_add(errs, "HY000", "You cannot specify both SERVERNAME and ADDRESS"); return 0; } } /* search for server (compatible with ms one) */ if (freetds_conf_less) { int address_specified = 0; if (myGetPrivateProfileString(DSN, odbc_param_Address, tmp) > 0) { address_specified = 1; /* TODO parse like MS */ if (TDS_FAILED(tds_lookup_host_set(tmp, &login->ip_addrs))) { odbc_errs_add(errs, "HY000", "Error parsing ADDRESS attribute"); return 0; } } if (myGetPrivateProfileString(DSN, odbc_param_Server, tmp) > 0) { if (!tds_dstr_copy(&login->server_name, tmp)) { odbc_errs_add(errs, "HY001", NULL); return 0; } if (!address_specified) { if (!parse_server(errs, tmp, login)) return 0; } } } if (myGetPrivateProfileString(DSN, odbc_param_Port, tmp) > 0) tds_parse_conf_section(TDS_STR_PORT, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_TDS_Version, tmp) > 0) tds_parse_conf_section(TDS_STR_VERSION, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_Language, tmp) > 0) tds_parse_conf_section(TDS_STR_LANGUAGE, tmp, login); if (tds_dstr_isempty(&login->database) && myGetPrivateProfileString(DSN, odbc_param_Database, tmp) > 0) if (!tds_dstr_copy(&login->database, tmp)) { odbc_errs_add(errs, "HY001", NULL); return 0; } if (myGetPrivateProfileString(DSN, odbc_param_TextSize, tmp) > 0) tds_parse_conf_section(TDS_STR_TEXTSZ, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_PacketSize, tmp) > 0) tds_parse_conf_section(TDS_STR_BLKSZ, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_ClientCharset, tmp) > 0) tds_parse_conf_section(TDS_STR_CLCHARSET, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_DumpFile, tmp) > 0) tds_parse_conf_section(TDS_STR_DUMPFILE, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_DumpFileAppend, tmp) > 0) tds_parse_conf_section(TDS_STR_APPENDMODE, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_DebugFlags, tmp) > 0) tds_parse_conf_section(TDS_STR_DEBUGFLAGS, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_Encryption, tmp) > 0) tds_parse_conf_section(TDS_STR_ENCRYPTION, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_UseNTLMv2, tmp) > 0) tds_parse_conf_section(TDS_STR_USENTLMV2, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_REALM, tmp) > 0) tds_parse_conf_section(TDS_STR_REALM, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_ServerSPN, tmp) > 0) tds_parse_conf_section(TDS_STR_SPN, tmp, login); if (myGetPrivateProfileString(DSN, odbc_param_Trusted_Connection, tmp) > 0 && tds_config_boolean(odbc_param_Trusted_Connection, tmp, login)) { tds_dstr_empty(&login->user_name); tds_dstr_empty(&login->password); } if (myGetPrivateProfileString(DSN, odbc_param_MARS_Connection, tmp) > 0 && tds_config_boolean(odbc_param_MARS_Connection, tmp, login)) { login->mars = 1; } if (myGetPrivateProfileString(DSN, odbc_param_AttachDbFilename, tmp) > 0) tds_parse_conf_section(TDS_STR_DBFILENAME, tmp, login); return 1; }