All of lore.kernel.org
 help / color / mirror / Atom feed
From: kupcevic@sourceware.org <kupcevic@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] conga ./conga.spec.in.in luci/Makefile luci/si ...
Date: 8 Dec 2006 18:27:36 -0000	[thread overview]
Message-ID: <20061208182736.29493.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/cluster
Module name:	conga
Branch: 	RHEL5
Changes by:	kupcevic at sourceware.org	2006-12-08 18:27:32

Modified files:
	.              : conga.spec.in.in 
	luci           : Makefile 
	luci/site      : Makefile 
	luci/site/luci/Extensions: HelperFunctions.py StorageReport.py 
	                           ricci_communicator.py 
	                           storage_adapters.py 
	luci/storage   : form-macros 
	ricci/ricci    : SSLInstance.cpp 
Added files:
	luci/conga_ssl : Makefile SSLClient.cpp SSLClient.h 
	                 conga_ssl_lib.cpp setup.py 
	luci/site/luci/Extensions: conga_ssl.py 

Log message:
	Improved bz201394: luci doesn't verify ricci's SSL cert against trusted list (part 1 - backend)

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/conga.spec.in.in.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.45.2.8&r2=1.45.2.9
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.20.2.1&r2=1.20.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/conga_ssl/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/conga_ssl/SSLClient.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/conga_ssl/SSLClient.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/conga_ssl/conga_ssl_lib.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/conga_ssl/setup.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.11&r2=1.11.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/conga_ssl.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/HelperFunctions.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.1&r2=1.4.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/StorageReport.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.20.2.1&r2=1.20.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ricci_communicator.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.9.2.6&r2=1.9.2.7
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/storage_adapters.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.7.2.1&r2=1.7.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/storage/form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.17.2.3&r2=1.17.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/ricci/SSLInstance.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.1&r2=1.5.2.2

--- conga/conga.spec.in.in	2006/11/29 22:33:50	1.45.2.8
+++ conga/conga.spec.in.in	2006/12/08 18:27:31	1.45.2.9
@@ -126,10 +126,11 @@
 				%{_sbindir}/luci_admin
 				%{_docdir}/luci-%{version}/
 %defattr(-,luci,luci)
+				%{_localstatedir}/lib/luci
+				%{_libdir}/luci/ssl
 %if "%{include_zope_and_plone}" == "yes"
-				%{_libdir}/luci/
+				%{_libdir}/luci/zope
 %endif
-				%{_localstatedir}/lib/luci
 
 %pre -n luci
 if ! /bin/grep luci\:x /etc/group 2>&1 >/dev/null; then
@@ -283,14 +284,14 @@
 
 %changelog
 
-* day month date 2006 Stanko Kupcevic <kupcevic@redhat.com> 0.8-26
+* Fri Dec 08 2006 Stanko Kupcevic <kupcevic@redhat.com> 0.8-26
 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 XXXXXXXXXXXXXXXXXXX UPDATE NOT RELEASED YET XXXXXXXXXXXXXXXXXXX
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 
 - luci storage: fix bytes->TB conversion
-
+- Improved bz201394: luci doesn't verify ricci's SSL cert against trusted list (part 1 - backend)
 
 
 * Thu Nov 16 2006 Stanko Kupcevic <kupcevic@redhat.com> 0.8-25
--- conga/luci/Makefile	2006/11/16 19:34:52	1.20.2.1
+++ conga/luci/Makefile	2006/12/08 18:27:32	1.20.2.2
@@ -18,6 +18,7 @@
 
 luci:
 	make -C site
+	make -C conga_ssl
 	make -C utils
 	make -C init.d
 	make -C sysconfig
@@ -46,6 +47,7 @@
 
 	install -d -m 700 ${DESTDIR}/var/lib/luci
 	make -C site install
+	make -C conga_ssl install
 	make -C utils install
 	make -C init.d install
 	make -C sysconfig install
/cvs/cluster/conga/luci/conga_ssl/Makefile,v  -->  standard output
revision 1.1.2.1
--- conga/luci/conga_ssl/Makefile
+++ -	2006-12-08 18:27:33.432667000 +0000
@@ -0,0 +1,21 @@
+
+include ../../make/version.in
+include ../make/defines.mk
+
+
+.PHONY: build
+
+build:
+	python setup.py build
+
+clean:
+	rm -rf build
+	rm -rf ricci
+
+install:
+	install -d ${libdir}/luci
+	install -d ${libdir}/luci/ssl
+	install -m 644 build/lib*/conga_ssl_lib.so ${libdir}/luci/ssl
+
+rebuild: clean build
+
/cvs/cluster/conga/luci/conga_ssl/SSLClient.cpp,v  -->  standard output
revision 1.1.2.1
--- conga/luci/conga_ssl/SSLClient.cpp
+++ -	2006-12-08 18:27:33.797469000 +0000
@@ -0,0 +1,552 @@
+/*
+  Copyright Red Hat, Inc. 2005
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+  MA 02139, USA.
+*/
+/*
+ * Author: Stanko Kupcevic <kupcevic@redhat.com>
+ */
+
+
+#include "SSLClient.h"
+#include "Mutex.h"
+#include "Time.h"
+#include "Random.h"
+#include "utils.h"
+#include "File.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <list>
+#include <set>
+
+
+
+#include <openssl/err.h>
+
+
+
+using namespace std;
+
+
+
+static Mutex global_lock;
+static bool ssl_inited = false;
+static SSL_CTX* ctx = 0;
+static vector<counting_auto_ptr<Mutex> > ssl_locks;
+
+class file_cert
+{
+public:
+  file_cert(const String& file, const String& cert) :
+    file(file),
+    cert(cert) {}
+  
+  String file;
+  String cert;
+};
+static list<file_cert> trusted_certs;
+
+
+
+static int 
+verify_cert_callback(int preverify_ok, X509_STORE_CTX *ctx)
+{
+  return 1;
+}
+static void 
+load_peer_certs()
+{
+  MutexLocker l(global_lock);
+  
+  // load trusted CAs
+  if (!SSL_CTX_load_verify_locations(ctx, 
+				     _trust_CAs, 
+				     NULL))
+    cout << "failed to load trusted CAs" << endl;
+  
+  STACK_OF(X509_NAME) *cert_names = 
+    SSL_load_client_CA_file(_trust_CAs);
+  if (cert_names)
+    SSL_CTX_set_client_CA_list(ctx, cert_names);
+  else
+    cout << "failed to load trusted CAs" << endl;
+  
+  // load saved certs
+  
+  set<String> files;
+  String dir_path(_certs_store_dir);
+  DIR* d = opendir(dir_path.c_str());
+  if (d == NULL)
+    throw String("unable to open directory ") + dir_path;
+  try {
+    while (true) {
+      struct dirent* ent = readdir(d);
+      if (ent == NULL) {
+	closedir(d);
+	break;
+      }
+      String kid_path = ent->d_name;
+      if (kid_path == "." || kid_path == "..")
+	continue;
+      kid_path = dir_path + "/" + kid_path;
+      struct stat st;
+      if (stat(kid_path.c_str(), &st))
+	continue;
+      if (S_ISREG(st.st_mode))
+	files.insert(kid_path);
+    }
+  } catch ( ... ) {
+    closedir(d);
+    throw;
+  }
+  
+  trusted_certs.clear();
+  
+  for (set<String>::const_iterator iter = files.begin();
+       iter != files.end();
+       iter++) {
+    try {
+      String cert(File::open(*iter).read());
+      if (cert.size() && cert.size() < 10 * 1024)
+	trusted_certs.push_back(file_cert(*iter, cert));
+    } catch ( ... ) {}
+  }
+}
+static void 
+ssl_mutex_callback(int mode, 
+		   int n, 
+		   const char *file, 
+		   int line)
+{
+  if (mode & CRYPTO_LOCK)
+    ssl_locks[n]->lock();
+  else
+    ssl_locks[n]->unlock();
+}
+static pthread_t
+ssl_id_callback(void)
+{
+  return pthread_self();
+}
+
+
+
+
+// ##### class SSLClient #####
+
+
+SSLClient::SSLClient(ClientSocket sock) :
+  _sock(sock), 
+  _connected(false)
+{
+  {
+    MutexLocker l(global_lock);
+    if (!ssl_inited) {
+      // init library
+      
+      SSL_library_init();
+      // TODO: random number generator,
+      // not on systems with /dev/urandom (eg. Linux)
+      
+      // thread support
+      ssl_locks.clear();
+      for (int i=0; i<CRYPTO_num_locks()+1; i++)
+	ssl_locks.push_back(counting_auto_ptr<Mutex>(new Mutex()));
+      CRYPTO_set_locking_callback(ssl_mutex_callback);
+      CRYPTO_set_id_callback(ssl_id_callback);
+      
+      // create context
+      if (!ctx)
+	ctx = SSL_CTX_new(SSLv23_client_method());
+      if (!ctx)
+	throw String("SSL context creation failed");
+      // set verify_callback() function
+      SSL_CTX_set_verify(ctx, 
+			 SSL_VERIFY_PEER, 
+			 verify_cert_callback);
+      // set mode
+      SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
+      SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+      
+      // load key
+      if (!SSL_CTX_use_PrivateKey_file(ctx, 
+				       _privkey, 
+				       SSL_FILETYPE_PEM))
+	throw String("error importing cert key file");
+      // load cert
+      if (!SSL_CTX_use_certificate_file(ctx, 
+					_pubkey, 
+					SSL_FILETYPE_PEM))
+	throw String("error importing cert file");
+      // load peers' certs
+      load_peer_certs();
+      
+      ssl_inited = true;
+    }
+    
+    // create SSL object, giving it context
+    _ssl = SSL_new(ctx);
+    if (!_ssl)
+      throw String("creation of ssl object failed");
+  }
+  
+  // make socket non-blocking
+  try {
+    _sock.nonblocking(true);
+  } catch ( ... ) {
+    SSL_free(_ssl);
+    throw;
+  }
+  
+  // assign fd to _ssl
+  if (!SSL_set_fd(_ssl, _sock.get_sock())) {
+    SSL_free(_ssl);
+    throw String("fd assignment to ssl_obj failed");
+  }
+}
+
+SSLClient::~SSLClient()
+{
+  SSL_shutdown(_ssl);
+  SSL_free(_ssl);
+}
+
+
+bool 
+SSLClient::connect(unsigned int timeout)
+{
+  if (_connected)
+    return _connected;
+  
+  unsigned int beg = time_mil();
+  while (time_mil() < beg + timeout) {
+    int ret = SSL_connect(_ssl);
+    if (ret == 1) {
+      _connected = true;
+      break;
+    } else {
+      bool want_read, want_write;
+      check_error(ret, want_read, want_write);
+      socket().ready(want_read, want_write, 250);
+    }
+  }
+  
+  return _connected;
+}
+
+String 
+SSLClient::send(const String& msg,
+		unsigned int timeout)
+{
+  if (!_connected)
+    throw String("cannot send, yet: SSL connection not connected");
+  
+  if (msg.empty())
+    return msg;
+  
+  unsigned int beg = time_mil();
+  while (time_mil() < beg + timeout) {
+    int ret = SSL_write(_ssl, msg.c_str(), msg.size());
+    if (ret > 0) {
+      return msg.substr(ret);
+    } else {
+      bool want_read, want_write;
+      check_error(ret, want_read, want_write);
+      socket().ready(want_read, want_write, 250);
+    }
+  }
+  
+  return msg;
+}
+
+String 
+SSLClient::recv(unsigned int timeout)
+{
+  if (!_connected)
+    throw String("cannot receive, yet: SSL connection not connected");
+  
+  char buff[1024];
+  
+  unsigned int beg = time_mil();
+  while (time_mil() < beg + timeout) {
+    int ret = SSL_read(_ssl, buff, sizeof(buff));
+    if (ret > 0) {
+      String data(buff, ret);
+      shred(buff, sizeof(buff));
+      return data;
+    } else {
+      bool want_read, want_write;
+      check_error(ret, want_read, want_write);
+      socket().ready(want_read, want_write, 250);
+    }
+  }
+  
+  return "";
+}
+
+bool 
+SSLClient::peer_has_cert()
+{
+  if (!_connected)
+    throw String("cannot determine if peer has certificate: SSL connection not connected");
+  
+  if (_cert_pem.size())
+    return true;
+  
+  X509* cert = SSL_get_peer_certificate(_ssl);
+  if (!cert) 
+    return false;
+  
+  // load cert into _cert_pem
+  FILE* f = NULL;
+  try {
+    if (!(f = tmpfile()))
+      throw String("unable to open temp file");
+    if (!PEM_write_X509(f, cert))
+      throw String("unable to write cert to tmp file");
+    X509_free(cert); cert = NULL;
+    
+    // read cert
+    rewind(f);
+    while (true) {
+      char buff[1024];
+      size_t i = fread(buff, sizeof(char), sizeof(buff), f);
+      _cert_pem.append(buff, i);
+      if (i == 0) {
+	if (feof(f))
+	  break;
+	else
+	  throw String("error while reading certificate from temp file");
+      }
+    }
+    fclose(f); f = NULL;
+  } catch ( ... ) {  
+    if (cert)
+      X509_free(cert);
+    if (f)
+      fclose(f);
+    _cert_pem.clear();
+    throw;
+  }
+  
+  return true;
+}
+
+String 
+SSLClient::peer_cert_fingerprint(String& digest)
+{
+  if (!peer_has_cert())
+    throw String("peer did not present cert");
+  
+  String f_name("/tmp/luci_tmp_XXXXXX");
+  int fd = -1;
+  char* buff = new char[f_name.size() + 1];
+  try {
+    // pick a filename
+    strcpy(buff, f_name.c_str());
+    if ((fd = mkstemp(buff)) == -1)
+      throw String("unable to generate random file");
+    f_name = buff;
+    delete[] buff; buff = 0;
+    while (close(fd) && errno == EINTR) ; fd = -1;
+    
+    File f = File::open(f_name, true);
+    f.replace(_cert_pem);
+    
+    String out, err;
+    int status;
+    vector<String> args;
+    args.push_back("x509");
+    args.push_back("-sha1");
+    args.push_back("-in");
+    args.push_back(f_name);
+    args.push_back("-noout");
+    args.push_back("-fingerprint");
+    if (utils::execute("/usr/bin/openssl", 
+		       args,
+		       out,
+		       err,
+		       status,
+		       false))
+      throw command_not_found_error_msg("/usr/bin/openssl");
+    if (status)
+      throw String("openssl command failed");
+    unlink(f_name.c_str());
+    
+    vector<String> words(utils::split(utils::strip(out)));
+    if (words.size() != 2)
+      throw String("error parsing fingerprint");
+    
+    String finger(words[1]);
+    String::size_type idx = finger.find('=');
+    if (idx == finger.npos ||
+	idx+1 == finger.size())
+      throw String("error parsing fingerprint");
+    
+    digest = words[0];
+    return finger.substr(idx+1);
+  } catch ( ... ) {
+    delete[] buff;
+    if (fd != -1)
+      while (close(fd) && errno == EINTR)
+	;
+    unlink(f_name.c_str());
+    throw;
+  }
+}
+
+bool 
+SSLClient::peer_cert_trusted()
+{
+  // signed by trusted CAs?
+  X509* cert = SSL_get_peer_certificate(_ssl);
+  if (!cert) 
+    return false;
+  X509_free(cert);
+  if (SSL_get_verify_result(_ssl) == X509_V_OK)
+    return true;
+  
+  // cert present among saved certs?
+  peer_has_cert();  // make sure cert is saved in _cert_pem
+  MutexLocker l(global_lock);
+  for (list<file_cert>::const_iterator iter = trusted_certs.begin();
+       iter != trusted_certs.end();
+       iter++)
+    if (iter->cert == _cert_pem)
+      return true;
+  return false;
+}
+
+bool 
+SSLClient::trust_peer_cert()
+{
+  MutexLocker l(global_lock);
+  
+  if (peer_cert_trusted())
+    return true;
+  
+  if (!peer_has_cert())
+    throw String("peer did not present cert");
+  
+  String f_name(_certs_store_dir);
+  f_name += "/peer_cert_XXXXXX";
+  int fd = -1;
+  char* buff = new char[f_name.size() + 1];
+  try {
+    // pick a filename
+    strcpy(buff, f_name.c_str());
+    if ((fd = mkstemp(buff)) == -1)
+      throw String("unable to generate random file");
+    f_name = buff;
+    delete[] buff; buff = 0;
+    
+    String data(_cert_pem);
+    while (data.size()) {
+      ssize_t i = write(fd, data.c_str(), data.size());
+      if (i == -1) {
+	if (errno != EINTR)
+	  throw String("error writing certificate");
+      } else
+	data = data.substr(i);
+    }
+    while (close(fd) && errno == EINTR)
+      ;
+  } catch ( ... ) {
+    delete[] buff;
+    if (fd != -1)
+      while (close(fd) && errno == EINTR)
+	;
+    unlink(f_name.c_str());
+    return false;
+  }
+  
+  load_peer_certs();
+  
+  return true;
+}
+
+bool 
+SSLClient::untrust_peer_cert()
+{
+  MutexLocker l(global_lock);
+  
+  if (!peer_has_cert())
+    throw String("peer did not present cert");
+  
+  for (list<file_cert>::const_iterator iter = trusted_certs.begin();
+       iter != trusted_certs.end();
+       iter++)
+    if (iter->cert == _cert_pem)
+      unlink(iter->file.c_str());
+  
+  load_peer_certs();
+  return true;
+}
+
+ClientSocket&
+SSLClient::socket()
+{
+  return _sock;
+}
+
+void
+SSLClient::check_error(int value, bool& want_read, bool& want_write)
+{
+  want_read = want_write = false;
+  
+  String e;
+  switch (SSL_get_error(_ssl, value)) {
+  case SSL_ERROR_NONE:
+    e = "SSL_ERROR_NONE";
+    break;
+  case SSL_ERROR_ZERO_RETURN:
+    e = "SSL_ERROR_ZERO_RETURN";
+    break;
+  case SSL_ERROR_WANT_READ:
+    want_read = true;
+    return;
+  case SSL_ERROR_WANT_WRITE:
+    want_write = true;
+    return;
+  case SSL_ERROR_WANT_CONNECT:
+    e = "SSL_ERROR_WANT_CONNECT";
+    break;
+  case SSL_ERROR_WANT_ACCEPT:
+    e = "SSL_ERROR_WANT_ACCEPT";
+    break;
+  case SSL_ERROR_WANT_X509_LOOKUP:
+    e = "SSL_ERROR_WANT_X509_LOOKUP";
+    break;
+  case SSL_ERROR_SYSCALL:
+    e = "SSL_ERROR_SYSCALL";
+    break;
+  case SSL_ERROR_SSL:
+    e = "SSL_ERROR_SSL";
+    break;
+  }
+  
+  //FILE* f = fopen("/tmp/ssl_error_que", "a");
+  //ERR_print_errors_fp(f);
+  //fclose(f);
+  
+  throw String("SSL error: ") + e;
+}
/cvs/cluster/conga/luci/conga_ssl/SSLClient.h,v  -->  standard output
revision 1.1.2.1
--- conga/luci/conga_ssl/SSLClient.h
+++ -	2006-12-08 18:27:34.372060000 +0000
@@ -0,0 +1,80 @@
+/*
+  Copyright Red Hat, Inc. 2005
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+  MA 02139, USA.
+*/
+/*
+ * Author: Stanko Kupcevic <kupcevic@redhat.com>
+ */
+
+
+#ifndef SSLClient_h
+#define SSLClient_h
+
+#include "Socket.h"
+
+#include "String.h"
+#include <openssl/ssl.h>
+
+
+#define _privkey          "/var/lib/luci/var/certs/privkey.pem"
+#define _pubkey           "/var/lib/luci/var/certs/cacert.pem"
+#define _trust_CAs        "/var/lib/luci/var/certs/trust_CAs"
+#define _certs_store_dir  "/var/lib/luci/var/certs/peers"
+
+
+// NOT THREAD SAFE
+
+
+class SSLClient
+{
+ public:
+  SSLClient(ClientSocket sock);
+  virtual ~SSLClient();
+  
+  bool connect(unsigned int timeout);
+  
+  String send(const String& msg, unsigned int timeout);
+  String recv(unsigned int timeout);
+  
+  
+  bool peer_has_cert();
+  bool peer_cert_trusted();  // return true if peer's cert is trusted (either thru CA chain, or saved in cert_store)
+  
+  String peer_cert_fingerprint(String& digest);
+  
+  bool trust_peer_cert();
+  bool untrust_peer_cert();  // remove peer's cert from cert_store
+  
+  ClientSocket& socket();
+  
+ private:
+  SSLClient(const SSLClient&);
+  SSLClient operator=(const SSLClient&);
+  
+  ClientSocket _sock;
+  SSL*         _ssl;
+  String  _cert_pem;
+  
+  bool _connected;
+  
+  void check_error(int value, bool& want_read, bool& want_write);
+  
+  
+};  // class SSLClient
+
+
+#endif  // SSLClient_h
/cvs/cluster/conga/luci/conga_ssl/conga_ssl_lib.cpp,v  -->  standard output
revision 1.1.2.1
--- conga/luci/conga_ssl/conga_ssl_lib.cpp
+++ -	2006-12-08 18:27:34.717960000 +0000
@@ -0,0 +1,374 @@
+/*
+  Copyright Red Hat, Inc. 2006
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+  MA 02139, USA.
+*/
+/*
+ * Author: Stanko Kupcevic <kupcevic@redhat.com>
+ */
+
+
+#include <Python.h>
+
+#include <Socket.h>
+#include <String.h>
+#include <Time.h>
+#include <XML.h>
+#include <utils.h>
+
+#include "SSLClient.h"
+
+#include <map>
+
+using namespace std;
+
+
+class PythonThreadsAllower
+{
+public:
+  PythonThreadsAllower()
+  { _save = PyEval_SaveThread(); }
+  
+  ~PythonThreadsAllower()
+  { PyEval_RestoreThread(_save); }
+  
+private:
+  PyThreadState *_save;
+};
+
+
+
+static Mutex mutex;
+static map<int, counting_auto_ptr<SSLClient> > ssls;
+
+
+
+static PyObject *
+conga_ssl_lib_connect(PyObject *self, PyObject *args);
+static PyObject *
+conga_ssl_lib_disconnect(PyObject *self, PyObject *args);
+
+static PyObject *
+conga_ssl_lib_send(PyObject *self, PyObject *args);
+static PyObject *
+conga_ssl_lib_recv(PyObject *self, PyObject *args);
+
+static PyObject *
+conga_ssl_lib_trust(PyObject *self, PyObject *args);
+static PyObject *
+conga_ssl_lib_trusted(PyObject *self, PyObject *args);
+static PyObject *
+conga_ssl_lib_untrust(PyObject *self, PyObject *args);
+
+static PyObject *
+conga_ssl_lib_peer_fingerprint(PyObject *self, PyObject *args);
+
+
+
+static PyMethodDef SSLMethods[] = {
+  {"connect", conga_ssl_lib_connect, METH_VARARGS,
+   "doc"},
+  {"disconnect", conga_ssl_lib_disconnect, METH_VARARGS,
+   "doc"},
+  {"send", conga_ssl_lib_send, METH_VARARGS,
+   "doc"},
+  {"recv", conga_ssl_lib_recv, METH_VARARGS,
+   "doc"},
+  {"trust", conga_ssl_lib_trust, METH_VARARGS,
+   "doc"},
+  {"trusted", conga_ssl_lib_trusted, METH_VARARGS,
+   "doc"},
+  {"untrust", conga_ssl_lib_untrust, METH_VARARGS,
+   "doc"},
+  {"peer_fingerprint", conga_ssl_lib_peer_fingerprint, METH_VARARGS,
+   "doc"},
+  {NULL, NULL, 0, NULL}        /* Sentinel */
+};
+
+
+
+PyMODINIT_FUNC
+initconga_ssl_lib(void)
+{
+  (void) Py_InitModule("conga_ssl_lib", SSLMethods);
+}
+
+
+
+PyObject *
+conga_ssl_lib_connect(PyObject *self, PyObject *args)
+{
+  const char* hostname;
+  int port;
+  int timeout;
+  if (!PyArg_ParseTuple(args, 
+			"sii", 
+			&hostname,
+			&port,
+			&timeout))
+    return NULL;
+  if (port < 1 || port > 65535) {
+    PyErr_SetString(PyExc_ValueError, "invalid port number");
+    return NULL;
+  }
+  if (timeout < 0) {
+    PyErr_SetString(PyExc_ValueError, "negative timeout");
+    return NULL;
+  }
+  
+  try {
+    counting_auto_ptr<SSLClient> ss;
+    {
+      PythonThreadsAllower all;
+      ClientSocket sock(hostname, port);
+      ss = counting_auto_ptr<SSLClient>(new SSLClient(sock));
+      ss->connect(timeout * 1000);
+    }
+    int id = (int) ss->socket().get_sock();
+    ssls[id] = ss;
+    return Py_BuildValue("i", id);
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
+
+PyObject *
+conga_ssl_lib_disconnect(PyObject *self, PyObject *args)
+{
+  int id;
+  if (!PyArg_ParseTuple(args, "i", &id))
+    return NULL;
+  
+  try {
+    map<int, counting_auto_ptr<SSLClient> >::iterator iter = 
+      ssls.find(id);
+    if (iter != ssls.end())
+      ssls.erase(iter);
+    Py_INCREF(Py_None);
+    return Py_None;
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
+
+PyObject *
+conga_ssl_lib_send(PyObject *self, PyObject *args)
+{
+  int id;
+  const char* msg;
+  int timeout;
+  if (!PyArg_ParseTuple(args, "isi", &id, &msg, &timeout))
+    return NULL;
+  if (timeout < 0) {
+    PyErr_SetString(PyExc_ValueError, "negative timeout");
+    return NULL;
+  }
+  
+  try {
+    map<int, counting_auto_ptr<SSLClient> >::const_iterator iter = 
+      ssls.find(id);
+    if (iter == ssls.end())
+      throw String("SSL connection closed");
+    
+    {
+      PythonThreadsAllower all;
+      int beg = int(time_sec());
+      String out(msg);
+      while (true) {
+	if (int(time_sec()) > beg + timeout)
+	  throw String("timeout");
+	else
+	  if ((out = iter->second->send(out, 400)).empty())
+	    break;
+      }
+    }
+    
+    Py_INCREF(Py_None);
+    return Py_None;
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
+
+PyObject *
+conga_ssl_lib_recv(PyObject *self, PyObject *args)
+{
+  int id, timeout;
+  if (!PyArg_ParseTuple(args, "ii", &id, &timeout))
+    return NULL;
+  if (timeout < 0) {
+    PyErr_SetString(PyExc_ValueError, "negative timeout");
+    return NULL;
+  }
+  
+  try {
+    map<int, counting_auto_ptr<SSLClient> >::const_iterator iter = 
+      ssls.find(id);
+    if (iter == ssls.end())
+      throw String("SSL connection closed");
+    
+    String resp;
+    {
+      PythonThreadsAllower all;
+      int beg = int(time_sec());
+      String xml_in;
+      while (true) {
+	if (int(time_sec()) > beg + timeout)
+	  throw String("timeout");
+	else
+	  xml_in += iter->second->recv(400);
+	try {
+	  parseXML(xml_in);
+	  resp = xml_in;
+	  break;
+	} catch ( ... ) {}
+      }
+    }
+    
+    PyObject* resp_p = Py_BuildValue("s", resp.c_str());
+    return resp_p;
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
+
+PyObject *
+conga_ssl_lib_trust(PyObject *self, PyObject *args)
+{
+  int id;
+  if (!PyArg_ParseTuple(args, "i", &id))
+    return NULL;
+  
+  try {
+    map<int, counting_auto_ptr<SSLClient> >::const_iterator iter = 
+      ssls.find(id);
+    if (iter == ssls.end())
+      throw String("SSL connection closed");
+    
+    bool resp;
+    {
+      PythonThreadsAllower all;
+      resp = iter->second->trust_peer_cert();
+    }
+    
+    PyObject* resp_p = Py_BuildValue("i", (resp)?1:0);
+    return resp_p;
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
+
+PyObject *
+conga_ssl_lib_trusted(PyObject *self, PyObject *args)
+{
+  int id;
+  if (!PyArg_ParseTuple(args, "i", &id))
+    return NULL;
+  
+  try {
+    map<int, counting_auto_ptr<SSLClient> >::const_iterator iter = 
+      ssls.find(id);
+    if (iter == ssls.end())
+      throw String("SSL connection closed");
+    
+    bool resp;
+    {
+      PythonThreadsAllower all;
+      resp = iter->second->peer_cert_trusted();
+    }
+    
+    PyObject* resp_p = Py_BuildValue("i", (resp)?1:0);
+    return resp_p;
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
+
+PyObject *
+conga_ssl_lib_untrust(PyObject *self, PyObject *args)
+{
+  int id;
+  if (!PyArg_ParseTuple(args, "i", &id))
+    return NULL;
+  
+  try {
+    map<int, counting_auto_ptr<SSLClient> >::const_iterator iter = 
+      ssls.find(id);
+    if (iter == ssls.end())
+      throw String("SSL connection closed");
+    
+    bool resp;
+    {
+      PythonThreadsAllower all;
+      resp = iter->second->untrust_peer_cert();
+    }
+    
+    PyObject* resp_p = Py_BuildValue("i", (resp)?1:0);
+    return resp_p;
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
+
+PyObject *
+conga_ssl_lib_peer_fingerprint(PyObject *self, PyObject *args)
+{
+  int id;
+  if (!PyArg_ParseTuple(args, "i", &id))
+    return NULL;
+  
+  try {
+    map<int, counting_auto_ptr<SSLClient> >::const_iterator iter = 
+      ssls.find(id);
+    if (iter == ssls.end())
+      throw String("SSL connection closed");
+    
+    String finger, digest;
+    {
+      PythonThreadsAllower all;
+      finger = iter->second->peer_cert_fingerprint(digest);
+    }
+    
+    PyObject* resp_p = Py_BuildValue("(ss)", digest.c_str(), finger.c_str());
+    return resp_p;
+  } catch (String e) {
+    PyErr_SetString(PyExc_Exception, e.c_str());
+  } catch ( ... ) {
+    PyErr_SetString(PyExc_Exception, "unknown");
+  }
+  return NULL;
+}
/cvs/cluster/conga/luci/conga_ssl/setup.py,v  -->  standard output
revision 1.1.2.1
--- conga/luci/conga_ssl/setup.py
+++ -	2006-12-08 18:27:35.171396000 +0000
@@ -0,0 +1,37 @@
+
+from distutils.core import setup, Extension
+
+
+module1 = Extension('conga_ssl_lib',
+                    define_macros = [('MAJOR_VERSION', '0'),
+                                     ('MINOR_VERSION', '8')],
+                    include_dirs = ['../../ricci/include',
+                                    '/usr/include/libxml2'],
+                    libraries = ['ssl', 'xml2'],
+                    #library_dirs = ['/usr/local/lib'],
+                    sources = ['conga_ssl_lib.cpp', 
+                               'SSLClient.cpp', 
+                               '../../ricci/common/ClientSocket.cpp', 
+                               '../../ricci/common/Socket.cpp', 
+                               '../../ricci/common/Logger.cpp', 
+                               '../../ricci/common/Time.cpp', 
+                               '../../ricci/common/File.cpp', 
+                               '../../ricci/common/XML.cpp', 
+                               '../../ricci/common/utils.cpp', 
+                               '../../ricci/common/executils.cpp'])
+
+
+
+setup (name = 'conga_ssl_lib',
+       version = '0.8',
+       description = 'SSL Python bindings for Conga', 
+       author = 'Stanko Kupcevic', 
+       author_email = 'kupcevic at redhat.com',
+       copyright = 'Red Hat, Inc.',
+       license = 'GPL', 
+       url = 'http://www.sourceware.org/cluster/conga',
+       long_description = '''
+       conga_ssl_lib
+       ''',
+       ext_modules = [module1])
+
--- conga/luci/site/Makefile	2006/08/24 14:38:28	1.11
+++ conga/luci/site/Makefile	2006/12/08 18:27:32	1.11.2.1
@@ -82,6 +82,7 @@
 	install -d ${DESTDIR}/var/lib/luci/var/pts
 #	install -m 644 `find luci/var/pts -maxdepth 1 -type f | grep .mo | grep -v \~ | grep -v \#` ${DESTDIR}/var/lib/luci/var/pts
 	install -d ${DESTDIR}/var/lib/luci/var/certs
+	install -d ${DESTDIR}/var/lib/luci/var/certs/peers
 	install -m 644 luci/var/certs/cacert.config ${DESTDIR}/var/lib/luci/var/certs
 	install -d ${DESTDIR}/var/lib/luci/var/stunnel
 
/cvs/cluster/conga/luci/site/luci/Extensions/conga_ssl.py,v  -->  standard output
revision 1.1.2.1
--- conga/luci/site/luci/Extensions/conga_ssl.py
+++ -	2006-12-08 18:27:35.466686000 +0000
@@ -0,0 +1,48 @@
+
+
+import sys
+sys.path.append('/usr/lib/luci/ssl')
+sys.path.append('/usr/lib64/luci/ssl')
+import conga_ssl_lib
+sys.path.remove('/usr/lib/luci/ssl')
+sys.path.remove('/usr/lib64/luci/ssl')
+
+
+
+# timeouts are in seconds (int)
+
+
+class SSLSocket:
+    
+    def __init__(self,
+                 hostname,
+                 port,
+                 timeout):
+        self.__id = -1
+        self.__id = conga_ssl_lib.connect(hostname, port, timeout)
+        pass
+    def __del__(self):
+        self.disconnect()
+        pass
+    def disconnect(self):
+        if self.__id != -1:
+            conga_ssl_lib.disconnect(self.__id)
+            self.__id = -1
+    
+    def peer_fingerprint(self):
+        return conga_ssl_lib.peer_fingerprint(self.__id)
+    
+    def trusted(self):
+        return conga_ssl_lib.trusted(self.__id) == 1
+    def trust(self):
+        if self.trusted():
+            return True
+        return conga_ssl_lib.trust(self.__id) == 1
+    def untrust(self):
+        return conga_ssl_lib.untrust(self.__id) == 1
+    
+    
+    def send(self, msg, timeout):
+        conga_ssl_lib.send(self.__id, msg, timeout)
+    def recv(self, timeout):
+        return conga_ssl_lib.recv(self.__id, timeout)
--- conga/luci/site/luci/Extensions/HelperFunctions.py	2006/11/29 22:33:50	1.4.2.1
+++ conga/luci/site/luci/Extensions/HelperFunctions.py	2006/12/08 18:27:32	1.4.2.2
@@ -1,6 +1,8 @@
 
 import AccessControl
 
+import threading
+from ricci_communicator import RicciCommunicator
 
 
 def add_commas(self, str1, str2):
@@ -29,17 +31,75 @@
 
 
 
+
+class Worker(threading.Thread):
+    def __init__(self,
+                 mutex,
+                 hosts,
+                 riccis):
+        threading.Thread.__init__(self)
+        self.mutex = mutex
+        self.hosts = hosts
+        self.riccis = riccis
+        return
+    def run(self):
+        while True:
+            self.mutex.acquire()
+            if len(self.hosts) == 0:
+                self.mutex.release()
+                return
+            host = self.hosts.pop()
+            self.mutex.release()
+            r = None
+            try:
+                r = RicciCommunicator(host)
+                #print host, 'done'
+            except Exception, e:
+                #print host, 'failed', str(e)
+                pass
+            except:
+                #print host, 'failed'
+                pass
+            self.mutex.acquire()
+            self.riccis[host] = r
+            self.mutex.release()
+        
+        
+                 
 # removes systems that user is not authorized access to
-def get_systems_statuses(self, systems):
-    ss = {}
+def get_systems_statuses(self, systems, from_cache=False):
+    CACHED_INDEX = '_get_systems_statuses()_cached_result_'
+    session = self.REQUEST.SESSION
+    if session.has_key(CACHED_INDEX):
+        res = session[CACHED_INDEX]
+        if res != None:
+            session.set(CACHED_INDEX, None)
+            if from_cache:
+                return res
+        pass
+    
     ass = self.allowed_systems(self, None, systems)
+    
+    mutex = threading.RLock()
+    hive  = [] # workers
+    ss    = {} # storage systems (will store riccis, and then use them to retrieve real info)
+    hosts = [] # hostnames
     for system in ass:
-        hostname = system[0]
+        hosts.append(system[0])
+        if len(hosts) < 10:
+            hive.append(Worker(mutex, hosts, ss))
+    
+    for bee in hive:
+        bee.start()
+    for bee in hive:
+        bee.join()
+    
+    for hostname in ss.keys():
         OS = ''
         cluname = ''
         cluali = ''
         authed = False
-        ricci = self.get_ricci_communicator(hostname, ass)
+        ricci = ss[hostname]
         if ricci != None:
             OS = ricci.os()
             cluname = ricci.cluster_info()[0]
@@ -53,6 +113,7 @@
              'clualias' : cluali, 
              'available': ricci != None,
              'authed'   : authed}
+        # replace ricci with system's info
         ss[hostname] = s
         pass
     ss_list = []
@@ -60,6 +121,9 @@
     sorted_keys.sort()
     for name in sorted_keys:
         ss_list.append(ss[name])
+    
+    session.set(CACHED_INDEX, ss_list)
+    
     return ss_list
 
 
@@ -88,7 +152,6 @@
     response.setCookie(cookie_prefix + var_name,
                        value, 
                        expires='Tue, 30 Jun 2060 12:00:00 GMT')
-    
     return value
 
 
--- conga/luci/site/luci/Extensions/StorageReport.py	2006/11/29 18:26:53	1.20.2.1
+++ conga/luci/site/luci/Extensions/StorageReport.py	2006/12/08 18:27:32	1.20.2.2
@@ -1878,17 +1878,8 @@
 
 
 
-def group_systems_by_cluster(self, allowed_systems, cache_it=False):
-    CACHED_INDEX = '_group_systems_by_cluster_cached_result_'
-    session = self.REQUEST.SESSION
-    if session.has_key(CACHED_INDEX):
-        res = session[CACHED_INDEX]
-        if res != None:
-            session.set(CACHED_INDEX, None)
-            return res
-        pass
-    
-    ss = get_systems_statuses(self, allowed_systems)
+def group_systems_by_cluster(self, allowed_systems, from_cache=False):
+    ss = get_systems_statuses(self, allowed_systems, from_cache)
     clusters = {}
     bad_list = []
     for s in ss:
@@ -1912,10 +1903,6 @@
     
     ret = [nonclu_list, clu_list, bad_list]
     
-    if cache_it:
-        session.set(CACHED_INDEX, ret)
-        pass
-    
     return ret
 
 
--- conga/luci/site/luci/Extensions/ricci_communicator.py	2006/11/20 23:32:43	1.9.2.6
+++ conga/luci/site/luci/Extensions/ricci_communicator.py	2006/12/08 18:27:32	1.9.2.7
@@ -1,8 +1,8 @@
-from socket import socket, ssl, AF_INET, SOCK_STREAM
 import xml
 import xml.dom
 from xml.dom import minidom
 from LuciSyslog import LuciSyslog
+from conga_ssl import SSLSocket
 
 CERTS_DIR_PATH = '/var/lib/luci/var/certs/'
 
@@ -15,32 +15,25 @@
     pass
 
 class RicciCommunicator:
-    def __init__(self, hostname, port=11111):
+    def __init__(self, hostname, enforce_trust=False, port=11111):
         self.__hostname = hostname
         self.__port = port
         
+        self.__timeout_init  = 4
+        self.__timeout_auth  = 4
+        self.__timeout_short = 6
+        self.__timeout_long  = 600
+        
         self.__privkey_file = CERTS_DIR_PATH + 'privkey.pem'
         self.__cert_file = CERTS_DIR_PATH + 'cacert.pem'
         
-        # socket
         try:
-            sock = socket(AF_INET, SOCK_STREAM)
-            sock.settimeout(2.0)
-            sock.connect((self.__hostname, self.__port))
-        except Exception, e:
-            raise RicciError, 'Error connecting to %s:%d: %s' \
-                    % (self.__hostname, self.__port, str(e))
-        except:
-            raise RicciError, 'Error connecting to %s:%d: unknown error' \
-                    % (self.__hostname, self.__port)
-
-        luci_log.debug_verbose('RC:init0: Connected to %s:%d' \
-            % (self.__hostname, self.__port))
-        try:
-            self.ss = ssl(sock, self.__privkey_file, self.__cert_file)
-            # TODO: data transfer timeout should be much less, 
-            # leave until all calls are async ricci calls
-            sock.settimeout(600.0) # 10 minutes
+            self.ss = SSLSocket(self.__hostname,
+                                self.__port,
+                                self.__timeout_init)
+            if enforce_trust:
+                if not self.ss.trusted():
+                    raise RicciError, 'ricci\'s certificate is not trusted'
         except Exception, e:
             raise RicciError, 'Error setting up SSL for connection to %s: %s' \
                 % (self.__hostname, str(e))
@@ -49,20 +42,20 @@
                 % self.__hostname
         
         # receive ricci header
-        hello = self.__receive()
+        hello = self.__receive(self.__timeout_init)
         try:
-            luci_log.debug_verbose('RC:init1: Received header from %s: \"%s\"' \
+            luci_log.debug_verbose('RC:init0: Received header from %s: \"%s\"' \
                 % (self.__hostname, hello.toxml()))
         except:
             pass
-
+        
         self.__authed = hello.firstChild.getAttribute('authenticated') == 'true'
         self.__cluname = hello.firstChild.getAttribute('clustername')
         self.__clualias = hello.firstChild.getAttribute('clusteralias')
         self.__reported_hostname = hello.firstChild.getAttribute('hostname')
         self.__os = hello.firstChild.getAttribute('os')
         self.__dom0 = hello.firstChild.getAttribute('xen_host') == 'true'
-
+        
         pass
     
     
@@ -104,10 +97,10 @@
         ricci.setAttribute("function", "authenticate")
         ricci.setAttribute("password", password)
         doc.appendChild(ricci)
-        self.__send(doc)
+        self.__send(doc, self.__timeout_auth)
         
         # receive response
-        resp = self.__receive()
+        resp = self.__receive(self.__timeout_auth)
         self.__authed = resp.firstChild.getAttribute('authenticated') == 'true'
 
         luci_log.debug_verbose('RC:auth1: auth call returning %d' \
@@ -121,8 +114,8 @@
         ricci.setAttribute('version', '1.0')
         ricci.setAttribute('function', 'unauthenticate')
         doc.appendChild(ricci)
-        self.__send(doc)
-        resp = self.__receive()
+        self.__send(doc, self.__timeout_auth)
+        resp = self.__receive(self.__timeout_auth)
 
         luci_log.debug_verbose('RC:unauth0: trying to unauthenticate to %s' \
             % self.__hostname)
@@ -167,7 +160,7 @@
         
         # send request
         try:
-            self.__send(doc)
+            self.__send(doc, self.__timeout_short)
         except Exception, e:
             luci_log.debug_verbose('RC:PB1: Error sending XML \"%s\" to host %s' \
                 % (doc.toxml(), self.__hostname))
@@ -177,7 +170,7 @@
             raise RicciError, 'Error sending XML to host %s' % self.__hostname
         
         # receive response
-        doc = self.__receive()
+        doc = self.__receive(self.__timeout_long)
         try:
             luci_log.debug_verbose('RC:PB2: received from %s XML \"%s\"' \
                 % (self.__hostname, doc.toxml()))
@@ -243,11 +236,11 @@
         doc.appendChild(ricci)
         
         # send request
-        self.__send(doc)
+        self.__send(doc, self.__timeout_short)
  
        
         # receive response
-        doc = self.__receive()
+        doc = self.__receive(self.__timeout_short)
         if doc.firstChild.getAttribute('success') == '12':
             return None
         if doc.firstChild.getAttribute('success') != '0':
@@ -265,20 +258,18 @@
     
     
     
-    def __send(self, xml_doc):
+    def __send(self, xml_doc, timeout):
         buff = xml_doc.toxml() + '\n'
-        while len(buff) != 0:
-            try:
-                pos = self.ss.write(buff)
-            except Exception, e:
-                luci_log.debug_verbose('RC:send0: Error sending XML \"%s\" to %s: %s' \
-                    % (buff, self.__hostname, str(e)))
-                raise RicciError, 'write error while sending XML to host %s' \
-                        % self.__hostname
-            except:
-                raise RicciError, 'write error while sending XML to host %s' \
-                        % self.__hostname
-            buff = buff[pos:]
+        try:
+            self.ss.send(buff, timeout)
+        except Exception, e:
+            luci_log.debug_verbose('RC:send0: Error sending XML \"%s\" to %s: %s' \
+                                   % (buff, self.__hostname, str(e)))
+            raise RicciError, 'write error while sending XML to host %s' \
+                  % self.__hostname
+        except:
+            raise RicciError, 'write error while sending XML to host %s' \
+                  % self.__hostname
         try:
             luci_log.debug_verbose('RC:send1: Sent XML \"%s\" to host %s' \
                 % (xml_doc.toxml(), self.__hostname))
@@ -286,21 +277,11 @@
             pass
         return
     
-    def __receive(self):
+    def __receive(self, timeout):
         doc = None
         xml_in = ''
         try:
-            while True:
-                buff = self.ss.read(10485760)
-                if buff == '':
-                    break
-                xml_in += buff
-                try:
-                    doc = minidom.parseString(xml_in)
-                    break
-                except:
-                    # we haven't received all of the XML data yet.
-                    continue
+            xml_in = self.ss.recv(timeout)
         except Exception, e:
             luci_log.debug_verbose('RC:recv0: Error reading data from %s: %s' \
                 % (self.__hostname, str(e)))
--- conga/luci/site/luci/Extensions/storage_adapters.py	2006/10/19 14:57:17	1.7.2.1
+++ conga/luci/site/luci/Extensions/storage_adapters.py	2006/12/08 18:27:32	1.7.2.2
@@ -61,7 +61,7 @@
     #display_clusters = True
     display_clusters = False
     if display_clusters:
-      sorted_data = self.group_systems_by_cluster(systems, cache_it=True)
+      sorted_data = self.group_systems_by_cluster(systems, from_cache=False)
       for sdl in sorted_data[:2]:
         for data in sdl:
           createStorageChooser_inner(url,
@@ -70,7 +70,7 @@
                                      data,
                                      syslist)
     else:
-      sorted_data = get_systems_statuses(self, systems)
+      sorted_data = get_systems_statuses(self, systems, from_cache=False)
       for data in sorted_data:
         createStorageChooser_inner(url,
                                    pagetype,
--- conga/luci/storage/form-macros	2006/10/31 17:48:33	1.17.2.3
+++ conga/luci/storage/form-macros	2006/12/08 18:27:32	1.17.2.4
@@ -293,7 +293,7 @@
     </form>
    </fieldset> 
    
-   <dl tal:define="tmp_triple   python:here.group_systems_by_cluster(allowed_systems);
+   <dl tal:define="tmp_triple   python:here.group_systems_by_cluster(allowed_systems, from_cache=True);
                    nonclu_list  python:tmp_triple[0];
                    clu_list     python:tmp_triple[1];
                    bad_list     python:tmp_triple[2]">
--- conga/ricci/ricci/SSLInstance.cpp	2006/10/23 21:13:22	1.5.2.1
+++ conga/ricci/ricci/SSLInstance.cpp	2006/12/08 18:27:32	1.5.2.2
@@ -137,6 +137,11 @@
   else
     ssl_locks[n]->unlock();
 }
+static pthread_t
+ssl_id_callback(void)
+{
+  return pthread_self();
+}
 
 
 
@@ -157,12 +162,12 @@
       // TODO: random number generator,
       // not on systems with /dev/urandom (eg. Linux)
       
-      // set up lockings
+      // thread support
       ssl_locks.clear();
-      for (int i=0; i<CRYPTO_num_locks(); i++)
+      for (int i=0; i<CRYPTO_num_locks()+1; i++)
 	ssl_locks.push_back(counting_auto_ptr<Mutex>(new Mutex()));
       CRYPTO_set_locking_callback(ssl_mutex_callback);
-      //CRYPTO_set_id_callback(ssl_id_function); not needed on Linux
+      CRYPTO_set_id_callback(ssl_id_callback);
       
       // create context
       if (!ctx)
@@ -354,6 +359,7 @@
   
   // cert present among saved certs?
   client_has_cert();  // make sure cert is saved in _cert_pem
+  MutexLocker l(global_lock);
   for (list<file_cert>::const_iterator iter = authorized_certs.begin();
        iter != authorized_certs.end();
        iter++)



             reply	other threads:[~2006-12-08 18:27 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-08 18:27 kupcevic [this message]
  -- strict thread matches above, loose matches on Subject: below --
2006-08-04 22:14 [Cluster-devel] conga ./conga.spec.in.in luci/Makefile luci/si kupcevic
2006-08-03 20:53 kupcevic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20061208182736.29493.qmail@sourceware.org \
    --to=kupcevic@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.