diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/conf.c | 69 | ||||
-rw-r--r-- | lib/examples/client-blocking.c | 14 | ||||
-rw-r--r-- | lib/examples/client-udp.conf | 10 | ||||
-rw-r--r-- | lib/examples/client.conf (renamed from lib/examples/client-tls.conf) | 17 | ||||
-rw-r--r-- | lib/include/radsec/radsec-impl.h | 16 | ||||
-rw-r--r-- | lib/include/radsec/radsec.h | 24 | ||||
-rw-r--r-- | lib/radsec.c | 111 |
7 files changed, 161 insertions, 100 deletions
@@ -13,8 +13,11 @@ #include "debug.h" #if 0 - # client config options - config NAME { + # common config options + dictionary = STRING + + # common realm config options + realm NAME { type = "UDP"|"TCP"|"TLS"|"DTLS" timeout = INT retries = INT @@ -22,6 +25,10 @@ #cacertpath = STRING certfile = STRING certkeyfile = STRING + } + + # client specific realm config options + realm NAME { server { hostname = STRING service = STRING @@ -33,11 +40,12 @@ int rs_context_read_config(struct rs_context *ctx, const char *config_file) { - /* FIXME: Missing some error handling in rs_context_read_config(). */ + /* FIXME: Missing some error handling! */ - cfg_t *cfg, *cfg_config, *cfg_server; + cfg_t *cfg, *cfg_realm, *cfg_server; int i, j; const char *s; + struct rs_config *config = NULL; cfg_opt_t server_opts[] = { @@ -46,7 +54,7 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file) CFG_STR ("secret", "radsec", CFGF_NONE), CFG_END () }; - cfg_opt_t config_opts[] = + cfg_opt_t realm_opts[] = { CFG_STR ("type", "UDP", CFGF_NONE), CFG_INT ("timeout", 2, CFGF_NONE), /* FIXME: Remove? */ @@ -60,7 +68,8 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file) }; cfg_opt_t opts[] = { - CFG_SEC ("config", config_opts, CFGF_TITLE | CFGF_MULTI), + CFG_STR ("dictionary", NULL, CFGF_NONE), + CFG_SEC ("realm", realm_opts, CFGF_TITLE | CFGF_MULTI), CFG_END () }; @@ -68,31 +77,37 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file) if (cfg_parse (cfg, config_file) == CFG_PARSE_ERROR) return rs_err_ctx_push (ctx, RSE_CONFIG, "%s: invalid configuration file", config_file); - for (i = 0; i < cfg_size (cfg, "config"); i++) + + config = rs_calloc (ctx, 1, sizeof (*config)); + if (config == NULL) + return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL); + ctx->config = config; + config->dictionary = cfg_getstr (cfg, "dictionary"); + + for (i = 0; i < cfg_size (cfg, "realm"); i++) { - struct rs_realm *r = rs_malloc (ctx, sizeof(*r)); + struct rs_realm *r = rs_calloc (ctx, 1, sizeof(*r)); const char *typestr; if (!r) return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL); - memset (r, 0, sizeof(*r)); - if (ctx->realms) + if (config->realms) { - r->next = ctx->realms->next; - ctx->realms->next = r; + r->next = config->realms->next; + config->realms->next = r; } else - ctx->realms = r; - cfg_config = cfg_getnsec (cfg, "config", i); - s = cfg_title (cfg_config); + config->realms = r; + cfg_realm = cfg_getnsec (cfg, "realm", i); + s = cfg_title (cfg_realm); if (s == NULL) return rs_err_ctx_push_fl (ctx, RSE_CONFIG, __FILE__, __LINE__, "missing config name"); - r->name = strdup (s); + r->name = strdup (s); /* FIXME: Don't strdup. */ if (!r->name) return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL); - typestr = cfg_getstr (cfg_config, "type"); + typestr = cfg_getstr (cfg_realm, "type"); if (!strcmp (typestr, "UDP")) r->type = RS_CONN_TYPE_UDP; else if (!strcmp (typestr, "TCP")) @@ -104,16 +119,16 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file) else return rs_err_ctx_push_fl (ctx, RSE_CONFIG, __FILE__, __LINE__, "invalid connection type: %s", typestr); - r->timeout = cfg_getint (cfg_config, "timeout"); - r->retries = cfg_getint (cfg_config, "retries"); + r->timeout = cfg_getint (cfg_realm, "timeout"); + r->retries = cfg_getint (cfg_realm, "retries"); - r->cacertfile = cfg_getstr (cfg_config, "cacertfile"); - /*r->cacertpath = cfg_getstr (cfg_config, "cacertpath");*/ - r->certfile = cfg_getstr (cfg_config, "certfile"); - r->certkeyfile = cfg_getstr (cfg_config, "certkeyfile"); + 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"); /* Add peers, one per server stanza. */ - for (j = 0; j < cfg_size (cfg_config, "server"); j++) + for (j = 0; j < cfg_size (cfg_realm, "server"); j++) { struct rs_peer *p = peer_create (ctx, &r->peers); if (!p) @@ -121,7 +136,7 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file) NULL); p->realm = r; - cfg_server = cfg_getnsec (cfg_config, "server", j); + cfg_server = cfg_getnsec (cfg_realm, "server", j); rs_resolv (&p->addr, r->type, cfg_getstr (cfg_server, "hostname"), cfg_getstr (cfg_server, "service")); p->secret = cfg_getstr (cfg_server, "secret"); @@ -130,7 +145,7 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file) /* Save config object in context, for freeing in rs_context_destroy(). */ - ctx->cfg = cfg; + ctx->config->cfg = cfg; return RSE_OK; } @@ -139,7 +154,7 @@ rs_conf_find_realm(struct rs_context *ctx, const char *name) { struct rs_realm *r; - for (r = ctx->realms; r; r = r->next) + for (r = ctx->config->realms; r; r = r->next) if (!strcmp (r->name, name)) return r; return NULL; diff --git a/lib/examples/client-blocking.c b/lib/examples/client-blocking.c index 718dc47..23cd674 100644 --- a/lib/examples/client-blocking.c +++ b/lib/examples/client-blocking.c @@ -23,13 +23,15 @@ blocking_client (const char *av1, const char *av2, int use_request_object_flag) struct rs_packet *req = NULL, *resp = NULL; struct rs_error *err = NULL; - if (rs_context_create (&h, "/usr/share/freeradius/dictionary")) + if (rs_context_create (&h)) return NULL; #if !defined (USE_CONFIG_FILE) { struct rs_peer *server; + if (rs_context_init_freeradius_dict (h, "/usr/share/freeradius/dictionary")) + goto cleanup; if (rs_conn_create (h, &conn, NULL)) goto cleanup; rs_conn_set_type (conn, RS_CONN_TYPE_UDP); @@ -42,12 +44,14 @@ blocking_client (const char *av1, const char *av2, int use_request_object_flag) if (rs_peer_set_secret (server, SECRET)) goto cleanup; } -#else +#else /* defined (USE_CONFIG_FILE) */ if (rs_context_read_config (h, av1)) goto cleanup; + if (rs_context_init_freeradius_dict (h, NULL)) + goto cleanup; if (rs_conn_create (h, &conn, av2)) goto cleanup; -#endif /* USE_CONFIG_FILE */ +#endif /* defined (USE_CONFIG_FILE) */ if (use_request_object_flag) { @@ -78,7 +82,9 @@ blocking_client (const char *av1, const char *av2, int use_request_object_flag) fprintf (stderr, "%s: no response\n", __func__); cleanup: - err = rs_err_conn_pop (conn); + err = rs_err_ctx_pop (h); + if (err == RSE_OK) + err = rs_err_conn_pop (conn); if (resp) rs_packet_destroy (resp); if (request) diff --git a/lib/examples/client-udp.conf b/lib/examples/client-udp.conf deleted file mode 100644 index 8578e8b..0000000 --- a/lib/examples/client-udp.conf +++ /dev/null @@ -1,10 +0,0 @@ -config blocking-udp { - type = "UDP" - timeout = 2 - retries = 2 - server { - hostname = "127.0.0.1" - service = "1820" - secret = "sikrit" - } -} diff --git a/lib/examples/client-tls.conf b/lib/examples/client.conf index 4d0904d..c9500e8 100644 --- a/lib/examples/client-tls.conf +++ b/lib/examples/client.conf @@ -1,9 +1,22 @@ -config blocking-tls { +dictionary = "/usr/share/freeradius/dictionary" + +realm blocking-udp { + type = "UDP" + timeout = 2 + retries = 2 + server { + hostname = "127.0.0.1" + service = "1820" + secret = "sikrit" + } +} + +realm blocking-tls { type = "TLS" timeout = 1 retries = 3 cacertfile = "/home/linus/nordberg-ca.crt" -# cacertfile = "/home/linus/p/moonshot/demoCA/cacert.pem" + #cacertfile = "/home/linus/p/moonshot/demoCA/cacert.pem" certfile = "/home/linus/p/moonshot/radsecproxy-test.crt" certkeyfile = "/home/linus/p/moonshot/radsecproxy-test.key" server { diff --git a/lib/include/radsec/radsec-impl.h b/lib/include/radsec/radsec-impl.h index 3c1c53c..f8891ee 100644 --- a/lib/include/radsec/radsec-impl.h +++ b/lib/include/radsec/radsec-impl.h @@ -35,7 +35,8 @@ struct rs_error { char buf[1024]; }; -struct rs_peer { /* Config object for a connection. */ +/** Configuration object for a connection. */ +struct rs_peer { struct rs_connection *conn; struct rs_realm *realm; struct evutil_addrinfo *addr; @@ -43,7 +44,8 @@ struct rs_peer { /* Config object for a connection. */ struct rs_peer *next; }; -struct rs_realm { /* Config object for a RADIUS realm. */ +/** Configuration object for a RADIUS realm. */ +struct rs_realm { char *name; enum rs_conn_type type; int timeout; @@ -56,12 +58,18 @@ struct rs_realm { /* Config object for a RADIUS realm. */ struct rs_realm *next; }; -struct rs_context { +/** Top configuration object. */ +struct rs_config { + char *dictionary; struct rs_realm *realms; + cfg_t *cfg; +}; + +struct rs_context { + struct rs_config *config; struct rs_alloc_scheme alloc_scheme; struct rs_error *err; fr_randctx fr_randctx; - cfg_t *cfg; }; struct rs_connection { diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h index 6b0a69c..a35077c 100644 --- a/lib/include/radsec/radsec.h +++ b/lib/include/radsec/radsec.h @@ -91,18 +91,30 @@ struct rs_conn_callbacks { that the context must not be freed before all other libradsec objects have been freed. - \a ctx Address of pointer to a struct rs_context. This is the output. + \a ctx Address of pointer to a struct rs_context. This is the + output of this function. - \a dict Name of a FreeRADIUS dictionary. - - \return RSE_OK (0) on success, RSE_NOMEM on out of memory or - RSE_FR on FreeRADIUS initialization error. */ -int rs_context_create(struct rs_context **ctx, const char *dict); + \return RSE_OK (0) on success or RSE_NOMEM on out of memory. */ +int rs_context_create(struct rs_context **ctx); /** Free a context. Note that the context must not be freed before all other libradsec objects have been freed. */ void rs_context_destroy(struct rs_context *ctx); +/** Initialize FreeRADIUS dictionary needed for creating packets. + + \a ctx Context. + + \a dict Optional string with full path to FreeRADIUS dictionary. + If \a dict is NULL the path to the dictionary file is taken from + the "dictionary" configuration directive. Note that the + configuration file must be read prior to using this option (see \a + rs_context_read_config). + + \return RSE_OK (0) on success, RSE_NOMEM on memory allocation + error and RSE_FR on FreeRADIUS error. */ +int rs_context_init_freeradius_dict(struct rs_context *ctx, const char *dict); + /** Set allocation scheme to use. \a scheme is the allocation scheme to use, see \a rs_alloc_scheme. \return On success, RSE_OK (0) is returned. On error, !0 is returned and a struct \a rs_error is diff --git a/lib/radsec.c b/lib/radsec.c index a05a22b..6ff047d 100644 --- a/lib/radsec.c +++ b/lib/radsec.c @@ -28,14 +28,9 @@ /* Public functions. */ int -rs_context_create (struct rs_context **ctx, const char *dict) +rs_context_create (struct rs_context **ctx) { - int err = RSE_OK; struct rs_context *h; - char *buf1 = NULL, *buf2 = NULL; - char *dir, *fn; - - assert (dict); if (ctx) *ctx = NULL; @@ -43,26 +38,6 @@ rs_context_create (struct rs_context **ctx, const char *dict) if (!h) return RSE_NOMEM; - /* Initialize freeradius dictionary. */ - buf1 = malloc (strlen (dict) + 1); - buf2 = malloc (strlen (dict) + 1); - if (!buf1 || !buf2) - { - err = RSE_NOMEM; - goto err_out; - } - strcpy (buf1, dict); - dir = dirname (buf1); - strcpy (buf2, dict); - fn = basename (buf2); - if (dict_init (dir, fn) < 0) - { - err = RSE_FR; - goto err_out; - } - free (buf1); - free (buf2); - #if defined (RS_ENABLE_TLS) ssl_init (); #endif @@ -80,15 +55,48 @@ rs_context_create (struct rs_context **ctx, const char *dict) *ctx = h; return RSE_OK; +} - err_out: - if (buf1) - free (buf1); - if (buf2) - free (buf2); - if (h) - free (h); - return err; +/** Initialize freeradius dictionary. */ +int +rs_context_init_freeradius_dict (struct rs_context *ctx, const char *dict) +{ + int r = RSE_OK; + size_t dictlen; + char *dir = NULL; + char *fn = NULL; + + if (dict == NULL) + if (ctx->config != NULL) + dict = ctx->config->dictionary; + + if (dict == NULL) + return rs_err_ctx_push_fl (ctx, RSE_INVAL, __FILE__, __LINE__, + "missing dictionary"); + + dictlen = strlen (dict); + dir = rs_calloc (ctx, 1, dictlen + 1); + fn = rs_calloc (ctx, 1, dictlen + 1); + if (dir == NULL || fn == NULL) + { + r = rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL); + goto out; + } + strncpy (dir, dict, dictlen); + strncpy (fn, dict, dictlen); + + if (dict_init (dirname (dir), basename (fn)) < 0) + { + r = rs_err_ctx_push_fl (ctx, RSE_FR, __FILE__, __LINE__, "dict_init"); + goto out; + } + + out: + if (dir) + rs_free (ctx, dir); + if (fn) + rs_free (ctx, fn); + return r; } struct rs_error * /* FIXME: Return int as all the others? */ @@ -137,25 +145,34 @@ rs_context_destroy (struct rs_context *ctx) struct rs_realm *r = NULL; struct rs_peer *p = NULL; - for (r = ctx->realms; r; ) + if (ctx->config) { - struct rs_realm *tmp = r; - for (p = r->peers; p; ) + for (r = ctx->config->realms; r; ) { - struct rs_peer *tmp = p; - if (p->addr) - evutil_freeaddrinfo (p->addr); - p = p->next; + struct rs_realm *tmp = r; + for (p = r->peers; p; ) + { + struct rs_peer *tmp = p; + if (p->addr) + evutil_freeaddrinfo (p->addr); + p = p->next; + rs_free (ctx, tmp); + } + rs_free (ctx, r->name); /* FIXME: Stop freeing once we stop strdup in rs_context_read_config(). */ + r = r->next; rs_free (ctx, tmp); } - rs_free (ctx, r->name); - r = r->next; - rs_free (ctx, tmp); } - if (ctx->cfg) - cfg_free (ctx->cfg); - ctx->cfg = NULL; + if (ctx->config) + { + if (ctx->config->cfg) + { + cfg_free (ctx->config->cfg); + ctx->config->cfg = NULL; + } + rs_free (ctx, ctx->config); + } rs_free (ctx, ctx); } |