sni: Install a post-client-hello function to check server name.
[ashd.git] / src / ssl-gnutls.c
index bad5f4a..1ee7306 100644 (file)
@@ -137,8 +137,11 @@ static cookie_io_functions_t iofuns = {
 static int initreq(struct conn *conn, struct hthead *req)
 {
     struct sslconn *ssl = conn->pdata;
+    struct sockaddr_storage sa;
+    socklen_t salen;
     char nmbuf[256];
     
+    headappheader(req, "X-Ash-Address", formathaddress((struct sockaddr *)&ssl->name, sizeof(sa)));
     if(ssl->name.ss_family == AF_INET) {
        headappheader(req, "X-Ash-Address", inet_ntop(AF_INET, &((struct sockaddr_in *)&ssl->name)->sin_addr, nmbuf, sizeof(nmbuf)));
        headappheader(req, "X-Ash-Port", sprintf3("%i", ntohs(((struct sockaddr_in *)&ssl->name)->sin_port)));
@@ -146,6 +149,9 @@ static int initreq(struct conn *conn, struct hthead *req)
        headappheader(req, "X-Ash-Address", inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&ssl->name)->sin6_addr, nmbuf, sizeof(nmbuf)));
        headappheader(req, "X-Ash-Port", sprintf3("%i", ntohs(((struct sockaddr_in6 *)&ssl->name)->sin6_port)));
     }
+    salen = sizeof(sa);
+    if(!getsockname(ssl->fd, (struct sockaddr *)&sa, &salen))
+       headappheader(req, "X-Ash-Server-Address", formathaddress((struct sockaddr *)&sa, sizeof(sa)));
     headappheader(req, "X-Ash-Server-Port", sprintf3("%i", ssl->port->sport));
     headappheader(req, "X-Ash-Protocol", "https");
     return(0);
@@ -162,11 +168,29 @@ static void servessl(struct muth *muth, va_list args)
     int ret;
     FILE *in;
     
+    int setcreds(gnutls_session_t sess)
+    {
+       int i;
+       unsigned int ntype;
+       char nambuf[256];
+       size_t namlen;
+       
+       for(i = 0; 1; i++) {
+           namlen = sizeof(nambuf);
+           if(gnutls_server_name_get(sess, nambuf, &namlen, &ntype, i) != 0)
+               break;
+           if(ntype != GNUTLS_NAME_DNS)
+               continue;
+       }
+       gnutls_credentials_set(sess, GNUTLS_CRD_CERTIFICATE, pd->creds);
+       gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST);
+       return(0);
+    }
+
     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
     gnutls_init(&sess, GNUTLS_SERVER);
     gnutls_set_default_priority(sess);
-    gnutls_credentials_set(sess, GNUTLS_CRD_CERTIFICATE, pd->creds);
-    gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST);
+    gnutls_handshake_set_post_client_hello_function(sess, setcreds);
     gnutls_transport_set_ptr(sess, (gnutls_transport_ptr_t)(intptr_t)fd);
     while((ret = gnutls_handshake(sess)) != 0) {
        if((ret != GNUTLS_E_INTERRUPTED) && (ret != GNUTLS_E_AGAIN))