mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-14 02:22:03 +08:00
kkdcp: perform the proper encoding and decoding on exchanged data
This commit is contained in:
+3
-1
@@ -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
@@ -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
@@ -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 $^ $@
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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));
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user