summaryrefslogtreecommitdiffstats
path: root/remote/modules/pam
diff options
context:
space:
mode:
authorMichael Neves2013-06-20 13:57:14 +0200
committerMichael Neves2013-06-20 13:57:14 +0200
commitcbc9a3a486bd77062a105ab457d323f65f370d1d (patch)
treee7af291c2563c266d2044262b0f58f1d10897a98 /remote/modules/pam
parent[udhcpc] remove old IP adress if new one is obtained. Update hostname if obta... (diff)
parent[rootfs-stage32] fixes (diff)
downloadtm-scripts-cbc9a3a486bd77062a105ab457d323f65f370d1d.tar.gz
tm-scripts-cbc9a3a486bd77062a105ab457d323f65f370d1d.tar.xz
tm-scripts-cbc9a3a486bd77062a105ab457d323f65f370d1d.zip
Merge branch 'master' of git.openslx.org:openslx-ng/tm-scripts
Diffstat (limited to 'remote/modules/pam')
-rw-r--r--remote/modules/pam/TODO1
-rw-r--r--remote/modules/pam/data/etc/gssapi_mech.conf21
-rw-r--r--remote/modules/pam/data/etc/idmapd.conf12
-rw-r--r--remote/modules/pam/data/etc/krb5.conf28
-rwxr-xr-xremote/modules/pam/data/etc/pam-script/pam_script_ses_close5
-rwxr-xr-xremote/modules/pam/data/etc/pam-script/pam_script_ses_open21
-rw-r--r--remote/modules/pam/data/etc/pam.d/common-account1
-rw-r--r--remote/modules/pam/data/etc/pam.d/common-auth3
-rw-r--r--remote/modules/pam/data/etc/pam.d/common-session6
l---------remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-gssd.service1
l---------remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-idmapd.service1
-rw-r--r--remote/modules/pam/data/etc/systemd/system/rpc-gssd.service7
-rw-r--r--remote/modules/pam/data/etc/systemd/system/rpc-idmapd.service7
-rw-r--r--remote/modules/pam/data/etc/systemd/system/run-rpc_pipefs.mount7
l---------remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_close1
l---------remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_open1
-rw-r--r--remote/modules/pam/pam.build21
-rw-r--r--remote/modules/pam/pam.conf98
-rw-r--r--remote/modules/pam/pam.conf.zypper44
-rw-r--r--remote/modules/pam/sslconnect.c201
20 files changed, 436 insertions, 51 deletions
diff --git a/remote/modules/pam/TODO b/remote/modules/pam/TODO
new file mode 100644
index 00000000..6f95e62d
--- /dev/null
+++ b/remote/modules/pam/TODO
@@ -0,0 +1 @@
+suse krb5 mount home dirs
diff --git a/remote/modules/pam/data/etc/gssapi_mech.conf b/remote/modules/pam/data/etc/gssapi_mech.conf
new file mode 100644
index 00000000..ac41f5fd
--- /dev/null
+++ b/remote/modules/pam/data/etc/gssapi_mech.conf
@@ -0,0 +1,21 @@
+# Example /etc/gssapi_mech.conf file
+#
+# GSSAPI Mechanism Definitions
+#
+# This configuration file determines which GSS-API mechanisms
+# the gssd code should use
+#
+# NOTE:
+# The initiaiization function "mechglue_internal_krb5_init"
+# is used for the MIT krb5 gssapi mechanism. This special
+# function name indicates that an internal function should
+# be used to determine the entry points for the MIT gssapi
+# mechanism funtions.
+#
+# library initialization function
+# ================================ ==========================
+# The MIT K5 gssapi library, use special function for initialization.
+libgssapi_krb5.so.2 mechglue_internal_krb5_init
+#
+# The SPKM3 gssapi library function. Use the function spkm3_gss_initialize.
+# /usr/local/gss_mechs/spkm/spkm3/libgssapi_spkm3.so spkm3_gss_initialize
diff --git a/remote/modules/pam/data/etc/idmapd.conf b/remote/modules/pam/data/etc/idmapd.conf
new file mode 100644
index 00000000..2253cf0d
--- /dev/null
+++ b/remote/modules/pam/data/etc/idmapd.conf
@@ -0,0 +1,12 @@
+[General]
+
+Verbosity = 0
+Pipefs-Directory = /run/rpc_pipefs
+# set your own domain here, if id differs from FQDN minus hostname
+Domain = uni-freiburg.de
+# localdomain
+
+[Mapping]
+
+Nobody-User = nobody
+Nobody-Group = nogroup
diff --git a/remote/modules/pam/data/etc/krb5.conf b/remote/modules/pam/data/etc/krb5.conf
new file mode 100644
index 00000000..6fd49243
--- /dev/null
+++ b/remote/modules/pam/data/etc/krb5.conf
@@ -0,0 +1,28 @@
+# file copied from configuration package (rootfs/etc/krb5.conf)
+#########################################################################
+[libdefaults]
+ noaddresses = false
+ clockskew = 300
+ default_realm = PUBLIC.ADS.UNI-FREIBURG.DE
+ forwardable = true
+ minimum_uid = 1000
+ proxiable = false
+ renew_lifetime = 30d
+ retain_after_close = false
+ ticket_lifetime = 3d
+ use_shmem = sshd
+ allow_weak_crypto=true
+#########################################################################
+[realms]
+ PUBLIC.ADS.UNI-FREIBURG.DE = {
+ kdc = kerberos.uni-freiburg.de
+ default_domain = uni-freiburg.de
+ admin_server = kerberos.uni-freiburg.de
+ }
+#########################################################################
+[domain_realm]
+ uni-freiburg.de = PUBLIC.ADS.UNI-FREIBURG.DE
+ .uni-freiburg.de = PUBLIC.ADS.UNI-FREIBURG.DE
+##########################################################################
+[appdefaults]
+#########################################################################
diff --git a/remote/modules/pam/data/etc/pam-script/pam_script_ses_close b/remote/modules/pam/data/etc/pam-script/pam_script_ses_close
new file mode 100755
index 00000000..48e778e2
--- /dev/null
+++ b/remote/modules/pam/data/etc/pam-script/pam_script_ses_close
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+echo "[$PAM_TYPE] Closing session for $PAM_USER"
+
+umount /home/$PAM_USER
diff --git a/remote/modules/pam/data/etc/pam-script/pam_script_ses_open b/remote/modules/pam/data/etc/pam-script/pam_script_ses_open
new file mode 100755
index 00000000..86386267
--- /dev/null
+++ b/remote/modules/pam/data/etc/pam-script/pam_script_ses_open
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/bin:/opt/openslx/sbin:/opt/openslx/usr/bin:/opt/openslx/usr/sbin"
+
+echo "[$PAM_TYPE] Opening session for $PAM_USER"
+echo "[$PAM_TYPE] Mounting home directory for $PAM_USER"
+
+# generate keytab
+sslconnect npserv.ruf.uni-freiburg.de:3 > /etc/krb5.keytab
+chmod 600 /etc/krb5.keytab
+
+# determine fileserver and share for home directories
+ldapsearch -x -LLL uid="$PAM_USER" homeDirectory rufFileserver > /tmp/ldapsearch."$PAM_USER"
+
+FILESERVER=$(cat /tmp/ldapsearch.$PAM_USER | grep rufFileserver | cut -d" " -f2)
+VOLUME=$(cat /tmp/ldapsearch.$PAM_USER | grep homeDirectory | cut -d" " -f2)
+
+# now we can mount the home directory
+mkdir -p /home/$PAM_USER
+mount -t nfs4 -o rw,nosuid,nodev,nolock,intr,hard,sloppy,sec=krb5p "$FILESERVER":"$VOLUME" /home/"$PAM_USER" \
+ || echo "[$PAM_TYPE] Failed to mount home directory for $PAM_USER"
diff --git a/remote/modules/pam/data/etc/pam.d/common-account b/remote/modules/pam/data/etc/pam.d/common-account
index 3a5d5a14..26055551 100644
--- a/remote/modules/pam/data/etc/pam.d/common-account
+++ b/remote/modules/pam/data/etc/pam.d/common-account
@@ -23,4 +23,5 @@ account requisite pam_deny.so
# since the modules above will each just jump around
account required pam_permit.so
# and here are more per-package modules (the "Additional" block)
+account required pam_krb5.so
# end of pam-auth-update config
diff --git a/remote/modules/pam/data/etc/pam.d/common-auth b/remote/modules/pam/data/etc/pam.d/common-auth
index 1fa577e7..088ed13f 100644
--- a/remote/modules/pam/data/etc/pam.d/common-auth
+++ b/remote/modules/pam/data/etc/pam.d/common-auth
@@ -14,7 +14,8 @@
# pam-auth-update(8) for details.
# here are the per-package modules (the "Primary" block)
-auth [success=2 default=ignore] pam_unix.so
+auth [success=3 default=ignore] pam_krb5.so minimum_uid=1000
+auth [success=2 default=ignore] pam_unix.so try_first_pass
auth [success=1 default=ignore] pam_ldap.so use_first_pass nullok_secure
# here's the fallback if no module succeeds
auth requisite pam_deny.so
diff --git a/remote/modules/pam/data/etc/pam.d/common-session b/remote/modules/pam/data/etc/pam.d/common-session
index c5813892..e3180dd4 100644
--- a/remote/modules/pam/data/etc/pam.d/common-session
+++ b/remote/modules/pam/data/etc/pam.d/common-session
@@ -26,8 +26,10 @@ session required pam_permit.so
# See "man pam_umask".
session optional pam_umask.so
# and here are more per-package modules (the "Additional" block)
-session [success=1] pam_unix.so
-session [success=ok] pam_ldap.so
+session [success=3] pam_unix.so
+session [success=2] pam_krb5.so minimum_uid=1000
+session [success=1] pam_ldap.so
session optional pam_mkhomedir.so skel=/etc/skel umask=0022
+session optional pam_script.so
session required pam_systemd.so kill-session-processes=1
# end of pam-auth-update config
diff --git a/remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-gssd.service b/remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-gssd.service
new file mode 120000
index 00000000..194aba77
--- /dev/null
+++ b/remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-gssd.service
@@ -0,0 +1 @@
+../rpc-gssd.service \ No newline at end of file
diff --git a/remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-idmapd.service b/remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-idmapd.service
new file mode 120000
index 00000000..66a28252
--- /dev/null
+++ b/remote/modules/pam/data/etc/systemd/system/getty.target.wants/rpc-idmapd.service
@@ -0,0 +1 @@
+../rpc-idmapd.service \ No newline at end of file
diff --git a/remote/modules/pam/data/etc/systemd/system/rpc-gssd.service b/remote/modules/pam/data/etc/systemd/system/rpc-gssd.service
new file mode 100644
index 00000000..6623428d
--- /dev/null
+++ b/remote/modules/pam/data/etc/systemd/system/rpc-gssd.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=NFS rpcsec_gss daemon
+Requires=run-rpc_pipefs.mount
+After=run-rpc_pipefs.mount
+
+[Service]
+ExecStart=/usr/sbin/rpc.gssd -f -vvv
diff --git a/remote/modules/pam/data/etc/systemd/system/rpc-idmapd.service b/remote/modules/pam/data/etc/systemd/system/rpc-idmapd.service
new file mode 100644
index 00000000..c4da93e7
--- /dev/null
+++ b/remote/modules/pam/data/etc/systemd/system/rpc-idmapd.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=NFSv4 ID-name mapping daemon
+Requires=network.target run-rpc_pipefs.mount
+After=network.target
+
+[Service]
+ExecStart=/usr/sbin/rpc.idmapd -f
diff --git a/remote/modules/pam/data/etc/systemd/system/run-rpc_pipefs.mount b/remote/modules/pam/data/etc/systemd/system/run-rpc_pipefs.mount
new file mode 100644
index 00000000..692adce8
--- /dev/null
+++ b/remote/modules/pam/data/etc/systemd/system/run-rpc_pipefs.mount
@@ -0,0 +1,7 @@
+[Unit]
+Description=Pipefs RPC filesystem
+
+[Mount]
+What=rpc_pipefs
+Where=/run/rpc_pipefs
+Type=rpc_pipefs
diff --git a/remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_close b/remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_close
new file mode 120000
index 00000000..a12002a7
--- /dev/null
+++ b/remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_close
@@ -0,0 +1 @@
+/etc/pam-script/pam_script_ses_close \ No newline at end of file
diff --git a/remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_open b/remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_open
new file mode 120000
index 00000000..783d5605
--- /dev/null
+++ b/remote/modules/pam/data/usr/share/libpam-script/pam_script_ses_open
@@ -0,0 +1 @@
+/etc/pam-script/pam_script_ses_open \ No newline at end of file
diff --git a/remote/modules/pam/pam.build b/remote/modules/pam/pam.build
index 4392e64d..d3c0dd88 100644
--- a/remote/modules/pam/pam.build
+++ b/remote/modules/pam/pam.build
@@ -3,9 +3,26 @@ fetch_source() {
}
build() {
- tarcopy "$(list_packet_files | sort -u)" "${MODULE_BUILD_DIR}"
+ mkdir -p "$MODULE_BUILD_DIR/opt/openslx/bin"
+ gcc -o "$MODULE_BUILD_DIR/opt/openslx/bin/sslconnect" "$MODULE_DIR/sslconnect.c" -lssl -lcrypto -O3 || perror "Could not compile sslconnect.c"
+ local COPYLIST="$MODULE_BUILD_DIR/list_packet_files"
+ list_packet_files | sort -u > "$COPYLIST"
+ tarcopy "$(cat "$COPYLIST")" "${MODULE_BUILD_DIR}"
}
post_copy() {
- :
+ if [ ! -d "${TARGET_BUILD_DIR}/run/rpc_pipefs" ]; then
+ mkdir -p "${TARGET_BUILD_DIR}/run/rpc_pipefs" || pwarning "Could not mkdir ${TARGET_BUILD_DIR}/run/rpc_pipefs"
+ fi
+
+ # find libnfsidmap run-time library directory
+ #local COPYLIST="$MODULE_BUILD_DIR/list_packet_files"
+ #local SEARCH=$(grep "/libsnfsidmap/" "$COPYLIST" | head -1)
+ #[ -z "$SEARCH" ] && perror "Hä"
+ #SEARCH=$(dirname "$SEARCH")
+ #if [ -d "${SEARCH}" ]; then
+ # tarcopy "${SEARCH}" "${TARGET_BUILD_DIR}" || pinfo "Something went wrong copying $SEARCH"
+ #fi
+
+
}
diff --git a/remote/modules/pam/pam.conf b/remote/modules/pam/pam.conf
index 94356d45..bbdd610f 100644
--- a/remote/modules/pam/pam.conf
+++ b/remote/modules/pam/pam.conf
@@ -1,37 +1,61 @@
-REQUIRED_INSTALLED_PACKAGES=" libpam-ldap
- libnss-ldap
- libpam-script
- krb5-user
- krb5-config
- libpam-krb5
- libpam-mount"
-REQUIRED_CONTENT_PACKAGES=" libpam0g
- libpam-modules
- libpam-ck-connector
- libpam-cap
- libpam-script
- libldap-2.4-2
- libpam-ldap
- libnss-ldap
- krb5-user
- krb5-config
- libpam-krb5
- libpam-mount"
-REQUIRED_BINARIES=" mount.crypt
- umount.crypt
- mount.crypt_LUKS
- umount.crypt_LUKS
- mount.crypto_LUKS
- umount.crypto_LUKS
- perl"
-REQUIRED_SYSTEM_FILES=" /lib/security/pam_mount.so"
-REQUIRED_DIRECTORIES=" /lib
- /usr/lib
- /etc/security"
-REQUIRED_SYSTEM_FILES=" /sbin/mkhomedir_helper
- /etc/pam.conf
- /etc/login.defs
- /etc/securetty
- /etc/default/locale
- /lib/security
- /lib/${ARCH_TRIPLET}/security"
+REQUIRED_INSTALLED_PACKAGES="
+ libpam-ldap
+ libnss-ldap
+ libpam-script
+ krb5-user
+ krb5-config
+ libpam-krb5
+ libssl-dev
+ ldap-utils
+ libnfsidmap2
+ nfs-common
+"
+REQUIRED_CONTENT_PACKAGES="
+ libpam0g
+ libpam-modules
+ libpam-ck-connector
+ libpam-cap
+ libpam-script
+ libldap-2.4-2
+ libpam-ldap
+ libnss-ldap
+ krb5-user
+ krb5-config
+ libpam-krb5
+ libpam-mount
+ ldap-utils
+ libnfsidmap2
+ nfs-common
+"
+REQUIRED_BINARIES="
+ rpc.gssd
+ rpc.idmapd
+ sslconnect
+ mount.crypt
+ umount.crypt
+ mount.crypt_LUKS
+ umount.crypt_LUKS
+ mount.crypto_LUKS
+ umount.crypto_LUKS
+ ldapsearch
+"
+REQUIRED_LIBRARIES="
+ nsswitch
+ static
+ umich_ldap
+ libnfsidmap
+"
+REQUIRED_DIRECTORIES="
+ /lib
+ /usr/lib
+ /etc/security
+"
+REQUIRED_SYSTEM_FILES="
+ /sbin/mkhomedir_helper
+ /etc/pam.conf
+ /etc/login.defs
+ /etc/securetty
+ /etc/default/locale
+ /lib/security
+ /lib/${ARCH_TRIPLET}/security
+"
diff --git a/remote/modules/pam/pam.conf.zypper b/remote/modules/pam/pam.conf.zypper
index 2defe1bb..48dc1d52 100644
--- a/remote/modules/pam/pam.conf.zypper
+++ b/remote/modules/pam/pam.conf.zypper
@@ -1,10 +1,36 @@
-REQUIRED_INSTALLED_PACKAGES=" pam_ldap pam pam-devel nss_ldap pam-modules"
-REQUIRED_CONTENT_PACKAGES=" pam_ldap pam pam-devel nss_ldap pam-modules nss-mdns"
-REQUIRED_BINARIES=" mkhomedir_helper"
-REQUIRED_DIRECTORIES=" /$LIB64
- /usr/$LIB64
- /etc/security"
-REQUIRED_SYSTEM_FILES=" /etc/login.defs
- /etc/securetty
- /$LIB64/security"
+REQUIRED_INSTALLED_PACKAGES="
+ pam_ldap
+ pam
+ pam-devel
+ nss_ldap
+ pam-modules
+ libopenssl-devel
+ openldap2-client
+ nfsidmap
+"
+REQUIRED_CONTENT_PACKAGES="
+ pam_ldap
+ pam
+ pam-devel
+ nss_ldap
+ pam-modules
+ nss-mdns
+ openldap2-client
+ nfsidmap
+"
+REQUIRED_BINARIES="
+ sslconnect
+ ldapsearch
+ mkhomedir_helper
+"
+REQUIRED_DIRECTORIES="
+ /$LIB64
+ /usr/$LIB64
+ /etc/security
+"
+REQUIRED_SYSTEM_FILES="
+ /etc/login.defs
+ /etc/securetty
+ /$LIB64/security
+"
diff --git a/remote/modules/pam/sslconnect.c b/remote/modules/pam/sslconnect.c
new file mode 100644
index 00000000..af43093c
--- /dev/null
+++ b/remote/modules/pam/sslconnect.c
@@ -0,0 +1,201 @@
+/************************
+ * sslconnect 0.2
+ * Last Change: 2013-06-17
+ * C Implementation by Simon Rettberg
+ * Original sslconnect 0.1 was written in perl by Martin Walter
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+/* Init libs and data strctures */
+void init();
+/* print error report of something failed */
+void ssl_error();
+/* connect via ssl */
+SSL* ssl_connect(char * host, uint16_t port, uint16_t local_port, SSL_CTX ** ctx);
+/* read from ssl connection */
+ssize_t ssl_read(SSL * bio, char * buffer, ssize_t length);
+/* write to ssl connection */
+int ssl_write(SSL * bio, char * buffer, ssize_t length);
+
+int main(int argc, char ** argv);
+
+void init()
+{
+ SSL_load_error_strings();
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+}
+
+void ssl_error(char* message)
+{
+ fprintf(stderr, message);
+ fprintf(stderr, "\n%s\n", ERR_error_string(ERR_get_error(), NULL));
+ fprintf(stderr, "Details: %s\n", ERR_reason_error_string(ERR_get_error()));
+ ERR_print_errors_fp(stderr);
+}
+
+SSL* ssl_connect(char * host, uint16_t port, uint16_t local_port, SSL_CTX ** ctx)
+{
+ int ret = 0;
+ /* create socket. needs to be done manually in order to bind to local port */
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd < 0) {
+ fprintf(stderr, "Could not create socket.\n");
+ return NULL;
+ }
+
+ struct sockaddr_in sa_dest, sa_local;
+ memset(&sa_local, 0, sizeof(sa_local));
+ memset(&sa_dest, 0, sizeof(sa_dest));
+
+ sa_local.sin_family = AF_INET;
+ sa_local.sin_port = htons(local_port);
+ ret = bind(fd, (struct sockaddr *)&sa_local, sizeof(struct sockaddr));
+ if (ret == -1) {
+ fprintf(stderr, "Could not bind local socket to 0.0.0.0:%d (%d)\n", (int)local_port, (int)errno);
+ close(fd);
+ return NULL;
+ }
+
+ sa_dest.sin_family = AF_INET;
+ sa_dest.sin_port = htons(port);
+ struct hostent * rec;
+ rec = gethostbyname(host);
+ if (rec == NULL) {
+ fprintf(stderr, "Error: Invalid host: %s\n", host);
+ return NULL;
+ }
+ memcpy(&(sa_dest.sin_addr), rec->h_addr, sizeof(struct in_addr));
+
+ ret = connect(fd, (struct sockaddr *)&sa_dest, sizeof(struct sockaddr));
+ if (ret == -1) {
+ fprintf(stderr, "Could not connect to %s:%d (%d)\n", host, (int)port, (int)errno);
+ close(fd);
+ return NULL;
+ }
+
+ /* openssl part */
+ SSL * ssl;
+
+ /* Set up the SSL pointers */
+ *ctx = SSL_CTX_new(SSLv23_client_method());
+ ssl = SSL_new(*ctx);
+ SSL_set_fd(ssl, fd);
+ ret = SSL_connect(ssl);
+
+ if (ret <= 0) {
+ ssl_error("Unable to SSL_connect");
+ return NULL;
+ }
+
+ SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
+
+ return ssl;
+}
+
+ssize_t ssl_read(SSL * ssl, char * buffer, ssize_t length)
+{
+ ssize_t ret = -1;
+ int retries = 10;
+
+ while (ret < 0 && --retries > 0) {
+
+ ret = SSL_read(ssl, buffer, length);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ ssl_error("SSL_read failed");
+ return -1;
+
+ }
+
+ return -1;
+}
+
+int ssl_write(SSL * ssl, char * buffer, ssize_t length)
+{
+ ssize_t ret = -1;
+ int retries = 10;
+
+ while (ret < 0 && --retries > 0) {
+
+ ret = SSL_write(ssl, buffer, length);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ ssl_error("SSL_write failed");
+ return -1;
+
+ }
+
+ return -1;
+}
+
+#define READBUF 5000
+int main(int argc, char ** argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s host:port\n", argv[0]);
+ return 1;
+ }
+
+ init();
+
+ char buffer[READBUF];
+ SSL_CTX * ctx = NULL;
+ SSL * ssl;
+ ssize_t len;
+ size_t ret;
+ char * pos;
+ int port, lport;
+ pos = strchr(argv[1], ':');
+ if (pos == NULL) {
+ fprintf(stderr, "Error: No Port given.\n");
+ return 5;
+ }
+ port = atoi(pos+1);
+ *pos = '\0';
+
+ lport = rand() % 800 + 95;
+
+ ssl = ssl_connect(argv[1], (uint16_t)port, (uint16_t)lport, &ctx);
+ if (ssl == NULL) {
+ return 2;
+ }
+
+ ssl_write(ssl, "", 0);
+ for (;;) {
+ len = ssl_read(ssl, buffer, READBUF);
+ if (len <= 0) {
+ break;
+ }
+ ret = fwrite(buffer, 1, len, stdout);
+ if (ret != len) {
+ fprintf(stderr, "Error: fwrite could not write all received data to stdout.\n");
+ return 3;
+ }
+ }
+
+ if (len < 0) {
+ return 4;
+ }
+
+ return 0;
+}
+