LCOV - code coverage report
Current view: top level - src/odbc/unittests - oldpwd.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 45 52 86.5 %
Date: 2026-07-19 14:02:14 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : #include <assert.h>
       4             : #include <freetds/utils.h>
       5             : 
       6             : /* change password on server */
       7             : 
       8             : #define USER "freetds_oldpwd"
       9             : #define PWD1 "TestPWD1?"
      10             : #define PWD2 "OtherPWDButLonger2@"
      11             : 
      12             : static void
      13           2 : my_attrs(void)
      14             : {
      15           2 :         SQLSetConnectAttr(odbc_conn, 1226 /* SQL_COPT_SS_OLDPWD */ ,
      16           1 :                           (SQLPOINTER) T(PWD1), SQL_NTS);
      17           2 :         strcpy(common_pwd.user, USER);
      18           2 :         strcpy(common_pwd.password, PWD2);
      19           2 : }
      20             : 
      21             : static HENV save_env;
      22             : static HDBC save_conn;
      23             : static HSTMT save_stmt;
      24             : 
      25             : static void
      26             : swap_conn(void)
      27             : {
      28           4 :         ODBC_SWAP(HENV, odbc_env, save_env);
      29           4 :         ODBC_SWAP(HDBC, odbc_conn, save_conn);
      30           4 :         ODBC_SWAP(HSTMT, odbc_stmt, save_stmt);
      31             : }
      32             : 
      33          10 : TEST_MAIN()
      34             : {
      35             :         const char *ci;
      36             :         SQLRETURN rc;
      37             : 
      38             :         /*
      39             :          * Check if we are in CI.
      40             :          * This test is doing some administration setting on the server, avoid
      41             :          * to do on all machines, especially if users are trying to run tests
      42             :          * without knowing this.
      43             :          */
      44          10 :         ci = getenv("CI");
      45          10 :         if (!ci || strcasecmp(ci, "true") != 0) {
      46           0 :                 odbc_test_skipped();
      47           0 :                 return 0;
      48             :         }
      49             : 
      50          10 :         odbc_connect();
      51             : 
      52             :         /* minimum TDS 7.2 and MSSQL 2012 */
      53          10 :         if (odbc_tds_version() < 0x702 || odbc_db_version_int() < 0x0a000000u) {
      54           6 :                 odbc_disconnect();
      55           6 :                 odbc_test_skipped();
      56           0 :                 return 0;
      57             :         }
      58             : 
      59             :         /* create new login for this test and disconnect */
      60           4 :         odbc_command_with_result(odbc_stmt, "DROP LOGIN " USER);
      61           4 :         rc = odbc_command2("CREATE LOGIN " USER " WITH PASSWORD='" PWD1 "' MUST_CHANGE, "
      62             :                            "DEFAULT_DATABASE = tempdb, CHECK_EXPIRATION = ON", "SENo");
      63           4 :         if (rc == SQL_ERROR) {
      64           2 :                 odbc_read_error();
      65           2 :                 odbc_disconnect();
      66           2 :                 if (strstr(odbc_err, "MUST_CHANGE") == NULL)
      67             :                         return 1;
      68           2 :                 odbc_test_skipped();
      69           0 :                 return 0;
      70             :         }
      71           2 :         swap_conn();
      72             : 
      73             :         /* login with new password should fail */
      74           2 :         strcpy(common_pwd.user, USER);
      75           2 :         strcpy(common_pwd.password, PWD1);
      76             : 
      77           2 :         CHKAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &odbc_env, "S");
      78           2 :         SQLSetEnvAttr(odbc_env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) (SQL_OV_ODBC3), SQL_IS_UINTEGER);
      79           2 :         CHKAllocHandle(SQL_HANDLE_DBC, odbc_env, &odbc_conn, "S");
      80           2 :         CHKConnect(T(common_pwd.server), SQL_NTS, T(common_pwd.user), SQL_NTS, T(common_pwd.password), SQL_NTS, "E");
      81           2 :         odbc_read_error();
      82           4 :         if (strcmp(odbc_sqlstate, "42000") != 0 ||
      83           4 :             strstr(odbc_err, USER) == NULL || strstr(odbc_err, "The password of the account must be changed") == NULL) {
      84           0 :                 fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate);
      85           0 :                 odbc_disconnect();
      86           0 :                 return 1;
      87             :         }
      88           2 :         odbc_disconnect();
      89             : 
      90             :         /* login and change password */
      91           2 :         odbc_set_conn_attr = my_attrs;
      92           2 :         odbc_connect();
      93           2 :         odbc_disconnect();
      94             : 
      95             :         /* login wiht new password */
      96           2 :         odbc_set_conn_attr = NULL;
      97           2 :         odbc_connect();
      98           2 :         odbc_disconnect();
      99             : 
     100             :         /* drop created login */
     101           2 :         tds_sleep_ms(500);      /* give time for logoff */
     102           2 :         swap_conn();
     103           2 :         odbc_command("DROP LOGIN " USER);
     104           2 :         odbc_disconnect();
     105             : 
     106           2 :         return 0;
     107             : }

Generated by: LCOV version 1.13