Skip to content

Commit

Permalink
Expose user certificate details to command line.
Browse files Browse the repository at this point in the history
Summary:
This is a change to help the implementation of SSL based authentication efforts. Currently the certificate details are unavailable to the sys admin. The v3 extensions usually carry important information for identifying the user.

This change adds a new table to the information schema to expose auth details. It is organized by process ID like processlist table.

Test Plan: Run newly added test case

Reviewers: pengt, tianx, jtolmer, santoshb

Reviewed By: santoshb
  • Loading branch information
kradhakrishnan authored and jtolmer committed Jan 5, 2016
1 parent e6ad3df commit f29eb03
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 2 deletions.
2 changes: 2 additions & 0 deletions mysql-test/r/information_schema-big.result
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ USER_LATENCY_HISTOGRAMS USER_NAME
USER_PRIVILEGES GRANTEE
USER_STATISTICS USER_NAME
VIEWS TABLE_SCHEMA
AUTHINFO ID
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
Expand Down Expand Up @@ -111,3 +112,4 @@ USER_LATENCY_HISTOGRAMS USER_NAME
USER_PRIVILEGES GRANTEE
USER_STATISTICS USER_NAME
VIEWS TABLE_SCHEMA
AUTHINFO ID
6 changes: 4 additions & 2 deletions mysql-test/r/information_schema.result
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ USER_LATENCY_HISTOGRAMS
USER_PRIVILEGES
USER_STATISTICS
VIEWS
AUTHINFO
columns_priv
db
event
Expand Down Expand Up @@ -822,6 +823,7 @@ information_schema ROUTINES ROUTINE_COMMENT
information_schema TRIGGERS ACTION_CONDITION
information_schema TRIGGERS ACTION_STATEMENT
information_schema VIEWS VIEW_DEFINITION
information_schema AUTHINFO INFO
select table_name, column_name, data_type from information_schema.columns
where table_schema not like 'performance_schema'
and data_type = 'datetime'
Expand Down Expand Up @@ -910,7 +912,7 @@ table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest')
AND table_name not like 'ndb%' AND table_name not like 'innodb_%'
GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 37
information_schema 38
mysql 26
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
Expand Down Expand Up @@ -1332,7 +1334,6 @@ select 1 as f1 from information_schema.tables where "CHARACTER_SETS"=
where table_schema != 'performance_schema'
order by table_name limit 1) limit 1;
f1
1
select t.table_name, group_concat(t.table_schema, '.', t.table_name),
count(*) as num1
from information_schema.tables t
Expand All @@ -1350,6 +1351,7 @@ group by c2.column_type order by num limit 1)
and t.table_name not like 'innodb_%'
group by t.table_name order by num1, t.table_name;
table_name group_concat(t.table_schema, '.', t.table_name) num1
AUTHINFO information_schema.AUTHINFO 1
CHARACTER_SETS information_schema.CHARACTER_SETS 1
COLLATIONS information_schema.COLLATIONS 1
COLLATION_CHARACTER_SET_APPLICABILITY information_schema.COLLATION_CHARACTER_SET_APPLICABILITY 1
Expand Down
4 changes: 4 additions & 0 deletions mysql-test/r/information_schema_authinfo.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
select * from information_schema.authinfo;
ID USER HOST SSL INFO
<Id> root <Host> <SSL> <Info>
<Id> root <Host> <SSL> <Info>
4 changes: 4 additions & 0 deletions mysql-test/r/information_schema_authinfo_nossl.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
select * from information_schema.authinfo;
ID USER HOST SSL INFO
<Id> root <Host> 0 NULL
<Id> root <Host> 0 NULL
1 change: 1 addition & 0 deletions mysql-test/r/information_schema_db.result
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ USER_LATENCY_HISTOGRAMS
USER_PRIVILEGES
USER_STATISTICS
VIEWS
AUTHINFO
show tables from INFORMATION_SCHEMA like 'T%';
Tables_in_information_schema (T%)
TABLES
Expand Down
2 changes: 2 additions & 0 deletions mysql-test/r/mysqlshow.result
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ Database: information_schema
| USER_PRIVILEGES |
| USER_STATISTICS |
| VIEWS |
| AUTHINFO |
| INNODB_LOCKS |
| INNODB_TRX |
| INNODB_SYS_DATAFILES |
Expand Down Expand Up @@ -187,6 +188,7 @@ Database: INFORMATION_SCHEMA
| USER_PRIVILEGES |
| USER_STATISTICS |
| VIEWS |
| AUTHINFO |
| INNODB_LOCKS |
| INNODB_TRX |
| INNODB_SYS_DATAFILES |
Expand Down
10 changes: 10 additions & 0 deletions mysql-test/suite/funcs_1/r/is_columns_is.result
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ WHERE table_schema = 'information_schema'
AND table_name <> 'profiling' AND table_name not like 'innodb_%'
ORDER BY table_schema, table_name, column_name;
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE DATETIME_PRECISION CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT
def information_schema AUTHINFO HOST 3 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select
def information_schema AUTHINFO ID 1 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select
def information_schema AUTHINFO INFO 5 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select
def information_schema AUTHINFO SSL 4 0 NO int NULL NULL 10 0 NULL NULL NULL int(7) select
def information_schema AUTHINFO USER 2 NO varchar 80 240 NULL NULL NULL utf8 utf8_general_ci varchar(80) select
def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select
def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select
def information_schema CHARACTER_SETS DESCRIPTION 3 NO varchar 60 180 NULL NULL NULL utf8 utf8_general_ci varchar(60) select
Expand Down Expand Up @@ -579,6 +584,11 @@ WHERE table_schema = 'information_schema'
AND table_name <> 'profiling' AND table_name not like 'innodb_%'
ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION;
COL_CML TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE
NULL information_schema AUTHINFO ID bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema AUTHINFO USER varchar 80 240 utf8 utf8_general_ci varchar(80)
3.0000 information_schema AUTHINFO HOST varchar 64 192 utf8 utf8_general_ci varchar(64)
NULL information_schema AUTHINFO SSL int NULL NULL NULL NULL int(7)
1.0000 information_schema AUTHINFO INFO longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
3.0000 information_schema CHARACTER_SETS CHARACTER_SET_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema CHARACTER_SETS DESCRIPTION varchar 60 180 utf8 utf8_general_ci varchar(60)
Expand Down
46 changes: 46 additions & 0 deletions mysql-test/suite/funcs_1/r/is_tables_is.result
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,29 @@ AND table_name <> 'profiling' AND table_name not like 'innodb_%'
ORDER BY table_schema,table_name;
TABLE_CATALOG def
TABLE_SCHEMA information_schema
TABLE_NAME AUTHINFO
TABLE_TYPE SYSTEM VIEW
ENGINE MyISAM
VERSION 10
ROW_FORMAT Dynamic
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
MAX_DATA_LENGTH #MDL#
INDEX_LENGTH #IL#
DATA_FREE #DF#
AUTO_INCREMENT NULL
CREATE_TIME #CRT#
UPDATE_TIME #UT#
CHECK_TIME #CT#
TABLE_COLLATION utf8_general_ci
CHECKSUM NULL
CREATE_OPTIONS #CO#
TABLE_COMMENT #TC#
user_comment
Separator -----------------------------------------------------
TABLE_CATALOG def
TABLE_SCHEMA information_schema
TABLE_NAME CHARACTER_SETS
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
Expand Down Expand Up @@ -860,6 +883,29 @@ AND table_name <> 'profiling' AND table_name not like 'innodb_%'
ORDER BY table_schema,table_name;
TABLE_CATALOG def
TABLE_SCHEMA information_schema
TABLE_NAME AUTHINFO
TABLE_TYPE SYSTEM VIEW
ENGINE MyISAM
VERSION 10
ROW_FORMAT Dynamic
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
MAX_DATA_LENGTH #MDL#
INDEX_LENGTH #IL#
DATA_FREE #DF#
AUTO_INCREMENT NULL
CREATE_TIME #CRT#
UPDATE_TIME #UT#
CHECK_TIME #CT#
TABLE_COLLATION utf8_general_ci
CHECKSUM NULL
CREATE_OPTIONS #CO#
TABLE_COMMENT #TC#
user_comment
Separator -----------------------------------------------------
TABLE_CATALOG def
TABLE_SCHEMA information_schema
TABLE_NAME CHARACTER_SETS
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
Expand Down
4 changes: 4 additions & 0 deletions mysql-test/t/information_schema_authinfo-master.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--ssl=1
--ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem
--ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem
--ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem
10 changes: 10 additions & 0 deletions mysql-test/t/information_schema_authinfo.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--source include/have_ssl_communication.inc

# Repeat connect/disconnect

connect (test_con1,localhost,root,,,,,SSL);

--replace_column 1 <Id> 3 <Host> 4 <SSL> 5 <Info>
select * from information_schema.authinfo;

disconnect test_con1;
8 changes: 8 additions & 0 deletions mysql-test/t/information_schema_authinfo_nossl.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Repeat connect/disconnect

connect(test_con1,localhost,root,,,);

--replace_column 1 <Id> 3 <Host>
select * from information_schema.authinfo;

disconnect test_con1;
161 changes: 161 additions & 0 deletions sql/sql_show.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2115,6 +2115,59 @@ static const char *thread_state_info(THD *tmp)
}
}

#ifdef HAVE_OPENSSL
BUF_MEM *get_peer_cert_info(THD *thd)
{
assert(thd);

if(!thd->vio_ok() || !thd->net.vio->ssl_arg) {
return NULL;
}

assert(thd->vio_ok() && thd->net.vio->ssl_arg);

SSL *ssl= (SSL*) thd->net.vio->ssl_arg;

// extract user cert ref from the thread
X509 *cert= SSL_get_peer_certificate(ssl);
if (!cert) {
return NULL;
}

// Create new X509 buffer abstraction
BIO *bio = BIO_new(BIO_s_mem());
if (!bio) {
return NULL;
}

// Print the certificate to the buffer
int status = X509_print(bio, cert);
if (status != 1) {
BIO_free(bio);
return NULL;
}

// decouple buffer and close bio object
BUF_MEM *bufmem;
BIO_get_mem_ptr(bio, &bufmem);
(void) BIO_set_close(bio, BIO_NOCLOSE);
BIO_free(bio);

assert(bufmem->length <= bufmem->max);
if (bufmem->length) {
// the buffer is not null terminated, fix that
const size_t n = bufmem->length < bufmem->max ? bufmem->length
: bufmem->max - 1;
bufmem->data[n] = 0;
return bufmem;
}

assert(!bufmem->length);
BUF_MEM_free(bufmem);
return NULL;
}
#endif

void mysqld_list_processes(THD *thd,const char *user, bool verbose)
{
Item *field;
Expand Down Expand Up @@ -2376,6 +2429,100 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, Item* cond)
DBUG_RETURN(0);
}

int fill_schema_authinfo(THD* thd, TABLE_LIST* tables, Item* cond)
{
DBUG_ENTER("fill_schema_authinfo");

TABLE *table= tables->table;
CHARSET_INFO *cs= system_charset_info;

char *const user= thd->security_ctx->master_access & PROCESS_ACL ?
NullS : thd->security_ctx->priv_user;

if (thd->killed) {
DBUG_RETURN(0);
}

assert(!thd->killed);

/* take copy of global_thread_list */
std::set<THD*> global_thread_list_copy;

/*
Allow inserts to global_thread_list. Newly added thd
will not be accounted for `fill schema processlist` and
removal from global_thread_list is blocked as LOCK_thd_remove
mutex is not released yet
*/
mysql_mutex_lock(&LOCK_thd_remove);
copy_global_thread_list(&global_thread_list_copy);

Thread_iterator it= global_thread_list_copy.begin();
Thread_iterator end= global_thread_list_copy.end();
for (; it != end; ++it) {
THD* tmp= *it;
Security_context *tmp_sctx= tmp->security_ctx;

if ((!tmp->vio_ok() && !tmp->system_thread) ||
(user && (!tmp_sctx->user || strcmp(tmp_sctx->user, user))))
continue;

restore_record(table, s->default_values);

/* ID */
table->field[0]->store((ulonglong) tmp->thread_id, TRUE);

/* USER */
const char *val= tmp_sctx->user ? tmp_sctx->user :
(tmp->system_thread ? "system user" : "unauthenticated user");
table->field[1]->store(val, strlen(val), cs);

/* HOST */
if (tmp->peer_port && (tmp_sctx->get_host()->length() ||
tmp_sctx->get_ip()->length()) && thd->security_ctx->host_or_ip[0]) {
char host[LIST_PROCESS_HOST_LEN + 1];
my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u", tmp_sctx->host_or_ip,
tmp->peer_port);
table->field[2]->store(host, strlen(host), cs);
} else {
table->field[2]->store(tmp_sctx->host_or_ip, strlen(tmp_sctx->host_or_ip),
cs);
}

/* SSL */
bool ssl = false;
#ifdef HAVE_OPENSSL
ssl = (tmp->vio_ok() && tmp->net.vio->ssl_arg);
#endif
table->field[3]->store(ssl, /*unsigned=*/ TRUE);

/* Info */
char* cert = NULL;
#ifdef HAVE_OPENSSL
BUF_MEM *bufmem = get_peer_cert_info(tmp);
cert = bufmem ? bufmem->data : NULL;
#endif
if (cert) {
const size_t certlen = cert ? strlen(cert) : 0;
const size_t width = min<size_t>(PROCESS_LIST_INFO_WIDTH, certlen);
table->field[4]->store(cert, width, cs);
table->field[4]->set_notnull();
}

#ifdef HAVE_OPENSSL
BUF_MEM_free(bufmem);
#endif

if (schema_table_store_record(thd, table)) {
mysql_mutex_unlock(&LOCK_thd_remove);
DBUG_RETURN(1);
}
}

mysql_mutex_unlock(&LOCK_thd_remove);
DBUG_RETURN(0);
}

/*****************************************************************************
Status functions
*****************************************************************************/
Expand Down Expand Up @@ -8199,6 +8346,18 @@ ST_FIELD_INFO processlist_fields_info[]=
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};

ST_FIELD_INFO authinfo_fields_info[]=
{
{"ID", 21, MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, "Id", SKIP_OPEN_TABLE},
{"USER", USERNAME_CHAR_LENGTH, MYSQL_TYPE_STRING, 0, 0, "User",
SKIP_OPEN_TABLE},
{"HOST", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Host",
SKIP_OPEN_TABLE},
{"SSL", 7, MYSQL_TYPE_LONG, 0, 0, "Host", SKIP_OPEN_TABLE},
{"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};

ST_FIELD_INFO plugin_fields_info[]=
{
Expand Down Expand Up @@ -8473,6 +8632,8 @@ ST_SCHEMA_TABLE schema_tables[]=
{"VIEWS", view_fields_info, create_schema_table,
get_all_tables, 0, get_schema_views_record, 1, 2, 0,
OPEN_VIEW_ONLY|OPTIMIZE_I_S_TABLE},
{"AUTHINFO", authinfo_fields_info, create_schema_table,
fill_schema_authinfo, make_old_format, 0, -1, -1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

Expand Down

0 comments on commit f29eb03

Please sign in to comment.