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 : }
|