/* 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 { tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s' ... ignoring.\n", option); } if (!s) login->valid_configuration = 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; }
/** * Open and read the file 'file' searching for a logical server * by the name of 'host'. If one is found then lookup * the IP address and port number and store them in 'login' * * \param dir name of base directory for interface file * \param file name of the interface file * \param host logical host to search for * \return 0 if not fount 1 if found */ static int search_interface_file(TDSLOGIN * login, const char *dir, const char *file, const char *host) { char *pathname; char line[255]; char tmp_ip[sizeof(line)]; char tmp_port[sizeof(line)]; char tmp_ver[sizeof(line)]; FILE *in; char *field; int found = 0; int server_found = 0; char *lasts; line[0] = '\0'; tmp_ip[0] = '\0'; tmp_port[0] = '\0'; tmp_ver[0] = '\0'; tdsdump_log(TDS_DBG_INFO1, "Searching interfaces file %s/%s.\n", dir, file); pathname = (char *) malloc(strlen(dir) + strlen(file) + 10); if (!pathname) return 0; /* * create the full pathname to the interface file */ if (file[0] == '\0') { pathname[0] = '\0'; } else { if (dir[0] == '\0') { pathname[0] = '\0'; } else { strcpy(pathname, dir); strcat(pathname, TDS_SDIR_SEPARATOR); } strcat(pathname, file); } /* * parse the interfaces file and find the server and port */ if ((in = fopen(pathname, "r")) == NULL) { tdsdump_log(TDS_DBG_INFO1, "Couldn't open %s.\n", pathname); free(pathname); return 0; } tdsdump_log(TDS_DBG_INFO1, "Interfaces file %s opened.\n", pathname); while (fgets(line, sizeof(line) - 1, in)) { if (line[0] == '#') continue; /* comment */ if (!TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (!strcmp(field, host)) { found = 1; tdsdump_log(TDS_DBG_INFO1, "Found matching entry for host %s.\n", host); } else found = 0; } else if (found && TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (field != NULL && !strcmp(field, "query")) { field = strtok_r(NULL, "\n\t ", &lasts); /* tcp or tli */ if (!strcmp(field, "tli")) { tdsdump_log(TDS_DBG_INFO1, "TLI service.\n"); field = strtok_r(NULL, "\n\t ", &lasts); /* tcp */ field = strtok_r(NULL, "\n\t ", &lasts); /* device */ field = strtok_r(NULL, "\n\t ", &lasts); /* host/port */ if (strlen(field) >= 18) { sprintf(tmp_port, "%d", hex2num(&field[6]) * 256 + hex2num(&field[8])); sprintf(tmp_ip, "%d.%d.%d.%d", hex2num(&field[10]), hex2num(&field[12]), hex2num(&field[14]), hex2num(&field[16])); tdsdump_log(TDS_DBG_INFO1, "tmp_port = %s. tmp_ip = %s.\n", tmp_port, tmp_ip); } } else { field = strtok_r(NULL, "\n\t ", &lasts); /* ether */ strcpy(tmp_ver, field); field = strtok_r(NULL, "\n\t ", &lasts); /* host */ strcpy(tmp_ip, field); tdsdump_log(TDS_DBG_INFO1, "host field %s.\n", tmp_ip); field = strtok_r(NULL, "\n\t ", &lasts); /* port */ strcpy(tmp_port, field); } /* else */ server_found = 1; } /* if */ } /* else if */ } /* while */ fclose(in); free(pathname); /* * Look up the host and service */ if (server_found) { if (TDS_SUCCEED(tds_lookup_host_set(tmp_ip, &login->ip_addrs))) { struct addrinfo *addrs; if (!tds_dstr_copy(&login->server_host_name, tmp_ip)) return 0; for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) { tdsdump_log(TDS_DBG_INFO1, "Resolved IP as '%s'.\n", tds_addrinfo2str(login->ip_addrs, line, sizeof(line))); } } else { tdsdump_log(TDS_DBG_WARN, "Name resolution failed for IP '%s'.\n", tmp_ip); } if (tmp_port[0]) login->port = tds_lookup_port(tmp_port); if (tmp_ver[0]) tds_config_verstr(tmp_ver, login); } return server_found; } /* search_interface_file() */
/** * Read connection information from given DSN * @param DSN DSN name * @param connect_info where to store connection info * @return 1 if success 0 otherwhise */ int odbc_get_dsn_info(const char *DSN, TDSCONNECTINFO * connect_info) { char tmp[FILENAME_MAX]; int freetds_conf_less = 1; int address_specified = 0; /* use old servername */ tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Servername", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { freetds_conf_less = 0; tds_read_conf_file(connect_info, tmp); } /* search for server (compatible with ms one) */ if (freetds_conf_less) { tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Address", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { address_specified = 1; /* TODO parse like MS */ tds_lookup_host(tmp, tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Server", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->server_name, tmp); if (!address_specified) { tds_lookup_host(tds_dstr_cstr(&connect_info->server_name), tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); } } } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Port", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { connect_info->port = atoi(tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "TDS_Version", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_config_verstr(tmp, connect_info); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Language", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->language, tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Database", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->database, tmp); } #if 0 tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Authentication", "Server", tmp, FILENAME_MAX, "odbc.ini") > 0) { if (!strcasecmp(tmp, "Server")) { connect_info->try_domain_login = 0; connect_info->try_server_login = 1; } else if (!strcasecmp(tmp, "Domain")) { connect_info->try_domain_login = 1; connect_info->try_server_login = 0; } else if (!strcasecmp(tmp, "Both")) { connect_info->try_server_login = 1; connect_info->try_domain_login = 1; } else { /* default to server authentication */ connect_info->try_domain_login = 0; connect_info->try_server_login = 1; } } #endif tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Domain", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->default_domain, tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "TextSize", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { connect_info->text_size = atoi(tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "PacketSize", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { connect_info->block_size = atoi(tmp); } return 1; }