Add support for configuring client connections too.
authorLinus Nordberg <linus@nordberg.se>
Mon, 11 Feb 2013 15:41:47 +0000 (16:41 +0100)
committerLinus Nordberg <linus@nordberg.se>
Mon, 11 Feb 2013 15:41:47 +0000 (16:41 +0100)
We're moving x509 and psk config from rs_realm to rs_peer while
allowing these to be configured on the realm level and overriden at
peer level.

Also, add support for printing the read configuration, for debugging.

lib/conf.c
lib/confutil.c [new file with mode: 0644]
lib/event.c
lib/include/radsec/radsec-impl.h
lib/include/radsec/radsec.h
lib/radsec.c
lib/radsec.sym
lib/tls.c

index 8ad0a45..f75e9ed 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2010, 2011, 2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
 #include "util.h"
 #include "debug.h"
 
-#if 0
-  # common config options
-
-  # common realm config options
+#if 0 /* Configuration file syntax. */
+  # realm specific configuration
   realm STRING {
       type = "UDP"|"TCP"|"TLS"|"DTLS"
       timeout = INT
       retries = INT
+  }
+
+  # realm configuration inherited by clients and servers
+  realm STRING {
       cacertfile = STRING
       #cacertpath = STRING
       certfile = STRING
       certkeyfile = STRING
-      pskstr = STRING  # Transport pre-shared key, UTF-8 form.
+      pskstr = STRING   # Transport pre-shared key, UTF-8 form.
       pskhexstr = STRING # Transport pre-shared key, ASCII hex form.
       pskid = STRING
       pskex = "PSK"|"DHE_PSK"|"RSA_PSK"
   }
 
-  # client specific realm config options
+  # client configuration
   realm STRING {
       server {
           hostname = STRING
-         service = STRING
+         service = STRING      # name or port number
+          secret = STRING       # RADIUS secret
+      }
+  }
+
+  # server configuration
+  realm STRING {
+      client {
+          hostname = STRING
+         service = STRING      # name or port number
           secret = STRING       # RADIUS secret
       }
   }
 #endif
 
+struct confcommon {
+  struct rs_credentials *transport_cred;
+  char *cacertfile;
+  char *cacertpath;
+  char *certfile;
+  char *certkeyfile;
+  char *pskstr;
+  char *pskhexstr;
+};
+
+#define CONFGET_STR(dst,cfg,key,def) do {  \
+        (dst) = cfg_getstr ((cfg), (key)); \
+        if ((dst) == NULL) (dst) = (def);  \
+      } while (0)
+#define CONFGET_INT(dst,cfg,key,def) do {  \
+        (dst) = cfg_getint ((cfg), (key)); \
+        if ((dst) == -1) (dst) = (def);    \
+      } while (0)
+
+static int
+confload_peers (struct rs_context *ctx,
+                /*const*/ cfg_t *cfg_realm,
+                enum rs_peer_type type,
+                struct rs_realm *r)
+{
+  const char *peer_type_str[] = {"<no type>", "client", "server"};
+  cfg_t *cfg_peer = NULL;
+  int j;
+  char *def_cacertfile = cfg_getstr (cfg_realm, "cacertfile");
+  /*char *def_cacertpath = cfg_getstr (cfg_realm, "cacertpath");*/
+  char *def_certfile = cfg_getstr (cfg_realm, "certfile");
+  char *def_certkeyfile = cfg_getstr (cfg_realm, "certkeyfile");
+  char *def_pskstr = cfg_getstr (cfg_realm, "pskstr");
+  char *def_pskhexstr = cfg_getstr (cfg_realm, "pskhexstr");
+
+  for (j = 0; j < cfg_size (cfg_realm, peer_type_str[type]); j++)
+    {
+      char *pskstr = NULL;
+      char *pskhexstr = NULL;
+      struct rs_peer *p = peer_create (ctx, &r->peers);
+      if (p == NULL)
+        return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
+                                   NULL);
+      p->type = type;
+      p->realm = r;
+
+      cfg_peer = cfg_getnsec (cfg_realm, peer_type_str[type], j);
+      p->hostname = cfg_getstr (cfg_peer, "hostname");
+      p->service = cfg_getstr (cfg_peer, "service");
+      p->secret = cfg_getstr (cfg_peer, "secret");
+
+      CONFGET_STR (p->cacertfile, cfg_peer, "cacertfile", def_cacertfile);
+      CONFGET_STR (p->certfile, cfg_peer, "certfile", def_certfile);
+      CONFGET_STR (p->certkeyfile, cfg_peer, "certkeyfile", def_certkeyfile);
+      CONFGET_STR (pskstr, cfg_peer, "pskstr", def_pskstr);
+      CONFGET_STR (pskhexstr, cfg_peer, "pskhexstr", def_pskhexstr);
+
+      if (pskstr || pskhexstr)
+        {
+#if defined RS_ENABLE_TLS_PSK
+          char *def_pskex = cfg_getstr (cfg_realm, "pskex");
+          char *tmp_pskex = NULL;
+          rs_cred_type_t type = RS_CRED_NONE;
+          struct rs_credentials *cred = NULL;
+
+          CONFGET_STR (tmp_pskex, cfg_peer, "pskex", def_pskex);
+          if (!strcmp (tmp_pskex, "PSK"))
+            type = RS_CRED_TLS_PSK;
+          else
+            {
+              /* TODO: push a warning on the error stack:*/
+              /*rs_err_ctx_push (ctx, RSE_WARN, "%s: unsupported PSK key exchange"
+                               " algorithm -- PSK not used", kex);*/
+            }
+
+          if (type != RS_CRED_NONE)
+            {
+              char *def_pskid = cfg_getstr (cfg_realm, "pskid");
+              cred = rs_calloc (ctx, 1, sizeof (*cred));
+              if (cred == NULL)
+                return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
+                                           NULL);
+              cred->type = type;
+              CONFGET_STR (cred->identity, cfg_peer, "pskid", def_pskid);
+              if (pskhexstr)
+                {
+                  cred->secret_encoding = RS_KEY_ENCODING_ASCII_HEX;
+                  cred->secret = pskhexstr;
+                  if (pskstr)
+                    ;      /* TODO: warn that we're ignoring pskstr */
+                }
+              else
+                {
+                  cred->secret_encoding = RS_KEY_ENCODING_UTF8;
+                  cred->secret = pskstr;
+                }
+
+              p->transport_cred = cred;
+            }
+#else  /* !RS_ENABLE_TLS_PSK */
+          /* TODO: push a warning on the error stack: */
+          /* rs_err_ctx_push (ctx, RSE_WARN, "libradsec wasn't configured with "
+             "support for TLS preshared keys, ignoring pskstr "
+             "and pskhexstr");*/
+#endif  /* RS_ENABLE_TLS_PSK */
+        }
+
+
+      /* For a TLS or DTLS client or server, validate that we have either of CA
+         cert file/path or PSK.  */
+      if ((r->type == RS_CONN_TYPE_TLS || r->type == RS_CONN_TYPE_DTLS)
+          && (p->cacertfile == NULL && p->cacertpath == NULL)
+          && p->transport_cred == NULL)
+        return rs_err_ctx_push (ctx, RSE_CONFIG,
+                                "%s: missing both CA file/path and PSK",
+                                r->name);
+    }
+
+  return RSE_OK;
+}
+
 /* FIXME: Leaking memory in error cases.  */
 int
 rs_context_read_config(struct rs_context *ctx, const char *config_file)
 {
-  cfg_t *cfg, *cfg_realm, *cfg_server;
+  cfg_t *cfg, *cfg_realm;
   int err = 0;
-  int i, j;
+  int i;
   const char *s;
   struct rs_config *config = NULL;
 
-  cfg_opt_t server_opts[] =
+  cfg_opt_t peer_opts[] =
     {
       CFG_STR ("hostname", NULL, CFGF_NONE),
       CFG_STR ("service", "2083", CFGF_NONE),
       CFG_STR ("secret", "radsec", CFGF_NONE),
+      CFG_STR ("cacertfile", NULL, CFGF_NONE),
+      /*CFG_STR ("cacertpath", NULL, CFGF_NONE),*/
+      CFG_STR ("certfile", NULL, CFGF_NONE),
+      CFG_STR ("certkeyfile", NULL, CFGF_NONE),
+      CFG_STR ("pskstr", NULL, CFGF_NONE),
+      CFG_STR ("pskhexstr", NULL, CFGF_NONE),
+      CFG_STR ("pskid", NULL, CFGF_NONE),
+      CFG_STR ("pskex", "PSK", CFGF_NONE),
+
       CFG_END ()
     };
   cfg_opt_t realm_opts[] =
@@ -73,7 +214,8 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file)
       CFG_STR ("pskhexstr", NULL, CFGF_NONE),
       CFG_STR ("pskid", NULL, CFGF_NONE),
       CFG_STR ("pskex", "PSK", CFGF_NONE),
-      CFG_SEC ("server", server_opts, CFGF_MULTI),
+      CFG_SEC ("server", peer_opts, CFGF_MULTI),
+      CFG_SEC ("client", peer_opts, CFGF_MULTI),
       CFG_END ()
     };
   cfg_opt_t opts[] =
@@ -111,8 +253,9 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file)
     {
       struct rs_realm *r = NULL;
       const char *typestr;
-      char *pskstr = NULL, *pskhexstr = NULL;
+      struct confcommon cc;
 
+      memset (&cc, 0, sizeof(cc));
       r = rs_calloc (ctx, 1, sizeof(*r));
       if (r == NULL)
        return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
@@ -148,87 +291,17 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file)
        return rs_err_ctx_push (ctx, RSE_CONFIG,
                                 "%s: invalid connection type: %s",
                                 r->name, typestr);
+
       r->timeout = cfg_getint (cfg_realm, "timeout");
       r->retries = cfg_getint (cfg_realm, "retries");
 
-      r->cacertfile = cfg_getstr (cfg_realm, "cacertfile");
-      /*r->cacertpath = cfg_getstr (cfg_realm, "cacertpath");*/
-      r->certfile = cfg_getstr (cfg_realm, "certfile");
-      r->certkeyfile = cfg_getstr (cfg_realm, "certkeyfile");
-
-      pskstr = cfg_getstr (cfg_realm, "pskstr");
-      pskhexstr = cfg_getstr (cfg_realm, "pskhexstr");
-      if (pskstr || pskhexstr)
-        {
-#if defined RS_ENABLE_TLS_PSK
-          char *kex = cfg_getstr (cfg_realm, "pskex");
-          rs_cred_type_t type = RS_CRED_NONE;
-          struct rs_credentials *cred = NULL;
-          assert (kex != NULL);
-
-          if (!strcmp (kex, "PSK"))
-            type = RS_CRED_TLS_PSK;
-          else
-            {
-              /* TODO: push a warning on the error stack:*/
-              /*rs_err_ctx_push (ctx, RSE_WARN, "%s: unsupported PSK key exchange"
-                               " algorithm -- PSK not used", kex);*/
-            }
-
-          if (type != RS_CRED_NONE)
-            {
-              cred = rs_calloc (ctx, 1, sizeof (*cred));
-              if (cred == NULL)
-                return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
-                                           NULL);
-              cred->type = type;
-              cred->identity = cfg_getstr (cfg_realm, "pskid");
-              if (pskhexstr)
-                {
-                  cred->secret_encoding = RS_KEY_ENCODING_ASCII_HEX;
-                  cred->secret = pskhexstr;
-                  if (pskstr)
-                    ;      /* TODO: warn that we're ignoring pskstr */
-                }
-              else
-                {
-                  cred->secret_encoding = RS_KEY_ENCODING_UTF8;
-                  cred->secret = pskstr;
-                }
-
-              r->transport_cred = cred;
-            }
-#else  /* !RS_ENABLE_TLS_PSK */
-          /* TODO: push a warning on the error stack: */
-          /* rs_err_ctx_push (ctx, RSE_WARN, "libradsec wasn't configured with "
-                           "support for TLS preshared keys, ignoring pskstr "
-                           "and pskhexstr");*/
-#endif  /* RS_ENABLE_TLS_PSK */
-        }
-
-      /* For TLS and DTLS realms, validate that we either have (i) CA
-         cert file or path or (ii) PSK.  */
-      if ((r->type == RS_CONN_TYPE_TLS || r->type == RS_CONN_TYPE_DTLS)
-          && (r->cacertfile == NULL && r->cacertpath == NULL)
-          && r->transport_cred == NULL)
-        return rs_err_ctx_push (ctx, RSE_CONFIG,
-                                "%s: missing both CA file/path and PSK",
-                                r->name);
-
-      /* Add peers, one per server stanza.  */
-      for (j = 0; j < cfg_size (cfg_realm, "server"); j++)
-       {
-         struct rs_peer *p = peer_create (ctx, &r->peers);
-         if (p == NULL)
-           return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
-                                      NULL);
-         p->realm = r;
-
-         cfg_server = cfg_getnsec (cfg_realm, "server", j);
-         p->hostname = cfg_getstr (cfg_server, "hostname");
-          p->service = cfg_getstr (cfg_server, "service");
-         p->secret = cfg_getstr (cfg_server, "secret");
-       }
+      /* Add client and server peers. */
+      err = confload_peers (ctx, cfg_realm, RS_PEER_TYPE_CLIENT, r);
+      if (err)
+        return err;
+      err = confload_peers (ctx, cfg_realm, RS_PEER_TYPE_SERVER, r);
+      if (err)
+        return err;
     }
 
   /* Save config object in context, for freeing in rs_context_destroy().  */
diff --git a/lib/confutil.c b/lib/confutil.c
new file mode 100644 (file)
index 0000000..3a1d639
--- /dev/null
@@ -0,0 +1,146 @@
+/* Copyright 2013 NORDUnet A/S. All rights reserved.
+   See LICENSE for licensing information.  */
+
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <radsec/radsec.h>
+#include <radsec/radsec-impl.h>
+
+#if 0
+/* This code triggers the memory-stomping-detector of electric fence */
+
+#define MEMCHUNK 30
+
+static int
+print_to_buf (const struct rs_context *ctx,
+              char **buf_ptr, ssize_t *i_ptr, ssize_t *len_ptr,
+              const char *fmt, ...)
+{
+  char *buf = *buf_ptr;
+  ssize_t i = *i_ptr;
+  ssize_t len = *len_ptr;
+
+  va_list args;
+  for (;;)
+    {
+      int n;
+      va_start (args, fmt);
+      fprintf (stdout, "sprintf (%p + %ld, %ld, \"%s\") -->",
+               buf, i, len, buf);
+      fflush (stdout);
+      n = vsnprintf (buf + i, len - i, fmt, args);
+      fprintf (stdout, "%d\n", n);
+      va_end (args);
+      if (n < 0)
+        return -RSE_INTERNAL;
+      if (n >= len - i)
+        {
+          int newlen = len + MEMCHUNK;
+          buf = rs_realloc (ctx, buf, newlen);
+          if (buf == NULL)
+            return -RSE_NOMEM;
+          len = newlen;
+          continue;
+        }
+      len -= n;
+      i += n;
+
+      *buf_ptr = buf;
+      *i_ptr = i;
+      *len_ptr = len;
+      return RSE_OK;
+    }
+}
+#endif  /* 0 */
+
+static int
+pp (char **out, size_t *len, const char *fmt, ...)
+{
+  int n;
+  va_list args;
+  va_start (args, fmt);
+  n = vsnprintf (*out, *len, fmt, args);
+  va_end (args);
+  if (n == -1 || n >= *len)
+    return -RSE_INTERNAL;
+  *out += n;
+  *len -= n;
+  return RSE_OK;
+}
+
+int
+rs_context_print_config (struct rs_context *ctx, char **buf_out)
+{
+  char *buf = rs_malloc (ctx, 8192);
+  char *out = NULL;
+  size_t len = 8192;
+  struct rs_config *cfg = ctx->config;
+  struct rs_realm *r = NULL;
+  struct rs_peer *p = NULL;
+  char *peer_type[] = {"<no type>", "client", "server"};
+  char *realm_type[] = {"<no type>", "UDP", "TCP", "TLS", "DTLS"};
+  char *cred_type[] = {"<no type>", "PSK", "DHE_PSK", "RSA_PSK"};
+
+  out = buf;
+  assert (out);
+  assert (cfg);
+
+  for (r = cfg->realms; r != NULL; r = r->next)
+    {
+      if (pp (&out, &len, "realm %s {\n", r->name)
+          || pp (&out, &len, "\ttype = \"%s\"\n\ttimeout = %d\n\tretries = %d\n",
+                 realm_type[r->type],
+                 r->timeout,
+                 r->retries))
+        return -RSE_INTERNAL;
+      for (p = r->peers; p != NULL; p = p->next)
+        {
+          if (pp (&out, &len,
+                  "\t%s {\n"
+                  "\t\thostname = \"%s\"\n"
+                  "\t\tservice = \"%s\"\n"
+                  "\t\tsecret = \"%s\"\n",
+                  peer_type[p->type],
+                  p->hostname,
+                  p->service,
+                  p->secret))
+            return -RSE_INTERNAL;
+          if (p->cacertfile)
+            if (pp (&out, &len, "\t\tcacertfile = \"%s\"\n", p->cacertfile))
+              return -RSE_INTERNAL;
+          if (p->certfile)
+            if (pp (&out, &len, "\t\tcertfile = \"%s\"\n", p->certfile))
+              return -RSE_INTERNAL;
+          if (p->certkeyfile)
+            if (pp (&out, &len, "\t\tcertkeyfile = \"%s\"\n", p->certkeyfile))
+              return -RSE_INTERNAL;
+          if (p->transport_cred)
+            {
+              if (pp (&out, &len, "\t\tpskex = \"%s\"\n",
+                      cred_type[p->transport_cred->type])
+                  || pp (&out, &len, "\t\tpskid = \"%s\"\n",
+                         p->transport_cred->identity)
+                  || pp (&out, &len,
+                         "\t\t%s = \"%s\"\n", (p->transport_cred->secret_encoding
+                                               == RS_KEY_ENCODING_ASCII_HEX
+                                               ? "pskhexstr" : "pskstr"),
+                         p->transport_cred->secret))
+                return -RSE_INTERNAL;
+            }
+          if (pp (&out, &len, "\t}\n"))
+            return -RSE_INTERNAL;
+        }
+      if (pp (&out, &len, "}\n"))
+        return -RSE_INTERNAL;
+    }
+
+  if (buf_out)
+    *buf_out = buf;
+  return RSE_OK;
+}
index 138fa72..6b7ba48 100644 (file)
@@ -244,11 +244,12 @@ int
 event_on_connect (struct rs_connection *conn, struct rs_message *msg)
 {
   assert (!conn->is_connecting);
+  assert (conn->active_peer);
 
 #if defined (RS_ENABLE_TLS)
   if ((conn->realm->type == RS_CONN_TYPE_TLS
        || conn->realm->type == RS_CONN_TYPE_DTLS)
-      && conn->realm->transport_cred->type != RS_CRED_TLS_PSK)
+      && conn->active_peer->transport_cred->type != RS_CRED_TLS_PSK)
     if (tls_verify_cert (conn) != RSE_OK)
       {
         rs_debug (("%s: server cert verification failed\n", __func__));
index 9f8ebbb..ef01d70 100644 (file)
@@ -40,7 +40,6 @@ struct rs_credentials {
     char *identity;
     char *secret;
     enum rs_key_encoding secret_encoding;
-    unsigned int secret_len;
 };
 
 struct rs_error {
@@ -48,14 +47,25 @@ struct rs_error {
     char buf[1024];
 };
 
+enum rs_peer_type {
+    RS_PEER_TYPE_CLIENT = 1,
+    RS_PEER_TYPE_SERVER = 2
+};
+
 /** Configuration object for a connection.  */
 struct rs_peer {
+    enum rs_peer_type type;
     struct rs_connection *conn;
     struct rs_realm *realm;
     char *hostname;
     char *service;
     char *secret;               /* RADIUS secret.  */
     struct evutil_addrinfo *addr_cache;
+    char *cacertfile;
+    char *cacertpath;
+    char *certfile;
+    char *certkeyfile;
+    struct rs_credentials *transport_cred;
     struct rs_peer *next;
 };
 
@@ -65,11 +75,6 @@ struct rs_realm {
     enum rs_conn_type type;
     int timeout;
     int retries;
-    char *cacertfile;
-    char *cacertpath;
-    char *certfile;
-    char *certkeyfile;
-    struct rs_credentials *transport_cred;
     struct rs_peer *peers;
     struct rs_realm *next;
 };
index ee8c6a8..0a43f6f 100644 (file)
@@ -208,6 +208,9 @@ int rs_context_set_alloc_scheme(struct rs_context *ctx,
     accessed using \a rs_err_ctx_pop.  */
 int rs_context_read_config(struct rs_context *ctx, const char *config_file);
 
+int rs_context_print_config (struct rs_context *ctx, char **buf_out);
+
+
 /****************/
 /* Connection.  */
 /****************/
index db406ae..e6b79cf 100644 (file)
@@ -107,11 +107,11 @@ rs_context_destroy (struct rs_context *ctx)
                   evutil_freeaddrinfo (p->addr_cache);
                   p->addr_cache = NULL;
                 }
+              rs_free (ctx, p->transport_cred);
              p = p->next;
              rs_free (ctx, tmp);
            }
          free (r->name);
-          rs_free (ctx, r->transport_cred);
          r = r->next;
          rs_free (ctx, tmp);
        }
index 11f2468..6378cfd 100644 (file)
@@ -53,6 +53,7 @@ rs_conn_set_timeout
 rs_conn_set_type
 rs_context_create
 rs_context_destroy
+rs_context_print_config
 rs_context_read_config
 rs_context_set_alloc_scheme
 rs_dump_message
index a5040f4..29e7264 100644 (file)
--- a/lib/tls.c
+++ b/lib/tls.c
@@ -25,13 +25,15 @@ _get_tlsconf (struct rs_connection *conn, const struct rs_realm *realm)
   if (c)
     {
       memset (c, 0, sizeof (struct tls));
+      /* _conn_open() should've picked a peer by now. */
+      assert (conn->active_peer);
       /* TODO: Make sure old radsecproxy code doesn't free these all
         of a sudden, or strdup them.  */
       c->name = realm->name;
-      c->cacertfile = realm->cacertfile;
+      c->cacertfile = conn->active_peer->cacertfile;
       c->cacertpath = NULL;    /* NYI */
-      c->certfile = realm->certfile;
-      c->certkeyfile = realm->certkeyfile;
+      c->certfile = conn->active_peer->certfile;
+      c->certkeyfile = conn->active_peer->certkeyfile;
       c->certkeypwd = NULL;    /* NYI */
       c->cacheexpiry = 0;      /* NYI */
       c->crlcheck = 0;         /* NYI */
@@ -54,10 +56,11 @@ psk_client_cb (SSL *ssl,
 {
   struct rs_connection *conn = NULL;
   struct rs_credentials *cred = NULL;
+  unsigned int secret_len;
 
   conn = SSL_get_ex_data (ssl, 0);
   assert (conn != NULL);
-  cred = conn->active_peer->realm->transport_cred;
+  cred = conn->active_peer->transport_cred;
   assert (cred != NULL);
   /* NOTE: Ignoring identity hint from server.  */
 
@@ -72,14 +75,14 @@ psk_client_cb (SSL *ssl,
   switch (cred->secret_encoding)
     {
     case RS_KEY_ENCODING_UTF8:
-      cred->secret_len = strlen (cred->secret);
-      if (cred->secret_len > max_psk_len)
+      secret_len = strlen (cred->secret);
+      if (secret_len > max_psk_len)
         {
           rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
                             max_psk_len);
           return 0;
         }
-      memcpy (psk, cred->secret, cred->secret_len);
+      memcpy (psk, cred->secret, secret_len);
       break;
     case RS_KEY_ENCODING_ASCII_HEX:
       {
@@ -99,7 +102,7 @@ psk_client_cb (SSL *ssl,
             BN_clear_free (bn);
             return 0;
           }
-        cred->secret_len = BN_bn2bin (bn, psk);
+        secret_len = BN_bn2bin (bn, psk);
         BN_clear_free (bn);
       }
       break;
@@ -107,7 +110,7 @@ psk_client_cb (SSL *ssl,
       assert (!"unknown psk encoding");
     }
 
-  return cred->secret_len;
+  return secret_len;
 }
 #endif  /* RS_ENABLE_TLS_PSK */
 
@@ -144,7 +147,7 @@ rs_tls_init (struct rs_connection *conn)
     }
 
 #if defined RS_ENABLE_TLS_PSK
-  if (conn->active_peer->realm->transport_cred != NULL)
+  if (conn->active_peer->transport_cred != NULL)
     {
       SSL_set_psk_client_callback (ssl, psk_client_cb);
       SSL_set_ex_data (ssl, 0, conn);