From aa354bb116fb38c9b049070dea4752afe9a3ea34 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Mon, 27 Sep 2010 18:47:07 +0200 Subject: [PATCH] WIP on libradsec: 94e3f46 Example client crafting simple packet using freeradius-libradius. --- lib/Makefile | 10 +++-- lib/err.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/examples/Makefile | 2 +- lib/examples/client.c | 97 ++++++++-------------------------------- lib/libradsec-impl.h | 45 +++++++++++-------- lib/libradsec.h | 54 ++++++++++++++++++++-- lib/radsec.c | 85 ++++++++++++++++++++++++----------- 7 files changed, 285 insertions(+), 129 deletions(-) create mode 100644 lib/err.c diff --git a/lib/Makefile b/lib/Makefile index 0c29f7a..bc35e88 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,11 +1,15 @@ -CFLAGS = -Wall -g +CFLAGS = -Wall -g -DDEBUG +OFILES = radsec.o err.o packet.o attr.o -all: base.o +all: libradsec.a base.o: base.c libradsec-base.h libradsec.h ../tlv11.h +libradsec.a: $(OFILES) + ar rc $@ $^ + doc: doxygen clean: - -rm *.o + -rm *.o *.a diff --git a/lib/err.c b/lib/err.c new file mode 100644 index 0000000..66c5d94 --- /dev/null +++ b/lib/err.c @@ -0,0 +1,121 @@ +#include +#include "libradsec.h" +#include "libradsec-impl.h" + +const char *_errtxt[] = { + "SUCCESS", /* 0 RSE_OK */ + "NOMEM", /* 1 RSE_NOMEM */ + "NYI -- not yet implemented", /* 2 RSE_NOSYS */ + "invalid handle" /* 3 RSE_INVALID_CTX */ + "invalid connection" /* 4 RSE_INVALID_CONN */ + "ERR 5" /* RSE_ */ + "ERR 6" /* RSE_ */ + "ERR 7" /* RSE_ */ + "ERR 8" /* RSE_ */ + "ERR 9" /* RSE_ */ + "ERR 10" /* RSE_ */ + "ERR 11" /* RSE_ */ + "ERR 12" /* RSE_ */ + "ERR 13" /* RSE_ */ + "ERR " /* RSE_ */ + "ERR " /* RSE_ */ + "ERR " /* RSE_ */ + "ERR " /* RSE_ */ + "ERR " /* RSE_ */ + "ERR " /* RSE_ */ + "ERR " /* RSE_ */ + "some error" /* 21 RSE_SOME_ERROR */ +}; + +static struct rs_error * +_err_new (unsigned int code, const char *msg) +{ + struct rs_error *err; + + err = malloc (sizeof (struct rs_error)); + if (err) + { + memset (err, 0, sizeof (struct rs_error)); + err->code = code; + snprintf (err->buf, sizeof (err->buf), "%s: %s", + code < sizeof (_errtxt) / sizeof (*_errtxt) ? + _errtxt[code] : "invalid error index", + msg); + } + return err; +} + +int +rs_ctx_err_push (struct rs_handle *ctx, int code, const char *msg) +{ + struct rs_error *err = _err_new (code, msg); + + if (err) + ctx->err = err; + return code; +} + +int +rs_conn_err_push (struct rs_connection *conn, int code, const char *msg) +{ + struct rs_error *err = _err_new (code, msg); + + if (err) + conn->err = err; + return code; +} + +struct rs_error * +rs_ctx_err_pop (struct rs_handle *ctx) +{ + struct rs_error *err; + + if (!ctx) + return NULL; /* FIXME: RSE_INVALID_CTX. */ + err = ctx->err; + ctx->err = NULL; + return err; +} + +struct rs_error * +rs_conn_err_pop (struct rs_connection *conn) +{ + struct rs_error *err; + + if (!conn) + return NULL; /* FIXME: RSE_INVALID_CONN */ + err = conn->err; + conn->err = NULL; + return err; +} + +void +rs_err_free (struct rs_error *err) +{ + assert (err); + if (err->msg) + free (err->msg); + free (err); +} + +char * +rs_err_msg (struct rs_error *err) +{ + char *msg; + + if (err->msg) + msg = err->msg; + else + msg = strdup (err->buf); + + rs_err_free (err); + return msg; +} + +int +rs_err_code (struct rs_error *err) +{ + int code = err->code; + rs_err_free(err); + return code; +} diff --git a/lib/examples/Makefile b/lib/examples/Makefile index 1817d90..e07a32b 100644 --- a/lib/examples/Makefile +++ b/lib/examples/Makefile @@ -5,7 +5,7 @@ all: blocking.o blocking.o: blocking.c blocking.h ../libradsec-base.h ../libradsec.h $(CC) $(CFLAGS) -c -I .. $^ -client: client.c ../radsec.o ../libradsec.h ../debug.h +client: client.c ../libradsec.a ../libradsec.h ../libradsec-impl.h $(CC) $(CFLAGS) -o $@ -L /usr/lib/freeradius -lfreeradius-radius $^ clean: diff --git a/lib/examples/client.c b/lib/examples/client.c index 64a4436..37601b6 100644 --- a/lib/examples/client.c +++ b/lib/examples/client.c @@ -3,7 +3,6 @@ #include #include #include -#include #include "../libradsec.h" #include "../debug.h" @@ -12,90 +11,32 @@ #define USER_PW "hemligt" int -rsx_client () +rsx_client (const char *srvname, int srvport) { - fr_randctx fr_ctx; - struct rs_handle *ctx; - struct rs_connection *conn; - RADIUS_PACKET *pkt; - VALUE_PAIR *vp; - char user_pw[MAX_STRING_LEN]; - uint8_t reqauth[AUTH_VECTOR_LEN]; + struct rs_context *h; + struct rs_connecion *conn; + struct rs_packet *req, *resp; - fr_log_fp = stderr; - fr_debug_flag = 1; - fr_randinit (&fr_ctx, 0); - fr_rand_seed (NULL, 0); + if (rs_context_create (&h, "/usr/share/freeradius/dictionary")) + return rs_err_code (rs_ctx_err_code (h)); - printf ("creating context\n"); - if (rs_context_create(&ctx)) - return -1; + if (rs_conn_new (h, &conn)) + return rs_err_code (rs_conn_err_code (conn)); + if (rs_conn_add_server (conn, RS_CONN_TYPE_UDP, srvname, srvport, 10, 3, SECRET)) + return rs_err_code (rs_conn_err_code (conn)); -#if 0 - printf ("reading config\n"); - if (rs_context_config_read(ctx, "libradsec.conf")) - return -1; -#endif + if (rs_packet_create_acc_request (conn, &req, USER_NAME, USER_PW)) + return rs_err_code (rs_conn_err_code (conn)); - printf ("init dict"); - if (dict_init("/usr/share/freeradius", "dictionary")) - return -1; + if (rs_packet_send (req)) + return rs_err_code (rs_conn_err_code (conn)); + req = NULL; -#if 0 - printf ("creating connection\n"); - if (rs_conn_create(ctx, &conn)) - return -1; -#endif + if (rs_packet_recv (conn, &resp)) + return rs_err_code (rs_conn_err_code (conn)); - printf ("creating a packet\n"); - pkt = rad_alloc (1); - if (!pkt) { - fr_perror ("pairmake"); - return -1; - } - - { - size_t pwlen = sizeof(USER_PW); - strncpy (user_pw, USER_PW, sizeof(user_pw)); - rad_pwencode(user_pw, &pwlen, SECRET, reqauth); - } - - printf ("creating value pairs\n"); - vp = pairmake ("User-Name", USER_NAME, 0); - if (!vp) { - fr_perror ("paircreate"); - return -1; - } - pairadd (&vp, pairmake ("User-Password", user_pw, 0)); - pkt->vps = vp; - - printf ("attributes:\n"); - vp_printlist (stdout, vp); - - printf ("encoding packet\n"); - rad_encode (pkt, NULL, SECRET); - print_hex (pkt); /* DEBUG */ - -#if 0 - rs_packet_create (&pkt, RS_ACCESS_REQUEST); - rs_attrib_create (&attr, RS_...); - rs_packet_add_attrib (pkt, attr); -#endif - - //rs_packet_send (conn, pkt, ...); - - rad_free(&pkt); - -#if 0 - printf ("destroying connection\n"); - if (rs_conn_destroy(conn)) - return -1; -#endif - - printf ("destroying context\n"); - rs_context_destroy(ctx); - - return 0; + rs_conn_destroy (conn); + rs_context_destroy (h); } int diff --git a/lib/libradsec-impl.h b/lib/libradsec-impl.h index 913de4a..e9ec644 100644 --- a/lib/libradsec-impl.h +++ b/lib/libradsec-impl.h @@ -3,19 +3,12 @@ /* See the file COPYING for licensing information. */ +#include + /* Constants. */ #define RS_HEADER_LEN 4 /* Data types. */ -enum rs_conn_type { - RS_CONN_TYPE_NONE = 0, - RS_CONN_TYPE_UDP, - RS_CONN_TYPE_TCP, - RS_CONN_TYPE_TLS, - RS_CONN_TYPE_DTLS, -}; -typedef unsigned int rs_conn_type_t; - enum rs_cred_type { RS_CRED_NONE = 0, RS_CRED_TLS_PSK_RSA, /* RFC 4279. */ @@ -28,6 +21,12 @@ struct rs_credentials { char *secret; }; +struct rs_error { + int code; + char *msg; + char buf[1024]; +}; + typedef void * (*rs_calloc_fp)(size_t nmemb, size_t size); typedef void * (*rs_malloc_fp)(size_t size); typedef void (*rs_free_fp)(void *ptr); @@ -59,29 +58,39 @@ struct rs_conn_callbacks { struct rs_handle { struct rs_alloc_scheme alloc_scheme; + struct rs_error *err; + fr_randctx fr_randctx; + /* TODO: dictionary? */ }; +struct rs_peer { + struct addrinfo addr; + char *secret; + int timeout; /* client only */ + int tries; /* client only */ +}; + struct rs_connection { struct rs_handle *ctx; enum rs_conn_type conn_type; struct rs_credentials transport_credentials; struct rs_conn_callbacks callbacks; + struct rs_error *err; + struct rs_peer *peer; }; -struct rs_attribute { - uint8_t type; - uint8_t length; - uint8_t *value; +struct rs_packet { + struct rs_connection *conn; + RADIUS_PACKET *rpkt; }; -struct rs_packet { - uint8_t code; - uint8_t id; - uint8_t auth[16]; - struct list *attrs; +struct rs_attr { + struct rs_packet *pkt; + VALUE_PAIR *vp; }; + /* Convenience macros. */ #define rs_calloc(ctx, nmemb, size) \ (ctx->alloc_scheme.calloc ? ctx->alloc_scheme.calloc : calloc)(nmemb, size) diff --git a/lib/libradsec.h b/lib/libradsec.h index e371747..629e7e1 100644 --- a/lib/libradsec.h +++ b/lib/libradsec.h @@ -4,6 +4,24 @@ #include +enum rs_err_code { + RSE_OK = 0, + RSE_NOMEM = 1, + RSE_NOSYS = 2, + RSE_INVALID_CTX = 3, + RSE_INVALID_CONN = 4, + RSE_SOME_ERROR = 21 +}; + +enum rs_conn_type { + RS_CONN_TYPE_UDP = 0, + RS_CONN_TYPE_TCP, + RS_CONN_TYPE_TLS, + RS_CONN_TYPE_DTLS, +}; +typedef unsigned int rs_conn_type_t; + + /* Data types. */ struct rs_handle; /* radsec-impl.h */ struct rs_alloc_scheme; /* radsec-impl.h */ @@ -11,23 +29,53 @@ struct rs_connection; /* radsec-impl.h */ struct rs_conn_callbacks; /* radsec-impl.h */ struct rs_packet; /* radsec-impl.h */ struct rs_conn; /* radsec-impl.h */ +struct rs_attr; /* radsec-impl.h */ +struct rs_error; /* radsec-impl.h */ struct event_base; /* */ /* Function prototypes. */ -int rs_context_create(struct rs_handle **ctx); +int rs_context_create(struct rs_handle **ctx, const char *dict); void rs_context_destroy(struct rs_handle *ctx); int rs_context_set_alloc_scheme(struct rs_handle *ctx, struct rs_alloc_scheme *scheme); int rs_context_config_read(struct rs_handle *ctx, const char *config_file); int rs_conn_create(const struct rs_handle *ctx, struct rs_connection **conn); +int rs_conn_add_server(struct rs_connection *conn, rs_conn_type_t type, const char *host, int port, int timeout, int tries, const char *secret); +int rs_conn_add_listener(struct rs_connection *conn, rs_conn_type_t type, const char *host, int port, const char *secret); int rs_conn_destroy(struct rs_connection *conn); int rs_conn_set_eventbase(struct rs_connection *conn, struct event_base *eb); int rs_conn_set_callbacks(struct rs_connection *conn, struct rs_conn_callbacks *cb); int rs_conn_set_server(struct rs_connection *conn, const char *name); int rs_conn_get_server(const struct rs_connection *conn, const char *name, size_t buflen); /* NAME <-- most recent server we spoke to */ -int rs_packet_send(const struct rs_conn *conn, const struct rs_packet *pkt, void *user_data); -int rs_packet_receive(const struct rs_conn *conn, struct rs_packet **pkt); +int rs_packet_create_acc_request(struct rs_connection *conn, struct rs_packet **pkt, const char *user_name, const char *user_pw); +//int rs_packet_create_acc_accept(cstruct rs_connection *conn, struct rs_packet **pkt); +//int rs_packet_create_acc_reject(struct rs_connection *conn, struct rs_packet **pkt); +//int rs_packet_create_acc_challenge(struct rs_connection *conn, struct rs_packet **pkt); +void rs_packet_destroy(struct rs_packet *pkt); +int rs_packet_add_attr(struct rs_packet *pkt, const struct rs_attr *attr); +//int rs_packet_add_new_attr(struct rs_packet *pkt, const char *attr_name, const char *attr_val); + +int rs_attr_create(struct rs_connection *conn, struct rs_attr **attr, const char *type, const char *val); +void rs_attr_destroy(struct rs_attr *attr); + +int rs_packet_send(struct rs_conn *conn, const struct rs_packet *pkt, void *user_data); +int rs_packet_receive(struct rs_conn *conn, struct rs_packet **pkt); + + +int rs_ctx_err_push (struct rs_handle *ctx, int code, const char *msg); +int rs_conn_err_push (struct rs_connection *conn, int code, const char *msg); +struct rs_error *rs_ctx_err_pop (struct rs_handle *ctx); +struct rs_error *rs_conn_err_pop (struct rs_connection *conn); +void rs_err_free (struct rs_error *err); +char *rs_err_msg (struct rs_error *err); +int rs_err_code (struct rs_error *err); + +/* Local Variables: */ +/* c-file-style: "stroustrup" */ +/* End: */ + + /* Local Variables: */ /* c-file-style: "stroustrup" */ diff --git a/lib/radsec.c b/lib/radsec.c index 760da84..f645ee1 100644 --- a/lib/radsec.c +++ b/lib/radsec.c @@ -1,17 +1,51 @@ +#include #include #include +#include + +#include #include "libradsec.h" #include "libradsec-impl.h" -#define ERR_OK 0 -#define ERR_NOMEM 1 -#define ERR_NOSYS 2 -#define ERR_SOME_ERROR 99 - -int rs_context_create(struct rs_handle **ctx) +int +rs_context_create(struct rs_handle **ctx, const char *dict) { - *ctx = (struct rs_handle *) malloc (sizeof (struct rs_handle)); - return (ctx ? ERR_OK : ERR_NOMEM); + struct rs_handle *h; + + *ctx = NULL; + h = (struct rs_handle *) malloc (sizeof (struct rs_handle)); + if (h) + { + char *buf; + char *dir, *fn; + + buf = malloc (strlen (dict) + 1); + if (!buf) + { + free (h); + return RSE_NOMEM; + } + strcpy (buf, dict); + dir = dirname (buf); + free (buf); + strcpy (buf, dict); + fn = basename (buf); + free (buf); + if (dict_init (dir, fn) < 0) + { + free (h); + return RSE_SOME_ERROR; + } +#if defined (DEBUG) + fr_log_fp = stderr; + fr_debug_flag = 1; +#endif + fr_randinit (&h->fr_randctx, 0); + fr_rand_seed (NULL, 0); + + *ctx = h; + } + return (h ? RSE_OK : RSE_NOMEM); } void rs_context_destroy(struct rs_handle *ctx) @@ -21,51 +55,50 @@ void rs_context_destroy(struct rs_handle *ctx) int rs_context_set_alloc_scheme(struct rs_handle *ctx, struct rs_alloc_scheme *scheme) { - return ERR_NOSYS; + return RSE_NOSYS; } int rs_context_config_read(struct rs_handle *ctx, const char *config_file) { - return ERR_NOSYS; + return RSE_NOSYS; } int rs_conn_create(const struct rs_handle *ctx, struct rs_connection **conn) { - return ERR_NOSYS; + return RSE_NOSYS; } -int rs_conn_destroy(struct rs_connection *conn) +int rs_conn_add_server(struct rs_connection *conn, rs_conn_type_t type, const char *host, int port, int timeout, int tries, const char *secret) { - return ERR_NOSYS; + return RSE_NOSYS; } -int rs_conn_set_eventbase(struct rs_connection *conn, struct event_base *eb) +int rs_conn_add_listener(struct rs_connection *conn, rs_conn_type_t type, const char *host, int port, const char *secret) { - return ERR_NOSYS; + return RSE_NOSYS; } -int rs_conn_set_callbacks(struct rs_connection *conn, struct rs_conn_callbacks *cb) +int rs_conn_destroy(struct rs_connection *conn) { - return ERR_NOSYS; + return RSE_NOSYS; } -int rs_conn_set_server(struct rs_connection *conn, const char *name) +int rs_conn_set_eventbase(struct rs_connection *conn, struct event_base *eb) { - return ERR_NOSYS; + return RSE_NOSYS; } -int rs_conn_get_server(const struct rs_connection *conn, const char *name, size_t buflen) +int rs_conn_set_callbacks(struct rs_connection *conn, struct rs_conn_callbacks *cb) { - return ERR_NOSYS; + return RSE_NOSYS; } -int rs_packet_send(const struct rs_conn *conn, const struct rs_packet *pkt, void *user_data) +int rs_conn_set_server(struct rs_connection *conn, const char *name) { - return ERR_NOSYS; + return RSE_NOSYS; } -int rs_packet_receive(const struct rs_conn *conn, struct rs_packet **pkt) +int rs_conn_get_server(const struct rs_connection *conn, const char *name, size_t buflen) { - return ERR_NOSYS; + return RSE_NOSYS; } - -- 2.1.4