Blob Blame History Raw
commit 48f0bfc70363ca31c8889ca68759e587bc6d7cbd
Author:     Aris Adamantiadis <aris@0xbadc0de.be>
AuthorDate: Wed Feb 5 21:24:12 2014 +0100
Commit:     Aris Adamantiadis <aris@0xbadc0de.be>
CommitDate: Tue Mar 4 09:54:25 2014 +0100

    security: fix for vulnerability CVE-2014-0017
    
    When accepting a new connection, a forking server based on libssh forks
    and the child process handles the request. The RAND_bytes() function of
    openssl doesn't reset its state after the fork, but simply adds the
    current process id (getpid) to the PRNG state, which is not guaranteed
    to be unique.
    This can cause several children to end up with same PRNG state which is
    a security issue.
    
    Conflicts:
    	src/bind.c
---
 include/libssh/wrapper.h | 1 +
 src/bind.c               | 3 ++-
 src/libcrypto.c          | 9 +++++++++
 src/libgcrypt.c          | 3 +++
 4 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index 8c03497..b8cd4d2 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -44,5 +44,6 @@ int crypt_set_algorithms_server(ssh_session session);
 struct ssh_crypto_struct *crypto_new(void);
 void crypto_free(struct ssh_crypto_struct *crypto);
 
+void ssh_reseed(void);
 
 #endif /* WRAPPER_H_ */
diff --git a/src/bind.c b/src/bind.c
index cc79f8e..cdcdabe 100644
--- a/src/bind.c
+++ b/src/bind.c
@@ -374,7 +374,8 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
   ssh_socket_get_poll_handle_out(session->socket);
   session->dsa_key = dsa;
   session->rsa_key = rsa;
-
+  /* force PRNG to change state in case we fork after ssh_bind_accept */
+  ssh_reseed();
   return SSH_OK;
 }
 
diff --git a/src/libcrypto.c b/src/libcrypto.c
index f43a91e..0932cbe 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/time.h>
 
 #include "libssh/priv.h"
 #include "libssh/session.h"
@@ -38,6 +39,8 @@
 #include <openssl/rsa.h>
 #include <openssl/hmac.h>
 #include <openssl/opensslv.h>
+#include <openssl/rand.h>
+
 #ifdef HAVE_OPENSSL_AES_H
 #define HAS_AES
 #include <openssl/aes.h>
@@ -66,6 +69,12 @@ static int alloc_key(struct crypto_struct *cipher) {
     return 0;
 }
 
+void ssh_reseed(void){
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    RAND_add(&tv, sizeof(tv), 0.0);
+}
+
 SHACTX sha1_init(void) {
   SHACTX c = malloc(sizeof(*c));
   if (c == NULL) {
diff --git a/src/libgcrypt.c b/src/libgcrypt.c
index f8fe96f..9a7ea43 100644
--- a/src/libgcrypt.c
+++ b/src/libgcrypt.c
@@ -41,6 +41,9 @@ static int alloc_key(struct crypto_struct *cipher) {
     return 0;
 }
 
+void ssh_reseed(void){
+	}
+
 SHACTX sha1_init(void) {
   SHACTX ctx = NULL;
   gcry_md_open(&ctx, GCRY_MD_SHA1, 0);