0

I'm trying to read remote website ssl cert with this cli command openssl s_client -connect www.yahoo.no:443 2> /dev/null | openssl x509 -noout -enddate | cut -d = -f 2.

This works fine in cli, but when I execute it in golang:

package main

import (
    "bytes"
    "log"
    "os/exec"
    "time"
)

func main() {
    cmd := exec.Command("echo", "| openssl s_client -connect www.yahoo.com:443 2> /dev/null | openssl x509 -noout -enddate | cut -d = -f 2")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()

    log.Println(out.String())
}

I get nothing in return. How can I run this command in go?

UPDATE:

this is what I've tried but no success

func command() {

    cmd1 := exec.Command("openssl", "s_client", "-connect", "www.yahoo.no:443", "2>", "/dev/null")
    cmd2 := exec.Command("openssl", "x509", "-noout", "-enddate")

    var out bytes.Buffer

    reader, writer := io.Pipe()
    cmd1.Stdout = writer
    cmd2.Stdin = reader

    cmd2.Stdout = &out

    cmd1.Start()
    cmd2.Start()

    cmd1.Wait()
    writer.Close()

    cmd2.Wait()
    reader.Close()

    io.Copy(&out, reader)
    log.Println(out.String())

}

I get empty response.

Lord Zed
  • 750
  • 7
  • 28

1 Answers1

1

Go's standard library contains a perfectly capable TLS implementation, so there is really no reason to launch two hefty openssl processes:

package main

import (
    "crypto/tls"
    "fmt"
    "log"
    "net"
    "time"
)

func main() {
    conn, err := net.Dial("tcp", "example.com:443")
    if err != nil {
            log.Fatal(err)
    }

    client := tls.Client(conn, &tls.Config{
            ServerName: "example.com",
    })
    defer client.Close()

    if err := client.Handshake(); err != nil {
            log.Fatal(err)
    }

    cert := client.ConnectionState().PeerCertificates[0]
    fmt.Println(cert.NotAfter.Format(time.RFC3339)) // Output: 2020-12-02T12:00:00Z
}
Peter
  • 29,454
  • 5
  • 48
  • 60
  • try this url `blogspot.es` it will exit with status 1. I want to be able to use go routines, if ssl not valid I still need to create some sort of output. – Lord Zed Dec 17 '18 at 15:02
  • Set the `ServerName` to one of the valid names (`"accounts.blogdiario.com"`, `"www.accounts.blogdiario.com"`), or, if you must, enable [`InsecureSkipVerify`](https://golang.org/pkg/crypto/tls/#Config). – Peter Dec 17 '18 at 15:46
  • I actually tried `tls` before but I've posted question and it was panicing if on this `blogspot.es` domain. The only part that differs is `client.Handshake()` I had something else. So now it does not panic but return string that I can check for at the end for `not blogspot.es` and will know its invalid (as it really is). – Lord Zed Dec 17 '18 at 21:46
  • How to extract Acceptable client certificate CA Names with this? As peer certificates are only the server certificates? – Калоян Ников Dec 01 '22 at 11:03