add ssl_ca to accepted connection url query params

This commit is contained in:
Thomas Constantine Moore 2022-02-18 12:02:17 -05:00
parent 66cb13d3da
commit 9754975e8f
4 changed files with 50 additions and 2 deletions

View File

@ -8,6 +8,8 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/
### Added
* `MysqlConnection::establish` is able to initiate SSL connection while specifying certificate roots. The database URL should contain `ssl_ca` parameter with a path pointing to the certificate roots. [See docs](https://dev.mysql.com/doc/refman/5.7/en/connection-options.html#option_general_ssl-ca) if desired.
* `MysqlConnection::establish` is able to initiate SSL connection. The database URL should contain `ssl_mode` parameter with a value of the [MySQL client command option `--ssl-mode`](https://dev.mysql.com/doc/refman/5.7/en/connection-options.html#option_general_ssl-mode) if desired.
* `Connection` and `SimpleConnection` traits are implemented for a broader range

View File

@ -58,9 +58,10 @@ impl Connection for MysqlConnection {
/// Establishes a new connection to the MySQL database
/// `database_url` may be enhanced by GET parameters
/// `mysql://[user[:password]@]host/database_name[?unix_socket=socket-path&ssl_mode=SSL_MODE*]`
/// `mysql://[user[:password]@]host/database_name[?unix_socket=socket-path&ssl_mode=SSL_MODE*&ssl_ca=/etc/ssl/certs/ca-certificates.crt]`
///
/// * `unix_socket` excepts the path to the unix socket
/// * `unix_socket` expects the path to the unix socket
/// * `ssl_ca` accepts a path to the system's certificate roots
/// * `ssl_mode` expects a value defined for MySQL client command option `--ssl-mode`
/// See <https://dev.mysql.com/doc/refman/5.7/en/connection-options.html#option_general_ssl-mode>
fn establish(database_url: &str) -> ConnectionResult<Self> {

View File

@ -51,6 +51,9 @@ impl RawConnection {
if let Some(ssl_mode) = connection_options.ssl_mode() {
self.set_ssl_mode(ssl_mode)
}
if let Some(ssl_ca) = connection_options.ssl_ca() {
self.set_ssl_ca(ssl_ca)
}
unsafe {
// Make sure you don't use the fake one!
@ -197,6 +200,16 @@ impl RawConnection {
)
};
}
fn set_ssl_ca(&self, ssl_ca: &CStr) {
unsafe {
mysqlclient_sys::mysql_options(
self.0.as_ptr(),
mysqlclient_sys::mysql_option::MYSQL_OPT_SSL_CA,
ssl_ca.as_ptr() as *const std::ffi::c_void,
)
};
}
}
impl Drop for RawConnection {

View File

@ -49,6 +49,7 @@ pub struct ConnectionOptions {
unix_socket: Option<CString>,
client_flags: CapabilityFlags,
ssl_mode: Option<mysql_ssl_mode>,
ssl_ca: Option<CString>,
}
impl ConnectionOptions {
@ -76,6 +77,11 @@ impl ConnectionOptions {
_ => None,
};
let ssl_ca = match query_pairs.get("ssl_ca") {
Some(v) => Some(CString::new(v.as_bytes())?),
_ => None,
};
let ssl_mode = match query_pairs.get("ssl_mode") {
Some(v) => {
let ssl_mode = match v.to_lowercase().as_str() {
@ -123,6 +129,7 @@ impl ConnectionOptions {
unix_socket: unix_socket,
client_flags: client_flags,
ssl_mode: ssl_mode,
ssl_ca: ssl_ca,
})
}
@ -150,6 +157,10 @@ impl ConnectionOptions {
self.unix_socket.as_deref()
}
pub fn ssl_ca(&self) -> Option<&CStr> {
self.ssl_ca.as_deref()
}
pub fn client_flags(&self) -> CapabilityFlags {
self.client_flags
}
@ -293,6 +304,27 @@ fn unix_socket_tests() {
);
}
#[test]
fn ssl_ca_tests() {
let ssl_ca = "/etc/ssl/certs/ca-certificates.crt";
let username = "foo";
let password = "bar";
let db_url = format!(
"mysql://{}:{}@localhost?ssl_ca={}",
username, password, ssl_ca
);
let conn_opts = ConnectionOptions::parse(db_url.as_str()).unwrap();
let cstring = |s| CString::new(s).unwrap();
assert_eq!(None, conn_opts.host);
assert_eq!(None, conn_opts.port);
assert_eq!(cstring(username), conn_opts.user);
assert_eq!(cstring(password), conn_opts.password.unwrap());
assert_eq!(
CString::new(ssl_ca).unwrap(),
conn_opts.ssl_ca.unwrap()
);
}
#[test]
fn ssl_mode() {
let ssl_mode = |url| ConnectionOptions::parse(url).unwrap().ssl_mode();