LCOV - code coverage report
Current view: top level - src/tds - config.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 343 600 57.2 %
Date: 2025-12-03 08:48:55 Functions: 22 28 78.6 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
       3             :  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011  Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #include <stdarg.h>
      24             : #include <stdio.h>
      25             : 
      26             : #if HAVE_ERRNO_H
      27             : #include <errno.h>
      28             : #endif /* HAVE_ERRNO_H */
      29             : 
      30             : #include <assert.h>
      31             : #include <ctype.h>
      32             : 
      33             : #if HAVE_STDLIB_H
      34             : #include <stdlib.h>
      35             : #endif /* HAVE_STDLIB_H */
      36             : 
      37             : #if HAVE_LIMITS_H
      38             : #include <limits.h>
      39             : #endif 
      40             : 
      41             : #if HAVE_STRING_H
      42             : #include <string.h>
      43             : #endif /* HAVE_STRING_H */
      44             : 
      45             : #if HAVE_UNISTD_H
      46             : #include <unistd.h>
      47             : #endif /* HAVE_UNISTD_H */
      48             : 
      49             : #if HAVE_NETDB_H
      50             : #include <netdb.h>
      51             : #endif /* HAVE_NETDB_H */
      52             : 
      53             : #if HAVE_SYS_SOCKET_H
      54             : #include <sys/socket.h>
      55             : #endif /* HAVE_SYS_SOCKET_H */
      56             : 
      57             : #if HAVE_SYS_TYPES_H
      58             : #include <sys/types.h>
      59             : #endif /* HAVE_SYS_TYPES_H */
      60             : 
      61             : #if HAVE_NETINET_IN_H
      62             : #include <netinet/in.h>
      63             : #endif /* HAVE_NETINET_IN_H */
      64             : 
      65             : #if HAVE_ARPA_INET_H
      66             : #include <arpa/inet.h>
      67             : #endif /* HAVE_ARPA_INET_H */
      68             : 
      69             : #ifdef _WIN32
      70             : #include <process.h>
      71             : #endif
      72             : 
      73             : #include <freetds/tds.h>
      74             : #include <freetds/configs.h>
      75             : #include <freetds/utils/string.h>
      76             : #include <freetds/utils.h>
      77             : #include <freetds/replacements.h>
      78             : 
      79             : static bool tds_config_login(TDSLOGIN * connection, TDSLOGIN * login);
      80             : static bool tds_config_env_tdsdump(TDSLOGIN * login);
      81             : static void tds_config_env_tdsver(TDSLOGIN * login);
      82             : static void tds_config_env_tdsport(TDSLOGIN * login);
      83             : static bool tds_config_env_tdshost(TDSLOGIN * login);
      84             : static bool tds_read_conf_sections(FILE * in, const char *server, TDSLOGIN * login);
      85             : static bool tds_read_interfaces(const char *server, TDSLOGIN * login);
      86             : static bool parse_server_name_for_port(TDSLOGIN * connection, TDSLOGIN * login, bool update_server);
      87             : static int tds_lookup_port(const char *portname);
      88             : static bool tds_config_encryption(const char * value, TDSLOGIN * login);
      89             : 
      90             : static tds_dir_char *interf_file = NULL;
      91             : 
      92             : #define TDS_ISSPACE(c) isspace((unsigned char ) (c))
      93             : 
      94             : const char STD_DATETIME_FMT[] = "%b %e %Y %I:%M%p";
      95             : 
      96             : #if !defined(_WIN32) && !defined(DOS32X)
      97             : static const char pid_config_logpath[] = "/tmp/tdsconfig.log.%d";
      98             : static const char freetds_conf[] = "etc/freetds.conf";
      99             : static const char location[] = "(from $FREETDS/etc)";
     100             : static const char pid_logpath[] = "/tmp/freetds.log.%d";
     101             : static const char interfaces_path[] = "/etc/freetds";
     102             : #else
     103             : static const tds_dir_char pid_config_logpath[] = L"c:\\tdsconfig.log.%d";
     104             : static const tds_dir_char freetds_conf[] = L"freetds.conf";
     105             : static const char location[] = "(from $FREETDS)";
     106             : static const tds_dir_char pid_logpath[] = L"c:\\freetds.log.%d";
     107             : static const tds_dir_char interfaces_path[] = L"c:\\";
     108             : #endif
     109             : 
     110             : /**
     111             :  * \ingroup libtds
     112             :  * \defgroup config Configuration
     113             :  * Handle reading of configuration
     114             :  */
     115             : 
     116             : /**
     117             :  * \addtogroup config
     118             :  * @{ 
     119             :  */
     120             : 
     121             : /**
     122             :  * tds_read_config_info() will fill the tds connection structure based on configuration 
     123             :  * information gathered in the following order:
     124             :  * 1) Program specified in TDSLOGIN structure
     125             :  * 2) The environment variables TDSVER, TDSDUMP, TDSPORT, TDSQUERY, TDSHOST
     126             :  * 3) A config file with the following search order:
     127             :  *    a) a readable file specified by environment variable FREETDSCONF
     128             :  *    b) a readable file in ~/.freetds.conf
     129             :  *    c) a readable file in $prefix/etc/freetds.conf
     130             :  * 3) ~/.interfaces if exists
     131             :  * 4) $SYBASE/interfaces if exists
     132             :  * 5) TDS_DEF_* default values
     133             :  *
     134             :  * .tdsrc and freetds.conf have been added to make the package easier to 
     135             :  * integration with various Linux and *BSD distributions.
     136             :  */
     137             : TDSLOGIN *
     138        2590 : tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale)
     139             : {
     140             :         TDSLOGIN *connection;
     141             :         tds_dir_char *s;
     142        2590 :         int opened = 0;
     143             :         bool found;
     144             : 
     145             :         /* allocate a new structure with hard coded and build-time defaults */
     146        2590 :         connection = tds_alloc_login(false);
     147        2590 :         if (!connection || !tds_init_login(connection, locale)) {
     148           0 :                 tds_free_login(connection);
     149           0 :                 return NULL;
     150             :         }
     151             : 
     152        2590 :         s = tds_dir_getenv(TDS_DIR("TDSDUMPCONFIG"));
     153        2590 :         if (s) {
     154           0 :                 if (*s) {
     155           0 :                         opened = tdsdump_topen(s);
     156             :                 } else {
     157             :                         tds_dir_char path[TDS_VECTOR_SIZE(pid_config_logpath) + 22];
     158           0 :                         pid_t pid = getpid();
     159           0 :                         tds_dir_snprintf(path, TDS_VECTOR_SIZE(path), pid_config_logpath, (int) pid);
     160           0 :                         opened = tdsdump_topen(path);
     161             :                 }
     162             :         }
     163             : 
     164        2590 :         tdsdump_log(TDS_DBG_INFO1, "Getting connection information for [%s].\n", 
     165           0 :                             tds_dstr_cstr(&login->server_name)); /* (The server name is set in login.c.) */
     166             : 
     167             :         /* Read the config files. */
     168        2590 :         tdsdump_log(TDS_DBG_INFO1, "Attempting to read conf files.\n");
     169        5180 :         found = tds_read_conf_file(connection, tds_dstr_cstr(&login->server_name));
     170        2590 :         if (!found) {
     171          74 :                 if (parse_server_name_for_port(connection, login, true)) {
     172             : 
     173         148 :                         found = tds_read_conf_file(connection, tds_dstr_cstr(&connection->server_name));
     174             :                         /* do it again to really override what found in freetds.conf */
     175          74 :                         parse_server_name_for_port(connection, login, false);
     176         124 :                         if (!found && TDS_SUCCEED(tds_lookup_host_set(tds_dstr_cstr(&connection->server_name), &connection->ip_addrs))) {
     177          50 :                                 if (!tds_dstr_dup(&connection->server_host_name, &connection->server_name)) {
     178           0 :                                         tds_free_login(connection);
     179           0 :                                         return NULL;
     180             :                                 }
     181             :                                 found = true;
     182             :                         }
     183          74 :                         if (!tds_dstr_dup(&login->server_name, &connection->server_name)) {
     184           0 :                                 tds_free_login(connection);
     185           0 :                                 return NULL;
     186             :                         }
     187             :                 }
     188             :         }
     189        2590 :         if (!found) {
     190             :                 /* fallback to interfaces file */
     191           0 :                 tdsdump_log(TDS_DBG_INFO1, "Failed in reading conf file.  Trying interface files.\n");
     192           0 :                 if (!tds_read_interfaces(tds_dstr_cstr(&login->server_name), connection)) {
     193           0 :                         tdsdump_log(TDS_DBG_INFO1, "Failed to find [%s] in configuration files; trying '%s' instead.\n", 
     194           0 :                                                    tds_dstr_cstr(&login->server_name), tds_dstr_cstr(&connection->server_name));
     195           0 :                         if (connection->ip_addrs == NULL)
     196           0 :                                 tdserror(tds_get_ctx(tds), tds, TDSEINTF, 0);
     197             :                 }
     198             :         }
     199             : 
     200             :         /* Override config file settings with environment variables. */
     201        2590 :         tds_fix_login(connection);
     202             : 
     203             :         /* And finally apply anything from the login structure */
     204        2590 :         if (!tds_config_login(connection, login)) {
     205           0 :                 tds_free_login(connection);
     206           0 :                 return NULL;
     207             :         }
     208             :         
     209        2590 :         if (opened) {
     210             :                 struct addrinfo *addrs;
     211             :                 char tmp[128];
     212             : 
     213           0 :                 tdsdump_log(TDS_DBG_INFO1, "Final connection parameters:\n");
     214           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_name", tds_dstr_cstr(&connection->server_name));
     215           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_host_name", tds_dstr_cstr(&connection->server_host_name));
     216             : 
     217           0 :                 for (addrs = connection->ip_addrs; addrs != NULL; addrs = addrs->ai_next)
     218           0 :                         tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "ip_addr", tds_addrinfo2str(addrs, tmp, sizeof(tmp)));
     219             : 
     220           0 :                 if (connection->ip_addrs == NULL)
     221           0 :                         tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "ip_addr", "");
     222             : 
     223           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "instance_name", tds_dstr_cstr(&connection->instance_name));
     224           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "port", connection->port);
     225           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "major_version", TDS_MAJOR(connection));
     226           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "minor_version", TDS_MINOR(connection));
     227           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "block_size", connection->block_size);
     228           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "language", tds_dstr_cstr(&connection->language));
     229           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_charset", tds_dstr_cstr(&connection->server_charset));
     230           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "connect_timeout", connection->connect_timeout);
     231           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_host_name", tds_dstr_cstr(&connection->client_host_name));
     232           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_charset", tds_dstr_cstr(&connection->client_charset));
     233           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "use_utf16", connection->use_utf16);
     234           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "app_name", tds_dstr_cstr(&connection->app_name));
     235           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "user_name", tds_dstr_cstr(&connection->user_name));
     236             :                 /* tdsdump_log(TDS_DBG_PASSWD, "\t%20s = %s\n", "password", tds_dstr_cstr(&connection->password)); 
     237             :                         (no such flag yet) */
     238           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "library", tds_dstr_cstr(&connection->library));
     239           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "bulk_copy", (int)connection->bulk_copy);
     240           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "suppress_language", (int)connection->suppress_language);
     241           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "encrypt level", (int)connection->encryption_level);
     242           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "query_timeout", connection->query_timeout);
     243             :                 /* tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "capabilities", tds_dstr_cstr(&connection->capabilities)); 
     244             :                         (not null terminated) */
     245           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "database", tds_dstr_cstr(&connection->database));
     246           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %" tdsPRIdir "\n", "dump_file", connection->dump_file);
     247           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %x\n", "debug_flags", connection->debug_flags);
     248           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "text_size", connection->text_size);
     249           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_realm_name", tds_dstr_cstr(&connection->server_realm_name));
     250           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_spn", tds_dstr_cstr(&connection->server_spn));
     251           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "cafile", tds_dstr_cstr(&connection->cafile));
     252           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "crlfile", tds_dstr_cstr(&connection->crlfile));
     253           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "check_ssl_hostname", connection->check_ssl_hostname);
     254           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "db_filename", tds_dstr_cstr(&connection->db_filename));
     255           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "readonly_intent", connection->readonly_intent);
     256             : #ifdef HAVE_OPENSSL
     257           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "openssl_ciphers", tds_dstr_cstr(&connection->openssl_ciphers));
     258             : #endif
     259             : #ifdef HAVE_GNUTLS
     260           0 :                 tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "gnutls_ciphers", tds_dstr_cstr(&connection->gnutls_ciphers));
     261             : #endif
     262             : 
     263           0 :                 tdsdump_close();
     264             :         }
     265             : 
     266             :         /*
     267             :          * If a dump file has been specified, start logging
     268             :          */
     269        2590 :         if (connection->dump_file != NULL && !tdsdump_isopen()) {
     270           4 :                 if (connection->debug_flags)
     271           4 :                         tds_debug_flags = connection->debug_flags;
     272           4 :                 tdsdump_topen(connection->dump_file);
     273             :         }
     274             : 
     275             :         return connection;
     276             : }
     277             : 
     278             : /**
     279             :  * Fix configuration after reading it. 
     280             :  * Currently this read some environment variables and replace some options.
     281             :  */
     282             : void
     283        4610 : tds_fix_login(TDSLOGIN * login)
     284             : {
     285             :         /* Now check the environment variables */
     286        4610 :         tds_config_env_tdsver(login);
     287        4610 :         tds_config_env_tdsdump(login);
     288        4610 :         tds_config_env_tdsport(login);
     289        4610 :         tds_config_env_tdshost(login);
     290        4610 : }
     291             : 
     292             : static bool
     293        7984 : tds_try_conf_file(const tds_dir_char *path, const char *how, const char *server, TDSLOGIN * login)
     294             : {
     295        7984 :         bool found = false;
     296             :         FILE *in;
     297             : 
     298        7984 :         if ((in = tds_dir_open(path, TDS_DIR("r"))) == NULL) {
     299        3800 :                 tdsdump_log(TDS_DBG_INFO1, "Could not open '%" tdsPRIdir "' (%s).\n", path, how);
     300             :                 return found;
     301             :         }
     302             : 
     303        4184 :         tdsdump_log(TDS_DBG_INFO1, "Found conf file '%" tdsPRIdir "' %s.\n", path, how);
     304        4184 :         found = tds_read_conf_sections(in, server, login);
     305             : 
     306        4184 :         if (found) {
     307        3696 :                 tdsdump_log(TDS_DBG_INFO1, "Success: [%s] defined in %" tdsPRIdir ".\n", server, path);
     308             :         } else {
     309         488 :                 tdsdump_log(TDS_DBG_INFO2, "[%s] not found.\n", server);
     310             :         }
     311             : 
     312        4184 :         fclose(in);
     313             : 
     314        4184 :         return found;
     315             : }
     316             : 
     317             : /**
     318             :  * Read configuration info for given server
     319             :  * return 0 on error
     320             :  * @param login where to store configuration
     321             :  * @param server       section of file configuration that hold 
     322             :  *                     configuration for a server
     323             :  */
     324             : bool
     325        3820 : tds_read_conf_file(TDSLOGIN * login, const char *server)
     326             : {
     327        3820 :         tds_dir_char *path = NULL;
     328        3820 :         tds_dir_char *eptr = NULL;
     329        3820 :         bool found = false;
     330             : 
     331        3820 :         if (interf_file) {
     332         140 :                 found = tds_try_conf_file(interf_file, "set programmatically", server, login);
     333             :         }
     334             : 
     335             :         /* FREETDSCONF env var, pkleef@openlinksw.com 01/21/02 */
     336         140 :         if (!found) {
     337        3800 :                 path = tds_dir_getenv(TDS_DIR("FREETDSCONF"));
     338        3800 :                 if (path) {
     339         120 :                         found = tds_try_conf_file(path, "(from $FREETDSCONF)", server, login);
     340             :                 } else {
     341        3680 :                         tdsdump_log(TDS_DBG_INFO2, "... $FREETDSCONF not set.  Trying $FREETDS/etc.\n");
     342             :                 }
     343             :         }
     344             : 
     345             :         /* FREETDS env var, Bill Thompson 16/07/03 */
     346        3820 :         if (!found) {
     347        3800 :                 eptr = tds_dir_getenv(TDS_DIR("FREETDS"));
     348        3800 :                 if (eptr) {
     349           0 :                         path = tds_join_path(eptr, freetds_conf);
     350           0 :                         if (path) {
     351           0 :                                 found = tds_try_conf_file(path, location, server, login);
     352           0 :                                 free(path);
     353             :                         }
     354             :                 } else {
     355        3800 :                         tdsdump_log(TDS_DBG_INFO2, "... $FREETDS not set.  Trying $HOME.\n");
     356             :                 }
     357             :         }
     358             : 
     359             : #if !defined(_WIN32) && !defined(DOS32X)
     360        3820 :         if (!found) {
     361        3800 :                 path = tds_get_home_file(TDS_DIR(".config/freetds.conf"));
     362        3800 :                 if (path) {
     363        3800 :                         found = tds_try_conf_file(path, "(.config/freetds.conf)", server, login);
     364        3800 :                         free(path);
     365             :                 }
     366             :         }
     367             : #endif
     368             : 
     369        3820 :         if (!found) {
     370        3800 :                 path = tds_get_home_file(TDS_DIR(".freetds.conf"));
     371        3800 :                 if (path) {
     372        3800 :                         found = tds_try_conf_file(path, "(.freetds.conf)", server, login);
     373        3800 :                         free(path);
     374             :                 } else {
     375           0 :                         tdsdump_log(TDS_DBG_INFO2, "... Error getting ~/.freetds.conf.  Trying %" tdsPRIdir ".\n",
     376             :                                     FREETDS_SYSCONFFILE);
     377             :                 }
     378             :         }
     379             : 
     380        3820 :         if (!found) {
     381         124 :                 found = tds_try_conf_file(FREETDS_SYSCONFFILE, "(default)", server, login);
     382             :         }
     383             : 
     384        3820 :         return found;
     385             : }
     386             : 
     387             : static bool
     388        4184 : tds_read_conf_sections(FILE * in, const char *server, TDSLOGIN * login)
     389             : {
     390        4184 :         DSTR default_instance = DSTR_INITIALIZER;
     391             :         int default_port;
     392             : 
     393             :         bool found;
     394             : 
     395        4184 :         tds_read_conf_section(in, "global", tds_parse_conf_section, login);
     396             : 
     397        4184 :         if (!server[0])
     398             :                 return false;
     399        4184 :         rewind(in);
     400             : 
     401        4184 :         if (!tds_dstr_dup(&default_instance, &login->instance_name))
     402             :                 return false;
     403        4184 :         default_port = login->port;
     404             : 
     405        4184 :         found = tds_read_conf_section(in, server, tds_parse_conf_section, login);
     406        4184 :         if (!login->valid_configuration) {
     407           0 :                 tds_dstr_free(&default_instance);
     408           0 :                 return false;
     409             :         }
     410             : 
     411             :         /* 
     412             :          * If both instance and port are specified and neither one came from the default, it's an error 
     413             :          * TODO: If port/instance is specified in the non-default, it has priority over the default setting. 
     414             :          * TODO: test this. 
     415             :          */
     416        8460 :         if (!tds_dstr_isempty(&login->instance_name) && login->port &&
     417          92 :             !(!tds_dstr_isempty(&default_instance) || default_port)) {
     418           0 :                 tdsdump_log(TDS_DBG_ERROR, "error: cannot specify both port %d and instance %s.\n", 
     419           0 :                                                 login->port, tds_dstr_cstr(&login->instance_name));
     420             :                 /* tdserror(tds_get_ctx(tds), tds, TDSEPORTINSTANCE, 0); */
     421             :         }
     422        4184 :         tds_dstr_free(&default_instance);
     423        4184 :         return found;
     424             : }
     425             : 
     426             : static const struct {
     427             :         char value[7];
     428             :         unsigned char to_return;
     429             : } boolean_values[] = {
     430             :         { "yes",      1 },
     431             :         { "no",               0 },
     432             :         { "on",               1 },
     433             :         { "off",      0 },
     434             :         { "true",     1 },
     435             :         { "false",    0 }
     436             : };
     437             : 
     438             : int
     439           0 : tds_parse_boolean(const char *value, int default_value)
     440             : {
     441             :         int p;
     442             : 
     443       10232 :         for (p = 0; p < TDS_VECTOR_SIZE(boolean_values); ++p) {
     444       10232 :                 if (!strcasecmp(value, boolean_values[p].value))
     445        2920 :                         return boolean_values[p].to_return;
     446             :         }
     447             :         return default_value;
     448             : }
     449             : 
     450             : int
     451           0 : tds_config_boolean(const char *option, const char *value, TDSLOGIN *login)
     452             : {
     453           0 :         int ret = tds_parse_boolean(value, -1);
     454           0 :         if (ret >= 0)
     455             :                 return ret;
     456             : 
     457           0 :         tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for boolean setting '%s'!\n",
     458             :                     value, option);
     459           0 :         login->valid_configuration = 0;
     460           0 :         return 0;
     461             : }
     462             : 
     463             : static int
     464        2920 : tds_parse_boolean_option(const char *option, const char *value, int default_value, bool *p_error)
     465             : {
     466        2920 :         int ret = tds_parse_boolean(value, -1);
     467        2920 :         if (ret >= 0)
     468             :                 return ret;
     469             : 
     470           0 :         tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for boolean setting '%s'!\n",
     471             :                     value, option);
     472           0 :         *p_error = true;
     473           0 :         return default_value;
     474             : }
     475             : 
     476             : static bool
     477        1476 : tds_config_encryption(const char * value, TDSLOGIN * login)
     478             : {
     479        1476 :         TDS_ENCRYPTION_LEVEL lvl = TDS_ENCRYPTION_OFF;
     480             : 
     481        1476 :         if (!strcasecmp(value, TDS_STR_ENCRYPTION_OFF))
     482             :                 ;
     483        1476 :         else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUEST))
     484             :                 lvl = TDS_ENCRYPTION_REQUEST;
     485        1456 :         else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUIRE))
     486             :                 lvl = TDS_ENCRYPTION_REQUIRE;
     487           0 :         else if (!strcasecmp(value, TDS_STR_ENCRYPTION_STRICT))
     488             :                 lvl = TDS_ENCRYPTION_STRICT;
     489             :         else {
     490           0 :                 tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for '%s' setting!\n",
     491             :                             value, TDS_STR_ENCRYPTION);
     492           0 :                 tdsdump_log(TDS_DBG_ERROR, "Valid settings are: ('%s', '%s', '%s', '%s')\n",
     493             :                         TDS_STR_ENCRYPTION_OFF, TDS_STR_ENCRYPTION_REQUEST, TDS_STR_ENCRYPTION_REQUIRE,
     494             :                         TDS_STR_ENCRYPTION_STRICT);
     495             :                 lvl = TDS_ENCRYPTION_REQUIRE;  /* Assuming "require" is safer than "no" */
     496             :                 return false;
     497             :         }
     498             : 
     499        1476 :         login->encryption_level = lvl;
     500             :         return true;
     501             : }
     502             : 
     503             : /**
     504             :  * Read a section of configuration file (INI style file)
     505             :  * @param in             configuration file
     506             :  * @param section        section to read
     507             :  * @param tds_conf_parse callback that receive every entry in section
     508             :  * @param param          parameter to pass to callback function
     509             :  */
     510             : bool
     511       45264 : tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *param)
     512             : {
     513             :         char line[256], *value;
     514             : #define option line
     515             :         char *s;
     516             :         char p;
     517             :         int i;
     518       45264 :         bool insection = false;
     519       45264 :         bool found = false;
     520             : 
     521       45264 :         tdsdump_log(TDS_DBG_INFO1, "Looking for section %s.\n", section);
     522     2610210 :         while (fgets(line, sizeof(line), in)) {
     523             :                 s = line;
     524             : 
     525             :                 /* skip leading whitespace */
     526     4036020 :                 while (*s && TDS_ISSPACE(*s))
     527     1471074 :                         s++;
     528             : 
     529             :                 /* skip it if it's a comment line */
     530     2564946 :                 if (*s == ';' || *s == '#')
     531      903004 :                         continue;
     532             : 
     533             :                 /* read up to the = ignoring duplicate spaces */
     534             :                 p = 0;
     535             :                 i = 0;
     536    14013328 :                 while (*s && *s != '=') {
     537    12351386 :                         if (!TDS_ISSPACE(*s)) {
     538    10600260 :                                 if (TDS_ISSPACE(p))
     539      418158 :                                         option[i++] = ' ';
     540    10600260 :                                 option[i++] = tolower((unsigned char) *s);
     541             :                         }
     542    12351386 :                         p = *s;
     543    12351386 :                         s++;
     544             :                 }
     545             : 
     546             :                 /* skip if empty option */
     547     1661942 :                 if (!i)
     548      335260 :                         continue;
     549             : 
     550             :                 /* skip the = */
     551     1326682 :                 if (*s)
     552     1038614 :                         s++;
     553             : 
     554             :                 /* terminate the option, must be done after skipping = */
     555     1326682 :                 option[i] = '\0';
     556             : 
     557             :                 /* skip leading whitespace */
     558     3690858 :                 while (*s && TDS_ISSPACE(*s))
     559     1037494 :                         s++;
     560             : 
     561             :                 /* read up to a # ; or null ignoring duplicate spaces */
     562             :                 value = s;
     563             :                 p = 0;
     564             :                 i = 0;
     565    11110552 :                 while (*s && *s != ';' && *s != '#') {
     566     9783870 :                         if (!TDS_ISSPACE(*s)) {
     567     8664360 :                                 if (TDS_ISSPACE(p))
     568       80836 :                                         value[i++] = ' ';
     569     8664360 :                                 value[i++] = *s;
     570             :                         }
     571     9783870 :                         p = *s;
     572     9783870 :                         s++;
     573             :                 }
     574     1326682 :                 value[i] = '\0';
     575             : 
     576     1326682 :                 if (option[0] == '[') {
     577      288068 :                         s = strchr(option, ']');
     578      288068 :                         if (s)
     579      288068 :                                 *s = '\0';
     580      288068 :                         tdsdump_log(TDS_DBG_INFO1, "\tFound section %s.\n", &option[1]);
     581             : 
     582      288068 :                         if (!strcasecmp(section, &option[1])) {
     583       40971 :                                 tdsdump_log(TDS_DBG_INFO1, "Got a match.\n");
     584             :                                 insection = true;
     585             :                                 found = true;
     586             :                         } else {
     587             :                                 insection = false;
     588             :                         }
     589     1038614 :                 } else if (insection) {
     590      126988 :                         tds_conf_parse(option, value, param);
     591             :                 }
     592             : 
     593             :         }
     594       45264 :         tdsdump_log(TDS_DBG_INFO1, "\tReached EOF\n");
     595       45264 :         return found;
     596             : #undef option
     597             : }
     598             : 
     599             : /* Also used to scan ODBC.INI entries */
     600             : bool
     601       31302 : tds_parse_conf_section(const char *option, const char *value, void *param)
     602             : {
     603             : #define parse_boolean(option, value, variable) do { \
     604             :         variable = tds_parse_boolean_option(option, value, variable, &got_error); \
     605             : } while(0)
     606       31302 :         TDSLOGIN *login = (TDSLOGIN *) param;
     607       31302 :         void *s = param;
     608       31302 :         bool got_error = false;
     609             : 
     610       31302 :         tdsdump_log(TDS_DBG_INFO1, "\t%s = '%s'\n", option, value);
     611             : 
     612       31302 :         if (!strcmp(option, TDS_STR_VERSION)) {
     613        3830 :                 tds_config_verstr(value, login);
     614       27472 :         } else if (!strcmp(option, TDS_STR_BLKSZ)) {
     615           0 :                 int val = atoi(value);
     616           0 :                 if (val >= 512 && val < 65536)
     617           0 :                         login->block_size = val;
     618       27472 :         } else if (!strcmp(option, TDS_STR_SWAPDT)) {
     619             :                 /* this option is deprecated, just check value for compatibility */
     620           0 :                 tds_config_boolean(option, value, login);
     621       27472 :         } else if (!strcmp(option, TDS_GSSAPI_DELEGATION)) {
     622             :                 /* gssapi flag addition */
     623           0 :                 parse_boolean(option, value, login->gssapi_use_delegation);
     624       27472 :         } else if (!strcmp(option, TDS_STR_MUTUAL_AUTHENTICATION)) {
     625           0 :                 parse_boolean(option, value, login->mutual_authentication);
     626       27472 :         } else if (!strcmp(option, TDS_STR_DUMPFILE)) {
     627           0 :                 TDS_ZERO_FREE(login->dump_file);
     628           0 :                 if (value[0]) {
     629           0 :                         login->dump_file = tds_dir_from_cstr(value);
     630           0 :                         if (!login->dump_file)
     631             :                                 s = NULL;
     632             :                 }
     633       27472 :         } else if (!strcmp(option, TDS_STR_DEBUGFLAGS)) {
     634             :                 char *end;
     635             :                 long flags;
     636        3800 :                 flags = strtol(value, &end, 0);
     637        3800 :                 if (*value != '\0' && *end == '\0' && flags > INT_MIN && flags < INT_MAX)
     638        3800 :                     login->debug_flags = (int) flags;
     639       23672 :         } else if (!strcmp(option, TDS_STR_TIMEOUT) || !strcmp(option, TDS_STR_QUERY_TIMEOUT)) {
     640        3800 :                 if (atoi(value) > 0)
     641        3800 :                         login->query_timeout = atoi(value);
     642       19872 :         } else if (!strcmp(option, TDS_STR_CONNTIMEOUT)) {
     643        3800 :                 if (atoi(value) > 0)
     644        3800 :                         login->connect_timeout = atoi(value);
     645       16072 :         } else if (!strcmp(option, TDS_STR_HOST)) {
     646             :                 char tmp[128];
     647             :                 struct addrinfo *addrs;
     648             : 
     649        3696 :                 if (TDS_FAILED(tds_lookup_host_set(value, &login->ip_addrs))) {
     650           0 :                         tdsdump_log(TDS_DBG_WARN, "Found host entry %s however name resolution failed. \n", value);
     651           0 :                         return false;
     652             :                 }
     653             : 
     654        3696 :                 tdsdump_log(TDS_DBG_INFO1, "Found host entry %s \n", value);
     655        3696 :                 s = tds_dstr_copy(&login->server_host_name, value);
     656        7392 :                 for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next)
     657        3696 :                         tdsdump_log(TDS_DBG_INFO1, "IP addr is %s.\n", tds_addrinfo2str(addrs, tmp, sizeof(tmp)));
     658             : 
     659       12376 :         } else if (!strcmp(option, TDS_STR_PORT)) {
     660        3916 :                 if (atoi(value) > 0)
     661        3916 :                         login->port = atoi(value);
     662        8460 :         } else if (!strcmp(option, TDS_STR_EMUL_LE)) {
     663             :                 /* obsolete, ignore */
     664           0 :                 tds_config_boolean(option, value, login);
     665        8460 :         } else if (!strcmp(option, TDS_STR_TEXTSZ)) {
     666        3924 :                 if (atoi(value) > 0)
     667        3924 :                         login->text_size = atoi(value);
     668        4536 :         } else if (!strcmp(option, TDS_STR_CHARSET)) {
     669           0 :                 s = tds_dstr_copy(&login->server_charset, value);
     670           0 :                 tdsdump_log(TDS_DBG_INFO1, "%s is %s.\n", option, tds_dstr_cstr(&login->server_charset));
     671        4536 :         } else if (!strcmp(option, TDS_STR_CLCHARSET)) {
     672         100 :                 s = tds_dstr_copy(&login->client_charset, value);
     673         100 :                 tdsdump_log(TDS_DBG_INFO1, "tds_parse_conf_section: %s is %s.\n", option, tds_dstr_cstr(&login->client_charset));
     674        4436 :         } else if (!strcmp(option, TDS_STR_USE_UTF_16)) {
     675           0 :                 parse_boolean(option, value, login->use_utf16);
     676        4436 :         } else if (!strcmp(option, TDS_STR_LANGUAGE)) {
     677           0 :                 s = tds_dstr_copy(&login->language, value);
     678        4436 :         } else if (!strcmp(option, TDS_STR_APPENDMODE)) {
     679           0 :                 parse_boolean(option, value, tds_append_mode);
     680        4436 :         } else if (!strcmp(option, TDS_STR_INSTANCE)) {
     681           0 :                 s = tds_dstr_copy(&login->instance_name, value);
     682        4436 :         } else if (!strcmp(option, TDS_STR_ENCRYPTION)) {
     683        1476 :                 if (!tds_config_encryption(value, login))
     684             :                         s = NULL;
     685        2960 :         } else if (!strcmp(option, TDS_STR_ASA_DATABASE)) {
     686          20 :                 s = tds_dstr_copy(&login->server_name, value);
     687        2940 :         } else if (!strcmp(option, TDS_STR_USENTLMV2)) {
     688           0 :                 parse_boolean(option, value, login->use_ntlmv2);
     689           0 :                 login->use_ntlmv2_specified = 1;
     690        2940 :         } else if (!strcmp(option, TDS_STR_USELANMAN)) {
     691           0 :                 parse_boolean(option, value, login->use_lanman);
     692        2940 :         } else if (!strcmp(option, TDS_STR_REALM)) {
     693           0 :                 s = tds_dstr_copy(&login->server_realm_name, value);
     694        2940 :         } else if (!strcmp(option, TDS_STR_SPN)) {
     695           0 :                 s = tds_dstr_copy(&login->server_spn, value);
     696        2940 :         } else if (!strcmp(option, TDS_STR_CAFILE)) {
     697           0 :                 s = tds_dstr_copy(&login->cafile, value);
     698        2940 :         } else if (!strcmp(option, TDS_STR_CRLFILE)) {
     699           0 :                 s = tds_dstr_copy(&login->crlfile, value);
     700        2940 :         } else if (!strcmp(option, TDS_STR_CHECKSSLHOSTNAME)) {
     701        1456 :                 parse_boolean(option, value, login->check_ssl_hostname);
     702        1484 :         } else if (!strcmp(option, TDS_STR_SSLHOSTNAME)) {
     703           0 :                 s = tds_dstr_copy(&login->certificate_host_name, value);
     704        1484 :         } else if (!strcmp(option, TDS_STR_DBFILENAME)) {
     705           0 :                 s = tds_dstr_copy(&login->db_filename, value);
     706        1484 :         } else if (!strcmp(option, TDS_STR_DATABASE)) {
     707           0 :                 s = tds_dstr_copy(&login->database, value);
     708        1484 :         } else if (!strcmp(option, TDS_STR_READONLY_INTENT)) {
     709           0 :                 parse_boolean(option, value, login->readonly_intent);
     710           0 :                 tdsdump_log(TDS_DBG_FUNC, "Setting ReadOnly Intent to '%s'.\n", value);
     711        1484 :         } else if (!strcmp(option, TLS_STR_OPENSSL_CIPHERS)) {
     712           0 :                 s = tds_dstr_copy(&login->openssl_ciphers, value);
     713        1484 :         } else if (!strcmp(option, TLS_STR_GNUTLS_CIPHERS)) {
     714           0 :                 s = tds_dstr_copy(&login->gnutls_ciphers, value);
     715        1484 :         } else if (!strcmp(option, TDS_STR_ENABLE_TLS_V1)) {
     716        1464 :                 parse_boolean(option, value, login->enable_tls_v1);
     717        1464 :                 login->enable_tls_v1_specified = 1;
     718          20 :         } else if (!strcmp(option, TDS_STR_ENABLE_TLS_V1_1)) {
     719           0 :                 parse_boolean(option, value, login->enable_tls_v1_1);
     720           0 :                 login->enable_tls_v1_1_specified = 1;
     721             :         } else {
     722          20 :                 tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s' ... ignoring.\n", option);
     723             :         }
     724             : 
     725       31302 :         if (!s || got_error) {
     726           0 :                 login->valid_configuration = 0;
     727           0 :                 return false;
     728             :         }
     729             :         return true;
     730             : #undef parse_boolean
     731             : }
     732             : 
     733             : static bool
     734        2590 : tds_config_login(TDSLOGIN * connection, TDSLOGIN * login)
     735             : {
     736        2590 :         DSTR *res = &login->server_name;
     737             : 
     738        5180 :         if (!tds_dstr_isempty(&login->server_name)) {
     739             :                 if (1 || tds_dstr_isempty(&connection->server_name))
     740        2590 :                         res = tds_dstr_dup(&connection->server_name, &login->server_name);
     741             :         }
     742             : 
     743        2590 :         if (login->tds_version)
     744          22 :                 connection->tds_version = login->tds_version;
     745             : 
     746        5180 :         if (res && !tds_dstr_isempty(&login->language))
     747         326 :                 res = tds_dstr_dup(&connection->language, &login->language);
     748             : 
     749        5180 :         if (res && !tds_dstr_isempty(&login->server_charset))
     750           0 :                 res = tds_dstr_dup(&connection->server_charset, &login->server_charset);
     751             : 
     752        5180 :         if (res && !tds_dstr_isempty(&login->client_charset)) {
     753         174 :                 res = tds_dstr_dup(&connection->client_charset, &login->client_charset);
     754         174 :                 tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "client_charset",
     755           0 :                             tds_dstr_cstr(&connection->client_charset));
     756             :         }
     757             : 
     758        2590 :         if (!login->use_utf16)
     759           0 :                 connection->use_utf16 = login->use_utf16;
     760             : 
     761        5180 :         if (res && !tds_dstr_isempty(&login->database)) {
     762          54 :                 res = tds_dstr_dup(&connection->database, &login->database);
     763          54 :                 tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "database_name",
     764           0 :                             tds_dstr_cstr(&connection->database));
     765             :         }
     766             : 
     767        5180 :         if (res && !tds_dstr_isempty(&login->client_host_name))
     768         494 :                 res = tds_dstr_dup(&connection->client_host_name, &login->client_host_name);
     769             : 
     770        5180 :         if (res && !tds_dstr_isempty(&login->app_name))
     771        1180 :                 res = tds_dstr_dup(&connection->app_name, &login->app_name);
     772             : 
     773        5180 :         if (res && !tds_dstr_isempty(&login->user_name))
     774        2520 :                 res = tds_dstr_dup(&connection->user_name, &login->user_name);
     775             : 
     776        5180 :         if (res && !tds_dstr_isempty(&login->password)) {
     777             :                 /* for security reason clear memory */
     778        2520 :                 tds_dstr_zero(&connection->password);
     779        2520 :                 res = tds_dstr_dup(&connection->password, &login->password);
     780             :         }
     781             : 
     782        5180 :         if (res && !tds_dstr_isempty(&login->library))
     783        2520 :                 res = tds_dstr_dup(&connection->library, &login->library);
     784             : 
     785        2590 :         if (login->encryption_level)
     786           0 :                 connection->encryption_level = login->encryption_level;
     787             : 
     788        2590 :         if (login->suppress_language)
     789           0 :                 connection->suppress_language = 1;
     790             : 
     791        2590 :         if (!login->bulk_copy)
     792           0 :                 connection->bulk_copy = 0;
     793             : 
     794        2590 :         if (login->block_size)
     795           0 :                 connection->block_size = login->block_size;
     796             : 
     797        2590 :         if (login->gssapi_use_delegation)
     798           0 :                 connection->gssapi_use_delegation = login->gssapi_use_delegation;
     799             : 
     800        2590 :         if (login->mutual_authentication)
     801           0 :                 connection->mutual_authentication = login->mutual_authentication;
     802             : 
     803        2590 :         if (login->port)
     804          42 :                 connection->port = login->port;
     805             : 
     806        2590 :         if (login->connect_timeout)
     807           0 :                 connection->connect_timeout = login->connect_timeout;
     808             : 
     809        2590 :         if (login->query_timeout)
     810           0 :                 connection->query_timeout = login->query_timeout;
     811             : 
     812        2590 :         if (!login->check_ssl_hostname)
     813           0 :                 connection->check_ssl_hostname = login->check_ssl_hostname;
     814             : 
     815        5180 :         if (res && !tds_dstr_isempty(&login->db_filename))
     816           0 :                 res = tds_dstr_dup(&connection->db_filename, &login->db_filename);
     817             : 
     818        5180 :         if (res && !tds_dstr_isempty(&login->openssl_ciphers))
     819           0 :                 res = tds_dstr_dup(&connection->openssl_ciphers, &login->openssl_ciphers);
     820             : 
     821        5180 :         if (res && !tds_dstr_isempty(&login->gnutls_ciphers))
     822           0 :                 res = tds_dstr_dup(&connection->gnutls_ciphers, &login->gnutls_ciphers);
     823             : 
     824        5180 :         if (res && !tds_dstr_isempty(&login->server_spn))
     825           0 :                 res = tds_dstr_dup(&connection->server_spn, &login->server_spn);
     826             : 
     827             :         /* copy other info not present in configuration file */
     828        2590 :         connection->capabilities = login->capabilities;
     829             : 
     830        2590 :         if (login->readonly_intent)
     831           0 :                 connection->readonly_intent = login->readonly_intent;
     832             : 
     833        2590 :         connection->use_new_password = login->use_new_password;
     834             : 
     835        2590 :         if (login->use_ntlmv2_specified) {
     836           0 :                 connection->use_ntlmv2_specified = login->use_ntlmv2_specified;
     837           0 :                 connection->use_ntlmv2 = login->use_ntlmv2;
     838             :         }
     839             : 
     840        2590 :         if (login->enable_tls_v1_specified) {
     841           0 :                 connection->enable_tls_v1_specified = login->enable_tls_v1_specified;
     842           0 :                 connection->enable_tls_v1 = login->enable_tls_v1;
     843             :         }
     844             : 
     845        2590 :         if (login->enable_tls_v1_1_specified) {
     846           0 :                 connection->enable_tls_v1_1_specified = login->enable_tls_v1_1_specified;
     847           0 :                 connection->enable_tls_v1_1 = login->enable_tls_v1_1;
     848             :         }
     849             : 
     850        2590 :         if (res)
     851        2590 :                 res = tds_dstr_dup(&connection->new_password, &login->new_password);
     852             : 
     853        2590 :         return res != NULL;
     854             : }
     855             : 
     856             : static bool
     857        4610 : tds_config_env_tdsdump(TDSLOGIN * login)
     858             : {
     859             :         tds_dir_char path[TDS_VECTOR_SIZE(pid_logpath) + 22];
     860             : 
     861        4610 :         tds_dir_char *s = tds_dir_getenv(TDS_DIR("TDSDUMP"));
     862        4610 :         if (!s)
     863             :                 return true;
     864             : 
     865           4 :         if (!tds_dir_len(s)) {
     866           0 :                 pid_t pid = getpid();
     867           0 :                 tds_dir_snprintf(path, TDS_VECTOR_SIZE(path), pid_logpath, (int) pid);
     868           0 :                 s = path;
     869             :         }
     870             : 
     871           4 :         if (!(s = tds_dir_dup(s)))
     872             :                 return false;
     873           4 :         free(login->dump_file);
     874           4 :         login->dump_file = s;
     875             : 
     876           4 :         tdsdump_log(TDS_DBG_INFO1, "Setting 'dump_file' to '%" tdsPRIdir "' from $TDSDUMP.\n", login->dump_file);
     877             :         return true;
     878             : }
     879             : 
     880             : static void
     881        4610 : tds_config_env_tdsport(TDSLOGIN * login)
     882             : {
     883             :         char *s;
     884             : 
     885        4610 :         if ((s = getenv("TDSPORT"))) {
     886          12 :                 login->port = tds_lookup_port(s);
     887          12 :                 tds_dstr_empty(&login->instance_name);
     888          12 :                 tdsdump_log(TDS_DBG_INFO1, "Setting 'port' to %s from $TDSPORT.\n", s);
     889             :         }
     890        4610 :         return;
     891             : }
     892             : static void
     893        4610 : tds_config_env_tdsver(TDSLOGIN * login)
     894             : {
     895             :         char *tdsver;
     896             : 
     897        4610 :         if ((tdsver = getenv("TDSVER"))) {
     898          14 :                 TDS_USMALLINT *pver = tds_config_verstr(tdsver, login);
     899          14 :                 tdsdump_log(TDS_DBG_INFO1, "TDS version %sset to %s from $TDSVER.\n", (pver? "":"not "), tdsver);
     900             : 
     901             :         }
     902        4610 :         return;
     903             : }
     904             : 
     905             : /* TDSHOST env var, pkleef@openlinksw.com 01/21/02 */
     906             : static bool
     907        4610 : tds_config_env_tdshost(TDSLOGIN * login)
     908             : {
     909             :         const char *tdshost;
     910             :         char tmp[128];
     911             :         struct addrinfo *addrs;
     912             : 
     913        4610 :         if (!(tdshost = getenv("TDSHOST")))
     914             :                 return true;
     915             : 
     916          10 :         if (TDS_FAILED(tds_lookup_host_set(tdshost, &login->ip_addrs))) {
     917           0 :                 tdsdump_log(TDS_DBG_WARN, "Name resolution failed for '%s' from $TDSHOST.\n", tdshost);
     918             :                 return false;
     919             :         }
     920             : 
     921          10 :         if (!tds_dstr_copy(&login->server_host_name, tdshost))
     922             :                 return false;
     923          20 :         for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) {
     924          10 :                 tdsdump_log(TDS_DBG_INFO1, "Setting IP Address to %s (%s) from $TDSHOST.\n",
     925             :                             tds_addrinfo2str(addrs, tmp, sizeof(tmp)), tdshost);
     926             :         }
     927             :         return true;
     928             : }
     929             : #define TDS_FIND(k,b,c) tds_find(k, b, TDS_VECTOR_SIZE(b), sizeof(b[0]), c)
     930             : 
     931             : 
     932             : static const void *
     933             : tds_find(const void *key, const void *base, size_t nelem, size_t width,
     934             :          int (*compar)(const void *, const void *))
     935             : {
     936             :         size_t n;
     937             :         const char *p = (const char*) base;
     938             : 
     939       27642 :         for (n = nelem; n != 0; --n) {
     940       31486 :                 if (0 == compar(key, p))
     941             :                         return p;
     942       27642 :                 p += width;
     943             :         }
     944             :         return NULL;
     945             : }
     946             : 
     947             : struct tdsvername_t 
     948             : {
     949             :         const char name[6];
     950             :         TDS_USMALLINT version;
     951             : };
     952             : 
     953             : static int
     954       31486 : tds_vername_cmp(const void *key, const void *pelem)
     955             : {
     956       31486 :         return strcmp((const char *)key, ((const struct tdsvername_t *)pelem)->name);
     957             : }
     958             : 
     959             : /**
     960             :  * Set TDS version from given string
     961             :  * @param tdsver tds string version
     962             :  * @param login where to store information
     963             :  * @return as encoded hex value: high byte major, low byte minor.
     964             :  */
     965             : TDS_USMALLINT *
     966        3844 : tds_config_verstr(const char *tdsver, TDSLOGIN * login)
     967             : {
     968             :         static const struct tdsvername_t tds_versions[] = 
     969             :                 { {   "0", 0x000 }
     970             :                 , {"auto", 0x000 }
     971             :                 , { "4.2", 0x402 }
     972             :                 , {  "50", 0x500 }
     973             :                 , { "5.0", 0x500 }
     974             :                 , {  "70", 0x700 }
     975             :                 , { "7.0", 0x700 }
     976             :                 , { "7.1", 0x701 }
     977             :                 , { "7.2", 0x702 }
     978             :                 , { "7.3", 0x703 }
     979             :                 , { "7.4", 0x704 }
     980             :                 , { "8.0", 0x800 }
     981             :                 };
     982             :         const struct tdsvername_t *pver;
     983             : 
     984        3844 :         if (!login) {
     985           0 :                 assert(login);
     986             :                 return NULL;
     987             :         }
     988             : 
     989        3844 :         if ((pver = (const struct tdsvername_t *) TDS_FIND(tdsver, tds_versions, tds_vername_cmp)) == NULL) {
     990           0 :                 tdsdump_log(TDS_DBG_INFO1, "error: no such version: %s\n", tdsver);
     991             :                 return NULL;
     992             :         }
     993             :         
     994        3844 :         login->tds_version = pver->version;
     995        3844 :         tdsdump_log(TDS_DBG_INFO1, "Setting tds version to %s (0x%0x).\n", tdsver, pver->version);
     996             : 
     997        3844 :         return &login->tds_version;
     998             : }
     999             : 
    1000             : /**
    1001             :  * Set the full name of interface file
    1002             :  * @param interf file name
    1003             :  */
    1004             : TDSRET
    1005          20 : tds_set_interfaces_file_loc(const char *interf)
    1006             : {
    1007          20 :         tds_dir_char *copy = NULL;
    1008             : 
    1009             :         /* If filename passed, copy filename */
    1010          20 :         if (interf != NULL && interf[0] != '\0') {
    1011          10 :                 copy = tds_dir_from_cstr(interf);
    1012          10 :                 if (copy == NULL)
    1013             :                         return -TDSEMEM;
    1014             :         }
    1015             : 
    1016             :         /* Free it if already set */
    1017          20 :         free(interf_file);
    1018             : 
    1019             :         /* Set */
    1020          20 :         interf_file = copy;
    1021             : 
    1022          20 :         return TDS_SUCCESS;
    1023             : }
    1024             : 
    1025             : /**
    1026             :  * Get the IP address for a hostname. Store server's IP address 
    1027             :  * in the string 'ip' in dotted-decimal notation.  (The "hostname" might itself
    1028             :  * be a dotted-decimal address.  
    1029             :  *
    1030             :  * If we can't determine the IP address then 'ip' will be set to empty
    1031             :  * string.
    1032             :  */
    1033             : /* TODO callers seem to set always connection info... change it */
    1034             : struct addrinfo *
    1035        3856 : tds_lookup_host(const char *servername) /* (I) name of the server                  */
    1036             : {
    1037        3856 :         struct addrinfo hints, *addr = NULL;
    1038        3856 :         assert(servername != NULL);
    1039             : 
    1040        3856 :         memset(&hints, '\0', sizeof(hints));
    1041             :         hints.ai_family = AF_UNSPEC;
    1042        3856 :         hints.ai_socktype = SOCK_STREAM;
    1043        3856 :         hints.ai_protocol = IPPROTO_TCP;
    1044             : 
    1045             : #ifdef AI_ADDRCONFIG
    1046        3856 :         hints.ai_flags |= AI_ADDRCONFIG;
    1047        3856 :         switch (getaddrinfo(servername, NULL, &hints, &addr)) {
    1048        3856 :         case 0:
    1049        3856 :                 return addr;
    1050           0 :         case EAI_FAMILY:
    1051             : #  ifdef EAI_ADDRFAMILY
    1052             :         case EAI_ADDRFAMILY:
    1053             : #  endif
    1054           0 :                 hints.ai_flags &= ~AI_ADDRCONFIG;
    1055             :                 break;
    1056             :         default:
    1057             :                 return NULL;
    1058             :         }
    1059             : #endif
    1060             : 
    1061           0 :         if (getaddrinfo(servername, NULL, &hints, &addr))
    1062             :                 return NULL;
    1063           0 :         return addr;
    1064             : }
    1065             : 
    1066             : TDSRET
    1067        3856 : tds_lookup_host_set(const char *servername, struct addrinfo **addr)
    1068             : {
    1069             :         struct addrinfo *newaddr;
    1070        3856 :         assert(servername != NULL && addr != NULL);
    1071             : 
    1072        3856 :         if ((newaddr = tds_lookup_host(servername)) != NULL) {
    1073        3856 :                 if (*addr != NULL)
    1074          30 :                         freeaddrinfo(*addr);
    1075        3856 :                 *addr = newaddr;
    1076        3856 :                 return TDS_SUCCESS;
    1077             :         }
    1078             :         return TDS_FAIL;
    1079             : }
    1080             : 
    1081             : /**
    1082             :  * Given a portname lookup the port.
    1083             :  *
    1084             :  * If we can't determine the port number then return 0.
    1085             :  */
    1086             : static int
    1087          12 : tds_lookup_port(const char *portname)
    1088             : {
    1089          12 :         int num = atoi(portname);
    1090          12 :         if (!num)
    1091           2 :                 num = tds_getservice(portname);
    1092          12 :         return num;
    1093             : }
    1094             : 
    1095             : /* TODO same code in convert.c ?? */
    1096             : static int
    1097             : hexdigit(int c)
    1098             : {
    1099           0 :         if (c >= '0' && c <= '9')
    1100           0 :                 return c - '0';
    1101             :         /* ASCII optimization, 'A' -> 'a', 'a' -> 'a' */
    1102           0 :         c |= 0x20;
    1103           0 :         if (c >= 'a' && c <= 'f')
    1104           0 :                 return c - 'a' + 10;
    1105             :         return 0;       /* bad hex digit */
    1106             : }
    1107             : 
    1108             : static int
    1109           0 : hex2num(char *hex)
    1110             : {
    1111           0 :         return hexdigit(hex[0]) * 16 + hexdigit(hex[1]);
    1112             : }
    1113             : 
    1114             : /**
    1115             :  * Open and read the file 'file' searching for a logical server
    1116             :  * by the name of 'host'.  If one is found then lookup
    1117             :  * the IP address and port number and store them in 'login'
    1118             :  *
    1119             :  * \param dir name of base directory for interface file
    1120             :  * \param file name of the interface file
    1121             :  * \param host logical host to search for
    1122             :  * \return false if not fount true if found
    1123             :  */
    1124             : static bool
    1125           0 : search_interface_file(TDSLOGIN * login, const tds_dir_char *dir, const tds_dir_char *file, const char *host)
    1126             : {
    1127             :         tds_dir_char *pathname;
    1128             :         char line[255];
    1129             :         char tmp_ip[sizeof(line)];
    1130             :         char tmp_port[sizeof(line)];
    1131             :         char tmp_ver[sizeof(line)];
    1132             :         FILE *in;
    1133             :         char *field;
    1134           0 :         bool found = false;
    1135           0 :         bool server_found = false;
    1136             :         char *lasts;
    1137             : 
    1138           0 :         line[0] = '\0';
    1139           0 :         tmp_ip[0] = '\0';
    1140           0 :         tmp_port[0] = '\0';
    1141           0 :         tmp_ver[0] = '\0';
    1142             : 
    1143           0 :         tdsdump_log(TDS_DBG_INFO1, "Searching interfaces file %" tdsPRIdir "/%" tdsPRIdir ".\n", dir, file);
    1144             : 
    1145             :         /*
    1146             :          * create the full pathname to the interface file
    1147             :          */
    1148           0 :         if (file[0] == '\0') {
    1149           0 :                 pathname = tds_dir_dup(TDS_DIR(""));
    1150             :         } else {
    1151           0 :                 pathname = tds_join_path(dir, file);
    1152             :         }
    1153           0 :         if (!pathname)
    1154             :                 return false;
    1155             : 
    1156             :         /*
    1157             :          * parse the interfaces file and find the server and port
    1158             :          */
    1159           0 :         if ((in = tds_dir_open(pathname, TDS_DIR("r"))) == NULL) {
    1160           0 :                 tdsdump_log(TDS_DBG_INFO1, "Couldn't open %" tdsPRIdir ".\n", pathname);
    1161           0 :                 free(pathname);
    1162           0 :                 return false;
    1163             :         }
    1164           0 :         tdsdump_log(TDS_DBG_INFO1, "Interfaces file %" tdsPRIdir " opened.\n", pathname);
    1165             : 
    1166           0 :         while (fgets(line, sizeof(line) - 1, in)) {
    1167           0 :                 if (line[0] == '#')
    1168           0 :                         continue;       /* comment */
    1169             : 
    1170           0 :                 if (!TDS_ISSPACE(line[0])) {
    1171           0 :                         field = strtok_r(line, "\n\t ", &lasts);
    1172           0 :                         if (!strcmp(field, host)) {
    1173           0 :                                 found = true;
    1174           0 :                                 tdsdump_log(TDS_DBG_INFO1, "Found matching entry for host %s.\n", host);
    1175             :                         } else
    1176             :                                 found = false;
    1177           0 :                 } else if (found && TDS_ISSPACE(line[0])) {
    1178           0 :                         field = strtok_r(line, "\n\t ", &lasts);
    1179           0 :                         if (field != NULL && !strcmp(field, "query")) {
    1180           0 :                                 field = strtok_r(NULL, "\n\t ", &lasts);  /* tcp or tli */
    1181           0 :                                 if (!strcmp(field, "tli")) {
    1182           0 :                                         tdsdump_log(TDS_DBG_INFO1, "TLI service.\n");
    1183           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* tcp */
    1184           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* device */
    1185           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* host/port */
    1186           0 :                                         if (strlen(field) >= 18) {
    1187           0 :                                                 sprintf(tmp_port, "%d", hex2num(&field[6]) * 256 + hex2num(&field[8]));
    1188           0 :                                                 sprintf(tmp_ip, "%d.%d.%d.%d", hex2num(&field[10]),
    1189             :                                                         hex2num(&field[12]), hex2num(&field[14]), hex2num(&field[16]));
    1190           0 :                                                 tdsdump_log(TDS_DBG_INFO1, "tmp_port = %s. tmp_ip = %s.\n", tmp_port, tmp_ip);
    1191             :                                         }
    1192             :                                 } else {
    1193           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* ether */
    1194           0 :                                         strcpy(tmp_ver, field);
    1195           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* host */
    1196           0 :                                         strcpy(tmp_ip, field);
    1197           0 :                                         tdsdump_log(TDS_DBG_INFO1, "host field %s.\n", tmp_ip);
    1198           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* port */
    1199           0 :                                         strcpy(tmp_port, field);
    1200             :                                 }       /* else */
    1201             :                                 server_found = true;
    1202             :                         }       /* if */
    1203             :                 }               /* else if */
    1204             :         }                       /* while */
    1205           0 :         fclose(in);
    1206           0 :         free(pathname);
    1207             : 
    1208             : 
    1209             :         /*
    1210             :          * Look up the host and service
    1211             :          */
    1212           0 :         if (server_found) {
    1213             : 
    1214           0 :                 if (TDS_SUCCEED(tds_lookup_host_set(tmp_ip, &login->ip_addrs))) {
    1215             :                         struct addrinfo *addrs;
    1216           0 :                         if (!tds_dstr_copy(&login->server_host_name, tmp_ip))
    1217             :                                 return false;
    1218           0 :                         for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) {
    1219           0 :                                 tdsdump_log(TDS_DBG_INFO1, "Resolved IP as '%s'.\n",
    1220             :                                             tds_addrinfo2str(login->ip_addrs, line, sizeof(line)));
    1221             :                         }
    1222             :                 } else {
    1223           0 :                         tdsdump_log(TDS_DBG_WARN, "Name resolution failed for IP '%s'.\n", tmp_ip);
    1224             :                 }
    1225             : 
    1226           0 :                 if (tmp_port[0])
    1227           0 :                         login->port = tds_lookup_port(tmp_port);
    1228           0 :                 if (tmp_ver[0])
    1229           0 :                         tds_config_verstr(tmp_ver, login);
    1230             :         }
    1231             :         return server_found;
    1232             : }                               /* search_interface_file()  */
    1233             : 
    1234             : /**
    1235             :  * Try to find the IP number and port for a (possibly) logical server name.
    1236             :  *
    1237             :  * @note This function uses only the interfaces file and is deprecated.
    1238             :  */
    1239             : static bool
    1240           0 : tds_read_interfaces(const char *server, TDSLOGIN * login)
    1241             : {
    1242           0 :         bool found = false;
    1243             : 
    1244             :         /* read $SYBASE/interfaces */
    1245             : 
    1246           0 :         if (!server || !server[0]) {
    1247           0 :                 server = getenv("TDSQUERY");
    1248           0 :                 if (!server || !server[0])
    1249           0 :                         server = "SYBASE";
    1250           0 :                 tdsdump_log(TDS_DBG_INFO1, "Setting server to %s from $TDSQUERY.\n", server);
    1251             : 
    1252             :         }
    1253           0 :         tdsdump_log(TDS_DBG_INFO1, "Looking for server %s....\n", server);
    1254             : 
    1255             :         /*
    1256             :          * Look for the server in the interf_file iff interf_file has been set.
    1257             :          */
    1258           0 :         if (interf_file) {
    1259           0 :                 tdsdump_log(TDS_DBG_INFO1, "Looking for server in file %" tdsPRIdir ".\n", interf_file);
    1260           0 :                 found = search_interface_file(login, TDS_DIR(""), interf_file, server);
    1261             :         }
    1262             : 
    1263             :         /*
    1264             :          * if we haven't found the server yet then look for a $HOME/.interfaces file
    1265             :          */
    1266           0 :         if (!found) {
    1267           0 :                 tds_dir_char *path = tds_get_home_file(TDS_DIR(".interfaces"));
    1268             : 
    1269           0 :                 if (path) {
    1270           0 :                         tdsdump_log(TDS_DBG_INFO1, "Looking for server in %" tdsPRIdir ".\n", path);
    1271           0 :                         found = search_interface_file(login, TDS_DIR(""), path, server);
    1272           0 :                         free(path);
    1273             :                 }
    1274             :         }
    1275             : 
    1276             :         /*
    1277             :          * if we haven't found the server yet then look in $SYBBASE/interfaces file
    1278             :          */
    1279           0 :         if (!found) {
    1280           0 :                 const tds_dir_char *sybase = tds_dir_getenv(TDS_DIR("SYBASE"));
    1281             : #ifdef __VMS
    1282             :                 /* We've got to be in unix syntax for later slash-joined concatenation. */
    1283             :                 #include <unixlib.h>
    1284             :                 const char *unixspec = decc$translate_vms(sybase);
    1285             :                 if ( (int)unixspec != 0 && (int)unixspec != -1 ) sybase = unixspec;
    1286             : #endif
    1287           0 :                 if (!sybase || !sybase[0])
    1288           0 :                         sybase = interfaces_path;
    1289             : 
    1290           0 :                 tdsdump_log(TDS_DBG_INFO1, "Looking for server in %" tdsPRIdir "/interfaces.\n", sybase);
    1291           0 :                 found = search_interface_file(login, sybase, TDS_DIR("interfaces"), server);
    1292             :         }
    1293             : 
    1294             :         /*
    1295             :          * If we still don't have the server and port then assume the user
    1296             :          * typed an actual server host name.
    1297             :          */
    1298           0 :         if (!found) {
    1299             :                 int ip_port;
    1300             :                 const char *env_port;
    1301             : 
    1302             :                 /*
    1303             :                  * Make a guess about the port number
    1304             :                  */
    1305             : 
    1306           0 :                 if (login->port == 0) {
    1307             :                         /*
    1308             :                          * Not set in the [global] section of the
    1309             :                          * configure file, take a guess.
    1310             :                          */
    1311             :                         ip_port = TDS_DEF_PORT;
    1312             :                 } else {
    1313             :                         /*
    1314             :                          * Preserve setting from the [global] section
    1315             :                          * of the configure file.
    1316             :                          */
    1317           0 :                         ip_port = login->port;
    1318             :                 }
    1319           0 :                 if ((env_port = getenv("TDSPORT")) != NULL) {
    1320           0 :                         ip_port = tds_lookup_port(env_port);
    1321           0 :                         tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %s from $TDSPORT.\n", env_port);
    1322             :                 } else
    1323           0 :                         tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %d as a guess.\n", ip_port);
    1324             : 
    1325             :                 /*
    1326             :                  * look up the host
    1327             :                  */
    1328             : 
    1329           0 :                 if (TDS_SUCCEED(tds_lookup_host_set(server, &login->ip_addrs)))
    1330           0 :                         if (!tds_dstr_copy(&login->server_host_name, server))
    1331             :                                 return false;
    1332             : 
    1333           0 :                 if (ip_port)
    1334           0 :                         login->port = ip_port;
    1335             :         }
    1336             : 
    1337             :         return found;
    1338             : }
    1339             : 
    1340             : /**
    1341             :  * Check the server name to find port info first
    1342             :  * Warning: connection-> & login-> are all modified when needed
    1343             :  * \return true when found, else false
    1344             :  */
    1345             : static bool
    1346         148 : parse_server_name_for_port(TDSLOGIN * connection, TDSLOGIN * login, bool update_server)
    1347             : {
    1348             :         const char *pSep;
    1349             :         const char *server;
    1350             : 
    1351             :         /* seek the ':' in login server_name */
    1352         296 :         server = tds_dstr_cstr(&login->server_name);
    1353             : 
    1354             :         /* IPv6 address can be quoted */
    1355         148 :         if (server[0] == '[') {
    1356          40 :                 pSep = strstr(server, "]:");
    1357          40 :                 if (pSep)
    1358          20 :                         ++pSep;
    1359             :         } else {
    1360         108 :                 pSep = strrchr(server, ':');
    1361             :         }
    1362             : 
    1363         148 :         if (pSep && pSep != server) {   /* yes, i found it! */
    1364             :                 /* modify connection-> && login->server_name & ->port */
    1365         168 :                 login->port = connection->port = atoi(pSep + 1);
    1366          84 :                 tds_dstr_empty(&connection->instance_name);
    1367             :         } else {
    1368             :                 /* handle instance name */
    1369          64 :                 pSep = strrchr(server, '\\');
    1370          64 :                 if (!pSep || pSep == server)
    1371             :                         return false;
    1372             : 
    1373          64 :                 if (!tds_dstr_copy(&connection->instance_name, pSep + 1))
    1374             :                         return false;
    1375          64 :                 connection->port = 0;
    1376             :         }
    1377             : 
    1378         148 :         if (!update_server)
    1379             :                 return true;
    1380             : 
    1381          74 :         if (server[0] == '[' && pSep > server && pSep[-1] == ']') {
    1382          20 :                 server++;
    1383          20 :                 pSep--;
    1384             :         }
    1385          74 :         if (!tds_dstr_copyn(&connection->server_name, server, pSep - server))
    1386             :                 return false;
    1387             : 
    1388          74 :         return true;
    1389             : }
    1390             : 
    1391             : /**
    1392             :  * Return a structure capturing the compile-time settings provided to the
    1393             :  * configure script.  
    1394             :  */
    1395             : 
    1396             : const TDS_COMPILETIME_SETTINGS *
    1397           0 : tds_get_compiletime_settings(void)
    1398             : {
    1399             :         static const TDS_COMPILETIME_SETTINGS settings = {
    1400             :                   TDS_VERSION_NO
    1401             :                 , FREETDS_SYSCONFDIR
    1402             :                 , "unknown"   /* need fancy script in makefile */
    1403             : #               if TDS50
    1404             :                         , "5.0"
    1405             : #               elif TDS71
    1406             :                         , "7.1"
    1407             : #               elif TDS72
    1408             :                         , "7.2"
    1409             : #               elif TDS73
    1410             :                         , "7.3"
    1411             : #               elif TDS74
    1412             :                         , "7.4"
    1413             : #               else
    1414             :                         , "auto"
    1415             : #               endif
    1416             : #               ifdef MSDBLIB
    1417             :                         , true
    1418             : #               else
    1419             :                         , false
    1420             : #               endif
    1421             : #               ifdef TDS_SYBASE_COMPAT
    1422             :                         , true
    1423             : #               else
    1424             :                         , false
    1425             : #               endif
    1426             : #               ifdef _REENTRANT
    1427             :                         , true
    1428             : #               else
    1429             :                         , false
    1430             : #               endif
    1431             : #               ifdef HAVE_ICONV
    1432             :                         , true
    1433             : #               else
    1434             :                         , false
    1435             : #               endif
    1436             : #               ifdef IODBC
    1437             :                         , true
    1438             : #               else
    1439             :                         , false
    1440             : #               endif
    1441             : #               ifdef UNIXODBC
    1442             :                         , true
    1443             : #               else
    1444             :                         , false
    1445             : #               endif
    1446             : #               ifdef HAVE_OPENSSL
    1447             :                         , true
    1448             : #               else
    1449             :                         , false
    1450             : #               endif
    1451             : #               ifdef HAVE_GNUTLS
    1452             :                         , true
    1453             : #               else
    1454             :                         , false
    1455             : #               endif
    1456             : #               if ENABLE_ODBC_MARS
    1457             :                         , true
    1458             : #               else
    1459             :                         , false
    1460             : #               endif
    1461             : #               ifdef HAVE_SSPI
    1462             :                         , true
    1463             : #               else
    1464             :                         , false
    1465             : #               endif
    1466             : #               ifdef ENABLE_KRB5
    1467             :                         , true
    1468             : #               else
    1469             :                         , false
    1470             : #               endif
    1471             :         };
    1472             : 
    1473             :         assert(settings.tdsver);
    1474             : 
    1475           0 :         return &settings;
    1476             : }
    1477             : 
    1478             : /**
    1479             :  * Make sure proper setting are in place for TDS 8.0
    1480             :  */
    1481             : TDSRET
    1482        3686 : tds8_adjust_login(TDSLOGIN *login)
    1483             : {
    1484             :         /* TDS 8.0 requires TDS_ENCRYPTION_STRICT (entire-connection encryption) */
    1485        3686 :         if (IS_TDS80_PLUS(login))
    1486           0 :                 login->encryption_level = TDS_ENCRYPTION_STRICT;
    1487             : 
    1488        3686 :         if (login->encryption_level == TDS_ENCRYPTION_STRICT) {
    1489             :                 /* TDS 5.0 (Sybase/SAP ASE) it is optional; but TDS 7.x does not allow it.
    1490             :                  * So, try 8.0 unless they specifically requested 5.0 */
    1491           0 :                 if (!IS_TDS50(login) && !IS_TDS80_PLUS(login))
    1492           0 :                         login->tds_version = 0x800;
    1493             : 
    1494             :                 /* Validate server certificate signature to reduce risk of MITM attacks */
    1495           0 :                 if (tds_dstr_isempty(&login->cafile))
    1496           0 :                         if (!tds_dstr_copy(&login->cafile, "system"))
    1497             :                                 return -TDSEMEM;
    1498             :         }
    1499             : 
    1500             :         return TDS_SUCCESS;
    1501             : }
    1502             : 
    1503             : /** @} */

Generated by: LCOV version 1.13