Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2.x 240118 [DONOTMERGE] #4431

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5091edc
Refactoring of process_pkt_handshake_response
renecannao Feb 17, 2023
1b3ee81
Cleanup on MySQL_Protocol.h
renecannao Feb 17, 2023
d23b286
2nd refactoring of process_pkt_handshake_response
renecannao Feb 23, 2023
5c40ee5
Fix clickhouse compiling
renecannao Feb 23, 2023
1fa074a
3rd refactoring of process_pkt_handshake_response
renecannao Mar 3, 2023
b9473aa
Deprecate SHA1_* also in this branch
renecannao May 9, 2023
094f77a
Temporary commit 01 for caching_sha2_password
renecannao May 10, 2023
76bb204
New variable mysql-default_authentication_plugin
renecannao May 13, 2023
117b9d3
caching_sha2_password automatically enables SSL
renecannao May 13, 2023
29da662
enum proxysql_auth_plugins for mysql plugin ids
renecannao May 13, 2023
e7745fe
First implementation of caching_sha2_password
renecannao May 13, 2023
e6e6bb0
Adding sha256crypt.cpp
renecannao May 13, 2023
cf6f4f7
Working prototype of caching_sha2_password
renecannao May 14, 2023
4c704e2
Deprecate admin-hash_passwords #4218
renecannao May 14, 2023
52052de
Adding warning for deprecated admin-hash_passwords #4218
renecannao May 14, 2023
1799f7a
Stop dumping the list of cipher avaiable in DEBUG
renecannao May 14, 2023
7690798
Deprecate admin-hash_passwords in TAP tests #4218
renecannao May 14, 2023
7e5b3e8
Rememeber clear text password if provided by client
renecannao May 14, 2023
08cc2f0
Fixed length of hash + salt
renecannao May 14, 2023
a593407
Removing commented code used for POC
renecannao May 14, 2023
33b4f30
Fix TAP reg_test_3504-change_user-t for new values of switching_auth_…
renecannao May 16, 2023
629aa3d
Drafting TAP test_change_user-t
renecannao Jun 13, 2023
36183a4
Further testing in TAP test_change_user-t
renecannao Jun 13, 2023
8106ae5
Merge branch 'v2.x' into v2.x_sha2pass_draft3
renecannao Jun 14, 2023
9ede04d
Merge branch 'v2.x' into v2.x_sha2pass_draft3
renecannao Jul 1, 2023
f9b3b70
Create ProxySQL_Authentication.md
renecannao Jul 2, 2023
e3865be
Minor changes in branches
renecannao Jul 2, 2023
636d81e
Merge branch 'v2.x_sha2pass_draft3' of https://github.com/sysown/prox…
renecannao Jul 2, 2023
3c24182
Merge branch 'v2.x' into v2.x_sha2pass_draft3
renecannao Dec 8, 2023
c3c9746
Merge branch 'v2.x' into v2.x_sha2pass_draft3
renecannao Jan 15, 2024
29b7cd0
Modify generate_one_byte_pkt()
renecannao Jan 17, 2024
496ee02
Input validation for mysql-server_capabilities
renecannao Jan 18, 2024
93fca24
Fast shutdown for TERM signal #4355
renecannao Jan 18, 2024
e958946
Handle STATUS command without backends
renecannao Jan 18, 2024
5326298
Added new status variable mysql_listener_paused
renecannao Jan 18, 2024
d2c8d65
Deprecate mysql-default_tx_isolation #4335
renecannao Jan 18, 2024
41cd740
Added metric MultiplexDisabled_ext #4241
renecannao Jan 18, 2024
97215f5
Merge branch 'v2.x-2091' into v2.x-240118
renecannao Jan 18, 2024
f4ff116
Merge branch 'v2.x-4355' into v2.x-240118
renecannao Jan 18, 2024
aafd660
Merge branch 'v2.x-4396' into v2.x-240118
renecannao Jan 18, 2024
e31a571
Merge branch 'v2.x-pause_status' into v2.x-240118
renecannao Jan 18, 2024
1bc58a0
Merge branch 'v2.x-4335' into v2.x-240118
renecannao Jan 18, 2024
0f61565
Merge branch 'v2.x-4241' into v2.x-240118
renecannao Jan 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
798 changes: 798 additions & 0 deletions doc/internal/ProxySQL_Authentication.md

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions include/MySQL_Authentication.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ typedef struct _account_details_t {
char *username;
char *password;
void *sha1_pass;
bool use_ssl;
int default_hostgroup;
char *clear_text_password;
char *default_schema;
int default_hostgroup;
bool use_ssl;
bool schema_locked;
bool transaction_persistent;
bool fast_forward;
Expand Down Expand Up @@ -79,6 +80,7 @@ class MySQL_Authentication {
void set_all_inactive(enum cred_username_type usertype);
void remove_inactives(enum cred_username_type usertype);
bool set_SHA1(char *username, enum cred_username_type usertype, void *sha_pass);
bool set_clear_text_password(char *username, enum cred_username_type usertype, const char *clear_text_password);
unsigned int memory_usage();
uint64_t get_runtime_checksum();
/**
Expand Down
3 changes: 2 additions & 1 deletion include/MySQL_Data_Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ class MySQL_Data_Stream
int status; // status . FIXME: make it a ORable variable

int switching_auth_stage;
int switching_auth_type;
enum proxysql_auth_plugins switching_auth_type;
int auth_in_progress; // if 0 , no authentication is in progress. Any value greater than 0 depends from the implementation
unsigned int tmp_charset;

short revents;
Expand Down
62 changes: 62 additions & 0 deletions include/MySQL_Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ extern MySQL_Variables mysql_variables;
#define CLIENT_DEPRECATE_EOF (1UL << 24)
#endif


enum proxysql_auth_plugins {
AUTH_UNKNOWN_PLUGIN = -1,
AUTH_MYSQL_NATIVE_PASSWORD = 0,
AUTH_MYSQL_CLEAR_PASSWORD,
AUTH_MYSQL_CACHING_SHA2_PASSWORD
};

class MySQL_ResultSet {
private:
bool deprecate_eof_active;
Expand Down Expand Up @@ -91,6 +99,36 @@ uint8_t mysql_decode_length(unsigned char *ptr, uint64_t *len);
*/
my_bool proxy_mysql_stmt_close(MYSQL_STMT* mysql_stmt);

class MyProt_tmp_auth_vars {
public:
unsigned char *user = NULL;
char *db = NULL;
char *db_tmp = NULL;
unsigned char *pass = NULL;
char *password = NULL;
unsigned char *auth_plugin = NULL;
void *sha1_pass=NULL;
unsigned char *_ptr = NULL;;
unsigned int charset;
uint32_t capabilities = 0;
uint32_t max_pkt;
uint32_t pass_len;
bool use_ssl = false;
enum proxysql_session_type session_type;
};

class MyProt_tmp_auth_attrs {
public:
char *default_schema = NULL;
char *attributes = NULL;
int default_hostgroup=-1;
int max_connections;
bool schema_locked;
bool transaction_persistent = true;
bool fast_forward = false;
bool _ret_use_ssl = false;
};

class MySQL_Protocol {
private:
MySQL_Connection_userinfo *userinfo;
Expand All @@ -101,10 +139,16 @@ class MySQL_Protocol {
bool dump_pkt;
#endif
MySQL_Prepared_Stmt_info *current_PreStmt;
enum proxysql_auth_plugins sent_auth_plugin_id;
enum proxysql_auth_plugins auth_plugin_id;
uint16_t prot_status;
bool more_data_needed;
MySQL_Data_Stream *get_myds() { return *myds; }
MySQL_Protocol() {
sent_auth_plugin_id = AUTH_MYSQL_NATIVE_PASSWORD;
auth_plugin_id = AUTH_UNKNOWN_PLUGIN;
prot_status=0;
more_data_needed = false;
}
void init(MySQL_Data_Stream **, MySQL_Connection_userinfo *, MySQL_Session *);

Expand Down Expand Up @@ -139,6 +183,24 @@ class MySQL_Protocol {
// - pointer to the packet
// - size of the packet
bool process_pkt_handshake_response(unsigned char *pkt, unsigned int len);

// all the following functions were inline inside process_pkt_handshake_response() , but it was split for readibility
int PPHR_1(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1);
bool PPHR_2(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1);
void PPHR_3(MyProt_tmp_auth_vars& vars1);
bool PPHR_4auth0(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1);
bool PPHR_4auth1(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1);
void PPHR_5passwordTrue(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1);
void PPHR_5passwordFalse_0(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1);
void PPHR_5passwordFalse_auth2(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1 , void *& sha1_pass);
void PPHR_6auth2(bool& ret, MyProt_tmp_auth_vars& vars1);
void PPHR_sha2full(bool& ret, MyProt_tmp_auth_vars& vars1, enum proxysql_auth_plugins passformat);
void PPHR_7auth1(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1 , void *& sha1_pass);
void PPHR_7auth2(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1 , void *& sha1_pass);
void PPHR_SetConnAttrs(MyProt_tmp_auth_vars& vars1, MyProt_tmp_auth_attrs& attr1);

void generate_one_byte_pkt(unsigned char b);

bool process_pkt_COM_CHANGE_USER(unsigned char *pkt, unsigned int len);
void * Query_String_to_packet(uint8_t sid, std::string *s, unsigned int *l);
/**
Expand Down
1 change: 1 addition & 0 deletions include/MySQL_Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class MySQL_Session

void return_proxysql_internal(PtrSize_t *);
bool handler_special_queries(PtrSize_t *);
bool handler_special_queries_STATUS(PtrSize_t *);
/**
* @brief Handles 'COMMIT|ROLLBACK' commands.
* @details Forwarding the packet is required when there are active transactions. Since we are limited to
Expand Down
4 changes: 2 additions & 2 deletions include/MySQL_Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#define SQLITE_HOSTGROUP -4


#define MYSQL_DEFAULT_TX_ISOLATION "READ-COMMITTED"
#define MYSQL_DEFAULT_SESSION_TRACK_GTIDS "OFF"
#define MYSQL_DEFAULT_COLLATION_CONNECTION ""
#define MYSQL_DEFAULT_NET_WRITE_TIMEOUT "60"
Expand Down Expand Up @@ -448,8 +447,10 @@ class MySQL_Threads_Handler
char *interfaces;
char *server_version;
char *keep_multiplexing_variables;
char *default_authentication_plugin;
//unsigned int default_charset; // removed in 2.0.13 . Obsoleted previously using MySQL_Variables instead
int handle_unknown_charset;
int default_authentication_plugin_int;
bool servers_stats;
bool commands_stats;
bool query_digests;
Expand Down Expand Up @@ -509,7 +510,6 @@ class MySQL_Threads_Handler
char *init_connect;
char *ldap_user_variable;
char *add_ldap_user_comment;
char *default_tx_isolation;
char *default_session_track_gtids;
char *default_variables[SQL_NAME_LAST_LOW_WM];
char *firewall_whitelist_errormsg;
Expand Down
2 changes: 1 addition & 1 deletion include/SQLite3_Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SQLite3_Server {
char *telnet_admin_ifaces;
char *telnet_stats_ifaces;
bool read_only;
bool hash_passwords;
// bool hash_passwords;
char * admin_version;
#ifdef DEBUG
bool debug;
Expand Down
2 changes: 1 addition & 1 deletion include/mysql_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "../deps/json/json.hpp"
using json = nlohmann::json;

#define STATUS_MYSQL_CONNECTION_TRANSACTION 0x00000001
//#define STATUS_MYSQL_CONNECTION_TRANSACTION 0x00000001 // DEPRECATED
#define STATUS_MYSQL_CONNECTION_COMPRESSION 0x00000002
#define STATUS_MYSQL_CONNECTION_USER_VARIABLE 0x00000004
#define STATUS_MYSQL_CONNECTION_PREPARED_STATEMENT 0x00000008
Expand Down
3 changes: 2 additions & 1 deletion include/proxysql_admin.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ struct p_admin_gauge {
stmt_cached,
fds_in_use,
version_info,
mysql_listener_paused,
__size
};
};
Expand Down Expand Up @@ -225,7 +226,7 @@ class ProxySQL_Admin {
char *telnet_admin_ifaces;
char *telnet_stats_ifaces;
bool admin_read_only;
bool hash_passwords;
// bool hash_passwords;
bool vacuum_stats;
char * admin_version;
char * cluster_username;
Expand Down
6 changes: 4 additions & 2 deletions include/proxysql_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -776,11 +776,12 @@ MySQL_HostGroups_Manager *MyHGM;
__thread char *mysql_thread___default_schema;
__thread char *mysql_thread___server_version;
__thread char *mysql_thread___keep_multiplexing_variables;
__thread char *mysql_thread___default_authentication_plugin;
__thread char *mysql_thread___init_connect;
__thread char *mysql_thread___ldap_user_variable;
__thread char *mysql_thread___default_tx_isolation;
__thread char *mysql_thread___default_session_track_gtids;
__thread char *mysql_thread___firewall_whitelist_errormsg;
__thread int mysql_thread___default_authentication_plugin_int;
__thread int mysql_thread___max_allowed_packet;
__thread bool mysql_thread___automatic_detect_sqli;
__thread bool mysql_thread___firewall_whitelist_enabled;
Expand Down Expand Up @@ -945,11 +946,12 @@ extern MySQL_HostGroups_Manager *MyHGM;
extern __thread char *mysql_thread___default_schema;
extern __thread char *mysql_thread___server_version;
extern __thread char *mysql_thread___keep_multiplexing_variables;
extern __thread char *mysql_thread___default_authentication_plugin;
extern __thread char *mysql_thread___init_connect;
extern __thread char *mysql_thread___ldap_user_variable;
extern __thread char *mysql_thread___default_tx_isolation;
extern __thread char *mysql_thread___default_session_track_gtids;
extern __thread char *mysql_thread___firewall_whitelist_errormsg;
extern __thread int mysql_thread___default_authentication_plugin_int;
extern __thread int mysql_thread___max_allowed_packet;
extern __thread bool mysql_thread___automatic_detect_sqli;
extern __thread bool mysql_thread___firewall_whitelist_enabled;
Expand Down
1 change: 1 addition & 0 deletions include/sqlite3db.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class SQLite3_result {
void add_column_definition(int a, const char *b);
int add_row(sqlite3_stmt *stmt, bool skip=false);
int add_row(char **_fields);
int add_row(const char **_fields) { return add_row((char **)_fields); }
int add_row(SQLite3_row *old_row);
int add_row(const char* _field, ...);
SQLite3_result(sqlite3_stmt *stmt);
Expand Down
1 change: 1 addition & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ default: libproxysql.a
.PHONY: default

_OBJ_CXX := ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo ProxySQL_Config.oo ProxySQL_Restapi.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo ClickHouse_Authentication.oo ClickHouse_Server.oo ProxySQL_Statistics.oo Chart_bundle_js.oo ProxySQL_HTTP_Server.oo ProxySQL_RESTAPI_Server.oo font-awesome.min.css.oo main-bundle.min.css.oo set_parser.oo MySQL_Variables.oo c_tokenizer.oo proxysql_utils.oo proxysql_coredump.oo proxysql_sslkeylog.oo \
sha256crypt.oo \
proxysql_find_charset.oo ProxySQL_Poll.oo
OBJ_CXX := $(patsubst %,$(ODIR)/%,$(_OBJ_CXX))
HEADERS := ../include/*.h ../include/*.hpp
Expand Down
56 changes: 55 additions & 1 deletion lib/MySQL_Authentication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,18 @@ bool MySQL_Authentication::add(char * username, char * password, enum cred_usern
if (lookup != cg.bt_map.end()) {
ad=lookup->second;
if (strcmp(ad->password,password)) {
// the password has changed
free(ad->password);
ad->password=strdup(password);
if (ad->sha1_pass) {
free(ad->sha1_pass);
ad->sha1_pass=NULL;
}
if (ad->clear_text_password) {
free(ad->clear_text_password);
ad->clear_text_password=NULL;
}
// FIXME: if the password is a clear text password, automatically generate sha1_pass and clear_text_password
}
if (strcmp(ad->default_schema,default_schema)) {
free(ad->default_schema);
Expand Down Expand Up @@ -195,6 +201,8 @@ bool MySQL_Authentication::add(char * username, char * password, enum cred_usern
new_ad=true;
ad->sha1_pass=NULL;
ad->num_connections_used=0;
ad->clear_text_password = NULL;
// FIXME: if the password is a clear text password, automatically generate sha1_pass and clear_text_password
}

ad->use_ssl=use_ssl;
Expand Down Expand Up @@ -233,6 +241,7 @@ unsigned int MySQL_Authentication::memory_usage() {
if (ado->username) ret += strlen(ado->username) + 1;
if (ado->password) ret += strlen(ado->password) + 1;
if (ado->sha1_pass) ret += SHA_DIGEST_LENGTH;
if (ado->clear_text_password) ret += strlen(ado->clear_text_password) + 1;
if (ado->default_schema) ret += strlen(ado->default_schema) + 1;
if (ado->comment) ret += strlen(ado->comment) + 1;
if (ado->attributes) ret += strlen(ado->attributes) + 1;
Expand All @@ -246,6 +255,7 @@ unsigned int MySQL_Authentication::memory_usage() {
if (ado->username) ret += strlen(ado->username) + 1;
if (ado->password) ret += strlen(ado->password) + 1;
if (ado->sha1_pass) ret += SHA_DIGEST_LENGTH;
if (ado->clear_text_password) ret += strlen(ado->clear_text_password) + 1;
if (ado->default_schema) ret += strlen(ado->default_schema) + 1;
if (ado->comment) ret += strlen(ado->comment) + 1;
if (ado->attributes) ret += strlen(ado->attributes) + 1;
Expand Down Expand Up @@ -297,6 +307,7 @@ int MySQL_Authentication::dump_all_users(account_details_t ***ads, bool _complet
ad->num_connections_used=ado->num_connections_used;
ad->password=strdup(ado->password);
ad->sha1_pass=NULL;
ad->clear_text_password = NULL;
ad->use_ssl=ado->use_ssl;
ad->default_schema=strdup(ado->default_schema);
ad->attributes=strdup(ado->attributes);
Expand All @@ -318,6 +329,7 @@ int MySQL_Authentication::dump_all_users(account_details_t ***ads, bool _complet
ad->username=strdup(ado->username);
ad->password=strdup(ado->password);
ad->sha1_pass=NULL;
ad->clear_text_password = NULL;
ad->use_ssl=ado->use_ssl;
ad->default_hostgroup=ado->default_hostgroup;
ad->default_schema=strdup(ado->default_schema);
Expand Down Expand Up @@ -434,6 +446,7 @@ bool MySQL_Authentication::del(char * username, enum cred_username_type usertype
free(ad->username);
free(ad->password);
if (ad->sha1_pass) { free(ad->sha1_pass); ad->sha1_pass=NULL; }
if (ad->clear_text_password) { free(ad->clear_text_password); ad->clear_text_password=NULL; }
free(ad->default_schema);
free(ad->attributes);
free(ad->comment);
Expand Down Expand Up @@ -484,6 +497,40 @@ bool MySQL_Authentication::set_SHA1(char * username, enum cred_username_type use
return ret;
};

bool MySQL_Authentication::set_clear_text_password(char * username, enum cred_username_type usertype, const char *clear_text_password) {
bool ret=false;
uint64_t hash1, hash2;
SpookyHash *myhash=new SpookyHash();
myhash->Init(1,2);
myhash->Update(username,strlen(username));
myhash->Final(&hash1,&hash2);
delete myhash;

creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);

#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator lookup;
lookup = cg.bt_map.find(hash1);
if (lookup != cg.bt_map.end()) {
account_details_t *ad=lookup->second;
if (ad->clear_text_password) { free(ad->clear_text_password); ad->clear_text_password=NULL; }
if (clear_text_password) {
ad->clear_text_password = strdup(clear_text_password);
}
ret=true;
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
return ret;
};

bool MySQL_Authentication::exists(char * username) {
bool ret = false;
uint64_t hash1, hash2;
Expand Down Expand Up @@ -522,7 +569,13 @@ char * MySQL_Authentication::lookup(char * username, enum cred_username_type use
lookup = cg.bt_map.find(hash1);
if (lookup != cg.bt_map.end()) {
account_details_t *ad=lookup->second;
ret=l_strdup(ad->password);
if (ad->clear_text_password == NULL) {
ret=strdup(ad->password);
} else {
// we return the best password we have
// if we were able to derive the clear text password, we provide that
ret=strdup(ad->clear_text_password);
}
if (use_ssl) *use_ssl=ad->use_ssl;
if (default_hostgroup) *default_hostgroup=ad->default_hostgroup;
if (default_schema) *default_schema=l_strdup(ad->default_schema);
Expand Down Expand Up @@ -565,6 +618,7 @@ bool MySQL_Authentication::_reset(enum cred_username_type usertype) {
free(ad->username);
free(ad->password);
if (ad->sha1_pass) { free(ad->sha1_pass); ad->sha1_pass=NULL; }
if (ad->clear_text_password) { free(ad->clear_text_password); ad->clear_text_password=NULL; }
free(ad->default_schema);
free(ad->comment);
free(ad->attributes);
Expand Down
Loading
Loading