getssl icon indicating copy to clipboard operation
getssl copied to clipboard

Creating a new config directory may hang

Open rdebath opened this issue 8 years ago • 10 comments
trafficstars

When a domain config file is begin created the script attempts to download the current certificate from port 443 on the named host. If the name is on a host that's currently firewalled and so doesn't respond the script will wait for the default timeout of the openssl s_client command which could be a very long time (it seems to be two minutes by default on my machine). The code that does this is shown below.

It's only purpose seems to be to guess what the SAN list should be in the new file. The only workaround I can think of is to use curl with a short timeout to check the host is there before fetching the certificate as now.

  if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then
    info "domain config already exists $DOMAIN_DIR/getssl.cfg"
  else
    info "creating domain config file in $DOMAIN_DIR/getssl.cfg"
#-----FROM HERE-----
    # if domain has an existing cert, copy from domain and use to create defaults.
    EX_CERT=$(echo \
      | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \
      | openssl x509 2>/dev/null)
    EX_SANS="www.${DOMAIN}"
    if [[ ! -z "${EX_CERT}" ]]; then
      EX_SANS=$(echo "$EX_CERT" \
        | openssl x509 -noout -text 2>/dev/null| grep "Subject Alternative Name" -A2 \
        | grep -Eo "DNS:[a-zA-Z 0-9.-]*" | sed "s@DNS:$DOMAIN@@g" | grep -v '^$' | cut -c 5-)
      EX_SANS=${EX_SANS//$'\n'/','}
    fi
#-----TO HERE-----
    write_domain_template "$DOMAIN_DIR/getssl.cfg"
  fi

rdebath avatar May 05 '17 20:05 rdebath

Or at least add to the message - one doesn't expect creating a file to take very long. How about: info "Contacting ${DOMAIN} to determine other host names" Perhaps trap ^C and add info "If this takes too long, type ^C to skip this step" On ^C, continue with just the primary name.

tlhackque avatar May 15 '17 17:05 tlhackque

I remembered this is bash only, so we could use this fragment. It adds a two second timeout to the openssl command.

(
    openssl s_client -servername $DOMAIN -connect $DOMAIN:443 </dev/null & PID=$!
    sleep 2 & PIDW=$!

    wait -n
    kill -9 "$PID" "$PIDW" 2>/dev/null
)

rdebath avatar May 16 '17 08:05 rdebath

Good idea. That should work. Perhaps '2' should be a variable.

I still think that there should be a message indicating that the server is being contacted; if s_client happens to talk, the user shouldn't be surprised - creating a directory doesn't involve OpenSSL.

tlhackque avatar May 16 '17 13:05 tlhackque

The whole point is for s_client to chatter, part of the output (when it works) is the certificate that's needed to find the SAN list it's after. So the full substitution would be something like this:

EX_CERT=$( {
    openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 </dev/null 2>/dev/null & PID=$!
    sleep 2 & PIDW=$!

    wait -n
    kill -9 "$PID" "$PIDW" 2>/dev/null
} | openssl x509 2>/dev/null)

in place of

    EX_CERT=$(echo \
      | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \
      | openssl x509 2>/dev/null)

rdebath avatar May 16 '17 13:05 rdebath

I got that. I like the solution.

But look at it from the user's POV. The terminal output is:

creating domain config file in ...

If something is making a network connection, it should say so. Both for timing (your original issue), and to avoid surprises (mine). It's astonishing when creating a file materializes data from thin air. And when your firewall pops up with "process foo established TLS connection to ..." Especially in these days of command and control viruses...

The technology is fine. Just don't surprise the user. I suggest something more like this:

info "Contacting ${DOMAIN} to inspect current certificate"
EX_CERT=$( {
    openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 </dev/null 2>/dev/null & PID=$!
    sleep ${CERT_TIMEOUT} & PIDW=$!

    wait -n
    kill -9 "$PID" "$PIDW" 2>/dev/null
} | openssl x509 2>/dev/null)

tlhackque avatar May 16 '17 13:05 tlhackque

I will experiment with this & add it to my PR if it works out.

Thanks for the prod.

tlhackque avatar May 16 '17 15:05 tlhackque

It turns out that wait -n requires bash 4.3. I made the timeout conditional and configurable. Doesn't seem worth trying to figure out another approach.

I've updated my fork, which has an outstanding PR ( #289 ). Since I was in the code, seemed worth doing.

Hopefully it will be accepted. You're welcome to test / review for any bugs.

tlhackque avatar May 17 '17 01:05 tlhackque

Are there more than just the openssl process in the background? I wouldn't expect so; so the "-n" could be dropped from the "wait".

wurtel2 avatar Sep 01 '20 14:09 wurtel2

Is it possible to bypass this check and/or is there an option to already inform the contents of SAN?

paulocoghi avatar Jun 25 '23 17:06 paulocoghi

Hi @paulocoghi It looks like the fix mentioned above was never implemented and the only way to bypass the check is to manually create the configuration file for a new domain. I'll try and fix this tomorrow.

timkimber avatar Jun 25 '23 21:06 timkimber