diff options
59 files changed, 646 insertions, 267 deletions
diff --git a/BUILD/compile-pentium-max b/BUILD/compile-pentium-max index 55f88ef4748..9838e6a287b 100755 --- a/BUILD/compile-pentium-max +++ b/BUILD/compile-pentium-max @@ -8,6 +8,6 @@ extra_configs="$pentium_configs" strip=yes extra_configs="$extra_configs --with-innodb --with-berkeley-db \ - --enable-thread-safe-client" + --enable-thread-safe-client --with-openssl --with-vio" . "$path/FINISH.sh" diff --git a/Docs/manual.ja.texi b/Docs/manual.ja.texi index d3ee43acd29..dea7046b538 100644 --- a/Docs/manual.ja.texi +++ b/Docs/manual.ja.texi @@ -3187,7 +3187,7 @@ encounter per year, but we are as always very flexible towards our customers! @c @image{Flags/estonia} Estonia [Tradenet] @ @c @uref{http://mysql.tradenet.ee, WWW} @item -@c EMAIL: tonu@spamm.ee (Tonu Samuel) +@c EMAIL: tonu@spam.ee (Tonu Samuel) @image{Flags/estonia} Estonia [OKinteractive] @ @uref{http://mysql.mirror.ok.ee, WWW} @item diff --git a/Docs/manual.texi b/Docs/manual.texi index 5e45881ec61..d3dcb6ee0db 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -15577,7 +15577,7 @@ Users of Java JDBC: Do not transmit plain (unencrypted) data over the Internet. These data are accessible to everyone who has the time and ability to intercept it and use it for their own purposes. Instead, use an encrypted protocol such as SSL or -SSH. MySQL supports internal SSL connections as of Version 3.23.9. +SSH. MySQL supports internal SSL connections as of Version 4.0.0. SSH port-forwarding can be used to create an encrypted (and compressed) tunnel for the communication. @item @@ -16979,7 +16979,11 @@ GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...] ON @{tbl_name | * | *.* | db_name.*@} TO user_name [IDENTIFIED BY 'password'] [, user_name [IDENTIFIED BY 'password'] ...] - [REQUIRE @{SSL|X509@} [ISSUER issuer] [SUBJECT subject]] + [REQUIRE + [@{SSL| X509@}] + [CIPHER cipher [AND]] + [ISSUER issuer [AND]] + [SUBJECT subject]] [WITH GRANT OPTION] REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...] @@ -17202,6 +17206,120 @@ dropped only with explicit @code{REVOKE} commands or by manipulating the MySQL grant tables. @end itemize +----------- +@cindex SSL and X509 Basics +MySQL has support for SSL encrypted connetions. To understand how MySQL uses +SSL we need to explain some basics about SSL and X509. People who are already +aware of it can skip this chapter. + +By default, MySQL uses unencrypted connections between client and server. This means +that anyone on the way can listen and read all your data which moves there. Even +more, some people can change content of data while it is moving between client and +server. Sometime you may need to move really secret data over public networks and +such publicity is unacceptable. + +SSL is a protocol which uses different encryption algorithms to ensure that data +which comes from public network can be trusted. It have mechanisms to detect any +change, loss or replay of data. SSL also incorpores algorithms to recognize and +verification of identity using X509 standard. + +@cindex What is encryption +Encryption is the way to make any kind of data unreadable. Even more, today's +practice require many additional security elements from encryption algorithms. +They should resist many kind of known attacks like just messing with order +of encrypted messages or replaying data twice. + +@cindex What is X509/Certificate? +X509 is standard which makes possible to identity someone in the Internet. Mostly +it is used in e-commerce over the Internet. Shortly speaking there should be some +company called "Certificate Authority" which assigns electronic certificates to +everyone who needs. Certificates rely on asymmetric encryption algorithms which +have two encryption keys - public and secret. Certificate owner can prove his +identity showing certificate to other party. Certificate consists his owner public +key. Any data encrypted with it can be decrypted only by secret key holder. + +@cindex Possible questions: +Q: Why MySQL not uses encrypted connections by default? +A: Because it makes MySQL slower. Any kind of additional functionality requires +computer to do additional work and encrypting data is CPU-intensive operation which +can overcome MySQL own work and consumed time. MySQL is tuned to be fast by default. + +Q: I need more information about SSL/X509/encrpytion/whatever +A: Use your favourite internet search engine and search for keywords you are interested in. + +------------ + + +@cindex SSL related options + +MySQL can check x509 certificate attributes additionally to most used username/password +cheme. All usual options are still required (username, password, IP address mask, database/table name). + +There are different possibilities to limit connections: + +@itemize @bullet +@item +Without any SSL/X509 options all kind of encrypted/unencrypted connections are allowed if + username and password are valid. + +@item +@code{REQUIRE SSL} option makes SSL encrypted connection must. Note that this requirement +can be omitted of there are any other ACL record which allows non-SSL connection. + +Example: +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE SSL +@end example + + +@item +* @code{REQUIRE X509} Requiring X509 certificate means that client should have valid certificate +but we do not care about exact certificate, issuer or subject. Only restriction is it should +be possible to verify its signature with some of our CA certificates. + +Example: +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE X509 +@end example + +@item +@code{REQUIRE ISSUER issuer} makes connection more restrictive: now client must present + valid x509 certificate issued by CA "issuer". Using x509 certificates always implies encryption, + so option "SSL" is not neccessary anymore. + +Example: +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE ISSUER "C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com" +@end example + +@item +@code{REQUIRE SUBJECT subject} requires client to have valid x509 certificate with subject "subject" on it. If client have valid certificate but having different "subject" then connection is still +not allowed. + +Example: +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn, O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com" +@end example + +@item +@code{REQUIRE CIPHER cipher} is needed to assure enough strong ciphers and keylengths to be used. SSL himself can be weak if old algorithms with short encryption keys are used. Using this option we can ask for some exact cipher to allow connection. + +Example: +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA" +@end example + +Also it is allowed to combine those options with each other like this: +@example +GRANT ALL PRIVILEGES ON test.* TO root@@localhost IDENTIFIED BY "goodsecret" + REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn, O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com" + AND ISSUER "C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com" + AND CIPHER "EDH-RSA-DES-CBC3-SHA" +@end example + +But it is not allowed to use any of options twice. Only different options can be mixed. +@end itemize +----------- @node User names, Privilege changes, GRANT, User Account Management @subsection MySQL User Names and Passwords @@ -19829,7 +19947,7 @@ differ somewhat: | have_bdb | YES | | have_innodb | YES | | have_raid | YES | -| have_ssl | NO | +| have_openssl | NO | | init_file | | | interactive_timeout | 28800 | | join_buffer_size | 131072 | @@ -20016,7 +20134,7 @@ if @code{--skip-bdb} is used. if @code{--skip-innodb} is used. @item @code{have_raid} @code{YES} if @code{mysqld} supports the @code{RAID} option. -@item @code{have_ssl} +@item @code{have_openssl} @code{YES} if @code{mysqld} supports SSL (encryption) on the client/server protocol. @@ -21680,7 +21798,7 @@ mysql> show variables like "have_%"; | have_innodb | NO | | have_isam | YES | | have_raid | NO | -| have_ssl | NO | +| have_openssl | NO | +---------------+-------+ @end example @@ -48424,7 +48542,7 @@ Allow hex constants in the @code{--fields-*-by} and Added option @code{--safe-show-database} to @code{mysqld}. @item Added @code{have_bdb}, @code{have_gemini}, @code{have_innobase}, -@code{have_raid} and @code{have_ssl} to @code{SHOW VARIABLES} to make it +@code{have_raid} and @code{have_openssl} to @code{SHOW VARIABLES} to make it easy to test for supported extensions. @item Added option @code{--open-files-limit} to @code{mysqld}. diff --git a/acinclude.m4 b/acinclude.m4 index 0a767227ce4..1535f0df5f7 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -663,7 +663,7 @@ if test "$cpu_vendor" = "AuthenticAMD"; then fi elif test "$cpu_vendor" = "GenuineIntel"; then if test $cpu_family>=6; then - cpu_set=" pentiumpro pentium i486 i386"; + cpu_set="pentiumpro pentium i486 i386"; elif test $cpu_family=5; then cpu_set="pentium i486 i386"; elif test $cpu_family=4; then @@ -682,9 +682,9 @@ done if test "$mysql_cv_cpu" = "unknown" then CFLAGS="$ac_save_CFLAGS" - AC_MSG_RESULT(none) + AC_MSG_RESULT(none) else - AC_MSG_RESULT($mysql_cv_cpu) + AC_MSG_RESULT($mysql_cv_cpu) fi ])) diff --git a/client/mysql.cc b/client/mysql.cc index 6382fd66f35..dbaff8e57f5 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -24,6 +24,7 @@ * Jani Tolonen <jani@mysql.com> * Matt Wagner <mwagner@mysql.com> * Jeremy Cole <jcole@mysql.com> + * Tonu Samuel <tonu@mysql.com> * **/ @@ -1232,6 +1233,7 @@ You can turn off this feature to get a quicker startup with -A\n\n"); } } } + /* FIXME: free() on small chunks is sloooowwww. glibc bug */ if (field_names) { for (i=0; field_names[i]; i++) { for (j=0; field_names[i][j]; j++) { @@ -2219,7 +2221,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath); + opt_ssl_capath, opt_ssl_cipher); #endif if (safe_updates) { diff --git a/client/mysqladmin.c b/client/mysqladmin.c index ca568a914f2..87a5be2aad2 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -265,7 +265,7 @@ int main(int argc,char *argv[]) #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath); + opt_ssl_capath, opt_ssl_cipher); #endif /* HAVE_OPENSSL */ if (sql_connect(&mysql,host,user,opt_password,option_wait)) error = 1; diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 0f7bfb37ecf..75190e34267 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -591,7 +591,7 @@ static int dbConnect(char *host, char *user, char *passwd) #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath); + opt_ssl_capath, opt_ssl_cipher); #endif if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0))) diff --git a/client/mysqldump.c b/client/mysqldump.c index 9d80fd9a6c9..3c9e36e8a70 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -523,7 +523,7 @@ static int dbConnect(char *host, char *user,char *passwd) #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath); + opt_ssl_capath, opt_ssl_cipher); #endif if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd, NULL,opt_mysql_port,opt_mysql_unix_port, diff --git a/client/mysqlimport.c b/client/mysqlimport.c index d8f763b9653..1883b2a062e 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -400,7 +400,7 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd) #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath); + opt_ssl_capath, opt_ssl_cipher); #endif if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd, database,opt_mysql_port,opt_mysql_unix_port, diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 8bce1203df8..9c682047c0e 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -87,7 +87,7 @@ int main(int argc, char **argv) #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath); + opt_ssl_capath, opt_ssl_cipher); #endif if (!(mysql_real_connect(&mysql,host,user,opt_password, argv[0],opt_mysql_port,opt_mysql_unix_port, diff --git a/include/mysql.h b/include/mysql.h index a1bd96540e8..7867dea2c31 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -135,6 +135,7 @@ struct st_mysql_options { char *ssl_cert; /* PEM cert file */ char *ssl_ca; /* PEM CA file */ char *ssl_capath; /* PEM directory of CA-s? */ + char *ssl_cipher; /* cipher to use */ my_bool use_ssl; /* if to use SSL or not */ my_bool compress,named_pipe; /* @@ -262,7 +263,7 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql); MYSQL * STDCALL mysql_init(MYSQL *mysql); int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, - const char *capath); + const char *capath, const char *cipher); int STDCALL mysql_ssl_clear(MYSQL *mysql); my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, const char *passwd, const char *db); diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 8f78d6190b1..cb555eb8066 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -221,4 +221,7 @@ #define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1218 #define ER_CANT_UPDATE_WITH_READLOCK 1219 #define ER_MIXING_NOT_ALLOWED 1220 -#define ER_ERROR_MESSAGES 221 +#define ER_GRANT_DUPL_SUBJECT 1221 +#define ER_GRANT_DUPL_ISSUER 1222 +#define ER_GRANT_DUPL_CIPHER 1223 +#define ER_ERROR_MESSAGES 224 diff --git a/include/sslopt-case.h b/include/sslopt-case.h index d995e31044e..b5720286778 100644 --- a/include/sslopt-case.h +++ b/include/sslopt-case.h @@ -39,4 +39,10 @@ my_free(opt_ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); opt_ssl_ca = my_strdup(optarg, MYF(0)); break; + case OPT_SSL_CIPHER: + opt_use_ssl = 1; /* true */ + my_free(opt_ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + opt_ssl_cipher = my_strdup(optarg, MYF(0)); + break; + #endif diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index 2f58f0e9265..697c2f647bf 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -22,10 +22,12 @@ #define OPT_SSL_CERT 202 #define OPT_SSL_CA 203 #define OPT_SSL_CAPATH 204 +#define OPT_SSL_CIPHER 205 {"ssl", no_argument, 0, OPT_SSL_SSL}, {"ssl-key", required_argument, 0, OPT_SSL_KEY}, {"ssl-cert", required_argument, 0, OPT_SSL_CERT}, {"ssl-ca", required_argument, 0, OPT_SSL_CA}, {"ssl-capath", required_argument, 0, OPT_SSL_CAPATH}, + {"ssl-cipher", required_argument, 0, OPT_SSL_CIPHER}, #endif /* HAVE_OPENSSL */ diff --git a/include/sslopt-usage.h b/include/sslopt-usage.h index 5b2b4a88709..cd6a06fb459 100644 --- a/include/sslopt-usage.h +++ b/include/sslopt-usage.h @@ -21,5 +21,6 @@ --ssl-key X509 key in PEM format (implies --ssl)\n\ --ssl-cert X509 cert in PEM format (implies --ssl)\n\ --ssl-ca CA file in PEM format (check OpenSSL docs, implies --ssl)\n\ - --ssl-capath CA directory (check OpenSSL docs, implies --ssl)"); + --ssl-capath CA directory (check OpenSSL docs, implies --ssl)\n\ + --ssl-cipher SSL cipher to use (implies --ssl)"); #endif diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index 597ab4d9fa6..756a35589aa 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -21,4 +21,5 @@ static char *opt_ssl_key = 0; static char *opt_ssl_cert = 0; static char *opt_ssl_ca = 0; static char *opt_ssl_capath = 0; +static char *opt_ssl_cipher = 0; #endif diff --git a/include/violite.h b/include/violite.h index 947b874c46a..c59f6124838 100644 --- a/include/violite.h +++ b/include/violite.h @@ -169,9 +169,6 @@ struct st_VioSSLAcceptorFd state_connect = 1, state_accept = 2 }; -// BIO* bio_; -// char desc_[100]; -// Vio* sd_; /* function pointers which are only once for SSL server Vio*(*sslaccept)(struct st_VioSSLAcceptorFd*,Vio*); */ @@ -184,15 +181,17 @@ struct st_VioSSLConnectorFd SSL_METHOD* ssl_method_; /* function pointers which are only once for SSL client */ }; -void sslaccept(struct st_VioSSLAcceptorFd*, Vio*); -void sslconnect(struct st_VioSSLConnectorFd*, Vio*); +void sslaccept(struct st_VioSSLAcceptorFd*, Vio*, long timeout); +void sslconnect(struct st_VioSSLConnectorFd*, Vio*, long timeout); struct st_VioSSLConnectorFd *new_VioSSLConnectorFd(const char* key_file, const char* cert_file, - const char* ca_file, const char* ca_path); + const char* ca_file, const char* ca_path, + const char* cipher); struct st_VioSSLAcceptorFd *new_VioSSLAcceptorFd(const char* key_file, const char* cert_file, - const char* ca_file,const char* ca_path); + const char* ca_file,const char* ca_path, + const char* cipher); Vio* new_VioSSL(struct st_VioSSLAcceptorFd* fd, Vio* sd,int state); #ifdef __cplusplus @@ -200,6 +199,9 @@ Vio* new_VioSSL(struct st_VioSSLAcceptorFd* fd, Vio* sd,int state); #endif #endif /* HAVE_OPENSSL */ +/* This enumerator is used in parser - should be always visible */ +enum SSL_type {SSL_TYPE_NONE, SSL_TYPE_ANY, SSL_TYPE_X509, SSL_TYPE_SPECIFIED}; + #ifndef EMBEDDED_LIBRARY /* This structure is for every connection on both sides */ struct st_vio @@ -229,10 +231,8 @@ struct st_vio my_bool (*poll_read)(Vio*,uint); #ifdef HAVE_OPENSSL - BIO* bio_; SSL* ssl_; my_bool open_; - char *ssl_cip_; #endif /* HAVE_OPENSSL */ #endif /* HAVE_VIO */ }; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 03162bc1dfa..5924a4f13c2 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -695,7 +695,7 @@ mysql_free_result(MYSQL_RES *result) static const char *default_options[]= {"port","socket","compress","password","pipe", "timeout", "user", "init-command", "host", "database", "debug", "return-found-rows", - "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", + "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", "ssl-cipher" "character-set-dir", "default-character-set", "interactive-timeout", "connect_timeout", "replication-probe", "enable-reads-from-master", "repl-parse-query", @@ -1368,15 +1368,17 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , const char *key __attribute__((unused)), const char *cert __attribute__((unused)), const char *ca __attribute__((unused)), - const char *capath __attribute__((unused))) + const char *capath __attribute__((unused)), + const char *cipher __attribute__((unused))) { #ifdef HAVE_OPENSSL mysql->options.ssl_key = key==0 ? 0 : my_strdup(key,MYF(0)); mysql->options.ssl_cert = cert==0 ? 0 : my_strdup(cert,MYF(0)); mysql->options.ssl_ca = ca==0 ? 0 : my_strdup(ca,MYF(0)); mysql->options.ssl_capath = capath==0 ? 0 : my_strdup(capath,MYF(0)); + mysql->options.ssl_cipher = cipher==0 ? 0 : my_strdup(cipher,MYF(0)); mysql->options.use_ssl = TRUE; - mysql->connector_fd = (gptr)new_VioSSLConnectorFd(key, cert, ca, capath); + mysql->connector_fd = (gptr)new_VioSSLConnectorFd(key, cert, ca, capath, cipher); DBUG_PRINT("info",("mysql_ssl_set, context: %p",((struct st_VioSSLConnectorFd *)(mysql->connector_fd))->ssl_context_)); #endif return 0; @@ -1396,10 +1398,12 @@ mysql_ssl_clear(MYSQL *mysql __attribute__((unused))) my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); mysql->options.ssl_key = 0; mysql->options.ssl_cert = 0; mysql->options.ssl_ca = 0; mysql->options.ssl_capath = 0; + mysql->options.ssl_cipher= 0; mysql->options.use_ssl = FALSE; my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); mysql->connector_fd = 0; @@ -1797,7 +1801,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Do the SSL layering. */ DBUG_PRINT("info", ("IO layer change in progress...")); DBUG_PRINT("info", ("IO context %p",((struct st_VioSSLConnectorFd*)mysql->connector_fd)->ssl_context_)); - sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio); + sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio, (long)(mysql->options.connect_timeout)); DBUG_PRINT("info", ("IO layer change done!")); } #endif /* HAVE_OPENSSL */ @@ -1887,7 +1891,7 @@ static my_bool mysql_reconnect(MYSQL *mysql) if (!mysql->reconnect || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { - /* Allov reconnect next time */ + /* Allow reconnect next time */ mysql->server_status&= ~SERVER_STATUS_IN_TRANS; DBUG_RETURN(1); } @@ -1995,13 +1999,13 @@ mysql_close(MYSQL *mysql) my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); +#ifdef HAVE_OPENSSL + mysql_ssl_clear(mysql); +#endif /* HAVE_OPENSSL */ /* Clear pointers for better safety */ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; bzero((char*) &mysql->options,sizeof(mysql->options)); mysql->net.vio = 0; -#ifdef HAVE_OPENSSL - mysql_ssl_clear(mysql); -#endif /* HAVE_OPENSSL */ /* free/close slave list */ if (mysql->rpl_pivot) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index e7da577ab0c..116219372fd 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -257,7 +257,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, send_error(net,ER_OUT_OF_RESOURCES); return 1; } - thd->master_access=acl_getroot(thd->host, thd->ip, thd->user, + thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, passwd, thd->scramble, &thd->priv_user, protocol_version == 9 || !(thd->client_capabilities & diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh index 0535b66e289..f810d2d9ad4 100644 --- a/mysql-test/install_test_db.sh +++ b/mysql-test/install_test_db.sh @@ -134,7 +134,7 @@ then c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u ssl_type enum('none', 'cipher', 'x509','issuer','subject') NOT NULL," + c_u="$c_u ssl_type enum('NONE','ANY', 'X509', 'SPECIFIED') NOT NULL," c_u="$c_u ssl_cipher char(60) NULL," c_u="$c_u x509_issuer blob NULL," c_u="$c_u x509_subject blob NULL," diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 7e232692ba1..f064e6ca0ca 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -224,18 +224,22 @@ then c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u ssl_type enum('NONE','ANY','X509', 'SPECIFIED') DEFAULT 'NONE' NOT NULL," + c_u="$c_u ssl_cipher BLOB NULL," + c_u="$c_u x509_issuer BLOB NULL," + c_u="$c_u x509_subject BLOB NULL," c_u="$c_u PRIMARY KEY Host (Host,User)" c_u="$c_u )" c_u="$c_u comment='Users and global privileges';" - i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); - INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE',NULL,NULL,NULL); + INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE',NULL,NULL,NULL); - REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); - REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); + REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE',NULL,NULL,NULL); + REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE',NULL,NULL,NULL); - INSERT INTO user VALUES ('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N'); - INSERT INTO user VALUES ('$hostname','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N');" + INSERT INTO user VALUES ('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','NONE',NULL,NULL,NULL); + INSERT INTO user VALUES ('$hostname','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','NONE',NULL,NULL,NULL);" fi if test ! -f $mdata/func.frm diff --git a/sql/lex.h b/sql/lex.h index 5decf089e68..72d77e18910 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -319,6 +319,7 @@ static SYMBOL symbols[] = { { "SQL_SLAVE_SKIP_COUNTER", SYM(SQL_SLAVE_SKIP_COUNTER),0,0}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0}, { "SQL_WARNINGS", SYM(SQL_WARNINGS),0,0}, + { "SSL", SYM(SSL_SYM),0,0}, { "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0}, { "START", SYM(START_SYM),0,0}, { "STARTING", SYM(STARTING),0,0}, @@ -362,6 +363,7 @@ static SYMBOL symbols[] = { { "WRITE", SYM(WRITE_SYM),0,0}, { "WHEN", SYM(WHEN_SYM),0,0}, { "WHERE", SYM(WHERE),0,0}, + { "X509", SYM(X509_SYM),0,0}, { "YEAR", SYM(YEAR_SYM),0,0}, { "YEAR_MONTH", SYM(YEAR_MONTH_SYM),0,0}, { "ZEROFILL", SYM(ZEROFILL),0,0}, diff --git a/sql/mini_client.cc b/sql/mini_client.cc index d60a3bce880..266a292fe1d 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -803,7 +803,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, /* Do the SSL layering. */ DBUG_PRINT("info", ("IO layer change in progress...")); DBUG_PRINT("info", ("IO context %p",((struct st_VioSSLConnectorFd*)mysql->connector_fd)->ssl_context_)); - sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio); + sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio,60L); DBUG_PRINT("info", ("IO layer change done!")); } #endif /* HAVE_OPENSSL */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a6b6c9914b4..b27cb8a6bf3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -242,16 +242,11 @@ static char **defaults_argv,time_zone[30]; static const char *default_table_type_name; static char glob_hostname[FN_REFLEN]; +#include "sslopt-vars.h" #ifdef HAVE_OPENSSL -static bool opt_use_ssl = FALSE; -static char *opt_ssl_key = 0; -static char *opt_ssl_cert = 0; -static char *opt_ssl_ca = 0; -static char *opt_ssl_capath = 0; struct st_VioSSLAcceptorFd * ssl_acceptor_fd = 0; #endif /* HAVE_OPENSSL */ - I_List <i_string_pair> replicate_rewrite_db; I_List<i_string> replicate_do_db, replicate_ignore_db; // allow the user to tell us which db to replicate and which to ignore @@ -725,6 +720,7 @@ void clean_up(bool print_message) my_free(opt_ssl_cert,MYF(MY_ALLOW_ZERO_PTR)); my_free(opt_ssl_ca,MYF(MY_ALLOW_ZERO_PTR)); my_free(opt_ssl_capath,MYF(MY_ALLOW_ZERO_PTR)); + my_free(opt_ssl_cipher,MYF(MY_ALLOW_ZERO_PTR)); opt_ssl_key=opt_ssl_cert=opt_ssl_ca=opt_ssl_capath=0; #endif /* HAVE_OPENSSL */ free_defaults(defaults_argv); @@ -1712,7 +1708,7 @@ int main(int argc, char **argv) if (opt_use_ssl) { ssl_acceptor_fd = new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert, - opt_ssl_ca, opt_ssl_capath); + opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); DBUG_PRINT("info",("ssl_acceptor_fd: %p",ssl_acceptor_fd)); if (!ssl_acceptor_fd) opt_use_ssl=0; @@ -3110,21 +3106,29 @@ struct show_var_st status_vars[]= { {"Sort_rows", (char*) &filesort_rows, SHOW_LONG}, {"Sort_scan", (char*) &filesort_scan_count, SHOW_LONG}, #ifdef HAVE_OPENSSL - {"SSL_CTX_sess_accept", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT}, - {"SSL_CTX_sess_accept_good", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_GOOD}, - {"SSL_CTX_sess_accept_renegotiate", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE}, - {"SSL_CTX_sess_cb_hits", (char*) 0, SHOW_SSL_CTX_SESS_CB_HITS}, - {"SSL_CTX_sess_number", (char*) 0, SHOW_SSL_CTX_SESS_NUMBER}, - {"SSL_CTX_get_session_cache_mode", (char*) 0, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE}, - {"SSL_CTX_sess_get_cache_size", (char*) 0, SHOW_SSL_CTX_SESS_GET_CACHE_SIZE}, - {"SSL_CTX_get_verify_mode", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_MODE}, - {"SSL_CTX_get_verify_depth", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_DEPTH}, - {"SSL_get_verify_mode", (char*) 0, SHOW_SSL_GET_VERIFY_MODE}, - {"SSL_get_verify_depth", (char*) 0, SHOW_SSL_GET_VERIFY_DEPTH}, - {"SSL_session_reused", (char*) 0, SHOW_SSL_SESSION_REUSED}, - {"SSL_get_version", (char*) 0, SHOW_SSL_GET_VERSION}, - {"SSL_get_cipher", (char*) 0, SHOW_SSL_GET_CIPHER}, - {"SSL_get_default_timeout", (char*) 0, SHOW_SSL_GET_DEFAULT_TIMEOUT}, + {"ssl_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT}, + {"ssl_finished_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_GOOD}, + {"ssl_finished_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_GOOD}, + {"ssl_accept_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE}, + {"ssl_connect_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE}, + {"ssl_callback_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_CB_HITS}, + {"ssl_session_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_HITS}, + {"ssl_session_cache_misses", (char*) 0, SHOW_SSL_CTX_SESS_MISSES}, + {"ssl_session_cache_timeouts", (char*) 0, SHOW_SSL_CTX_SESS_TIMEOUTS}, + {"ssl_used_session_cache_entries",(char*) 0, SHOW_SSL_CTX_SESS_NUMBER}, + {"ssl_client_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT}, + {"ssl_session_cache_overflows", (char*) 0, SHOW_SSL_CTX_SESS_CACHE_FULL}, + {"ssl_session_cache_size", (char*) 0, SHOW_SSL_CTX_SESS_GET_CACHE_SIZE}, + {"ssl_session_cache_mode", (char*) 0, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE}, + {"ssl_sessions_reused", (char*) 0, SHOW_SSL_SESSION_REUSED}, + {"ssl_ctx_verify_mode", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_MODE}, + {"ssl_ctx_verify_depth", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_DEPTH}, + {"ssl_verify_mode", (char*) 0, SHOW_SSL_GET_VERIFY_MODE}, + {"ssl_verify_depth", (char*) 0, SHOW_SSL_GET_VERIFY_DEPTH}, + {"ssl_version", (char*) 0, SHOW_SSL_GET_VERSION}, + {"ssl_cipher", (char*) 0, SHOW_SSL_GET_CIPHER}, + {"ssl_cipher_list", (char*) 0, SHOW_SSL_GET_CIPHER_LIST}, + {"ssl_default_timeout", (char*) 0, SHOW_SSL_GET_DEFAULT_TIMEOUT}, #endif /* HAVE_OPENSSL */ {"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG}, {"Table_locks_waited", (char*) &locks_waited, SHOW_LONG}, diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index b92297abbf8..9a6768d7025 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -231,3 +231,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 9adc2f5fb73..42ff7206046 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -225,3 +225,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 61db11f39f8..0819e355422 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -228,3 +228,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index bd328dbb6e4..f5888440743 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -222,3 +222,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 166637c43e1..7ad829d1f04 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -226,3 +226,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 0db8b69622e..2ac778877f6 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -222,3 +222,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index a9ba1f41c42..6cf9d8dd2a1 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -225,3 +225,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index aa8d659b263..65954ce1c2e 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -222,3 +222,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 5cc5ac663b1..28ee01934c0 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -224,3 +224,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 7c44e0bf4c7..2d778692e9a 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -222,3 +222,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 5d6f0158ea2..248c5e1b566 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -224,3 +224,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 6288ac535d4..3a2086accf1 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -222,3 +222,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index de783f93d1a..f701bdd1ade 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -224,3 +224,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 3cbc5b6138d..00c23acaca9 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -224,3 +224,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index c144dda47ae..56573f93a00 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -226,3 +226,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index c11adc3af70..f15cbc930cb 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -222,3 +222,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 32b6eddfeeb..9f83e98828e 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -226,3 +226,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index fbff74993fb..8851866b249 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -225,3 +225,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index d60dbf0956c..08b5bfe6ba9 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -230,3 +230,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 9234de04786..6348f416277 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -223,3 +223,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 25309cd0598..83e08254f90 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -222,3 +222,6 @@ "SELECT kommandona har olika antal kolumner" "Kan inte utföra kommandot emedan du har ett READ lås", "Blandning av transaktionella och icke-transaktionella tabeller är inaktiverat", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 49ab4399664..776103cf681 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -227,3 +227,6 @@ "The used SELECT statements have a different number of columns", "Can't execute the query because you have a conflicting read lock", "Mixing of transactional and non-transactional tables is disabled", +"Duplicate SUBJECT option in GRANT clause", +"Duplicate ISSUER option in GRANT clause", +"Duplicate CIPHER option in GRANT clause", diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4c128a882c6..2f6c126e693 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -62,8 +62,9 @@ public: char *user,*password; ulong salt[2]; #ifdef HAVE_OPENSSL - char *ssl_type, *ssl_cipher, *x509_issuer, *x509_subject; -#endif + enum SSL_type ssl_type; + const char *ssl_cipher, *x509_issuer, *x509_subject; +#endif /* HAVE_OPENSSL */ }; class ACL_DB :public ACL_ACCESS @@ -204,13 +205,19 @@ int acl_init(bool dont_read_acl_tables) user.password=get_field(&mem, table,2); #ifdef HAVE_OPENSSL DBUG_PRINT("info",("table->fields=%d",table->fields)); - if (table->fields >= 21) { - user.ssl_type=get_field(&mem, table,17); + if (table->fields >= 21) { /* From 4.0.0 we have more fields */ + if(!strcmp(get_field(&mem, table,17),"ANY")) + user.ssl_type=SSL_TYPE_ANY; + else if(!strcmp(get_field(&mem, table,17),"X509")) + user.ssl_type=SSL_TYPE_X509; + else if(!strcmp(get_field(&mem, table,17),"SPECIFIED")) + user.ssl_type=SSL_TYPE_SPECIFIED; + else user.ssl_type=SSL_TYPE_NONE; user.ssl_cipher=get_field(&mem, table,18); user.x509_issuer=get_field(&mem, table,19); user.x509_subject=get_field(&mem, table,20); } -#endif +#endif /* HAVE_OPENSSL */ if (user.password && (length=(uint) strlen(user.password)) == 8 && protocol_version == PROTOCOL_VERSION) { @@ -410,15 +417,14 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) } -/* Get master privilges for user (priviliges for all tables) */ - - -uint acl_getroot(const char *host, const char *ip, const char *user, +/* Get master privilges for user (priviliges for all tables). Required to connect */ +uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user, const char *password,const char *message,char **priv_user, bool old_ver) { uint user_access=NO_ACCESS; *priv_user=(char*) user; + char *ptr=0; if (!initialized) return (uint) ~NO_ACCESS; // If no data allow anything /* purecov: tested */ @@ -440,7 +446,88 @@ uint acl_getroot(const char *host, const char *ip, const char *user, !check_scramble(password,message,acl_user->salt, (my_bool) old_ver))) { +#ifdef HAVE_OPENSSL +#define vio (thd->net.vio) + /* In this point we know that user is allowed to connect + * from given host by given username/password pair. Now + * we check if SSL is required, if user is using SSL and + * if X509 certificate attributes are OK + */ + switch(acl_user->ssl_type) { + case SSL_TYPE_NONE: /* SSL is not required to connect */ + user_access=acl_user->access; + break; + case SSL_TYPE_ANY: /* Any kind of SSL is good enough */ + if(vio_type(vio) == VIO_TYPE_SSL) + user_access=acl_user->access; + break; + case SSL_TYPE_X509: /* Client should have any valid certificate. */ + /* Connections with non-valid certificates are dropped already + * in sslaccept() anyway, so we do not check validity here. + */ + if(SSL_get_peer_certificate(vio->ssl_)) + user_access=acl_user->access; + break; + case SSL_TYPE_SPECIFIED: /* Client should have attributes as specified */ + /* We do not check for absence of SSL because without SSL it does not + * pass all checks here anyway. + */ + /* If cipher name is specified, we compare it to actual cipher in use */ + if(acl_user->ssl_cipher) + DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'", + acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_))); + if(!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_))) + user_access=acl_user->access; + else + { + user_access=NO_ACCESS; + break; + } + /* Prepare certificate (if exists) */ + DBUG_PRINT("info",("checkpoint 1")); + X509* cert=SSL_get_peer_certificate(vio->ssl_); + DBUG_PRINT("info",("checkpoint 2")); + /* If X509 issuer is speified, we check it... */ + if(acl_user->x509_issuer) + { + DBUG_PRINT("info",("checkpoint 3")); + ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); + DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", + acl_user->x509_issuer, ptr)); + if(!strcmp(acl_user->x509_issuer,ptr)) + user_access=acl_user->access; + else + { + user_access=NO_ACCESS; + free(ptr); + break; + } + free(ptr); + } + DBUG_PRINT("info",("checkpoint 4")); + /* X509 subject is specified, we check it .. */ + if(acl_user->x509_subject) + { + ptr = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); + DBUG_PRINT("info",("comparing subjects: '%s' and '%s'", + acl_user->x509_subject, ptr)); + if(!strcmp(acl_user->x509_subject,ptr)) + user_access=acl_user->access; + else + { + user_access=NO_ACCESS; + free(ptr); + break; + } + free(ptr); + } + DBUG_PRINT("info",("checkpoint 5")); + break; + } + DBUG_PRINT("info",("checkpoint 6")); +#else /* HAVE_OPENSSL */ user_access=acl_user->access; +#endif /* HAVE_OPENSSL */ if (!acl_user->user) *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */ break; @@ -469,7 +556,14 @@ static byte* check_get_key(ACL_USER *buff,uint *length, } static void acl_update_user(const char *user, const char *host, - const char *password, uint privileges) + const char *password, +#ifdef HAVE_OPENSSL + enum SSL_type ssl_type, + const char *ssl_cipher, + const char *x509_issuer, + const char *x509_subject, +#endif /* HAVE_OPENSSL */ + uint privileges) { for (uint i=0 ; i < acl_users.elements ; i++) { @@ -482,6 +576,12 @@ static void acl_update_user(const char *user, const char *host, acl_user->host.hostname && !strcmp(host,acl_user->host.hostname)) { acl_user->access=privileges; +#ifdef HAVE_OPENSSL + acl_user->ssl_type=ssl_type; + acl_user->ssl_cipher=ssl_cipher; + acl_user->x509_issuer=x509_issuer; + acl_user->x509_subject=x509_subject; +#endif /* HAVE_OPENSSL */ if (password) { if (!password[0]) @@ -500,7 +600,13 @@ static void acl_update_user(const char *user, const char *host, static void acl_insert_user(const char *user, const char *host, - const char *password, + const char *password, +#ifdef HAVE_OPENSSL + enum SSL_type ssl_type, + const char *ssl_cipher, + const char *x509_issuer, + const char *x509_subject, +#endif /* HAVE_OPENSSL */ uint privileges) { ACL_USER acl_user; @@ -510,6 +616,12 @@ static void acl_insert_user(const char *user, const char *host, acl_user.access=privileges; acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user); acl_user.hostname_length=(uint) strlen(acl_user.host.hostname); +#ifdef HAVE_OPENSSL + acl_user.ssl_type=ssl_type; + acl_user.ssl_cipher=ssl_cipher; + acl_user.x509_issuer=x509_issuer; + acl_user.x509_subject=x509_subject; +#endif /* HAVE_OPENSSL */ if (password) { acl_user.password=(char*) ""; // Just point at something @@ -984,7 +1096,7 @@ static bool test_if_create_new_users(THD *thd) ** Handle GRANT commands ****************************************************************************/ -static int replace_user_table(TABLE *table, const LEX_USER &combo, +static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, uint rights, char what, bool create_user) { int error = -1; @@ -1044,7 +1156,40 @@ static int replace_user_table(TABLE *table, const LEX_USER &combo, table->field[i]->store(&what,1); } rights=get_access(table,3); - +#ifdef HAVE_OPENSSL + /* We write down SSL related ACL stuff */ + DBUG_PRINT("info",("table->fields=%d",table->fields)); + if (table->fields >= 21) { /* From 4.0.0 we have more fields */ + switch (thd->lex.ssl_type) { + case SSL_TYPE_ANY: + table->field[17]->store("ANY",3); + table->field[18]->store("",0); + table->field[19]->store("",0); + table->field[20]->store("",0); + break; + case SSL_TYPE_X509: + table->field[17]->store("X509",4); + table->field[18]->store("",0); + table->field[19]->store("",0); + table->field[20]->store("",0); + break; + case SSL_TYPE_SPECIFIED: + table->field[17]->store("SPECIFIED",9); + if(thd->lex.ssl_cipher) + table->field[18]->store(thd->lex.ssl_cipher,strlen(thd->lex.ssl_cipher)); + if(thd->lex.x509_issuer) + table->field[19]->store(thd->lex.x509_issuer,strlen(thd->lex.x509_issuer)); + if(thd->lex.x509_subject) + table->field[20]->store(thd->lex.x509_subject,strlen(thd->lex.x509_subject)); + break; + default: + table->field[17]->store("NONE",4); + table->field[18]->store("",0); + table->field[19]->store("",0); + table->field[20]->store("",0); + } + } +#endif /* HAVE_OPENSSL */ if (old_row_exists) { /* @@ -1078,9 +1223,23 @@ static int replace_user_table(TABLE *table, const LEX_USER &combo, if (!combo.password.str) password=0; // No password given on command if (old_row_exists) - acl_update_user(combo.user.str,combo.host.str,password,rights); + acl_update_user(combo.user.str,combo.host.str,password, +#ifdef HAVE_OPENSSL + thd->lex.ssl_type, + thd->lex.ssl_cipher, + thd->lex.x509_issuer, + thd->lex.x509_subject, +#endif /* HAVE_OPENSSL */ + rights); else - acl_insert_user(combo.user.str,combo.host.str,password,rights); + acl_insert_user(combo.user.str,combo.host.str,password, +#ifdef HAVE_OPENSSL + thd->lex.ssl_type, + thd->lex.ssl_cipher, + thd->lex.x509_issuer, + thd->lex.x509_subject, +#endif /* HAVE_OPENSSL */ + rights); } table->file->index_end(); DBUG_RETURN(error); @@ -1626,6 +1785,9 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list, TABLE_LIST tables[3]; bool create_new_users=0; DBUG_ENTER("mysql_table_grant"); + DBUG_PRINT("info",("ssl_cipher=%s",thd->lex.ssl_cipher)); + DBUG_PRINT("info",("x509_issuer=%s",thd->lex.x509_issuer)); + DBUG_PRINT("info",("x509_subject=%s",thd->lex.x509_subject)); if (!initialized) { @@ -1715,9 +1877,10 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list, continue; } /* Create user if needed */ - if (replace_user_table(tables[0].table, - *Str, - 0, + if (replace_user_table(thd, + tables[0].table, + *Str, + 0, revoke_grant ? 'N' : 'Y', create_new_users)) { @@ -1810,7 +1973,7 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list, pthread_mutex_unlock(&LOCK_grant); if (!result) send_ok(&thd->net); - /* Tables are automaticly closed */ + /* Tables are automatically closed */ DBUG_RETURN(result); } @@ -1871,7 +2034,8 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights, result= -1; continue; } - if ((replace_user_table(tables[0].table, + if ((replace_user_table(thd, + tables[0].table, *Str, (!db ? rights : 0), what, create_new_users))) result= -1; @@ -2332,6 +2496,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) { uint counter, want_access,index; int error = 0; + int ssl_options = 0; ACL_USER *acl_user; ACL_DB *acl_db; char buff[1024]; DBUG_ENTER("mysql_show_grants"); @@ -2426,30 +2591,37 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append('\''); } #ifdef HAVE_OPENSSL -/* SSL grant stuff */ - DBUG_PRINT("info",("acl_user->ssl_type=%s",acl_user->ssl_type)); - DBUG_PRINT("info",("acl_user->ssl_cipher=%s",acl_user->ssl_cipher)); - DBUG_PRINT("info",("acl_user->x509_subject=%s",acl_user->x509_subject)); - DBUG_PRINT("info",("acl_user->x509_issuer=%s",acl_user->x509_issuer)); - if(acl_user->ssl_type) { - if(!strcmp(acl_user->ssl_type,"ssl")) - global.append(" REQUIRE SSL",12); - else if(!strcmp(acl_user->ssl_type,"x509")) - { - global.append(" REQUIRE X509 ",14); - if(acl_user->x509_issuer) { - global.append("SUBJECT \"",9); - global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); - global.append("\"",1); - } - if(acl_user->x509_subject) { - global.append("ISSUER \"",8); - global.append(acl_user->x509_subject,strlen(acl_user->x509_subject)); - global.append("\"",1); - } - } +/* "show grants" SSL related stuff */ + if(acl_user->ssl_type==SSL_TYPE_ANY) + global.append(" REQUIRE SSL",12); + else if(acl_user->ssl_type==SSL_TYPE_X509) + global.append(" REQUIRE X509",13); + else if(acl_user->ssl_type==SSL_TYPE_SPECIFIED) + { + global.append(" REQUIRE ",9); + if(acl_user->x509_issuer) { + if(ssl_options++) + global.append(" AND ",5); + global.append("ISSUER \"",8); + global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); + global.append("\"",1); + } + if(acl_user->x509_subject) { + if(ssl_options++) + global.append(" AND ",5); + global.append("SUBJECT \"",9); + global.append(acl_user->x509_subject,strlen(acl_user->x509_subject)); + global.append("\"",1); } -#endif + if(acl_user->ssl_cipher) { + if(ssl_options++) + global.append(" AND ",5); + global.append("CIPHER \"",8); + global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher)); + global.append("\"",1); + } + } +#endif /* HAVE_OPENSSL */ if (want_access & GRANT_ACL) global.append(" WITH GRANT OPTION",18); thd->packet.length(0); diff --git a/sql/sql_acl.h b/sql/sql_acl.h index cf9696d51e7..e6a39f1b269 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -59,7 +59,7 @@ void acl_reload(void); void acl_free(bool end=0); uint acl_get(const char *host, const char *ip, const char *bin_ip, const char *user, const char *db); -uint acl_getroot(const char *host, const char *ip, const char *user, +uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user, const char *password,const char *scramble,char **priv_user, bool old_ver); bool acl_check_host(const char *host, const char *ip); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ec147c38e9b..6ccb0a6b059 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -56,7 +56,7 @@ enum enum_sql_command { SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_MULTI_DELETE, - SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, + SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER }; enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT, @@ -145,7 +145,8 @@ typedef struct st_lex { char *length,*dec,*change,*name; char *backup_dir; /* For RESTORE/BACKUP */ char* to_log; /* For PURGE MASTER LOGS TO */ - char* ssl_subject,*ssl_issuer,*ssl_chipher; + char* x509_subject,*x509_issuer,*ssl_cipher; + enum SSL_type ssl_type; /* defined in violite.h */ String *wild; sql_exchange *exchange; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 929891da889..e930dd2cfcb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -115,7 +115,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, send_error(net,ER_OUT_OF_RESOURCES); return 1; } - thd->master_access=acl_getroot(thd->host, thd->ip, thd->user, + thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, passwd, thd->scramble, &thd->priv_user, protocol_version == 9 || !(thd->client_capabilities & @@ -433,7 +433,7 @@ check_connections(THD *thd) DBUG_PRINT("info", ("Agreed to change IO layer to SSL") ); /* Do the SSL layering. */ DBUG_PRINT("info", ("IO layer change in progress...")); - sslaccept(ssl_acceptor_fd, net->vio); + sslaccept(ssl_acceptor_fd, net->vio, (long)60L); DBUG_PRINT("info", ("Reading user information over SSL layer")); if ((pkt_len=my_net_read(net)) == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 67713b85720..28d405690bd 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1173,18 +1173,46 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables) net_store_data(&packet2,(uint32) SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context_)); break; + case SHOW_SSL_CTX_SESS_CONNECT_GOOD: + net_store_data(&packet2,(uint32) + SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context_)); + break; case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE: net_store_data(&packet2,(uint32) SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)); break; + case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE: + net_store_data(&packet2,(uint32) + SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context_)); + break; case SHOW_SSL_CTX_SESS_CB_HITS: net_store_data(&packet2,(uint32) SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context_)); break; + case SHOW_SSL_CTX_SESS_HITS: + net_store_data(&packet2,(uint32) + SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context_)); + break; + case SHOW_SSL_CTX_SESS_CACHE_FULL: + net_store_data(&packet2,(uint32) + SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context_)); + break; + case SHOW_SSL_CTX_SESS_MISSES: + net_store_data(&packet2,(uint32) + SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context_)); + break; + case SHOW_SSL_CTX_SESS_TIMEOUTS: + net_store_data(&packet2,(uint32) + SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)); + break; case SHOW_SSL_CTX_SESS_NUMBER: net_store_data(&packet2,(uint32) SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)); break; + case SHOW_SSL_CTX_SESS_CONNECT: + net_store_data(&packet2,(uint32) + SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)); + break; case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE: net_store_data(&packet2,(uint32) SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)); @@ -1246,6 +1274,23 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables) break; case SHOW_SSL_GET_CIPHER: net_store_data(&packet2, thd->net.vio->ssl_ ? SSL_get_cipher(thd->net.vio->ssl_) : ""); + case SHOW_SSL_GET_CIPHER_LIST: + if(thd->net.vio->ssl_) + { + char buf[1024]=""; + for (int i=0; ; i++) + { + const char *p=SSL_get_cipher_list(thd->net.vio->ssl_,i); + if (p == NULL) + break; + if (i != 0) + strcat(buf,":"); + strcat(buf,p); + DBUG_PRINT("info",("cipher to add: %s,%s",p,buf)); + } + net_store_data(&packet2, buf); + } else + net_store_data(&packet2, ""); break; #endif /* HAVE_OPENSSL */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1995c1295f1..27f4d56b3a3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -285,6 +285,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token SERIALIZABLE_SYM %token SESSION_SYM %token SHUTDOWN +%token SSL_SYM %token STARTING %token STATUS_SYM %token STRAIGHT_JOIN @@ -316,6 +317,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token WHERE %token WITH %token WRITE_SYM +%token X509_SYM %token COMPRESSED_SYM %token BIGINT @@ -3265,10 +3267,11 @@ grant: lex->columns.empty(); lex->grant= lex->grant_tot_col=0; lex->select->db=0; - lex->ssl_chipher=lex->ssl_subject=lex->ssl_issuer=0; + lex->ssl_type=SSL_TYPE_NONE; + lex->ssl_cipher=lex->x509_subject=lex->x509_issuer=0; } grant_privileges ON opt_table TO_SYM user_list - grant_option require_clause + require_clause grant_option grant_privileges: grant_privilege_list {} @@ -3302,25 +3305,32 @@ grant_privilege: | FILE_SYM { Lex->grant |= FILE_ACL;} | GRANT OPTION { Lex->grant |= GRANT_ACL;} -require_clause: /* empty */ - | REQUIRE_SYM require_list - - require_list: require_list_element AND require_list | require_list_element - require_list_element: SUBJECT_SYM TEXT_STRING { - Lex->ssl_subject=$2.str; + if (Lex->x509_subject) { + send_error(&Lex->thd->net,ER_GRANT_DUPL_SUBJECT); + YYABORT; + } else + Lex->x509_subject=$2.str; } | ISSUER_SYM TEXT_STRING { - Lex->ssl_issuer=$2.str; + if (Lex->x509_issuer) { + send_error(&Lex->thd->net,ER_GRANT_DUPL_ISSUER); + YYABORT; + } else + Lex->x509_issuer=$2.str; } | CIPHER_SYM TEXT_STRING { - Lex->ssl_chipher=$2.str; + if (Lex->ssl_cipher) { + send_error(&Lex->thd->net,ER_GRANT_DUPL_CIPHER); + YYABORT; + } else + Lex->ssl_cipher=$2.str; } opt_table: @@ -3429,16 +3439,18 @@ column_list_id: require_clause: /* empty */ - | REQUIRE_SYM require_list { /* do magic */} - -require_list: require_list_element AND require_list - { /* do magic */} - | require_list_element {/*do magic*/} - -require_list_element: SUBJECT_SYM TEXT_STRING - | ISSUER TEXT_STRING - | CIPHER TEXT_STRING - + | REQUIRE_SYM require_list + { + Lex->ssl_type=SSL_TYPE_SPECIFIED; + } + | REQUIRE_SYM SSL_SYM + { + Lex->ssl_type=SSL_TYPE_ANY; + } + | REQUIRE_SYM X509_SYM + { + Lex->ssl_type=SSL_TYPE_X509; + } grant_option: /* empty */ {} diff --git a/sql/structs.h b/sql/structs.h index 469d3feea08..2f6f850bc9e 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -134,7 +134,11 @@ enum SHOW_TYPE { SHOW_LONG,SHOW_CHAR,SHOW_INT,SHOW_CHAR_PTR,SHOW_BOOL, ,SHOW_SSL_CTX_SESS_GET_CACHE_SIZE, SHOW_SSL_GET_CIPHER ,SHOW_SSL_GET_DEFAULT_TIMEOUT, SHOW_SSL_GET_VERIFY_MODE ,SHOW_SSL_CTX_GET_VERIFY_MODE, SHOW_SSL_GET_VERIFY_DEPTH - ,SHOW_SSL_CTX_GET_VERIFY_DEPTH + ,SHOW_SSL_CTX_GET_VERIFY_DEPTH, SHOW_SSL_CTX_SESS_CONNECT + ,SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE, SHOW_SSL_CTX_SESS_CONNECT_GOOD + ,SHOW_SSL_CTX_SESS_HITS, SHOW_SSL_CTX_SESS_MISSES + ,SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL + ,SHOW_SSL_GET_CIPHER_LIST #endif /* HAVE_OPENSSL */ }; diff --git a/vio/test-ssl.c b/vio/test-ssl.c index 0ae90f5001f..61d92bb7b84 100644 --- a/vio/test-ssl.c +++ b/vio/test-ssl.c @@ -41,6 +41,7 @@ main( int argc, char* server_key = 0, *server_cert = 0; char* client_key = 0, *client_cert = 0; char* ca_file = 0, *ca_path = 0; + char* cipher=0; int child_pid,sv[2]; struct st_VioSSLAcceptorFd* ssl_acceptor=0; struct st_VioSSLConnectorFd* ssl_connector=0; @@ -74,17 +75,17 @@ main( int argc, if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1) fatal_error("socketpair"); - ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path); - ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path); + ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path, cipher); + ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher); client_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); client_vio->sd = sv[0]; client_vio->vioblocking(client_vio,0); - sslconnect(ssl_connector,client_vio); + sslconnect(ssl_connector,client_vio,60L); server_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); server_vio->sd = sv[1]; server_vio->vioblocking(client_vio,0); - sslaccept(ssl_acceptor,server_vio); + sslaccept(ssl_acceptor,server_vio,60L); printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd); diff --git a/vio/test-sslclient.c b/vio/test-sslclient.c index c19a3589009..b50b0722b17 100644 --- a/vio/test-sslclient.c +++ b/vio/test-sslclient.c @@ -32,7 +32,7 @@ main( int argc __attribute__((unused)), char** argv) { char client_key[] = "../SSL/client-key.pem", client_cert[] = "../SSL/client-cert.pem"; - char ca_file[] = "../SSL/cacert.pem", *ca_path = 0; + char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher=0; struct st_VioSSLConnectorFd* ssl_connector=0; struct sockaddr_in sa; Vio* client_vio=0; @@ -48,7 +48,7 @@ main( int argc __attribute__((unused)), if (ca_path!=0) printf("CApath : %s\n", ca_path); - ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path); + ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher); if(!ssl_connector) { fatal_error("client:new_VioSSLConnectorFd failed"); } @@ -69,7 +69,7 @@ main( int argc __attribute__((unused)), /* ----------------------------------------------- */ /* Now we have TCP conncetion. Start SSL negotiation. */ read(client_vio->sd,xbuf, sizeof(xbuf)); - sslconnect(ssl_connector,client_vio); + sslconnect(ssl_connector,client_vio,60L); err = client_vio->read(client_vio,xbuf, sizeof(xbuf)); if (err<=0) { my_free((gptr)ssl_connector,MYF(0)); diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c index bad141dff17..610a4173875 100644 --- a/vio/test-sslserver.c +++ b/vio/test-sslserver.c @@ -46,7 +46,7 @@ do_ssl_stuff( TH_ARGS* args) /* TCP connection is ready. Do server side SSL. */ err = write(server_vio->sd,(gptr)s, strlen(s)); - sslaccept(args->ssl_acceptor,server_vio); + sslaccept(args->ssl_acceptor,server_vio,60L); err = server_vio->write(server_vio,(gptr)s, strlen(s)); DBUG_VOID_RETURN; } @@ -65,7 +65,8 @@ main( int argc __attribute__((unused)), char server_key[] = "../SSL/server-key.pem", server_cert[] = "../SSL/server-cert.pem"; char ca_file[] = "../SSL/cacert.pem", - *ca_path = 0; + *ca_path = 0, + *cipher = 0; struct st_VioSSLAcceptorFd* ssl_acceptor; pthread_t th; TH_ARGS th_args; @@ -89,7 +90,7 @@ main( int argc __attribute__((unused)), if (ca_path!=0) printf("CApath : %s\n", ca_path); - th_args.ssl_acceptor = ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path); + th_args.ssl_acceptor = ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path,cipher); /* ----------------------------------------------- */ /* Prepare TCP socket for receiving connections */ diff --git a/vio/viosocket.c b/vio/viosocket.c index 667e9b2b118..60272db3171 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -137,7 +137,7 @@ int vio_write(Vio * vio, const gptr buf, int size) } -int vio_blocking(Vio * vio, my_bool set_blocking_mode) +int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode) { int r=0; DBUG_ENTER("vio_blocking"); diff --git a/vio/viossl.c b/vio/viossl.c index c6f70081d18..e80dc0ce807 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -118,8 +118,11 @@ int vio_ssl_read(Vio * vio, gptr buf, int size) #endif /* DBUG_OFF */ r = SSL_read(vio->ssl_, buf, size); #ifndef DBUG_OFF - if ( r< 0) + if ( r<= 0) { + r=SSL_get_error(vio->ssl_, r); + DBUG_PRINT("info",("SSL_get_error returned %d",r)); report_errors(); + } #endif /* DBUG_OFF */ DBUG_PRINT("exit", ("%d", r)); DBUG_RETURN(r); @@ -207,7 +210,6 @@ int vio_ssl_close(Vio * vio) r = SSL_shutdown(vio->ssl_); SSL_free(vio->ssl_); vio->ssl_= 0; - vio->bio_ = 0; } if (shutdown(vio->sd,2)) r= -1; @@ -298,12 +300,11 @@ my_bool vio_ssl_poll_read(Vio *vio,uint timeout) #endif } -void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio) +void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) { - X509* client_cert; + X509* client_cert; char *str; - int i; -// const int blocking = vio_is_blocking(vio); + char buf[1024]; DBUG_ENTER("sslaccept"); DBUG_PRINT("enter", ("sd=%d ptr=%p", vio->sd,ptr)); vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); @@ -316,49 +317,12 @@ void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio) DBUG_VOID_RETURN; } DBUG_PRINT("info", ("ssl_=%p",vio->ssl_)); + SSL_clear(vio->ssl_); vio_blocking(vio, FALSE); + SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout); SSL_set_fd(vio->ssl_,vio->sd); SSL_set_accept_state(vio->ssl_); - - /* FIXME possibly infinite loop */ - while (SSL_is_init_finished(vio->ssl_)) { - DBUG_PRINT("info",("SSL_is_init_finished(vio->ssl_) is not 1")); - if((i=SSL_do_handshake(vio->ssl_))!=SSL_ERROR_NONE) - { - DBUG_PRINT("info",("*** errno %d",errno)); - switch (SSL_get_error(vio->ssl_,i)) - { - case SSL_ERROR_NONE: - DBUG_PRINT("info",("SSL_ERROR_NONE: handshake finished")); - break; - case SSL_ERROR_SSL: - DBUG_PRINT("info",("SSL_ERROR_SSL: SSL protocol error ")); - break; - case SSL_ERROR_WANT_CONNECT: - DBUG_PRINT("info",("SSL_ERROR_WANT_CONNECT:If you are doing non-blocking connects call again when the connection is established")); - break; - case SSL_ERROR_WANT_READ: - DBUG_PRINT("info",("SSL_ERROR_WANT_READ: if non-blocking etc, call again when data is available")); - break; - case SSL_ERROR_WANT_WRITE: - DBUG_PRINT("info",("SSL_ERROR_WANT_WRITE: if non-blocking etc, call again when data is available to write")); - break; - case SSL_ERROR_WANT_X509_LOOKUP: - DBUG_PRINT("info",("SSL_ERROR_WANT_X509_LOOKUP: /* not used yet but could be :-) */")); - break; - case SSL_ERROR_SYSCALL: - DBUG_PRINT("info",("SSL_ERROR_SYSCALL: An error than the error code can be found in errno (%d)",errno)); - break; - case SSL_ERROR_ZERO_RETURN: - DBUG_PRINT("info",("SSL_ERROR_ZERO_RETURN: 0 returned on the read, normally means the socket is closed :-) */")); - break; - default: - DBUG_PRINT("info",("Unknown SSL error returned")); - break; - } - } - usleep(100); - } + SSL_do_handshake(vio->ssl_); vio->open_ = TRUE; #ifndef DBUF_OFF DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" @@ -374,23 +338,28 @@ void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio) DBUG_PRINT("info",("\t issuer: %s", str)); free (str); - /* We could do all sorts of certificate verification stuff here before - * deallocating the certificate. */ - X509_free (client_cert); } else DBUG_PRINT("info",("Client does not have certificate.")); + + str=SSL_get_shared_ciphers(vio->ssl_, buf, sizeof(buf)); + if(str) + { + DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str)); + } + else + { + DBUG_PRINT("info",("no shared ciphers!")); + } + #endif DBUG_VOID_RETURN; } -void sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio) +void sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout) { char *str; -// char s[]="abc"; -int i; X509* server_cert; - const int blocking = vio_is_blocking(vio); DBUG_ENTER("sslconnect"); DBUG_PRINT("enter", ("sd=%d ptr=%p ctx: %p", vio->sd,ptr,ptr->ssl_context_)); vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); @@ -403,50 +372,13 @@ int i; report_errors(); DBUG_VOID_RETURN; } - DBUG_PRINT("info", ("ssl_=%p",vio->ssl_)); + DBUG_PRINT("info",("ssl_=%p",vio->ssl_)); + SSL_clear(vio->ssl_); vio_blocking(vio, FALSE); + SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout); SSL_set_fd (vio->ssl_, vio->sd); SSL_set_connect_state(vio->ssl_); - - /* FIXME possibly infinite loop */ - while (SSL_is_init_finished(vio->ssl_)) { - DBUG_PRINT("info",("SSL_is_init_finished(vio->ssl_) is not 1")); - if((i=SSL_do_handshake(vio->ssl_))!=SSL_ERROR_NONE) - { - DBUG_PRINT("info",("*** errno %d",errno)); - switch (SSL_get_error(vio->ssl_,i)) - { - case SSL_ERROR_NONE: - DBUG_PRINT("info",("SSL_ERROR_NONE: handshake finished")); - break; - case SSL_ERROR_SSL: - DBUG_PRINT("info",("SSL_ERROR_SSL: SSL protocol error ")); - break; - case SSL_ERROR_WANT_CONNECT: - DBUG_PRINT("info",("SSL_ERROR_WANT_CONNECT:If you are doing non-blocking connects call again when the connection is established")); - break; - case SSL_ERROR_WANT_READ: - DBUG_PRINT("info",("SSL_ERROR_WANT_READ: if non-blocking etc, call again when data is available")); - break; - case SSL_ERROR_WANT_WRITE: - DBUG_PRINT("info",("SSL_ERROR_WANT_WRITE: if non-blocking etc, call again when data is available to write")); - break; - case SSL_ERROR_WANT_X509_LOOKUP: - DBUG_PRINT("info",("SSL_ERROR_WANT_X509_LOOKUP: /* not used yet but could be :-) */")); - break; - case SSL_ERROR_SYSCALL: - DBUG_PRINT("info",("SSL_ERROR_SYSCALL: An error than the error code can be found in errno (%d)",errno)); - break; - case SSL_ERROR_ZERO_RETURN: - DBUG_PRINT("info",("SSL_ERROR_ZERO_RETURN: 0 returned on the read, normally means the socket is closed :-) */")); - break; - default: - DBUG_PRINT("info",("Unknown SSL error returned")); - break; - } - } - usleep(100); - } + SSL_do_handshake(vio->ssl_); vio->open_ = TRUE; #ifndef DBUG_OFF DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" @@ -469,9 +401,7 @@ int i; } else DBUG_PRINT("info",("Server does not have certificate.")); #endif - vio_blocking(vio, blocking); DBUG_VOID_RETURN; } - #endif /* HAVE_OPENSSL */ diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 077807726fe..579f37f3dda 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -168,15 +168,17 @@ vio_verify_callback(int ok, X509_STORE_CTX *ctx) struct st_VioSSLConnectorFd* new_VioSSLConnectorFd(const char* key_file, const char* cert_file, const char* ca_file, - const char* ca_path) + const char* ca_path, + const char* cipher) { int verify = SSL_VERIFY_PEER; struct st_VioSSLConnectorFd* ptr; + int result; DH *dh=NULL; DBUG_ENTER("new_VioSSLConnectorFd"); DBUG_PRINT("enter", - ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s", - key_file, cert_file, ca_path, ca_file)); + ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s", + key_file, cert_file, ca_path, ca_file, cipher)); ptr=(struct st_VioSSLConnectorFd*)my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0)); ptr->ssl_context_=0; ptr->ssl_method_=0; @@ -206,8 +208,12 @@ struct st_VioSSLConnectorFd* new_VioSSLConnectorFd(const char* key_file, /* * SSL_CTX_set_options * SSL_CTX_set_info_callback - * SSL_CTX_set_cipher_list */ + if(cipher) + { + result=SSL_CTX_set_cipher_list(ptr->ssl_context_, cipher); + DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + } SSL_CTX_set_verify(ptr->ssl_context_, verify, vio_verify_callback); if (vio_set_cert_stuff(ptr->ssl_context_, cert_file, key_file) == -1) { @@ -231,14 +237,6 @@ struct st_VioSSLConnectorFd* new_VioSSLConnectorFd(const char* key_file, SSL_CTX_set_tmp_dh(ptr->ssl_context_,dh); DH_free(dh); -/*if (cipher != NULL) - if(!SSL_CTX_set_cipher_list(ctx,cipher)) { - BIO_printf(bio_err,"error setting cipher list\n"); - ERR_print_errors(bio_err); - goto end; - } -*/ - DBUG_RETURN(ptr); ctor_failure: DBUG_PRINT("exit", ("there was an error")); @@ -253,18 +251,20 @@ struct st_VioSSLAcceptorFd* new_VioSSLAcceptorFd(const char* key_file, const char* cert_file, const char* ca_file, - const char* ca_path) + const char* ca_path, + const char* cipher) { int verify = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE); struct st_VioSSLAcceptorFd* ptr; + int result; DH *dh=NULL; DBUG_ENTER("new_VioSSLAcceptorFd"); DBUG_PRINT("enter", - ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s", - key_file, cert_file, ca_path, ca_file)); + ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s", + key_file, cert_file, ca_path, ca_file, cipher)); ptr=(struct st_VioSSLAcceptorFd*)my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0)); ptr->ssl_context_=0; @@ -293,12 +293,19 @@ new_VioSSLAcceptorFd(const char* key_file, report_errors(); goto ctor_failure; } + if(cipher) + { + result=SSL_CTX_set_cipher_list(ptr->ssl_context_, cipher); + DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + } /* * SSL_CTX_set_quiet_shutdown(ctx,1); * */ SSL_CTX_sess_set_cache_size(ptr->ssl_context_,128); + + /* DH? */ SSL_CTX_set_verify(ptr->ssl_context_, verify, vio_verify_callback); @@ -328,14 +335,6 @@ new_VioSSLAcceptorFd(const char* key_file, SSL_CTX_set_tmp_dh(ptr->ssl_context_,dh); DH_free(dh); -/*if (cipher != NULL) - if(!SSL_CTX_set_cipher_list(ctx,cipher)) { - BIO_printf(bio_err,"error setting cipher list\n"); - ERR_print_errors(bio_err); - goto end; - } -*/ - DBUG_RETURN(ptr); ctor_failure: DBUG_PRINT("exit", ("there was an error")); |