/** Create an empty DSNINFO struct */ static DSNINFO * alloc_dsninfo(void) { DSNINFO *di; /* allocate & initialize it */ di = (DSNINFO *) malloc(sizeof(DSNINFO)); tds_dstr_init(&di->origdsn); tds_dstr_init(&di->dsn); di->login = tds_alloc_connection(NULL); return di; }
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; }
/** * 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; }
/** * 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; 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); tds_dstr_init(&value); 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) || strcasecmp(option, "client_charset") == 0) { 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; } 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; }