kkdcp: perform the proper encoding and decoding on exchanged data

This commit is contained in:
Nikos Mavrogiannopoulos
2015-02-19 11:47:20 +01:00
parent 6334bada15
commit 773d277802
10 changed files with 194 additions and 13 deletions
+3 -1
View File
@@ -402,13 +402,15 @@ if test "$test_for_gssapi" = yes;then
PKG_CHECK_MODULES([LIBKRB5], [krb5-gssapi], [
enable_gssapi=yes
AC_DEFINE([HAVE_GSSAPI], [], [GSSAPI was found])
PKG_CHECK_MODULES(LIBTASN1, [libtasn1 >= 3.9])
],
[
AC_MSG_WARN([[
***
*** gssapi not found. Will disable compression support.
*** gssapi not found. Will disable gssapi (and Kerberos) support.
*** ]])
])
fi
dnl needed in the included PCL
+5 -4
View File
@@ -414,10 +414,11 @@ no-route = 192.168.5.0/255.255.255.0
#proxy-url = http://example.com/%{U}/
# This option allows you to specify a URL location where a client can
# post, and the message will be forwarded to the provided server. Any
# reply will be provided as body into POST reply.
#url-fw = /kerberos udp@127.0.0.1:88 application/kerberos
#url-fw = /kerberos1 tcp@127.0.0.1:88 application/kerberos
# post using MS-KKDCP, and the message will be forwarded to the provided
# KDC server. That is a translation URL between HTTP and Kerberos.
# This option is available if ocserv is compiled with GSSAPI support.
#kkdcp = /kerberos udp@127.0.0.1:88 application/kerberos
#kkdcp = /kerberos-tcp tcp@127.0.0.1:88 application/kerberos
#
# The following options are for (experimental) AnyConnect client
+8 -4
View File
@@ -6,11 +6,11 @@ AM_CPPFLAGS = -I$(srcdir)/../gl/ -I$(builddir)/../gl/ \
$(LIBPROTOBUF_C_CFLAGS) $(LIBLZ4_CFLAGS) \
$(LIBNL3_CFLAGS) $(LIBREADLINE_CFLAGS) \
$(LIBTALLOC_CFLAGS) $(LIBDBUS_CFLAGS) \
$(LIBKRB5_CFLAGS)
$(LIBKRB5_CFLAGS) $(LIBTASN1_CFLAGS)
BUILT_SOURCES = ocpasswd-args.c ocpasswd-args.h \
ocserv-args.c ocserv-args.h ipc.pb-c.c ipc.pb-c.h \
ctl.pb-c.c ctl.pb-c.h http-heads.h
ctl.pb-c.c ctl.pb-c.h http-heads.h kkdcp_asn1_tab.c
#AM_CPPFLAGS += -DDEBUG_LEAKS
@@ -82,7 +82,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
vasprintf.c vasprintf.h lzs.c lzs.h \
proc-search.c proc-search.h http-heads.h \
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
$(PROTOBUF_SOURCES)
$(PROTOBUF_SOURCES) kkdcp.asn kkdcp_asn1_tab.c
ocserv_SOURCES += ipc.pb-c.h ipc.pb-c.c ctl.pb-c.c ctl.pb-c.h
@@ -91,7 +91,8 @@ ocserv_LDADD = ../gl/libgnu.a $(NEEDED_LIBOPTS) libcmd-ocserv.a
ocserv_LDADD += $(LIBGNUTLS_LIBS) $(PAM_LIBS) $(LIBUTIL) \
$(LIBSECCOMP) $(LIBWRAP) $(LIBCRYPT) $(NEEDED_HTTP_PARSER_LIBS) \
$(LIBPROTOBUF_C_LIBS) $(LIBSYSTEMD) $(LIBTALLOC_LIBS) \
$(FREERADIUS_CLIENT_LIBS) $(LIBLZ4_LIBS) $(LIBKRB5_LIBS)
$(FREERADIUS_CLIENT_LIBS) $(LIBLZ4_LIBS) $(LIBKRB5_LIBS) \
$(LIBTASN1_LIBS)
if PCL
@@ -142,3 +143,6 @@ ctl.pb-c.h: ctl.pb-c.c
http-heads.h: $(srcdir)/http-heads.gperf
-gperf --global-table -t $^ > $@-tmp && mv $@-tmp $@
kkdcp_asn1_tab.c: $(srcdir)/kkdcp.asn
-asn1Parser $^ $@
+8
View File
@@ -95,7 +95,9 @@ static struct cfg_options available_options[] = {
{ .name = "connect-script", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "disconnect-script", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "pid-file", .type = OPTION_STRING, .mandatory = 0 },
#ifdef HAVE_GSSAPI
{ .name = "kkdcp", .type = OPTION_STRING, .mandatory = 0 },
#endif
{ .name = "socket-file", .type = OPTION_STRING, .mandatory = 1 },
{ .name = "listen-clear-file", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "occtl-socket-file", .type = OPTION_STRING, .mandatory = 0 },
@@ -525,6 +527,7 @@ static void figure_auth_funcs(struct cfg_st *config, char **auth, unsigned auth_
talloc_free(auth);
}
#ifdef HAVE_GSSAPI
static void parse_kkdcp(struct cfg_st *config, char **urlfw, unsigned urlfw_size)
{
unsigned i;
@@ -593,6 +596,7 @@ static void parse_kkdcp(struct cfg_st *config, char **urlfw, unsigned urlfw_size
config->kkdcp_size = urlfw_size;
}
#endif
static void parse_cfg_file(const char* file, struct cfg_st *config, unsigned reload)
{
@@ -656,11 +660,13 @@ unsigned urlfw_size = 0;
READ_TF("listen-host-is-dyndns", config->is_dyndns, 0);
READ_STRING("listen-clear-file", config->unix_conn_file);
#ifdef HAVE_GSSAPI
READ_MULTI_LINE("kkdcp", urlfw, urlfw_size);
if (urlfw_size > 0) {
parse_kkdcp(config, urlfw, urlfw_size);
talloc_free(urlfw);
}
#endif
READ_NUMERIC("tcp-port", config->port);
READ_NUMERIC("udp-port", config->udp_port);
@@ -1074,9 +1080,11 @@ unsigned i;
DEL(config->disconnect_script);
DEL(config->proxy_url);
#ifdef HAVE_GSSAPI
for (i=0;i<config->kkdcp_size;i++)
DEL(config->kkdcp[i].url);
DEL(config->kkdcp);
#endif
DEL(config->network.ipv4);
DEL(config->network.ipv4_netmask);
+13
View File
@@ -0,0 +1,13 @@
KKDCP { }
DEFINITIONS EXPLICIT TAGS ::=
BEGIN
KDC-PROXY-MESSAGE ::= SEQUENCE {
kerb-message [0] OCTET STRING,
target-domain [1] ANY OPTIONAL,
dclocator-hint [2] INTEGER OPTIONAL
}
END
+18
View File
@@ -0,0 +1,18 @@
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <libtasn1.h>
const asn1_static_node kkdcp_asn1_tab[] = {
{ "KKDCP", 536872976, NULL },
{ NULL, 1073741836, NULL },
{ "KDC-PROXY-MESSAGE", 536870917, NULL },
{ "kerb-message", 1610620935, NULL },
{ NULL, 2056, "0"},
{ "target-domain", 1610637325, NULL },
{ NULL, 2056, "1"},
{ "dclocator-hint", 536895491, NULL },
{ NULL, 2056, "2"},
{ NULL, 0, NULL }
};
+18
View File
@@ -61,6 +61,13 @@
#include <ip-lease.h>
#include <ccan/list/list.h>
#ifdef HAVE_GSSAPI
# include <libtasn1.h>
extern const ASN1_ARRAY_TYPE kkdcp_asn1_tab[];
ASN1_TYPE _kkdcp_pkix1_asn = ASN1_TYPE_EMPTY;
#endif
int syslog_open = 0;
static unsigned int terminate = 0;
static unsigned int reload_conf = 0;
@@ -1054,6 +1061,17 @@ int main(int argc, char** argv)
exit(1);
}
#ifdef HAVE_GSSAPI
/* Initialize kkdcp structures */
if (s->config->kkdcp) {
ret = asn1_array2tree(kkdcp_asn1_tab, &_kkdcp_pkix1_asn, NULL);
if (ret != ASN1_SUCCESS) {
fprintf(stderr, "KKDCP ASN.1 initialization error\n");
exit(1);
}
}
#endif
sigprocmask(SIG_BLOCK, &blockset, &sig_default_set);
alarm(MAINTAINANCE_TIME(s));
+7
View File
@@ -493,6 +493,13 @@ no-route = 192.168.5.0/255.255.255.0
#proxy-url = http://example.com/
#proxy-url = http://example.com/%{U}/
# This option allows you to specify a URL location where a client can
# post using MS-KKDCP, and the message will be forwarded to the provided
# KDC server. That is a translation URL between HTTP and Kerberos.
# This option is available if ocserv is compiled with GSSAPI support.
#kkdcp = /kerberos udp@127.0.0.1:88 application/kerberos
#kkdcp = /kerberos-tcp tcp@127.0.0.1:88 application/kerberos
#
# The following options are for (experimental) AnyConnect client
# compatibility.
+108 -4
View File
@@ -27,13 +27,87 @@
#include <vpn.h>
#include <worker.h>
#ifdef HAVE_GSSAPI
int der_decode(const uint8_t *der, unsigned der_size, uint8_t *out, unsigned *out_size, int *error)
{
int ret, len;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
ret = asn1_create_element(_kkdcp_pkix1_asn, "KDC-PROXY-MESSAGE", &c2);
if (ret != ASN1_SUCCESS) {
*error = ret;
return -1;
}
ret = asn1_der_decoding(&c2, der, der_size, NULL);
if (ret != ASN1_SUCCESS) {
*error = ret;
ret = -1;
goto cleanup;
}
len = *out_size;
ret = asn1_read_value(c2, "kerb-message", out, &len);
if (ret != ASN1_SUCCESS) {
*error = ret;
ret = -1;
goto cleanup;
}
*out_size = len;
ret = 0;
cleanup:
asn1_delete_structure(&c2);
return ret;
}
int der_encode_inplace(uint8_t *raw, unsigned *raw_size, unsigned max_size, int *error)
{
int ret, len;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
ret = asn1_create_element(_kkdcp_pkix1_asn, "KDC-PROXY-MESSAGE", &c2);
if (ret != ASN1_SUCCESS) {
*error = ret;
return -1;
}
ret = asn1_write_value(c2, "kerb-message", raw, *raw_size);
if (ret != ASN1_SUCCESS) {
*error = ret;
ret = -1;
goto cleanup;
}
asn1_write_value(c2, "target-domain", NULL, 0);
asn1_write_value(c2, "dclocator-hint", NULL, 0);
len = max_size;
ret = asn1_der_coding(c2, "", raw, &len, NULL);
if (ret != ASN1_SUCCESS) {
*error = ret;
ret = -1;
goto cleanup;
}
*raw_size = len;
ret = 0;
cleanup:
asn1_delete_structure(&c2);
return ret;
}
#define BUF_SIZE 16*1024
int post_kkdcp_handler(worker_st *ws, unsigned http_ver)
{
int ret, e, fd;
struct http_req_st *req = &ws->req;
unsigned i, length;
kkdcp_st *handler = NULL;
char buf[16*1024];
uint8_t *buf = NULL;
const char *reason = "Unknown";
for (i=0;i<ws->config->kkdcp_size;i++) {
@@ -71,8 +145,23 @@ int post_kkdcp_handler(worker_st *ws, unsigned http_ver)
goto fail;
}
ret = send(fd, req->body, req->body_length, 0);
if (ret != req->body_length) {
length = BUF_SIZE;
buf = talloc_size(ws, length);
if (buf == NULL) {
oclog(ws, LOG_INFO, "kkdcp: memory error");
reason = "Memory error";
goto fail;
}
ret = der_decode((uint8_t*)req->body, req->body_length, buf, &length, &e);
if (ret <= 0) {
oclog(ws, LOG_INFO, "kkdcp: DER decoding error: %s", asn1_strerror(e));
reason = "DER decoding error";
goto fail;
}
ret = send(fd, buf, length, 0);
if (ret != length) {
if (ret == -1) {
e = errno;
oclog(ws, LOG_INFO, "kkdcp: send error: %s", strerror(e));
@@ -106,6 +195,13 @@ int post_kkdcp_handler(worker_st *ws, unsigned http_ver)
}
}
ret = der_encode_inplace(buf, &length, BUF_SIZE, &e);
if (ret < 0) {
oclog(ws, LOG_INFO, "kkdcp: DER encoding error: %s", asn1_strerror(e));
reason = "DER encoding error";
goto fail;
}
ret =
cstp_printf(ws, "Content-Length: %u\r\n",
(unsigned int)length);
@@ -142,7 +238,15 @@ int post_kkdcp_handler(worker_st *ws, unsigned http_ver)
ret = -1;
cleanup:
talloc_free(buf);
close(fd);
return ret;
}
#else
int post_kkdcp_handler(worker_st *ws, unsigned http_ver)
{
return -1;
}
#endif
+6
View File
@@ -103,6 +103,12 @@ typedef struct dtls_ciphersuite_st {
unsigned gnutls_version;
} dtls_ciphersuite_st;
#ifdef HAVE_GSSAPI
# include <libtasn1.h>
/* main has initialized that for us */
extern ASN1_TYPE _kkdcp_pkix1_asn;
#endif
struct http_req_st {
char url[256];