+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;
+}
+