LCOV - code coverage report
Current view: top level - src/tds - config.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 341 595 57.3 %
Date: 2025-07-26 13:53:51 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_open(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_open(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             : 
     260           0 :                 tdsdump_close();
     261             :         }
     262             : 
     263             :         /*
     264             :          * If a dump file has been specified, start logging
     265             :          */
     266        2590 :         if (connection->dump_file != NULL && !tdsdump_isopen()) {
     267           4 :                 if (connection->debug_flags)
     268           4 :                         tds_debug_flags = connection->debug_flags;
     269           4 :                 tdsdump_open(connection->dump_file);
     270             :         }
     271             : 
     272             :         return connection;
     273             : }
     274             : 
     275             : /**
     276             :  * Fix configuration after reading it. 
     277             :  * Currently this read some environment variables and replace some options.
     278             :  */
     279             : void
     280        4584 : tds_fix_login(TDSLOGIN * login)
     281             : {
     282             :         /* Now check the environment variables */
     283        4584 :         tds_config_env_tdsver(login);
     284        4584 :         tds_config_env_tdsdump(login);
     285        4584 :         tds_config_env_tdsport(login);
     286        4584 :         tds_config_env_tdshost(login);
     287        4584 : }
     288             : 
     289             : static bool
     290        7932 : tds_try_conf_file(const tds_dir_char *path, const char *how, const char *server, TDSLOGIN * login)
     291             : {
     292        7932 :         bool found = false;
     293             :         FILE *in;
     294             : 
     295        7932 :         if ((in = tds_dir_open(path, TDS_DIR("r"))) == NULL) {
     296        3774 :                 tdsdump_log(TDS_DBG_INFO1, "Could not open '%" tdsPRIdir "' (%s).\n", path, how);
     297             :                 return found;
     298             :         }
     299             : 
     300        4158 :         tdsdump_log(TDS_DBG_INFO1, "Found conf file '%" tdsPRIdir "' %s.\n", path, how);
     301        4158 :         found = tds_read_conf_sections(in, server, login);
     302             : 
     303        4158 :         if (found) {
     304        3670 :                 tdsdump_log(TDS_DBG_INFO1, "Success: [%s] defined in %" tdsPRIdir ".\n", server, path);
     305             :         } else {
     306         488 :                 tdsdump_log(TDS_DBG_INFO2, "[%s] not found.\n", server);
     307             :         }
     308             : 
     309        4158 :         fclose(in);
     310             : 
     311        4158 :         return found;
     312             : }
     313             : 
     314             : /**
     315             :  * Read configuration info for given server
     316             :  * return 0 on error
     317             :  * @param login where to store configuration
     318             :  * @param server       section of file configuration that hold 
     319             :  *                     configuration for a server
     320             :  */
     321             : bool
     322        3794 : tds_read_conf_file(TDSLOGIN * login, const char *server)
     323             : {
     324        3794 :         tds_dir_char *path = NULL;
     325        3794 :         tds_dir_char *eptr = NULL;
     326        3794 :         bool found = false;
     327             : 
     328        3794 :         if (interf_file) {
     329         140 :                 found = tds_try_conf_file(interf_file, "set programmatically", server, login);
     330             :         }
     331             : 
     332             :         /* FREETDSCONF env var, pkleef@openlinksw.com 01/21/02 */
     333         140 :         if (!found) {
     334        3774 :                 path = tds_dir_getenv(TDS_DIR("FREETDSCONF"));
     335        3774 :                 if (path) {
     336         120 :                         found = tds_try_conf_file(path, "(from $FREETDSCONF)", server, login);
     337             :                 } else {
     338        3654 :                         tdsdump_log(TDS_DBG_INFO2, "... $FREETDSCONF not set.  Trying $FREETDS/etc.\n");
     339             :                 }
     340             :         }
     341             : 
     342             :         /* FREETDS env var, Bill Thompson 16/07/03 */
     343        3794 :         if (!found) {
     344        3774 :                 eptr = tds_dir_getenv(TDS_DIR("FREETDS"));
     345        3774 :                 if (eptr) {
     346           0 :                         path = tds_join_path(eptr, freetds_conf);
     347           0 :                         if (path) {
     348           0 :                                 found = tds_try_conf_file(path, location, server, login);
     349           0 :                                 free(path);
     350             :                         }
     351             :                 } else {
     352        3774 :                         tdsdump_log(TDS_DBG_INFO2, "... $FREETDS not set.  Trying $HOME.\n");
     353             :                 }
     354             :         }
     355             : 
     356             : #if !defined(_WIN32) && !defined(DOS32X)
     357        3794 :         if (!found) {
     358        3774 :                 path = tds_get_home_file(TDS_DIR(".config/freetds.conf"));
     359        3774 :                 if (path) {
     360        3774 :                         found = tds_try_conf_file(path, "(.config/freetds.conf)", server, login);
     361        3774 :                         free(path);
     362             :                 }
     363             :         }
     364             : #endif
     365             : 
     366        3794 :         if (!found) {
     367        3774 :                 path = tds_get_home_file(TDS_DIR(".freetds.conf"));
     368        3774 :                 if (path) {
     369        3774 :                         found = tds_try_conf_file(path, "(.freetds.conf)", server, login);
     370        3774 :                         free(path);
     371             :                 } else {
     372           0 :                         tdsdump_log(TDS_DBG_INFO2, "... Error getting ~/.freetds.conf.  Trying %" tdsPRIdir ".\n",
     373             :                                     FREETDS_SYSCONFFILE);
     374             :                 }
     375             :         }
     376             : 
     377        3794 :         if (!found) {
     378         124 :                 found = tds_try_conf_file(FREETDS_SYSCONFFILE, "(default)", server, login);
     379             :         }
     380             : 
     381        3794 :         return found;
     382             : }
     383             : 
     384             : static bool
     385        4158 : tds_read_conf_sections(FILE * in, const char *server, TDSLOGIN * login)
     386             : {
     387        4158 :         DSTR default_instance = DSTR_INITIALIZER;
     388             :         int default_port;
     389             : 
     390             :         bool found;
     391             : 
     392        4158 :         tds_read_conf_section(in, "global", tds_parse_conf_section, login);
     393             : 
     394        4158 :         if (!server[0])
     395             :                 return false;
     396        4158 :         rewind(in);
     397             : 
     398        4158 :         if (!tds_dstr_dup(&default_instance, &login->instance_name))
     399             :                 return false;
     400        4158 :         default_port = login->port;
     401             : 
     402        4158 :         found = tds_read_conf_section(in, server, tds_parse_conf_section, login);
     403        4158 :         if (!login->valid_configuration) {
     404           0 :                 tds_dstr_free(&default_instance);
     405           0 :                 return false;
     406             :         }
     407             : 
     408             :         /* 
     409             :          * If both instance and port are specified and neither one came from the default, it's an error 
     410             :          * TODO: If port/instance is specified in the non-default, it has priority over the default setting. 
     411             :          * TODO: test this. 
     412             :          */
     413        8408 :         if (!tds_dstr_isempty(&login->instance_name) && login->port &&
     414          92 :             !(!tds_dstr_isempty(&default_instance) || default_port)) {
     415           0 :                 tdsdump_log(TDS_DBG_ERROR, "error: cannot specify both port %d and instance %s.\n", 
     416           0 :                                                 login->port, tds_dstr_cstr(&login->instance_name));
     417             :                 /* tdserror(tds_get_ctx(tds), tds, TDSEPORTINSTANCE, 0); */
     418             :         }
     419        4158 :         tds_dstr_free(&default_instance);
     420        4158 :         return found;
     421             : }
     422             : 
     423             : static const struct {
     424             :         char value[7];
     425             :         unsigned char to_return;
     426             : } boolean_values[] = {
     427             :         { "yes",      1 },
     428             :         { "no",               0 },
     429             :         { "on",               1 },
     430             :         { "off",      0 },
     431             :         { "true",     1 },
     432             :         { "false",    0 }
     433             : };
     434             : 
     435             : int
     436           0 : tds_parse_boolean(const char *value, int default_value)
     437             : {
     438             :         int p;
     439             : 
     440       10164 :         for (p = 0; p < TDS_VECTOR_SIZE(boolean_values); ++p) {
     441       10164 :                 if (!strcasecmp(value, boolean_values[p].value))
     442        2898 :                         return boolean_values[p].to_return;
     443             :         }
     444             :         return default_value;
     445             : }
     446             : 
     447             : int
     448           0 : tds_config_boolean(const char *option, const char *value, TDSLOGIN *login)
     449             : {
     450           0 :         int ret = tds_parse_boolean(value, -1);
     451           0 :         if (ret >= 0)
     452             :                 return ret;
     453             : 
     454           0 :         tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for boolean setting '%s'!\n",
     455             :                     value, option);
     456           0 :         login->valid_configuration = 0;
     457           0 :         return 0;
     458             : }
     459             : 
     460             : static int
     461        2898 : tds_parse_boolean_option(const char *option, const char *value, int default_value, bool *p_error)
     462             : {
     463        2898 :         int ret = tds_parse_boolean(value, -1);
     464        2898 :         if (ret >= 0)
     465             :                 return ret;
     466             : 
     467           0 :         tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for boolean setting '%s'!\n",
     468             :                     value, option);
     469           0 :         *p_error = true;
     470           0 :         return default_value;
     471             : }
     472             : 
     473             : static bool
     474        1462 : tds_config_encryption(const char * value, TDSLOGIN * login)
     475             : {
     476        1462 :         TDS_ENCRYPTION_LEVEL lvl = TDS_ENCRYPTION_OFF;
     477             : 
     478        1462 :         if (!strcasecmp(value, TDS_STR_ENCRYPTION_OFF))
     479             :                 ;
     480        1462 :         else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUEST))
     481             :                 lvl = TDS_ENCRYPTION_REQUEST;
     482        1442 :         else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUIRE))
     483             :                 lvl = TDS_ENCRYPTION_REQUIRE;
     484           0 :         else if (!strcasecmp(value, TDS_STR_ENCRYPTION_STRICT))
     485             :                 lvl = TDS_ENCRYPTION_STRICT;
     486             :         else {
     487           0 :                 tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for '%s' setting!\n",
     488             :                             value, TDS_STR_ENCRYPTION);
     489           0 :                 tdsdump_log(TDS_DBG_ERROR, "Valid settings are: ('%s', '%s', '%s', '%s')\n",
     490             :                         TDS_STR_ENCRYPTION_OFF, TDS_STR_ENCRYPTION_REQUEST, TDS_STR_ENCRYPTION_REQUIRE,
     491             :                         TDS_STR_ENCRYPTION_STRICT);
     492             :                 lvl = TDS_ENCRYPTION_REQUIRE;  /* Assuming "require" is safer than "no" */
     493             :                 return false;
     494             :         }
     495             : 
     496        1462 :         login->encryption_level = lvl;
     497             :         return true;
     498             : }
     499             : 
     500             : /**
     501             :  * Read a section of configuration file (INI style file)
     502             :  * @param in             configuration file
     503             :  * @param section        section to read
     504             :  * @param tds_conf_parse callback that receive every entry in section
     505             :  * @param param          parameter to pass to callback function
     506             :  */
     507             : bool
     508       44464 : tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *param)
     509             : {
     510             :         char line[256], *value;
     511             : #define option line
     512             :         char *s;
     513             :         char p;
     514             :         int i;
     515       44464 :         bool insection = false;
     516       44464 :         bool found = false;
     517             : 
     518       44464 :         tdsdump_log(TDS_DBG_INFO1, "Looking for section %s.\n", section);
     519     2589534 :         while (fgets(line, sizeof(line), in)) {
     520             :                 s = line;
     521             : 
     522             :                 /* skip leading whitespace */
     523     4005728 :                 while (*s && TDS_ISSPACE(*s))
     524     1460658 :                         s++;
     525             : 
     526             :                 /* skip it if it's a comment line */
     527     2545070 :                 if (*s == ';' || *s == '#')
     528      896868 :                         continue;
     529             : 
     530             :                 /* read up to the = ignoring duplicate spaces */
     531             :                 p = 0;
     532             :                 i = 0;
     533    13893388 :                 while (*s && *s != '=') {
     534    12245186 :                         if (!TDS_ISSPACE(*s)) {
     535    10508464 :                                 if (TDS_ISSPACE(p))
     536      415178 :                                         option[i++] = ' ';
     537    10508464 :                                 option[i++] = tolower((unsigned char) *s);
     538             :                         }
     539    12245186 :                         p = *s;
     540    12245186 :                         s++;
     541             :                 }
     542             : 
     543             :                 /* skip if empty option */
     544     1648202 :                 if (!i)
     545      332872 :                         continue;
     546             : 
     547             :                 /* skip the = */
     548     1315330 :                 if (*s)
     549     1029806 :                         s++;
     550             : 
     551             :                 /* terminate the option, must be done after skipping = */
     552     1315330 :                 option[i] = '\0';
     553             : 
     554             :                 /* skip leading whitespace */
     555     3659346 :                 while (*s && TDS_ISSPACE(*s))
     556     1028686 :                         s++;
     557             : 
     558             :                 /* read up to a # ; or null ignoring duplicate spaces */
     559             :                 value = s;
     560             :                 p = 0;
     561             :                 i = 0;
     562    10967142 :                 while (*s && *s != ';' && *s != '#') {
     563     9651812 :                         if (!TDS_ISSPACE(*s)) {
     564     8541902 :                                 if (TDS_ISSPACE(p))
     565       80044 :                                         value[i++] = ' ';
     566     8541902 :                                 value[i++] = *s;
     567             :                         }
     568     9651812 :                         p = *s;
     569     9651812 :                         s++;
     570             :                 }
     571     1315330 :                 value[i] = '\0';
     572             : 
     573     1315330 :                 if (option[0] == '[') {
     574      285524 :                         s = strchr(option, ']');
     575      285524 :                         if (s)
     576      285524 :                                 *s = '\0';
     577      285524 :                         tdsdump_log(TDS_DBG_INFO1, "\tFound section %s.\n", &option[1]);
     578             : 
     579      285524 :                         if (!strcasecmp(section, &option[1])) {
     580       40207 :                                 tdsdump_log(TDS_DBG_INFO1, "Got a match.\n");
     581             :                                 insection = true;
     582             :                                 found = true;
     583             :                         } else {
     584             :                                 insection = false;
     585             :                         }
     586     1029806 :                 } else if (insection) {
     587      124670 :                         tds_conf_parse(option, value, param);
     588             :                 }
     589             : 
     590             :         }
     591       44464 :         tdsdump_log(TDS_DBG_INFO1, "\tReached EOF\n");
     592       44464 :         return found;
     593             : #undef option
     594             : }
     595             : 
     596             : /* Also used to scan ODBC.INI entries */
     597             : bool
     598       31084 : tds_parse_conf_section(const char *option, const char *value, void *param)
     599             : {
     600             : #define parse_boolean(option, value, variable) do { \
     601             :         variable = tds_parse_boolean_option(option, value, variable, &got_error); \
     602             : } while(0)
     603       31084 :         TDSLOGIN *login = (TDSLOGIN *) param;
     604       31084 :         void *s = param;
     605       31084 :         bool got_error = false;
     606             : 
     607       31084 :         tdsdump_log(TDS_DBG_INFO1, "\t%s = '%s'\n", option, value);
     608             : 
     609       31084 :         if (!strcmp(option, TDS_STR_VERSION)) {
     610        3804 :                 tds_config_verstr(value, login);
     611       27280 :         } else if (!strcmp(option, TDS_STR_BLKSZ)) {
     612           0 :                 int val = atoi(value);
     613           0 :                 if (val >= 512 && val < 65536)
     614           0 :                         login->block_size = val;
     615       27280 :         } else if (!strcmp(option, TDS_STR_SWAPDT)) {
     616             :                 /* this option is deprecated, just check value for compatibility */
     617           0 :                 tds_config_boolean(option, value, login);
     618       27280 :         } else if (!strcmp(option, TDS_GSSAPI_DELEGATION)) {
     619             :                 /* gssapi flag addition */
     620           0 :                 parse_boolean(option, value, login->gssapi_use_delegation);
     621       27280 :         } else if (!strcmp(option, TDS_STR_MUTUAL_AUTHENTICATION)) {
     622           0 :                 parse_boolean(option, value, login->mutual_authentication);
     623       27280 :         } else if (!strcmp(option, TDS_STR_DUMPFILE)) {
     624           0 :                 TDS_ZERO_FREE(login->dump_file);
     625           0 :                 if (value[0]) {
     626           0 :                         login->dump_file = tds_dir_from_cstr(value);
     627           0 :                         if (!login->dump_file)
     628             :                                 s = NULL;
     629             :                 }
     630       27280 :         } else if (!strcmp(option, TDS_STR_DEBUGFLAGS)) {
     631             :                 char *end;
     632             :                 long flags;
     633        3774 :                 flags = strtol(value, &end, 0);
     634        3774 :                 if (*value != '\0' && *end == '\0' && flags > INT_MIN && flags < INT_MAX)
     635        3774 :                     login->debug_flags = (int) flags;
     636       23506 :         } else if (!strcmp(option, TDS_STR_TIMEOUT) || !strcmp(option, TDS_STR_QUERY_TIMEOUT)) {
     637        3774 :                 if (atoi(value) > 0)
     638        3774 :                         login->query_timeout = atoi(value);
     639       19732 :         } else if (!strcmp(option, TDS_STR_CONNTIMEOUT)) {
     640        3774 :                 if (atoi(value) > 0)
     641        3774 :                         login->connect_timeout = atoi(value);
     642       15958 :         } else if (!strcmp(option, TDS_STR_HOST)) {
     643             :                 char tmp[128];
     644             :                 struct addrinfo *addrs;
     645             : 
     646        3670 :                 if (TDS_FAILED(tds_lookup_host_set(value, &login->ip_addrs))) {
     647           0 :                         tdsdump_log(TDS_DBG_WARN, "Found host entry %s however name resolution failed. \n", value);
     648           0 :                         return false;
     649             :                 }
     650             : 
     651        3670 :                 tdsdump_log(TDS_DBG_INFO1, "Found host entry %s \n", value);
     652        3670 :                 s = tds_dstr_copy(&login->server_host_name, value);
     653        7340 :                 for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next)
     654        3670 :                         tdsdump_log(TDS_DBG_INFO1, "IP addr is %s.\n", tds_addrinfo2str(addrs, tmp, sizeof(tmp)));
     655             : 
     656       12288 :         } else if (!strcmp(option, TDS_STR_PORT)) {
     657        3890 :                 if (atoi(value) > 0)
     658        3890 :                         login->port = atoi(value);
     659        8398 :         } else if (!strcmp(option, TDS_STR_EMUL_LE)) {
     660             :                 /* obsolete, ignore */
     661           0 :                 tds_config_boolean(option, value, login);
     662        8398 :         } else if (!strcmp(option, TDS_STR_TEXTSZ)) {
     663        3898 :                 if (atoi(value) > 0)
     664        3898 :                         login->text_size = atoi(value);
     665        4500 :         } else if (!strcmp(option, TDS_STR_CHARSET)) {
     666           0 :                 s = tds_dstr_copy(&login->server_charset, value);
     667           0 :                 tdsdump_log(TDS_DBG_INFO1, "%s is %s.\n", option, tds_dstr_cstr(&login->server_charset));
     668        4500 :         } else if (!strcmp(option, TDS_STR_CLCHARSET)) {
     669         100 :                 s = tds_dstr_copy(&login->client_charset, value);
     670         100 :                 tdsdump_log(TDS_DBG_INFO1, "tds_parse_conf_section: %s is %s.\n", option, tds_dstr_cstr(&login->client_charset));
     671        4400 :         } else if (!strcmp(option, TDS_STR_USE_UTF_16)) {
     672           0 :                 parse_boolean(option, value, login->use_utf16);
     673        4400 :         } else if (!strcmp(option, TDS_STR_LANGUAGE)) {
     674           0 :                 s = tds_dstr_copy(&login->language, value);
     675        4400 :         } else if (!strcmp(option, TDS_STR_APPENDMODE)) {
     676           0 :                 parse_boolean(option, value, tds_append_mode);
     677        4400 :         } else if (!strcmp(option, TDS_STR_INSTANCE)) {
     678           0 :                 s = tds_dstr_copy(&login->instance_name, value);
     679        4400 :         } else if (!strcmp(option, TDS_STR_ENCRYPTION)) {
     680        1462 :                 if (!tds_config_encryption(value, login))
     681             :                         s = NULL;
     682        2938 :         } else if (!strcmp(option, TDS_STR_ASA_DATABASE)) {
     683          20 :                 s = tds_dstr_copy(&login->server_name, value);
     684        2918 :         } else if (!strcmp(option, TDS_STR_USENTLMV2)) {
     685           0 :                 parse_boolean(option, value, login->use_ntlmv2);
     686           0 :                 login->use_ntlmv2_specified = 1;
     687        2918 :         } else if (!strcmp(option, TDS_STR_USELANMAN)) {
     688           0 :                 parse_boolean(option, value, login->use_lanman);
     689        2918 :         } else if (!strcmp(option, TDS_STR_REALM)) {
     690           0 :                 s = tds_dstr_copy(&login->server_realm_name, value);
     691        2918 :         } else if (!strcmp(option, TDS_STR_SPN)) {
     692           0 :                 s = tds_dstr_copy(&login->server_spn, value);
     693        2918 :         } else if (!strcmp(option, TDS_STR_CAFILE)) {
     694           0 :                 s = tds_dstr_copy(&login->cafile, value);
     695        2918 :         } else if (!strcmp(option, TDS_STR_CRLFILE)) {
     696           0 :                 s = tds_dstr_copy(&login->crlfile, value);
     697        2918 :         } else if (!strcmp(option, TDS_STR_CHECKSSLHOSTNAME)) {
     698        1442 :                 parse_boolean(option, value, login->check_ssl_hostname);
     699        1476 :         } else if (!strcmp(option, TDS_STR_SSLHOSTNAME)) {
     700           0 :                 s = tds_dstr_copy(&login->certificate_host_name, value);
     701        1476 :         } else if (!strcmp(option, TDS_STR_DBFILENAME)) {
     702           0 :                 s = tds_dstr_copy(&login->db_filename, value);
     703        1476 :         } else if (!strcmp(option, TDS_STR_DATABASE)) {
     704           0 :                 s = tds_dstr_copy(&login->database, value);
     705        1476 :         } else if (!strcmp(option, TDS_STR_READONLY_INTENT)) {
     706           0 :                 parse_boolean(option, value, login->readonly_intent);
     707           0 :                 tdsdump_log(TDS_DBG_FUNC, "Setting ReadOnly Intent to '%s'.\n", value);
     708        1476 :         } else if (!strcmp(option, TLS_STR_OPENSSL_CIPHERS)) {
     709           0 :                 s = tds_dstr_copy(&login->openssl_ciphers, value);
     710        1476 :         } else if (!strcmp(option, TDS_STR_ENABLE_TLS_V1)) {
     711        1456 :                 parse_boolean(option, value, login->enable_tls_v1);
     712        1456 :                 login->enable_tls_v1_specified = 1;
     713          20 :         } else if (!strcmp(option, TDS_STR_ENABLE_TLS_V1_1)) {
     714           0 :                 parse_boolean(option, value, login->enable_tls_v1_1);
     715           0 :                 login->enable_tls_v1_1_specified = 1;
     716             :         } else {
     717          20 :                 tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s' ... ignoring.\n", option);
     718             :         }
     719             : 
     720       31084 :         if (!s || got_error) {
     721           0 :                 login->valid_configuration = 0;
     722           0 :                 return false;
     723             :         }
     724             :         return true;
     725             : #undef parse_boolean
     726             : }
     727             : 
     728             : static bool
     729        2590 : tds_config_login(TDSLOGIN * connection, TDSLOGIN * login)
     730             : {
     731        2590 :         DSTR *res = &login->server_name;
     732             : 
     733        5180 :         if (!tds_dstr_isempty(&login->server_name)) {
     734             :                 if (1 || tds_dstr_isempty(&connection->server_name))
     735        2590 :                         res = tds_dstr_dup(&connection->server_name, &login->server_name);
     736             :         }
     737             : 
     738        2590 :         if (login->tds_version)
     739          22 :                 connection->tds_version = login->tds_version;
     740             : 
     741        5180 :         if (res && !tds_dstr_isempty(&login->language))
     742         326 :                 res = tds_dstr_dup(&connection->language, &login->language);
     743             : 
     744        5180 :         if (res && !tds_dstr_isempty(&login->server_charset))
     745           0 :                 res = tds_dstr_dup(&connection->server_charset, &login->server_charset);
     746             : 
     747        5180 :         if (res && !tds_dstr_isempty(&login->client_charset)) {
     748         174 :                 res = tds_dstr_dup(&connection->client_charset, &login->client_charset);
     749         174 :                 tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "client_charset",
     750           0 :                             tds_dstr_cstr(&connection->client_charset));
     751             :         }
     752             : 
     753        2590 :         if (!login->use_utf16)
     754           0 :                 connection->use_utf16 = login->use_utf16;
     755             : 
     756        5180 :         if (res && !tds_dstr_isempty(&login->database)) {
     757          54 :                 res = tds_dstr_dup(&connection->database, &login->database);
     758          54 :                 tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "database_name",
     759           0 :                             tds_dstr_cstr(&connection->database));
     760             :         }
     761             : 
     762        5180 :         if (res && !tds_dstr_isempty(&login->client_host_name))
     763         494 :                 res = tds_dstr_dup(&connection->client_host_name, &login->client_host_name);
     764             : 
     765        5180 :         if (res && !tds_dstr_isempty(&login->app_name))
     766        1180 :                 res = tds_dstr_dup(&connection->app_name, &login->app_name);
     767             : 
     768        5180 :         if (res && !tds_dstr_isempty(&login->user_name))
     769        2520 :                 res = tds_dstr_dup(&connection->user_name, &login->user_name);
     770             : 
     771        5180 :         if (res && !tds_dstr_isempty(&login->password)) {
     772             :                 /* for security reason clear memory */
     773        2520 :                 tds_dstr_zero(&connection->password);
     774        2520 :                 res = tds_dstr_dup(&connection->password, &login->password);
     775             :         }
     776             : 
     777        5180 :         if (res && !tds_dstr_isempty(&login->library))
     778        2520 :                 res = tds_dstr_dup(&connection->library, &login->library);
     779             : 
     780        2590 :         if (login->encryption_level)
     781           0 :                 connection->encryption_level = login->encryption_level;
     782             : 
     783        2590 :         if (login->suppress_language)
     784           0 :                 connection->suppress_language = 1;
     785             : 
     786        2590 :         if (!login->bulk_copy)
     787           0 :                 connection->bulk_copy = 0;
     788             : 
     789        2590 :         if (login->block_size)
     790           0 :                 connection->block_size = login->block_size;
     791             : 
     792        2590 :         if (login->gssapi_use_delegation)
     793           0 :                 connection->gssapi_use_delegation = login->gssapi_use_delegation;
     794             : 
     795        2590 :         if (login->mutual_authentication)
     796           0 :                 connection->mutual_authentication = login->mutual_authentication;
     797             : 
     798        2590 :         if (login->port)
     799          42 :                 connection->port = login->port;
     800             : 
     801        2590 :         if (login->connect_timeout)
     802           0 :                 connection->connect_timeout = login->connect_timeout;
     803             : 
     804        2590 :         if (login->query_timeout)
     805           0 :                 connection->query_timeout = login->query_timeout;
     806             : 
     807        2590 :         if (!login->check_ssl_hostname)
     808           0 :                 connection->check_ssl_hostname = login->check_ssl_hostname;
     809             : 
     810        5180 :         if (res && !tds_dstr_isempty(&login->db_filename))
     811           0 :                 res = tds_dstr_dup(&connection->db_filename, &login->db_filename);
     812             : 
     813        5180 :         if (res && !tds_dstr_isempty(&login->openssl_ciphers))
     814           0 :                 res = tds_dstr_dup(&connection->openssl_ciphers, &login->openssl_ciphers);
     815             : 
     816        5180 :         if (res && !tds_dstr_isempty(&login->server_spn))
     817           0 :                 res = tds_dstr_dup(&connection->server_spn, &login->server_spn);
     818             : 
     819             :         /* copy other info not present in configuration file */
     820        2590 :         connection->capabilities = login->capabilities;
     821             : 
     822        2590 :         if (login->readonly_intent)
     823           0 :                 connection->readonly_intent = login->readonly_intent;
     824             : 
     825        2590 :         connection->use_new_password = login->use_new_password;
     826             : 
     827        2590 :         if (login->use_ntlmv2_specified) {
     828           0 :                 connection->use_ntlmv2_specified = login->use_ntlmv2_specified;
     829           0 :                 connection->use_ntlmv2 = login->use_ntlmv2;
     830             :         }
     831             : 
     832        2590 :         if (login->enable_tls_v1_specified) {
     833           0 :                 connection->enable_tls_v1_specified = login->enable_tls_v1_specified;
     834           0 :                 connection->enable_tls_v1 = login->enable_tls_v1;
     835             :         }
     836             : 
     837        2590 :         if (login->enable_tls_v1_1_specified) {
     838           0 :                 connection->enable_tls_v1_1_specified = login->enable_tls_v1_1_specified;
     839           0 :                 connection->enable_tls_v1_1 = login->enable_tls_v1_1;
     840             :         }
     841             : 
     842        2590 :         if (res)
     843        2590 :                 res = tds_dstr_dup(&connection->new_password, &login->new_password);
     844             : 
     845        2590 :         return res != NULL;
     846             : }
     847             : 
     848             : static bool
     849        4584 : tds_config_env_tdsdump(TDSLOGIN * login)
     850             : {
     851             :         tds_dir_char path[TDS_VECTOR_SIZE(pid_logpath) + 22];
     852             : 
     853        4584 :         tds_dir_char *s = tds_dir_getenv(TDS_DIR("TDSDUMP"));
     854        4584 :         if (!s)
     855             :                 return true;
     856             : 
     857           4 :         if (!tds_dir_len(s)) {
     858           0 :                 pid_t pid = getpid();
     859           0 :                 tds_dir_snprintf(path, TDS_VECTOR_SIZE(path), pid_logpath, (int) pid);
     860           0 :                 s = path;
     861             :         }
     862             : 
     863           4 :         if (!(s = tds_dir_dup(s)))
     864             :                 return false;
     865           4 :         free(login->dump_file);
     866           4 :         login->dump_file = s;
     867             : 
     868           4 :         tdsdump_log(TDS_DBG_INFO1, "Setting 'dump_file' to '%" tdsPRIdir "' from $TDSDUMP.\n", login->dump_file);
     869             :         return true;
     870             : }
     871             : 
     872             : static void
     873        4584 : tds_config_env_tdsport(TDSLOGIN * login)
     874             : {
     875             :         char *s;
     876             : 
     877        4584 :         if ((s = getenv("TDSPORT"))) {
     878          12 :                 login->port = tds_lookup_port(s);
     879          12 :                 tds_dstr_empty(&login->instance_name);
     880          12 :                 tdsdump_log(TDS_DBG_INFO1, "Setting 'port' to %s from $TDSPORT.\n", s);
     881             :         }
     882        4584 :         return;
     883             : }
     884             : static void
     885        4584 : tds_config_env_tdsver(TDSLOGIN * login)
     886             : {
     887             :         char *tdsver;
     888             : 
     889        4584 :         if ((tdsver = getenv("TDSVER"))) {
     890          14 :                 TDS_USMALLINT *pver = tds_config_verstr(tdsver, login);
     891          14 :                 tdsdump_log(TDS_DBG_INFO1, "TDS version %sset to %s from $TDSVER.\n", (pver? "":"not "), tdsver);
     892             : 
     893             :         }
     894        4584 :         return;
     895             : }
     896             : 
     897             : /* TDSHOST env var, pkleef@openlinksw.com 01/21/02 */
     898             : static bool
     899        4584 : tds_config_env_tdshost(TDSLOGIN * login)
     900             : {
     901             :         const char *tdshost;
     902             :         char tmp[128];
     903             :         struct addrinfo *addrs;
     904             : 
     905        4584 :         if (!(tdshost = getenv("TDSHOST")))
     906             :                 return true;
     907             : 
     908          10 :         if (TDS_FAILED(tds_lookup_host_set(tdshost, &login->ip_addrs))) {
     909           0 :                 tdsdump_log(TDS_DBG_WARN, "Name resolution failed for '%s' from $TDSHOST.\n", tdshost);
     910             :                 return false;
     911             :         }
     912             : 
     913          10 :         if (!tds_dstr_copy(&login->server_host_name, tdshost))
     914             :                 return false;
     915          20 :         for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) {
     916          10 :                 tdsdump_log(TDS_DBG_INFO1, "Setting IP Address to %s (%s) from $TDSHOST.\n",
     917             :                             tds_addrinfo2str(addrs, tmp, sizeof(tmp)), tdshost);
     918             :         }
     919             :         return true;
     920             : }
     921             : #define TDS_FIND(k,b,c) tds_find(k, b, TDS_VECTOR_SIZE(b), sizeof(b[0]), c)
     922             : 
     923             : 
     924             : static const void *
     925             : tds_find(const void *key, const void *base, size_t nelem, size_t width,
     926             :          int (*compar)(const void *, const void *))
     927             : {
     928             :         size_t n;
     929             :         const char *p = (const char*) base;
     930             : 
     931       27434 :         for (n = nelem; n != 0; --n) {
     932       31252 :                 if (0 == compar(key, p))
     933             :                         return p;
     934       27434 :                 p += width;
     935             :         }
     936             :         return NULL;
     937             : }
     938             : 
     939             : struct tdsvername_t 
     940             : {
     941             :         const char name[6];
     942             :         TDS_USMALLINT version;
     943             : };
     944             : 
     945             : static int
     946       31252 : tds_vername_cmp(const void *key, const void *pelem)
     947             : {
     948       31252 :         return strcmp((const char *)key, ((const struct tdsvername_t *)pelem)->name);
     949             : }
     950             : 
     951             : /**
     952             :  * Set TDS version from given string
     953             :  * @param tdsver tds string version
     954             :  * @param login where to store information
     955             :  * @return as encoded hex value: high byte major, low byte minor.
     956             :  */
     957             : TDS_USMALLINT *
     958        3818 : tds_config_verstr(const char *tdsver, TDSLOGIN * login)
     959             : {
     960             :         static const struct tdsvername_t tds_versions[] = 
     961             :                 { {   "0", 0x000 }
     962             :                 , {"auto", 0x000 }
     963             :                 , { "4.2", 0x402 }
     964             :                 , {  "50", 0x500 }
     965             :                 , { "5.0", 0x500 }
     966             :                 , {  "70", 0x700 }
     967             :                 , { "7.0", 0x700 }
     968             :                 , { "7.1", 0x701 }
     969             :                 , { "7.2", 0x702 }
     970             :                 , { "7.3", 0x703 }
     971             :                 , { "7.4", 0x704 }
     972             :                 , { "8.0", 0x800 }
     973             :                 };
     974             :         const struct tdsvername_t *pver;
     975             : 
     976        3818 :         if (!login) {
     977           0 :                 assert(login);
     978             :                 return NULL;
     979             :         }
     980             : 
     981        3818 :         if ((pver = (const struct tdsvername_t *) TDS_FIND(tdsver, tds_versions, tds_vername_cmp)) == NULL) {
     982           0 :                 tdsdump_log(TDS_DBG_INFO1, "error: no such version: %s\n", tdsver);
     983             :                 return NULL;
     984             :         }
     985             :         
     986        3818 :         login->tds_version = pver->version;
     987        3818 :         tdsdump_log(TDS_DBG_INFO1, "Setting tds version to %s (0x%0x).\n", tdsver, pver->version);
     988             : 
     989        3818 :         return &login->tds_version;
     990             : }
     991             : 
     992             : /**
     993             :  * Set the full name of interface file
     994             :  * @param interf file name
     995             :  */
     996             : TDSRET
     997          20 : tds_set_interfaces_file_loc(const char *interf)
     998             : {
     999          20 :         tds_dir_char *copy = NULL;
    1000             : 
    1001             :         /* If filename passed, copy filename */
    1002          20 :         if (interf != NULL && interf[0] != '\0') {
    1003          10 :                 copy = tds_dir_from_cstr(interf);
    1004          10 :                 if (copy == NULL)
    1005             :                         return -TDSEMEM;
    1006             :         }
    1007             : 
    1008             :         /* Free it if already set */
    1009          20 :         free(interf_file);
    1010             : 
    1011             :         /* Set */
    1012          20 :         interf_file = copy;
    1013             : 
    1014          20 :         return TDS_SUCCESS;
    1015             : }
    1016             : 
    1017             : /**
    1018             :  * Get the IP address for a hostname. Store server's IP address 
    1019             :  * in the string 'ip' in dotted-decimal notation.  (The "hostname" might itself
    1020             :  * be a dotted-decimal address.  
    1021             :  *
    1022             :  * If we can't determine the IP address then 'ip' will be set to empty
    1023             :  * string.
    1024             :  */
    1025             : /* TODO callers seem to set always connection info... change it */
    1026             : struct addrinfo *
    1027        3830 : tds_lookup_host(const char *servername) /* (I) name of the server                  */
    1028             : {
    1029        3830 :         struct addrinfo hints, *addr = NULL;
    1030        3830 :         assert(servername != NULL);
    1031             : 
    1032        3830 :         memset(&hints, '\0', sizeof(hints));
    1033             :         hints.ai_family = AF_UNSPEC;
    1034        3830 :         hints.ai_socktype = SOCK_STREAM;
    1035        3830 :         hints.ai_protocol = IPPROTO_TCP;
    1036             : 
    1037             : #ifdef AI_ADDRCONFIG
    1038        3830 :         hints.ai_flags |= AI_ADDRCONFIG;
    1039        3830 :         switch (getaddrinfo(servername, NULL, &hints, &addr)) {
    1040        3830 :         case 0:
    1041        3830 :                 return addr;
    1042           0 :         case EAI_FAMILY:
    1043             : #  ifdef EAI_ADDRFAMILY
    1044             :         case EAI_ADDRFAMILY:
    1045             : #  endif
    1046           0 :                 hints.ai_flags &= ~AI_ADDRCONFIG;
    1047             :                 break;
    1048             :         default:
    1049             :                 return NULL;
    1050             :         }
    1051             : #endif
    1052             : 
    1053           0 :         if (getaddrinfo(servername, NULL, &hints, &addr))
    1054             :                 return NULL;
    1055           0 :         return addr;
    1056             : }
    1057             : 
    1058             : TDSRET
    1059        3830 : tds_lookup_host_set(const char *servername, struct addrinfo **addr)
    1060             : {
    1061             :         struct addrinfo *newaddr;
    1062        3830 :         assert(servername != NULL && addr != NULL);
    1063             : 
    1064        3830 :         if ((newaddr = tds_lookup_host(servername)) != NULL) {
    1065        3830 :                 if (*addr != NULL)
    1066          30 :                         freeaddrinfo(*addr);
    1067        3830 :                 *addr = newaddr;
    1068        3830 :                 return TDS_SUCCESS;
    1069             :         }
    1070             :         return TDS_FAIL;
    1071             : }
    1072             : 
    1073             : /**
    1074             :  * Given a portname lookup the port.
    1075             :  *
    1076             :  * If we can't determine the port number then return 0.
    1077             :  */
    1078             : static int
    1079          12 : tds_lookup_port(const char *portname)
    1080             : {
    1081          12 :         int num = atoi(portname);
    1082          12 :         if (!num)
    1083           2 :                 num = tds_getservice(portname);
    1084          12 :         return num;
    1085             : }
    1086             : 
    1087             : /* TODO same code in convert.c ?? */
    1088             : static int
    1089             : hexdigit(int c)
    1090             : {
    1091           0 :         if (c >= '0' && c <= '9')
    1092           0 :                 return c - '0';
    1093             :         /* ASCII optimization, 'A' -> 'a', 'a' -> 'a' */
    1094           0 :         c |= 0x20;
    1095           0 :         if (c >= 'a' && c <= 'f')
    1096           0 :                 return c - 'a' + 10;
    1097             :         return 0;       /* bad hex digit */
    1098             : }
    1099             : 
    1100             : static int
    1101           0 : hex2num(char *hex)
    1102             : {
    1103           0 :         return hexdigit(hex[0]) * 16 + hexdigit(hex[1]);
    1104             : }
    1105             : 
    1106             : /**
    1107             :  * Open and read the file 'file' searching for a logical server
    1108             :  * by the name of 'host'.  If one is found then lookup
    1109             :  * the IP address and port number and store them in 'login'
    1110             :  *
    1111             :  * \param dir name of base directory for interface file
    1112             :  * \param file name of the interface file
    1113             :  * \param host logical host to search for
    1114             :  * \return false if not fount true if found
    1115             :  */
    1116             : static bool
    1117           0 : search_interface_file(TDSLOGIN * login, const tds_dir_char *dir, const tds_dir_char *file, const char *host)
    1118             : {
    1119             :         tds_dir_char *pathname;
    1120             :         char line[255];
    1121             :         char tmp_ip[sizeof(line)];
    1122             :         char tmp_port[sizeof(line)];
    1123             :         char tmp_ver[sizeof(line)];
    1124             :         FILE *in;
    1125             :         char *field;
    1126           0 :         bool found = false;
    1127           0 :         bool server_found = false;
    1128             :         char *lasts;
    1129             : 
    1130           0 :         line[0] = '\0';
    1131           0 :         tmp_ip[0] = '\0';
    1132           0 :         tmp_port[0] = '\0';
    1133           0 :         tmp_ver[0] = '\0';
    1134             : 
    1135           0 :         tdsdump_log(TDS_DBG_INFO1, "Searching interfaces file %" tdsPRIdir "/%" tdsPRIdir ".\n", dir, file);
    1136             : 
    1137             :         /*
    1138             :          * create the full pathname to the interface file
    1139             :          */
    1140           0 :         if (file[0] == '\0') {
    1141           0 :                 pathname = tds_dir_dup(TDS_DIR(""));
    1142             :         } else {
    1143           0 :                 pathname = tds_join_path(dir, file);
    1144             :         }
    1145           0 :         if (!pathname)
    1146             :                 return false;
    1147             : 
    1148             :         /*
    1149             :          * parse the interfaces file and find the server and port
    1150             :          */
    1151           0 :         if ((in = tds_dir_open(pathname, TDS_DIR("r"))) == NULL) {
    1152           0 :                 tdsdump_log(TDS_DBG_INFO1, "Couldn't open %" tdsPRIdir ".\n", pathname);
    1153           0 :                 free(pathname);
    1154           0 :                 return false;
    1155             :         }
    1156           0 :         tdsdump_log(TDS_DBG_INFO1, "Interfaces file %" tdsPRIdir " opened.\n", pathname);
    1157             : 
    1158           0 :         while (fgets(line, sizeof(line) - 1, in)) {
    1159           0 :                 if (line[0] == '#')
    1160           0 :                         continue;       /* comment */
    1161             : 
    1162           0 :                 if (!TDS_ISSPACE(line[0])) {
    1163           0 :                         field = strtok_r(line, "\n\t ", &lasts);
    1164           0 :                         if (!strcmp(field, host)) {
    1165           0 :                                 found = true;
    1166           0 :                                 tdsdump_log(TDS_DBG_INFO1, "Found matching entry for host %s.\n", host);
    1167             :                         } else
    1168             :                                 found = false;
    1169           0 :                 } else if (found && TDS_ISSPACE(line[0])) {
    1170           0 :                         field = strtok_r(line, "\n\t ", &lasts);
    1171           0 :                         if (field != NULL && !strcmp(field, "query")) {
    1172           0 :                                 field = strtok_r(NULL, "\n\t ", &lasts);  /* tcp or tli */
    1173           0 :                                 if (!strcmp(field, "tli")) {
    1174           0 :                                         tdsdump_log(TDS_DBG_INFO1, "TLI service.\n");
    1175           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* tcp */
    1176           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* device */
    1177           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* host/port */
    1178           0 :                                         if (strlen(field) >= 18) {
    1179           0 :                                                 sprintf(tmp_port, "%d", hex2num(&field[6]) * 256 + hex2num(&field[8]));
    1180           0 :                                                 sprintf(tmp_ip, "%d.%d.%d.%d", hex2num(&field[10]),
    1181             :                                                         hex2num(&field[12]), hex2num(&field[14]), hex2num(&field[16]));
    1182           0 :                                                 tdsdump_log(TDS_DBG_INFO1, "tmp_port = %s. tmp_ip = %s.\n", tmp_port, tmp_ip);
    1183             :                                         }
    1184             :                                 } else {
    1185           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* ether */
    1186           0 :                                         strcpy(tmp_ver, field);
    1187           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* host */
    1188           0 :                                         strcpy(tmp_ip, field);
    1189           0 :                                         tdsdump_log(TDS_DBG_INFO1, "host field %s.\n", tmp_ip);
    1190           0 :                                         field = strtok_r(NULL, "\n\t ", &lasts);  /* port */
    1191           0 :                                         strcpy(tmp_port, field);
    1192             :                                 }       /* else */
    1193             :                                 server_found = true;
    1194             :                         }       /* if */
    1195             :                 }               /* else if */
    1196             :         }                       /* while */
    1197           0 :         fclose(in);
    1198           0 :         free(pathname);
    1199             : 
    1200             : 
    1201             :         /*
    1202             :          * Look up the host and service
    1203             :          */
    1204           0 :         if (server_found) {
    1205             : 
    1206           0 :                 if (TDS_SUCCEED(tds_lookup_host_set(tmp_ip, &login->ip_addrs))) {
    1207             :                         struct addrinfo *addrs;
    1208           0 :                         if (!tds_dstr_copy(&login->server_host_name, tmp_ip))
    1209             :                                 return false;
    1210           0 :                         for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) {
    1211           0 :                                 tdsdump_log(TDS_DBG_INFO1, "Resolved IP as '%s'.\n",
    1212             :                                             tds_addrinfo2str(login->ip_addrs, line, sizeof(line)));
    1213             :                         }
    1214             :                 } else {
    1215           0 :                         tdsdump_log(TDS_DBG_WARN, "Name resolution failed for IP '%s'.\n", tmp_ip);
    1216             :                 }
    1217             : 
    1218           0 :                 if (tmp_port[0])
    1219           0 :                         login->port = tds_lookup_port(tmp_port);
    1220           0 :                 if (tmp_ver[0])
    1221           0 :                         tds_config_verstr(tmp_ver, login);
    1222             :         }
    1223             :         return server_found;
    1224             : }                               /* search_interface_file()  */
    1225             : 
    1226             : /**
    1227             :  * Try to find the IP number and port for a (possibly) logical server name.
    1228             :  *
    1229             :  * @note This function uses only the interfaces file and is deprecated.
    1230             :  */
    1231             : static bool
    1232           0 : tds_read_interfaces(const char *server, TDSLOGIN * login)
    1233             : {
    1234           0 :         bool found = false;
    1235             : 
    1236             :         /* read $SYBASE/interfaces */
    1237             : 
    1238           0 :         if (!server || !server[0]) {
    1239           0 :                 server = getenv("TDSQUERY");
    1240           0 :                 if (!server || !server[0])
    1241           0 :                         server = "SYBASE";
    1242           0 :                 tdsdump_log(TDS_DBG_INFO1, "Setting server to %s from $TDSQUERY.\n", server);
    1243             : 
    1244             :         }
    1245           0 :         tdsdump_log(TDS_DBG_INFO1, "Looking for server %s....\n", server);
    1246             : 
    1247             :         /*
    1248             :          * Look for the server in the interf_file iff interf_file has been set.
    1249             :          */
    1250           0 :         if (interf_file) {
    1251           0 :                 tdsdump_log(TDS_DBG_INFO1, "Looking for server in file %" tdsPRIdir ".\n", interf_file);
    1252           0 :                 found = search_interface_file(login, TDS_DIR(""), interf_file, server);
    1253             :         }
    1254             : 
    1255             :         /*
    1256             :          * if we haven't found the server yet then look for a $HOME/.interfaces file
    1257             :          */
    1258           0 :         if (!found) {
    1259           0 :                 tds_dir_char *path = tds_get_home_file(TDS_DIR(".interfaces"));
    1260             : 
    1261           0 :                 if (path) {
    1262           0 :                         tdsdump_log(TDS_DBG_INFO1, "Looking for server in %" tdsPRIdir ".\n", path);
    1263           0 :                         found = search_interface_file(login, TDS_DIR(""), path, server);
    1264           0 :                         free(path);
    1265             :                 }
    1266             :         }
    1267             : 
    1268             :         /*
    1269             :          * if we haven't found the server yet then look in $SYBBASE/interfaces file
    1270             :          */
    1271           0 :         if (!found) {
    1272           0 :                 const tds_dir_char *sybase = tds_dir_getenv(TDS_DIR("SYBASE"));
    1273             : #ifdef __VMS
    1274             :                 /* We've got to be in unix syntax for later slash-joined concatenation. */
    1275             :                 #include <unixlib.h>
    1276             :                 const char *unixspec = decc$translate_vms(sybase);
    1277             :                 if ( (int)unixspec != 0 && (int)unixspec != -1 ) sybase = unixspec;
    1278             : #endif
    1279           0 :                 if (!sybase || !sybase[0])
    1280           0 :                         sybase = interfaces_path;
    1281             : 
    1282           0 :                 tdsdump_log(TDS_DBG_INFO1, "Looking for server in %" tdsPRIdir "/interfaces.\n", sybase);
    1283           0 :                 found = search_interface_file(login, sybase, TDS_DIR("interfaces"), server);
    1284             :         }
    1285             : 
    1286             :         /*
    1287             :          * If we still don't have the server and port then assume the user
    1288             :          * typed an actual server host name.
    1289             :          */
    1290           0 :         if (!found) {
    1291             :                 int ip_port;
    1292             :                 const char *env_port;
    1293             : 
    1294             :                 /*
    1295             :                  * Make a guess about the port number
    1296             :                  */
    1297             : 
    1298           0 :                 if (login->port == 0) {
    1299             :                         /*
    1300             :                          * Not set in the [global] section of the
    1301             :                          * configure file, take a guess.
    1302             :                          */
    1303             :                         ip_port = TDS_DEF_PORT;
    1304             :                 } else {
    1305             :                         /*
    1306             :                          * Preserve setting from the [global] section
    1307             :                          * of the configure file.
    1308             :                          */
    1309           0 :                         ip_port = login->port;
    1310             :                 }
    1311           0 :                 if ((env_port = getenv("TDSPORT")) != NULL) {
    1312           0 :                         ip_port = tds_lookup_port(env_port);
    1313           0 :                         tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %s from $TDSPORT.\n", env_port);
    1314             :                 } else
    1315           0 :                         tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %d as a guess.\n", ip_port);
    1316             : 
    1317             :                 /*
    1318             :                  * look up the host
    1319             :                  */
    1320             : 
    1321           0 :                 if (TDS_SUCCEED(tds_lookup_host_set(server, &login->ip_addrs)))
    1322           0 :                         if (!tds_dstr_copy(&login->server_host_name, server))
    1323             :                                 return false;
    1324             : 
    1325           0 :                 if (ip_port)
    1326           0 :                         login->port = ip_port;
    1327             :         }
    1328             : 
    1329             :         return found;
    1330             : }
    1331             : 
    1332             : /**
    1333             :  * Check the server name to find port info first
    1334             :  * Warning: connection-> & login-> are all modified when needed
    1335             :  * \return true when found, else false
    1336             :  */
    1337             : static bool
    1338         148 : parse_server_name_for_port(TDSLOGIN * connection, TDSLOGIN * login, bool update_server)
    1339             : {
    1340             :         const char *pSep;
    1341             :         const char *server;
    1342             : 
    1343             :         /* seek the ':' in login server_name */
    1344         296 :         server = tds_dstr_cstr(&login->server_name);
    1345             : 
    1346             :         /* IPv6 address can be quoted */
    1347         148 :         if (server[0] == '[') {
    1348          40 :                 pSep = strstr(server, "]:");
    1349          40 :                 if (pSep)
    1350          20 :                         ++pSep;
    1351             :         } else {
    1352         108 :                 pSep = strrchr(server, ':');
    1353             :         }
    1354             : 
    1355         148 :         if (pSep && pSep != server) {   /* yes, i found it! */
    1356             :                 /* modify connection-> && login->server_name & ->port */
    1357         168 :                 login->port = connection->port = atoi(pSep + 1);
    1358          84 :                 tds_dstr_empty(&connection->instance_name);
    1359             :         } else {
    1360             :                 /* handle instance name */
    1361          64 :                 pSep = strrchr(server, '\\');
    1362          64 :                 if (!pSep || pSep == server)
    1363             :                         return false;
    1364             : 
    1365          64 :                 if (!tds_dstr_copy(&connection->instance_name, pSep + 1))
    1366             :                         return false;
    1367          64 :                 connection->port = 0;
    1368             :         }
    1369             : 
    1370         148 :         if (!update_server)
    1371             :                 return true;
    1372             : 
    1373          74 :         if (server[0] == '[' && pSep > server && pSep[-1] == ']') {
    1374          20 :                 server++;
    1375          20 :                 pSep--;
    1376             :         }
    1377          74 :         if (!tds_dstr_copyn(&connection->server_name, server, pSep - server))
    1378             :                 return false;
    1379             : 
    1380          74 :         return true;
    1381             : }
    1382             : 
    1383             : /**
    1384             :  * Return a structure capturing the compile-time settings provided to the
    1385             :  * configure script.  
    1386             :  */
    1387             : 
    1388             : const TDS_COMPILETIME_SETTINGS *
    1389           0 : tds_get_compiletime_settings(void)
    1390             : {
    1391             :         static const TDS_COMPILETIME_SETTINGS settings = {
    1392             :                   TDS_VERSION_NO
    1393             :                 , FREETDS_SYSCONFDIR
    1394             :                 , "unknown"   /* need fancy script in makefile */
    1395             : #               if TDS50
    1396             :                         , "5.0"
    1397             : #               elif TDS71
    1398             :                         , "7.1"
    1399             : #               elif TDS72
    1400             :                         , "7.2"
    1401             : #               elif TDS73
    1402             :                         , "7.3"
    1403             : #               elif TDS74
    1404             :                         , "7.4"
    1405             : #               else
    1406             :                         , "auto"
    1407             : #               endif
    1408             : #               ifdef MSDBLIB
    1409             :                         , true
    1410             : #               else
    1411             :                         , false
    1412             : #               endif
    1413             : #               ifdef TDS_SYBASE_COMPAT
    1414             :                         , true
    1415             : #               else
    1416             :                         , false
    1417             : #               endif
    1418             : #               ifdef _REENTRANT
    1419             :                         , true
    1420             : #               else
    1421             :                         , false
    1422             : #               endif
    1423             : #               ifdef HAVE_ICONV
    1424             :                         , true
    1425             : #               else
    1426             :                         , false
    1427             : #               endif
    1428             : #               ifdef IODBC
    1429             :                         , true
    1430             : #               else
    1431             :                         , false
    1432             : #               endif
    1433             : #               ifdef UNIXODBC
    1434             :                         , true
    1435             : #               else
    1436             :                         , false
    1437             : #               endif
    1438             : #               ifdef HAVE_OPENSSL
    1439             :                         , true
    1440             : #               else
    1441             :                         , false
    1442             : #               endif
    1443             : #               ifdef HAVE_GNUTLS
    1444             :                         , true
    1445             : #               else
    1446             :                         , false
    1447             : #               endif
    1448             : #               if ENABLE_ODBC_MARS
    1449             :                         , true
    1450             : #               else
    1451             :                         , false
    1452             : #               endif
    1453             : #               ifdef HAVE_SSPI
    1454             :                         , true
    1455             : #               else
    1456             :                         , false
    1457             : #               endif
    1458             : #               ifdef ENABLE_KRB5
    1459             :                         , true
    1460             : #               else
    1461             :                         , false
    1462             : #               endif
    1463             :         };
    1464             : 
    1465             :         assert(settings.tdsver);
    1466             : 
    1467           0 :         return &settings;
    1468             : }
    1469             : 
    1470             : /**
    1471             :  * Make sure proper setting are in place for TDS 8.0
    1472             :  */
    1473             : TDSRET
    1474        3660 : tds8_adjust_login(TDSLOGIN *login)
    1475             : {
    1476             :         /* TDS 8.0 requires TDS_ENCRYPTION_STRICT (entire-connection encryption) */
    1477        3660 :         if (IS_TDS80_PLUS(login))
    1478           0 :                 login->encryption_level = TDS_ENCRYPTION_STRICT;
    1479             : 
    1480        3660 :         if (login->encryption_level == TDS_ENCRYPTION_STRICT) {
    1481             :                 /* TDS 5.0 (Sybase/SAP ASE) it is optional; but TDS 7.x does not allow it.
    1482             :                  * So, try 8.0 unless they specifically requested 5.0 */
    1483           0 :                 if (!IS_TDS50(login) && !IS_TDS80_PLUS(login))
    1484           0 :                         login->tds_version = 0x800;
    1485             : 
    1486             :                 /* Validate server certificate signature to reduce risk of MITM attacks */
    1487           0 :                 if (tds_dstr_isempty(&login->cafile))
    1488           0 :                         if (!tds_dstr_copy(&login->cafile, "system"))
    1489             :                                 return -TDSEMEM;
    1490             :         }
    1491             : 
    1492             :         return TDS_SUCCESS;
    1493             : }
    1494             : 
    1495             : /** @} */

Generated by: LCOV version 1.13