diff -urN openvpn-2.0.2/config.h.in openvpn-2.0.2parcheado/config.h.in
--- openvpn-2.0.2/config.h.in	2005-08-25 17:48:07.000000000 +0200
+++ openvpn-2.0.2parcheado/config.h.in	2005-09-08 11:19:20.585866184 +0200
@@ -87,6 +87,9 @@
 /* Define to 1 if you have the `ENGINE_cleanup' function. */
 #undef HAVE_ENGINE_CLEANUP
 
+/* Define to 1 if you have the `ENGINE_get_default_RSA' function. */
+#undef HAVE_ENGINE_GET_DEFAULT_RSA
+
 /* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
 #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
 
@@ -454,6 +457,9 @@
 /* Use LZO compression library */
 #undef USE_LZO
 
+/* Use OpenSC library */
+#undef USE_OPENSC
+
 /* Use pthread-based multithreading */
 #undef USE_PTHREAD
 
diff -urN openvpn-2.0.2/configure.ac openvpn-2.0.2parcheado/configure.ac
--- openvpn-2.0.2/configure.ac	2005-08-25 17:47:58.000000000 +0200
+++ openvpn-2.0.2parcheado/configure.ac	2005-09-08 08:59:39.000000000 +0200
@@ -47,6 +47,23 @@
    [SSL="yes"]
 )
 
+AC_ARG_ENABLE(opensc,
+   [  --disable-opensc          Disable OpenSC SmartCard support],
+   [OPENSC="$enableval"],
+   [OPENSC="yes"]
+)
+
+AC_ARG_WITH(opensc-headers,
+   [  --with-opensc-headers=DIR OpenSC Include files location],
+   [OPENCT_HDR_DIR="$withval"]
+   [CPPFLAGS="$CPPFLAGS -I$withval"] 
+)
+
+AC_ARG_WITH(opensc-lib,
+   [  --with-opensc-lib=DIR     OpenSC Library location],
+   [LDFLAGS="$LDFLAGS -L$withval"] 
+)
+
 AC_ARG_ENABLE(multi,
    [  --disable-multi         Disable client/server support (--mode server + client mode)],
    [MULTI="$enableval"],
@@ -375,6 +392,7 @@
 dnl
 dnl check libraries
 dnl
+AC_PATH_XTRA
 
 dnl Checking for a working epoll
 AC_CHECKING([for working epoll implementation])
@@ -384,6 +402,29 @@
 LDFLAGS="$OLDLDFLAGS"
 
 dnl
+dnl check for OpenSC library
+dnl
+
+if test "$OPENSC" = "yes"; then
+    USE_OPENSC=0
+    AC_CHECKING([for OpenSC Library and Header files])
+    AC_CHECK_HEADER(opensc/opensc.h,
+        [AC_CHECK_LIB(opensc, sc_establish_context,
+            [
+                USE_OPENSC=1
+                OPENVPN_ADD_LIBS(-lopensc)
+                dnl Check for engine support in openssl
+                AC_CHECK_FUNCS(ENGINE_get_default_RSA)
+            ],
+            [AC_MSG_WARN([OpenSC not found - OpenSC support disabled.])]
+        )],
+        [AC_MSG_WARN([OpenSC headers not found - OpenSC support disabled])]
+    )
+    AC_DEFINE(USE_OPENSC, 1, [Use OpenSC library])
+fi
+
+
+dnl
 dnl check for valgrind tool
 dnl
 
diff -urN openvpn-2.0.2/Makefile.am openvpn-2.0.2parcheado/Makefile.am
--- openvpn-2.0.2/Makefile.am	2005-08-08 21:08:24.000000000 +0200
+++ openvpn-2.0.2parcheado/Makefile.am	2005-09-08 08:59:40.000000000 +0200
@@ -65,6 +65,7 @@
 	multi.c multi.h \
         ntlm.c ntlm.h \
 	occ.c occ.h occ-inline.h \
+	opensc.c opensc.h \
 	openvpn.c openvpn.h \
 	openvpn-plugin.h \
 	options.c options.h \
diff -urN openvpn-2.0.2/opensc.c openvpn-2.0.2parcheado/opensc.c
--- openvpn-2.0.2/opensc.c	1970-01-01 01:00:00.000000000 +0100
+++ openvpn-2.0.2parcheado/opensc.c	2005-09-08 14:00:06.403479016 +0200
@@ -0,0 +1,557 @@
+#ifdef WIN32
+#include "config-win32.h"
+#else
+#include "config.h"
+#endif
+
+#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_OPENSC)
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+
+#include <opensc/opensc.h>
+#include <opensc/pkcs15.h>
+
+#include "opensc.h"
+#include "syshead.h"
+#include "error.h"
+#include "misc.h"
+#include "ssl.h"
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
+# define RSA_get_default_method RSA_get_default_openssl_method
+#else
+# ifdef HAVE_ENGINE_GET_DEFAULT_RSA
+#  include <openssl/engine.h>
+#  if OPENSSL_VERSION_NUMBER < 0x0090704fL
+#   define BROKEN_OPENSSL_ENGINE
+#  endif
+# endif
+#endif
+
+static sc_context_t *ctx = NULL;
+static sc_card_t *card = NULL;
+static sc_pkcs15_card_t *p15card = NULL;
+
+static char *sc_pin = NULL;
+static struct user_pass passbuf;
+
+struct sc_priv_data
+{
+    struct sc_pkcs15_id cert_id;
+    int ref_count;
+};
+
+static int
+CardRequestDialog(int show)
+{
+    if (show) {
+        char buf[5];
+        get_console_input("Insert SmartCard, then enter y<CR> to accept or <CR> to abort: ",
+            true, buf, sizeof(buf-1));
+        return (strcmp(buf, "y") == 0);
+    }
+    return 0;
+}
+
+static char *
+CardPinDialog(const char *pin_label)
+{
+    char prompt[255];
+    char pin[256];
+    char *ret = NULL;
+    if (pin_label)
+        openvpn_snprintf(prompt, sizeof(prompt), "Enter SmartCard PIN [%s]: ", pin_label);
+    else
+        openvpn_snprintf(prompt, sizeof(prompt), "Enter SmartCard PIN: ");
+    get_console_input(prompt, false, pin, sizeof(pin));
+    if (strlen(pin))
+        ret = strdup(pin);
+    memset(pin, 0, sizeof(pin));
+    return ret;
+}
+
+/*
+ * Wait for SmartCard to be inserted.
+ *
+ * Return 0, if SmartCard detected, 1 on failure or UserAbort
+ *
+ */
+static int 
+sc_request()
+{
+    int got_card = 0;
+    int user_abort = 0;
+    int rid;
+    sc_context_t *lctx = NULL;
+    sc_card_t *lcard = NULL;
+    
+    while (1) {
+        if (lcard) {
+            sc_disconnect_card(lcard, 0);
+            lcard = NULL;
+        }
+        if (lctx) {
+            sc_release_context(lctx);
+            lctx = NULL;
+        }
+        if (got_card || user_abort) {
+            if (got_card) {
+                CardRequestDialog(0);
+                return 0;
+            }
+            return user_abort;
+        }
+        if (sc_establish_context(&lctx, "openvpn_probe"))
+            return 1;
+        lctx->suppress_errors = 1;
+        for (rid = 0; rid < lctx->reader_count; rid++) {
+            lcard = NULL;
+            if (sc_connect_card(lctx->reader[rid], 0, &lcard) == 0)
+                break;
+        }
+        if (lcard) {
+            got_card = 1;
+            continue;
+        }
+        /* If we got here, no SmartCard is currently inserted
+         * so delete a probably kept PIN.
+         */
+        if (sc_pin) {
+            memset(sc_pin, 0, strlen(sc_pin));
+            free(sc_pin);
+            sc_pin = NULL;
+        }
+        if (!CardRequestDialog(1000))
+            user_abort = 1;
+    }
+    return 1;
+}
+
+/*
+ * Close smartcard and release local structures.
+ */
+void
+sc_close(void)
+{
+    if (p15card) {
+        sc_pkcs15_unbind(p15card);
+        p15card = NULL;
+    }
+    if (card) {
+        sc_disconnect_card(card, 0);
+        card = NULL;
+    }
+    if (ctx) {
+        sc_release_context(ctx);
+        ctx = NULL;
+    }
+}
+
+/*
+ * Open SmartCard for further use.
+ *
+ * Return 0 on success, !0 on error.
+ */
+static int 
+sc_init(void)
+{
+    int r;
+    int rid;
+    
+    if (p15card)
+        return 0;
+
+    r = sc_establish_context(&ctx, "openvpn");
+    if (r)
+        goto err;
+    if (ctx->reader_count == 0) {
+        r = SC_ERROR_NO_READERS_FOUND;
+        goto err;
+    }
+    ctx->suppress_errors = 1;
+    do {
+        for (rid = 0; rid < ctx->reader_count; rid++) {
+            card = NULL;
+            if (sc_connect_card(ctx->reader[rid], 0, &card) == 0)
+                break;
+        }
+        if (!card) {
+            if (sc_request()) {
+                r = SC_ERROR_NO_READERS_FOUND;
+                goto err;
+            }
+        }
+    } while (!card);
+    ctx->suppress_errors = 0;
+    r = sc_pkcs15_bind(card, &p15card);
+    if (r)
+        goto err;
+    return 0;
+err:
+    sc_close();
+    return r;
+}
+
+/*
+ * Initialize private key operations
+ */
+static int
+sc_prkey_op_init(const RSA *rsa, struct sc_pkcs15_object **key_obj_out,
+	unsigned int usage)
+{
+    int r;
+    struct sc_priv_data *priv;
+    struct sc_pkcs15_object *key_obj;
+    struct sc_pkcs15_object *pin_obj;
+    
+    priv = (struct sc_priv_data *)RSA_get_app_data(rsa);
+    if (priv == NULL)
+        return -1;
+    if (r = sc_init()) {
+        msg(M_FATAL, "SmartCard init failed: %s", sc_strerror(r));
+        goto end;
+    }
+
+    if (r = sc_pkcs15_find_prkey_by_id_usage(p15card, &priv->cert_id, usage, &key_obj)) {
+        msg(M_FATAL, "Unable to find private key from SmartCard: %s", sc_strerror(r));
+        goto end;
+    }
+    r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id, &pin_obj);
+    if (r == SC_ERROR_OBJECT_NOT_FOUND) {
+        /* no pin required */
+        r = sc_lock(card);
+        if (r) {
+            msg(M_FATAL, "Unable to lock smartcard: %s", sc_strerror(r));
+            goto end;
+        }
+        *key_obj_out = key_obj;
+        goto end;
+    } else if (r) {
+        msg(M_FATAL, "Unable to find PIN object from SmartCard: %s", sc_strerror(r));
+        goto end;
+    }
+    r = sc_lock(card);
+    if (r) {
+        msg(M_FATAL, "Unable to lock smartcard: %s", sc_strerror(r));
+        goto end;
+    }
+    r = sc_pkcs15_verify_pin(p15card, pin_obj->data, sc_pin, strlen(sc_pin));
+    if (r) {
+        sc_unlock(card);
+        if (sc_pin) {
+            /* Do not keep a wrong PIN */
+            memset(sc_pin, 0, strlen(sc_pin));
+            free(sc_pin);
+            sc_pin = NULL;
+        }
+        msg(M_FATAL, "PIN code verification failed: %s", sc_strerror(r));
+        goto end;
+    }
+    *key_obj_out = key_obj;
+
+end:
+    return r;
+}
+
+#define SC_USAGE_DECRYPT SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP
+#define SC_USAGE_SIGN SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
+
+static int
+sc_sign(int type, const unsigned char *m, unsigned int m_len,
+        unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
+{
+    struct sc_pkcs15_object *key_obj;
+    int r;
+    unsigned long flags = 0;
+    
+    /* XXX: sc_prkey_op_init will search for a pkcs15 private
+    * key object with the sign or signrecover usage flag set.
+    * If the signing key has only the non-repudiation flag set
+    * the key will be rejected as using a non-repudiation key
+    * for authentication is not recommended. Note: This does not
+    * prevent the use of a non-repudiation key for authentication
+    * if the sign or signrecover flag is set as well.
+    */
+    r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_SIGN);
+    if (r)
+        return -1;
+
+    /* FIXME: length of sigret correct? */
+    /* FIXME: check 'type' and modify flags accordingly */
+    flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_MD5_SHA1;
+    r = sc_pkcs15_compute_signature(p15card, key_obj, flags,
+        m, m_len, sigret, RSA_size(rsa));
+    sc_unlock(card);
+    if (r < 0) {
+        msg(M_WARN, "sc_pkcs15_compute_signature() failed: %s",
+            sc_strerror(r));
+        goto err;
+    }
+    *siglen = r;
+    return 1;
+err:
+    return 0;
+}
+
+static int
+sc_priv_dec(int flen, const unsigned char *from,
+            unsigned char *to, RSA *rsa, int padding)
+{
+    struct sc_pkcs15_object *key_obj;
+    int r;
+    
+    if (padding != RSA_PKCS1_PADDING)
+        return -1;	
+    r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_DECRYPT);
+    if (r)
+        return -1;
+    r = sc_pkcs15_decipher(p15card, key_obj, SC_ALGORITHM_RSA_PAD_PKCS1,
+        from, flen, to, flen);
+    sc_unlock(card);
+    if (r < 0) {
+        msg(M_NONFATAL, "sc_pkcs15_decipher() failed: %s", sc_strerror(r));
+        goto err;
+    }
+    return r;
+err:
+    return -1;
+}
+
+static int
+sc_priv_enc(int flen, const unsigned char *from,
+            unsigned char *to, RSA *rsa, int padding)
+{
+    msg(M_DEBUG, "Private key encryption not supported");
+    return -1;
+}
+
+/* called on free */
+static int (*orig_finish)(RSA *rsa) = NULL;
+
+static int
+sc_finish(RSA *rsa)
+{
+    struct sc_priv_data *priv;
+    
+    priv = RSA_get_app_data(rsa);
+    priv->ref_count--;
+    if (priv->ref_count == 0) {
+        free(priv);
+        sc_close();
+    }
+    if (orig_finish)
+        orig_finish(rsa);
+#ifdef BROKEN_OPENSSL_ENGINE
+    {
+        /* We get called TWICE here, once for
+           releasing the key and also for
+           releasing the engine.
+           To prevent endless recursion, FIRST
+           clear rsa->engine, THEN call engine->finish
+        */
+        ENGINE *e = rsa->engine;
+        rsa->engine = NULL;
+        if (e)
+            ENGINE_finish(e);
+    }
+#endif
+    return 1;
+}
+
+/* engine for overloading private key operations */
+
+static RSA_METHOD *
+sc_get_rsa_method(void)
+{
+    static RSA_METHOD smart_rsa;
+    const RSA_METHOD *def = RSA_get_default_method();
+    
+    /* use the OpenSSL version */
+    memcpy(&smart_rsa, def, sizeof(smart_rsa));
+    
+    /* save original */
+    orig_finish	     = def->finish;
+
+    smart_rsa.name = "OpenSC";
+    smart_rsa.rsa_priv_enc = sc_priv_enc;
+    smart_rsa.rsa_priv_dec = sc_priv_dec;
+    smart_rsa.rsa_sign = sc_sign;
+    smart_rsa.finish = sc_finish;
+    smart_rsa.flags  = RSA_METHOD_FLAG_NO_CHECK | RSA_FLAG_EXT_PKEY;
+    return &smart_rsa;
+}
+
+#ifdef BROKEN_OPENSSL_ENGINE
+static void broken_openssl_init() __attribute__ ((constructor));
+static void  broken_openssl_init()
+{
+    SSL_library_init();
+    ENGINE_load_openssl();
+    ENGINE_register_all_RSA();
+}
+#endif
+
+int SSL_CTX_use_OpenSC(SSL_CTX *ssl_ctx, const char *cert_prop, const char *pin_file, const char *pin)
+{
+    int i, r, cert_count;
+    struct sc_pkcs15_id id;
+    struct sc_pkcs15_cert *cert = NULL;
+    struct sc_priv_data *priv = NULL;
+    X509 *x509 = NULL;
+    EVP_PKEY *pubkey = NULL;
+    RSA *rsa = NULL;
+    struct sc_pkcs15_object *certs[32];
+
+    if (!cert_prop) {
+        msg(M_FATAL, "SSL_CTX_use_OpenSC: NULL pointer provided in cert_prop");
+        goto err;
+    }
+    id.len = SC_PKCS15_MAX_ID_SIZE;
+    sc_pkcs15_hex_string_to_id(cert_prop, &id);
+
+    if (r = sc_init()) {
+        msg(M_FATAL, "Smartcard init failed: %s", sc_strerror(r));
+        goto err;
+    }
+
+    r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, certs, 32);
+    if (r == 0) {
+        msg(M_FATAL, "No certificates found on smartcard");
+        r = -1;
+        goto err;
+    } else if (r < 0) {
+        msg(M_FATAL, "Certificate enumeration failed: %s", sc_strerror(r));
+        goto err;
+    }
+    cert_count = r;
+    for (i = 0; i < cert_count; i++) {
+        struct sc_pkcs15_cert_info *cinfo = (struct sc_pkcs15_cert_info *) certs[i]->data;
+        sc_pkcs15_object_t *tmp_obj;
+        u8 *p;
+
+        if (sc_pkcs15_compare_id(&id, &cinfo->id) != 1)
+            continue;
+
+        tmp_obj = NULL;
+        if (sc_pkcs15_find_prkey_by_id(p15card, &cinfo->id, &tmp_obj))
+            /* skip the public (certificate) if no
+             * corresponding private key is present
+             */
+            continue;
+
+        /* Clear data from previous loop */
+        if (cert) {
+            sc_pkcs15_free_certificate(cert);
+            cert = NULL;
+        }
+        if (x509) {
+            X509_free(x509);
+            x509 = NULL;
+        }
+        if (pubkey) {
+            EVP_PKEY_free(pubkey);
+            pubkey = NULL;
+        }
+        if (rsa) {
+            RSA_free(rsa);
+            rsa = NULL;
+        }
+
+        /* Read cert */
+        r = sc_pkcs15_read_certificate(p15card, cinfo, &cert);
+        if (r) {
+            msg(M_WARN, "Certificate read failed: %s\n", sc_strerror(r));
+            continue;
+        }
+        x509 = X509_new();
+        if (x509 == NULL)
+            continue;
+        p = cert->data;
+        if (!d2i_X509(&x509, &p, cert->data_len)) {
+            msg(M_WARN, "Unable to parse X.509 certificate");
+            continue;
+        }
+        sc_pkcs15_free_certificate(cert);
+        cert = NULL;
+
+        pubkey = X509_get_pubkey(x509);
+        if (pubkey->type != EVP_PKEY_RSA) {
+            msg(M_WARN, "Public key is of unknown type");
+            continue;
+        }
+        rsa = EVP_PKEY_get1_RSA(pubkey);
+        EVP_PKEY_free(pubkey);
+        pubkey = NULL;
+
+        rsa->flags |= RSA_FLAG_SIGN_VER;
+        RSA_set_method(rsa, sc_get_rsa_method());
+#ifdef BROKEN_OPENSSL_ENGINE
+        if (!rsa->engine)
+            rsa->engine = ENGINE_get_default_RSA();
+        ENGINE_set_RSA(ENGINE_get_default_RSA(), sc_get_rsa_method());
+        msg(M_WARN, "OpenSSL engine support is broken! Workaround enabled");
+#endif
+        priv = malloc(sizeof(struct sc_priv_data));
+        if (!priv) {
+            msg(M_FATAL, "Could not alloc private key data");
+            continue;
+        }
+        priv->cert_id = cinfo->id;
+        priv->ref_count = 1;
+        RSA_set_app_data(rsa, priv);
+
+        /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(),
+         * so we do it here then...  */
+        if (!SSL_CTX_use_certificate(ssl_ctx, x509))
+            goto err;
+
+        /* SSL_CTX_use_certificate() increased the reference count in 'cert', so
+         * we decrease it here with X509_free(), or it will never be cleaned up. */
+        X509_free(x509);
+        x509 = NULL;
+
+        if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa))
+            goto err;
+
+        /* SSL_CTX_use_RSAPrivateKey() increased the reference count in 'rsa', so
+         * we decrease it here with RSA_free(), or it will never be cleaned up. */
+
+	RSA_free(rsa);
+
+        /* Get the PIN to access the smartcard */
+        if(pin_file)
+        {
+        /* Get smartcard PIN from file */
+           if (!strlen (passbuf.password))
+               get_user_pass (&passbuf, pin_file, true, UP_TYPE_PRIVATE_KEY, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
+            sc_pin=strdup(passbuf.password);
+        }
+        else if (pin) /* Get sc PIN from program options */
+            sc_pin=strdup(pin);
+        else /* Get smartcard PIN from console input */
+            sc_pin = CardPinDialog(NULL);
+        if ((sc_pin == NULL) || (strlen(sc_pin) == 0)) {
+            msg(M_FATAL, "Don't know the PIN to access the smartcard\n");
+            return 0;
+	}
+	return 1;
+    }
+    msg(M_FATAL, "Certificate with ID '%s' not found.\n", cert_prop);
+
+err:
+    if (x509)
+        X509_free(x509);
+    if (rsa)
+        RSA_free(rsa);
+    if (cert)
+        sc_pkcs15_free_certificate(cert);
+    if (pubkey)
+        EVP_PKEY_free(pubkey);
+    return 0;
+}
+
+#else
+static void dummy(void) {}
+#endif /* USE_OPENSC && USE_SSL && USE_CRYPTO */
diff -urN openvpn-2.0.2/opensc.h openvpn-2.0.2parcheado/opensc.h
--- openvpn-2.0.2/opensc.h	1970-01-01 01:00:00.000000000 +0100
+++ openvpn-2.0.2parcheado/opensc.h	2005-09-08 14:00:06.406478560 +0200
@@ -0,0 +1,7 @@
+/*	opensc.h   */
+#ifndef _OPENSC_H_
+#define _OPENSC_H_
+#ifdef USE_OPENSC
+int SSL_CTX_use_OpenSC(SSL_CTX *ssl_ctx, const char *cert_prop, const char *pin_file, const char *pin);
+#endif
+#endif
Los ficheros binarios openvpn-2.0.2/openvpn y openvpn-2.0.2parcheado/openvpn son distintos
diff -urN openvpn-2.0.2/openvpn.spec openvpn-2.0.2parcheado/openvpn.spec
--- openvpn-2.0.2/openvpn.spec	2005-08-25 17:48:32.000000000 +0200
+++ openvpn-2.0.2parcheado/openvpn.spec	2005-09-08 08:59:40.408846736 +0200
@@ -7,6 +7,9 @@
 #
 # Disable PAM plugin
 #   rpmbuild -tb [openvpn.x.tar.gz] --define 'without_pam 1'
+# Disable OpenSC support
+#   rpmbuild -tb [openvpn.x.tar.gz] --define 'without_opensc 1'
+#
 #
 # Allow passwords to be read from files
 #   rpmbuild -tb [openvpn.x.tar.gz] --define 'with_password_save 1'
@@ -36,6 +39,9 @@
 BuildRequires: openssl-devel >= 0.9.6
 Requires:      openssl       >= 0.9.6
 
+%{!?without_opensc:BuildRequires: opensc-devel >= 0.9.1}
+%{!?without_opensc:Requires:      opensc       >= 0.9.1}
+
 %if "%{_vendor}" == "Mandrakesoft"
 %{!?without_lzo:BuildRequires: liblzo1-devel >= 1.07}
 %{!?without_lzo:Requires:      liblzo1       >= 1.07}
@@ -96,7 +102,12 @@
 %setup -q
 
 %build
-%configure --disable-dependency-tracking %{?with_password_save:--enable-password-save} %{?without_lzo:--disable-lzo} %{?with_kerberos:--with-ssl-headers=/usr/kerberos/include}
+%configure --disable-dependency-tracking \
+    %{?with_password_save:--enable-password-save} \
+    %{?without_lzo:--disable-lzo} \
+    %{?without_opensc:--disable-opensc} \
+    %{?with_kerberos:--with-ssl-headers=/usr/kerberos/include}
+
 %__make
 %__strip %{name}
 
diff -urN openvpn-2.0.2/openvpn.spec.in openvpn-2.0.2parcheado/openvpn.spec.in
--- openvpn-2.0.2/openvpn.spec.in	2005-08-03 00:46:02.000000000 +0200
+++ openvpn-2.0.2parcheado/openvpn.spec.in	2005-09-08 08:59:39.000000000 +0200
@@ -7,6 +7,9 @@
 #
 # Disable PAM plugin
 #   rpmbuild -tb [openvpn.x.tar.gz] --define 'without_pam 1'
+# Disable OpenSC support
+#   rpmbuild -tb [openvpn.x.tar.gz] --define 'without_opensc 1'
+#
 #
 # Allow passwords to be read from files
 #   rpmbuild -tb [openvpn.x.tar.gz] --define 'with_password_save 1'
@@ -36,6 +39,9 @@
 BuildRequires: openssl-devel >= 0.9.6
 Requires:      openssl       >= 0.9.6
 
+%{!?without_opensc:BuildRequires: opensc-devel >= 0.9.1}
+%{!?without_opensc:Requires:      opensc       >= 0.9.1}
+
 %if "%{_vendor}" == "Mandrakesoft"
 %{!?without_lzo:BuildRequires: liblzo1-devel >= 1.07}
 %{!?without_lzo:Requires:      liblzo1       >= 1.07}
@@ -96,7 +102,12 @@
 %setup -q
 
 %build
-%configure --disable-dependency-tracking %{?with_password_save:--enable-password-save} %{?without_lzo:--disable-lzo} %{?with_kerberos:--with-ssl-headers=/usr/kerberos/include}
+%configure --disable-dependency-tracking \
+    %{?with_password_save:--enable-password-save} \
+    %{?without_lzo:--disable-lzo} \
+    %{?without_opensc:--disable-opensc} \
+    %{?with_kerberos:--with-ssl-headers=/usr/kerberos/include}
+
 %__make
 %__strip %{name}
 
diff -urN openvpn-2.0.2/options.c openvpn-2.0.2parcheado/options.c
--- openvpn-2.0.2/options.c	2005-08-04 09:16:27.000000000 +0200
+++ openvpn-2.0.2parcheado/options.c	2005-09-08 14:00:18.917576584 +0200
@@ -402,6 +402,11 @@
   "--key file      : Local private key in .pem format.\n"
   "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"
   "                  and root CA certificate.\n"
+#ifdef USE_OPENSC
+  "--opensc-cert cert-id : Use certificate and private key provided by OpenSC based SmartCard\n"
+  "--opensc-pin pin : Smartcard PIN for accessing private key via OpenSC\n"
+  "--opensc-authfile : File where the PIN of the smartcard is stored (alternative to --opensc-pin)\n"
+#endif
 #ifdef WIN32
   "--cryptoapicert select-string : Load the certificate and private key from the\n"
   "                  Windows Certificate System Store.\n"
@@ -1109,6 +1114,11 @@
   SHOW_STR (cert_file);
   SHOW_STR (priv_key_file);
   SHOW_STR (pkcs12_file);
+#ifdef USE_OPENSC
+  SHOW_STR (opensc_cert);
+  SHOW_STR (opensc_authfile);
+  SHOW_STR (opensc_pin);
+#endif
 #ifdef WIN32
   SHOW_STR (cryptoapi_cert);
 #endif
@@ -1567,6 +1577,25 @@
     }
   if (options->tls_server || options->tls_client)
     {
+#ifdef USE_OPENSC
+      if (options->opensc_cert)
+	{
+	  if (options->opensc_authfile && options->opensc_pin)
+            msg(M_USAGE, "Parameter --opensc_authfile cannot be used when --opensc_pin is also specified.");
+          notnull (options->ca_file, "CA file (--ca)");
+          if (options->cert_file)
+	    msg(M_USAGE, "Parameter --cert cannot be used when --opensc-cert is also specified.");
+          if (options->priv_key_file)
+	    msg(M_USAGE, "Parameter --key cannot be used when --opensc-cert is also specified.");
+          if (options->pkcs12_file)
+	    msg(M_USAGE, "Parameter --pkcs12 cannot be used when --opensc-cert is also specified.");
+#ifdef WIN32
+          if (options->cryptoapi_cert)
+	    msg(M_USAGE, "Parameter --cryptoapicert cannot be used when --opensc-cert is also specified.");
+#endif
+	}
+      else
+#endif
 #ifdef WIN32
       if (options->cryptoapi_cert)
 	{
@@ -1577,6 +1606,10 @@
 	    msg(M_USAGE, "Parameter --key cannot be used when --cryptoapicert is also specified.");
           if (options->pkcs12_file)
 	    msg(M_USAGE, "Parameter --pkcs12 cannot be used when --cryptoapicert is also specified.");
+#ifdef USE_OPENSC
+          if (options->opensc_cert)
+	    msg(M_USAGE, "Parameter --opensc-cert cannot be used when --cryptoapicert is also specified.");
+#endif
 	}
       else
 #endif
@@ -4376,6 +4409,26 @@
       VERIFY_PERMISSION (OPT_P_GENERAL);
       options->cert_file = p[1];
     }
+#ifdef USE_OPENSC
+  else if (streq (p[0], "opensc-cert") && p[1])
+    {
+      ++i;
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->opensc_cert = p[1];
+    }
+  else if (streq (p[0], "opensc-authfile") && p[1])
+    {
+      ++i;
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->opensc_authfile = p[1];
+    }
+  else if (streq (p[0], "opensc-pin") && p[1])
+    {
+      ++i;
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->opensc_pin = p[1];
+    }
+#endif
 #ifdef WIN32
   else if (streq (p[0], "cryptoapicert") && p[1])
     {
diff -urN openvpn-2.0.2/options.h openvpn-2.0.2parcheado/options.h
--- openvpn-2.0.2/options.h	2005-08-04 09:16:26.000000000 +0200
+++ openvpn-2.0.2parcheado/options.h	2005-09-08 14:00:18.920576128 +0200
@@ -369,6 +369,11 @@
 #ifdef WIN32
   const char *cryptoapi_cert;
 #endif
+#ifdef USE_OPENSC
+  const char *opensc_cert;
+  const char *opensc_pin;
+  const char *opensc_authfile;
+#endif
 
   /* data channel key exchange method */
   int key_method;
diff -urN openvpn-2.0.2/ssl.c openvpn-2.0.2parcheado/ssl.c
--- openvpn-2.0.2/ssl.c	2005-08-04 20:50:08.000000000 +0200
+++ openvpn-2.0.2parcheado/ssl.c	2005-09-08 14:00:57.080774896 +0200
@@ -53,6 +53,10 @@
 #include "status.h"
 #include "gremlin.h"
 
+#ifdef USE_OPENSC
+#include "opensc.h"
+#endif
+
 #ifdef WIN32
 #include "cryptoapi.h"
 #endif
@@ -847,6 +851,17 @@
     {
       /* Use seperate PEM files for key, cert and CA certs */
 
+#ifdef USE_OPENSC
+      if (options->opensc_cert)
+	{
+	  /* Load Certificate and Private Key */
+	  if (!SSL_CTX_use_OpenSC(ctx, options->opensc_cert, options->opensc_authfile, options->opensc_pin))
+	    msg (M_SSLERR, "Cannot load certificate \"%s\" from OpenSC Framework",
+		 options->opensc_cert);
+	}
+      else
+#endif
+
 #ifdef WIN32
       if (options->cryptoapi_cert)
 	{
