Skip to content

Commit

Permalink
Imported rhn and up2date_client libraries from the RHEL4 up2date pac…
Browse files Browse the repository at this point in the history
…kage
  • Loading branch information
dagwieers committed Aug 15, 2008
1 parent 45de58d commit cb3ab3b
Show file tree
Hide file tree
Showing 43 changed files with 9,601 additions and 6 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Expand Up @@ -24,6 +24,7 @@
- Fix elementtree for python 2.5 and higher (Leo Eraly)
- Added hardlinkpy support
- Added X-Mailer header to emails send
- Imported rhn and up2date_client libraries from the RHEL4 up2date package

* 0.8.4 - Sint-Jacobsplein - released 13/12/2006
- Renamed Yam to mrepo (Matthew Hannigan)
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Expand Up @@ -38,6 +38,12 @@ install:
install -d -m0755 $(DESTDIR)$(wwwdir)
install -d -m0755 $(DESTDIR)$(cachedir)

install -d -m0755 $(DESTDIR)$(datadir)/mrepo/rhn/
install -d -m0755 $(DESTDIR)$(datadir)/mrepo/up2date_client/repoBackends/
cp -av rhn/*.py $(DESTDIR)$(datadir)/mrepo/rhn/
cp -av up2date_client/*.py $(DESTDIR)$(datadir)/mrepo/up2date_client/
cp -av up2date_client/repoBackends/*.py $(DESTDIR)$(datadir)/mrepo/up2date_client/repoBackends/

[ "$(DESTDIR)" -o ! -f "$(DESTDIR)$(sysconfdir)/cron.d/mrepo" ] && install -Dp -m0644 config/mrepo.cron $(DESTDIR)$(sysconfdir)/cron.d/mrepo || :

install -Dp -m0644 config/mrepo.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/mrepo
Expand Down
6 changes: 6 additions & 0 deletions rhn/README
@@ -0,0 +1,6 @@
### This directory contains the rhn and up2date code that ships with
### RHEL4 in order to have a working rhnget and gensystemid
### implementation on RHEL5 and other distributions.
###
### According to the information I have read this code is
### redistributable under the GPLv2 license.
294 changes: 294 additions & 0 deletions rhn/SSL.py
@@ -0,0 +1,294 @@
#
# Higher-level SSL objects used by rpclib
#
# Copyright (c) 2002-2005 Red Hat, Inc.
#
# Author: Mihai Ibanescu <misa@redhat.com>

# $Id: SSL.py 104814 2006-10-24 15:36:18Z jbowes $

"""
rhn.SSL builds an abstraction on top of the objects provided by pyOpenSSL
"""

from OpenSSL import SSL, crypto
import os
import time

import socket
import select

DEFAULT_TIMEOUT = 30


class SSLSocket:
"""
Class that wraps a pyOpenSSL Connection object, adding more methods
"""
def __init__(self, socket, trusted_certs=None):
# SSL.Context object
self._ctx = None
# SSL.Connection object
self._connection = None
self._sock = socket
self._trusted_certs = []
# convert None to empty list
trusted_certs = trusted_certs or []
for f in trusted_certs:
self.add_trusted_cert(f)
# SSL method to use
self._ssl_method = SSL.SSLv23_METHOD
# Flags to pass to the SSL layer
self._ssl_verify_flags = SSL.VERIFY_PEER

# Buffer size for reads
self._buffer_size = 8192

# Position, for tell()
self._pos = 0
# Buffer
self._buffer = ""

# Flag to show if makefile() was called
self._makefile_called = 0

self._closed = None

def add_trusted_cert(self, file):
"""
Adds a trusted certificate to the certificate store of the SSL context
object.
"""
if not os.access(file, os.R_OK):
raise ValueError, "Unable to read certificate file %s" % file
self._trusted_certs.append(file)

def init_ssl(self):
"""
Initializes the SSL connection.
"""
self._check_closed()
# Get a context
self._ctx = SSL.Context(self._ssl_method)
if self._trusted_certs:
# We have been supplied with trusted CA certs
for f in self._trusted_certs:
self._ctx.load_verify_locations(f)
else:
# Reset the verify flags
self._ssl_verify_flags = 0

self._ctx.set_verify(self._ssl_verify_flags, ssl_verify_callback)
if hasattr(SSL, "OP_DONT_INSERT_EMPTY_FRAGMENTS"):
# Certain SSL implementations break when empty fragments are
# initially sent (even if sending them is compliant to
# SSL 3.0 and TLS 1.0 specs). Play it safe and disable this
# feature (openssl 0.9.6e and later)
self._ctx.set_options(SSL.OP_DONT_INSERT_EMPTY_FRAGMENTS)

# Init the connection
self._connection = SSL.Connection(self._ctx, self._sock)
# Place the connection in client mode
self._connection.set_connect_state()

def makefile(self, mode, bufsize=None):
"""
Returns self, since we are a file-like object already
"""
if bufsize:
self._buffer_size = bufsize

# Increment the counter with the number of times we've called makefile
# - we don't want close to actually close things until all the objects
# that originally called makefile() are gone
self._makefile_called = self._makefile_called + 1
return self

def close(self):
"""
Closes the SSL connection
"""
# XXX Normally sock.makefile does a dup() on the socket file
# descriptor; httplib relies on this, but there is no dup for an ssl
# connection; so we have to count how may times makefile() was called
if self._closed:
# Nothing to do
return
if not self._makefile_called:
self._really_close()
return
self._makefile_called = self._makefile_called - 1

def _really_close(self):
self._connection.shutdown()
self._connection.close()
self._closed = 1

def _check_closed(self):
if self._closed:
raise ValueError, "I/O operation on closed file"

def __getattr__(self, name):
if hasattr(self._connection, name):
return getattr(self._connection, name)
raise AttributeError, name

# File methods
def isatty(self):
"""
Returns false always.
"""
return 0

def tell(self):
return self._pos

def seek(self, pos, mode=0):
raise NotImplementedError, "seek"

def read(self, amt=None):
"""
Reads up to amt bytes from the SSL connection.
"""
self._check_closed()
# Initially, the buffer size is the default buffer size.
# Unfortunately, pending() does not return meaningful data until
# recv() is called, so we only adjust the buffer size after the
# first read
buffer_size = self._buffer_size

# Read only the specified amount of data
while amt is None or len(self._buffer) < amt:
# if amt is None (read till the end), fills in self._buffer
if amt is not None:
buffer_size = min(amt - len(self._buffer), buffer_size)

try:
data = self._connection.recv(buffer_size)

self._buffer = self._buffer + data

# More bytes to read?
pending = self._connection.pending()
if pending == 0:
# we're done here
break
except SSL.ZeroReturnError:
# Nothing more to be read
break
except SSL.SysCallError, e:
print "SSL exception", e.args
break
except SSL.WantWriteError:
self._poll(select.POLLOUT, 'read')
except SSL.WantReadError:
self._poll(select.POLLIN, 'read')

if amt:
ret = self._buffer[:amt]
self._buffer = self._buffer[amt:]
else:
ret = self._buffer
self._buffer = ""

self._pos = self._pos + len(ret)
return ret

def _poll(self, filter_type, caller_name):
poller = select.poll()
poller.register(self._sock, filter_type)
res = poller.poll(self._sock.gettimeout() * 1000)
if len(res) != 1:
raise TimeoutException, "Connection timed out on %s" % caller_name

def write(self, data):
"""
Writes to the SSL connection.
"""
self._check_closed()

# XXX Should use sendall
# sent = self._connection.sendall(data)
origlen = len(data)
while True:
try:
sent = self._connection.send(data)
if sent == len(data):
break
data = data[sent:]
except SSL.WantWriteError:
self._poll(select.POLLOUT, 'write')
except SSL.WantReadError:
self._poll(select.POLLIN, 'write')

return origlen

def recv(self, amt):
return self.read(amt)

send = write

sendall = write

def readline(self, length=None):
"""
Reads a single line (up to `length' characters long) from the SSL
connection.
"""
self._check_closed()
while True:
# charcount contains the number of chars to be outputted (or None
# if none to be outputted at this time)
charcount = None
i = self._buffer.find('\n')
if i >= 0:
# Go one char past newline
charcount = i + 1
elif length and len(self._buffer) >= length:
charcount = length

if charcount is not None:
ret = self._buffer[:charcount]
self._buffer = self._buffer[charcount:]
self._pos = self._pos + len(ret)
return ret

# Determine the number of chars to be read next
bufsize = self._buffer_size
if length:
# we know length > len(self._buffer)
bufsize = min(self._buffer_size, length - len(self._buffer))

try:
data = self._connection.recv(bufsize)
self._buffer = self._buffer + data
except SSL.ZeroReturnError:
# Nothing more to be read
break
except SSL.WantWriteError:
self._poll(select.POLLOUT, 'readline')
except SSL.WantReadError:
self._poll(select.POLLIN, 'readline')

# We got here if we're done reading, so return everything
ret = self._buffer
self._buffer = ""
self._pos = self._pos + len(ret)
return ret


def ssl_verify_callback(conn, cert, errnum, depth, ok):
"""
Verify callback, which will be called for each certificate in the
certificate chain.
"""
# Nothing by default
return ok

class TimeoutException(SSL.Error, socket.timeout):

def __init__(self, *args):
self.args = args

def __str__(self):
return "Timeout Exception"

0 comments on commit cb3ab3b

Please sign in to comment.