sijms / go-ora

Pure go oracle client
MIT License
795 stars 176 forks source link

Allow SSL to Verify CN #517

Closed ColinLeeCampbell closed 5 months ago

ColinLeeCampbell commented 7 months ago

Can we allow for the use of SSL_SERVER_CERT_DN and SSL_SERVER_DN_MATCH as it is in a Net Description string?

As far as I know, current SSL only works when setting SSL Verify=False which leads me to believe that the driver is currently only valid for IP addresses. Whereas certificate verification should just be done purely on names plus validating the certificate chain. As a minimum the certificate chain should always be validated.

ColinLeeCampbell commented 7 months ago

there's 4 (or more) aspects to validating a cert: 1) Is it trusted by a certificate authority i.e. validating the chain. 2) Is the CN in the name or the SAN 3) Are the servers in the name or SANs. 4) Is the certificate valid (i.e. from/to dates). 5) Is the certificate revoked.

In Oracle we just use option 1+ 4 ..... and there's a parameter to disable 2 and 3 which we do. Option 5 I don't think Oracle has functionality to maintain a list of revoked certs.

So ideally we would want the driver to allow trusted cert validation only.

sijms commented 6 months ago

hi @ColinLeeCampbell sorry for late the code that use sllVerify

if !connOption.SSLVerify {
    config.InsecureSkipVerify = true
}

filed InsecureSkipVerify controls whether a client verifies the server's certificate chain and host name. I am not expert in TLS but I am using autonomous database with SSLVerify = true and working without error

sijms commented 6 months ago

if I am not wrong you need me to verify cert properties like CN after loading it so I need to add url option for CN and also read that from JDBC but my question now does this verification done by go code during tls connection?

sijms commented 6 months ago

also if JDBC SSL_SERVER_CERT_DN="CN=cname,O=org,L=location" which certificate properties I should use to verify if you make an example code it will help thanks

ColinLeeCampbell commented 6 months ago

I think for starters we can look at parsing out the CN server from the SSL_SERVER_CERT_DN key in the JDBC string and including it as the ServerName value in the tls.Config.

When looking at a desc string such as the following:

(DESCRIPTION =
     (ADDRESS = (PROTOCOL = TCPS) (HOST = example.host.com) (PORT = 1523))
     (CONNECT_DATA =
       (SERVER = DEDICATED)
       (SERVICE_NAME = example.tls.service.com)
     )
    (SECURITY=(SSL_SERVER_CERT_DN="CN= examplecn.host.com,OU=IEO,O=My Org,L=locationk,ST=state,C=country"))
  )

I am able to successfully form a secure connection using this code:

package main

import (
    "crypto/tls"
    "log"
)

func main() {

    tlsConfig := &tls.Config{
        InsecureSkipVerify: false,
        ServerName:         "examplecn.host.com",
    }

    conn, err := tls.Dial("tcp", "example.host.com:1523", tlsConfig)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    log.Println("Successfully connected to the server")
}

Hope this helps!

sijms commented 6 months ago

the code you write is same as code I use in the driver

ColinLeeCampbell commented 6 months ago

Do you parse out the c-name from the JDBC string?

ColinLeeCampbell commented 6 months ago

521 when using a JDBC string with something similar to (SECURITY=(SSL_SERVER_CERT_DN="CN= examplecn.host.com,OU=IEO,O=My Org,L=locationk,ST=state,C=country")) fails to authenticate the cert with the c-name.

sijms commented 6 months ago

did you try this:

options := map[string] string {
    "ssl": "enabled",
    "ssl verify": "true",
    "wallet": "path to wallet directory",
}
connStr := go_ora.BuildJDBC(username, password, jdbc_string, options)
db, err := sql.Open("oracle", connStr)
sijms commented 6 months ago

Do you parse out the c-name from the JDBC string?

until now the answer is no. but if I get CN from JDBC should I compare it to CN in wallet my second question is does go library make this inside tls library?