import cyrus-sasl-2.1.27-5.el8
This commit is contained in:
parent
9e8c8d78e1
commit
489acc6fdc
@ -0,0 +1,444 @@
|
|||||||
|
From aa8b6b2275fd14ba2cca3d2339ae61c7e7ddfa70 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simo Sorce <simo@redhat.com>
|
||||||
|
Date: Tue, 5 May 2020 14:08:48 -0400
|
||||||
|
Subject: [PATCH] Add Channel Binding support for GSSAPI/GSS-SPNEGO
|
||||||
|
|
||||||
|
Backport of commit ids:
|
||||||
|
829a6ed086432e26dafa9d1dcf892aef4c42cfbd
|
||||||
|
944bd8a6205f840b105206ef83e8f6b9dff0138e
|
||||||
|
|
||||||
|
Signed-off-by: Simo Sorce <simo@redhat.com>
|
||||||
|
---
|
||||||
|
plugins/gssapi.c | 30 +++++++++++---
|
||||||
|
tests/runtests.py | 93 ++++++++++++++++++++++++++++++++++++++++----
|
||||||
|
tests/t_common.c | 24 ++++++++----
|
||||||
|
tests/t_common.h | 5 ++-
|
||||||
|
tests/t_gssapi_cli.c | 24 ++++++++++--
|
||||||
|
tests/t_gssapi_srv.c | 24 ++++++++++--
|
||||||
|
6 files changed, 172 insertions(+), 28 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
|
||||||
|
index ff663da..5d900c5 100644
|
||||||
|
--- a/plugins/gssapi.c
|
||||||
|
+++ b/plugins/gssapi.c
|
||||||
|
@@ -830,7 +830,9 @@ gssapi_server_mech_authneg(context_t *text,
|
||||||
|
gss_buffer_desc name_without_realm;
|
||||||
|
gss_name_t client_name_MN = NULL, without = NULL;
|
||||||
|
gss_OID mech_type;
|
||||||
|
-
|
||||||
|
+ gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS;
|
||||||
|
+ struct gss_channel_bindings_struct cb = {0};
|
||||||
|
+
|
||||||
|
input_token = &real_input_token;
|
||||||
|
output_token = &real_output_token;
|
||||||
|
output_token->value = NULL; output_token->length = 0;
|
||||||
|
@@ -902,6 +904,12 @@ gssapi_server_mech_authneg(context_t *text,
|
||||||
|
real_input_token.length = clientinlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (params->cbinding != NULL) {
|
||||||
|
+ cb.application_data.length = params->cbinding->len;
|
||||||
|
+ cb.application_data.value = params->cbinding->data;
|
||||||
|
+ bindings = &cb;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
|
GSS_LOCK_MUTEX_CTX(params->utils, text);
|
||||||
|
maj_stat =
|
||||||
|
@@ -909,7 +917,7 @@ gssapi_server_mech_authneg(context_t *text,
|
||||||
|
&(text->gss_ctx),
|
||||||
|
server_creds,
|
||||||
|
input_token,
|
||||||
|
- GSS_C_NO_CHANNEL_BINDINGS,
|
||||||
|
+ bindings,
|
||||||
|
&text->client_name,
|
||||||
|
&mech_type,
|
||||||
|
output_token,
|
||||||
|
@@ -1505,7 +1513,8 @@ static sasl_server_plug_t gssapi_server_plugins[] =
|
||||||
|
| SASL_SEC_PASS_CREDENTIALS,
|
||||||
|
SASL_FEAT_WANT_CLIENT_FIRST
|
||||||
|
| SASL_FEAT_ALLOWS_PROXY
|
||||||
|
- | SASL_FEAT_DONTUSE_USERPASSWD, /* features */
|
||||||
|
+ | SASL_FEAT_DONTUSE_USERPASSWD
|
||||||
|
+ | SASL_FEAT_CHANNEL_BINDING, /* features */
|
||||||
|
NULL, /* glob_context */
|
||||||
|
&gssapi_server_mech_new, /* mech_new */
|
||||||
|
&gssapi_server_mech_step, /* mech_step */
|
||||||
|
@@ -1529,6 +1538,7 @@ static sasl_server_plug_t gssapi_server_plugins[] =
|
||||||
|
SASL_FEAT_WANT_CLIENT_FIRST
|
||||||
|
| SASL_FEAT_ALLOWS_PROXY
|
||||||
|
| SASL_FEAT_DONTUSE_USERPASSWD
|
||||||
|
+ | SASL_FEAT_CHANNEL_BINDING
|
||||||
|
| SASL_FEAT_SUPPORTS_HTTP, /* features */
|
||||||
|
&gss_spnego_oid, /* glob_context */
|
||||||
|
&gssapi_server_mech_new, /* mech_new */
|
||||||
|
@@ -1662,6 +1672,8 @@ static int gssapi_client_mech_step(void *conn_context,
|
||||||
|
input_token->value = NULL;
|
||||||
|
input_token->length = 0;
|
||||||
|
gss_cred_id_t client_creds = (gss_cred_id_t)params->gss_creds;
|
||||||
|
+ gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS;
|
||||||
|
+ struct gss_channel_bindings_struct cb = {0};
|
||||||
|
|
||||||
|
if (clientout)
|
||||||
|
*clientout = NULL;
|
||||||
|
@@ -1777,6 +1789,12 @@ static int gssapi_client_mech_step(void *conn_context,
|
||||||
|
req_flags = req_flags | GSS_C_DELEG_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (params->cbinding != NULL) {
|
||||||
|
+ cb.application_data.length = params->cbinding->len;
|
||||||
|
+ cb.application_data.value = params->cbinding->data;
|
||||||
|
+ bindings = &cb;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
GSS_LOCK_MUTEX_CTX(params->utils, text);
|
||||||
|
maj_stat = gss_init_sec_context(&min_stat,
|
||||||
|
client_creds, /* GSS_C_NO_CREDENTIAL */
|
||||||
|
@@ -1785,7 +1803,7 @@ static int gssapi_client_mech_step(void *conn_context,
|
||||||
|
text->mech_type,
|
||||||
|
req_flags,
|
||||||
|
0,
|
||||||
|
- GSS_C_NO_CHANNEL_BINDINGS,
|
||||||
|
+ bindings,
|
||||||
|
input_token,
|
||||||
|
NULL,
|
||||||
|
output_token,
|
||||||
|
@@ -2190,7 +2208,8 @@ static sasl_client_plug_t gssapi_client_plugins[] =
|
||||||
|
| SASL_SEC_PASS_CREDENTIALS, /* security_flags */
|
||||||
|
SASL_FEAT_NEEDSERVERFQDN
|
||||||
|
| SASL_FEAT_WANT_CLIENT_FIRST
|
||||||
|
- | SASL_FEAT_ALLOWS_PROXY, /* features */
|
||||||
|
+ | SASL_FEAT_ALLOWS_PROXY
|
||||||
|
+ | SASL_FEAT_CHANNEL_BINDING, /* features */
|
||||||
|
gssapi_required_prompts, /* required_prompts */
|
||||||
|
GSS_C_NO_OID, /* glob_context */
|
||||||
|
&gssapi_client_mech_new, /* mech_new */
|
||||||
|
@@ -2213,6 +2232,7 @@ static sasl_client_plug_t gssapi_client_plugins[] =
|
||||||
|
SASL_FEAT_NEEDSERVERFQDN
|
||||||
|
| SASL_FEAT_WANT_CLIENT_FIRST
|
||||||
|
| SASL_FEAT_ALLOWS_PROXY
|
||||||
|
+ | SASL_FEAT_CHANNEL_BINDING
|
||||||
|
| SASL_FEAT_SUPPORTS_HTTP, /* features */
|
||||||
|
gssapi_required_prompts, /* required_prompts */
|
||||||
|
&gss_spnego_oid, /* glob_context */
|
||||||
|
diff --git a/tests/runtests.py b/tests/runtests.py
|
||||||
|
index f645adf..fc9cf24 100755
|
||||||
|
--- a/tests/runtests.py
|
||||||
|
+++ b/tests/runtests.py
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
+import base64
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import signal
|
||||||
|
@@ -126,14 +127,7 @@ def setup_kdc(testdir, env):
|
||||||
|
|
||||||
|
return kdc, env
|
||||||
|
|
||||||
|
-
|
||||||
|
-def gssapi_tests(testdir):
|
||||||
|
- """ SASL/GSSAPI Tests """
|
||||||
|
- env = setup_socket_wrappers(testdir)
|
||||||
|
- kdc, kenv = setup_kdc(testdir, env)
|
||||||
|
- #print("KDC: {}, ENV: {}".format(kdc, kenv))
|
||||||
|
- kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
|
||||||
|
-
|
||||||
|
+def gssapi_basic_test(kenv):
|
||||||
|
try:
|
||||||
|
srv = subprocess.Popen(["../tests/t_gssapi_srv"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
@@ -155,11 +149,94 @@ def gssapi_tests(testdir):
|
||||||
|
srv.returncode, srv.stderr.read().decode('utf-8')))
|
||||||
|
except Exception as e:
|
||||||
|
print("FAIL: {}".format(e))
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
+ print("PASS: CLI({}) SRV({})".format(
|
||||||
|
+ cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
+ srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+
|
||||||
|
+def gssapi_channel_binding_test(kenv):
|
||||||
|
+ try:
|
||||||
|
+ bindings = base64.b64encode("MATCHING CBS".encode('utf-8'))
|
||||||
|
+ srv = subprocess.Popen(["../tests/t_gssapi_srv", "-c", bindings],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ srv.stdout.readline() # Wait for srv to say it is ready
|
||||||
|
+ cli = subprocess.Popen(["../tests/t_gssapi_cli", "-c", bindings],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ try:
|
||||||
|
+ cli.wait(timeout=5)
|
||||||
|
+ srv.wait(timeout=5)
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("Failed on {}".format(e));
|
||||||
|
+ cli.kill()
|
||||||
|
+ srv.kill()
|
||||||
|
+ if cli.returncode != 0 or srv.returncode != 0:
|
||||||
|
+ raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
|
||||||
|
+ cli.returncode, cli.stderr.read().decode('utf-8'),
|
||||||
|
+ srv.returncode, srv.stderr.read().decode('utf-8')))
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("FAIL: {}".format(e))
|
||||||
|
+ return
|
||||||
|
|
||||||
|
print("PASS: CLI({}) SRV({})".format(
|
||||||
|
cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
|
||||||
|
+def gssapi_channel_binding_mismatch_test(kenv):
|
||||||
|
+ result = "FAIL"
|
||||||
|
+ try:
|
||||||
|
+ bindings = base64.b64encode("SRV CBS".encode('utf-8'))
|
||||||
|
+ srv = subprocess.Popen(["../tests/t_gssapi_srv", "-c", bindings],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ srv.stdout.readline() # Wait for srv to say it is ready
|
||||||
|
+ bindings = base64.b64encode("CLI CBS".encode('utf-8'))
|
||||||
|
+ cli = subprocess.Popen(["../tests/t_gssapi_cli", "-c", bindings],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ try:
|
||||||
|
+ cli.wait(timeout=5)
|
||||||
|
+ srv.wait(timeout=5)
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("Failed on {}".format(e));
|
||||||
|
+ cli.kill()
|
||||||
|
+ srv.kill()
|
||||||
|
+ if cli.returncode != 0 or srv.returncode != 0:
|
||||||
|
+ cli_err = cli.stderr.read().decode('utf-8').strip()
|
||||||
|
+ srv_err = srv.stderr.read().decode('utf-8').strip()
|
||||||
|
+ if "authentication failure" in srv_err:
|
||||||
|
+ result = "PASS"
|
||||||
|
+ raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
|
||||||
|
+ cli.returncode, cli_err, srv.returncode, srv_err))
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("{}: {}".format(result, e))
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
+ print("FAIL: This test should fail [CLI({}) SRV({})]".format(
|
||||||
|
+ cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
+ srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+
|
||||||
|
+def gssapi_tests(testdir):
|
||||||
|
+ """ SASL/GSSAPI Tests """
|
||||||
|
+ env = setup_socket_wrappers(testdir)
|
||||||
|
+ kdc, kenv = setup_kdc(testdir, env)
|
||||||
|
+ #print("KDC: {}, ENV: {}".format(kdc, kenv))
|
||||||
|
+ kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
|
||||||
|
+
|
||||||
|
+ print('GSSAPI BASIC:')
|
||||||
|
+ print(' ', end='')
|
||||||
|
+ gssapi_basic_test(kenv)
|
||||||
|
+
|
||||||
|
+ print('GSSAPI CHANNEL BINDING:')
|
||||||
|
+ print(' ', end='')
|
||||||
|
+ gssapi_channel_binding_test(kenv)
|
||||||
|
+
|
||||||
|
+ print('GSSAPI CHANNEL BINDING MISMTACH:')
|
||||||
|
+ print(' ', end='')
|
||||||
|
+ gssapi_channel_binding_mismatch_test(kenv)
|
||||||
|
+
|
||||||
|
os.killpg(kdc.pid, signal.SIGTERM)
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/tests/t_common.c b/tests/t_common.c
|
||||||
|
index 7168b2f..478e6a1 100644
|
||||||
|
--- a/tests/t_common.c
|
||||||
|
+++ b/tests/t_common.c
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
-/* TBD, add (C) */
|
||||||
|
+/* Copyright (C) Simo Sorce <simo@redhat.com>
|
||||||
|
+ * See COPYING file for License */
|
||||||
|
|
||||||
|
#include <t_common.h>
|
||||||
|
|
||||||
|
@@ -13,9 +14,6 @@ void send_string(int sd, const char *s, unsigned int l)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
-fprintf(stderr, "s:%u ", l);
|
||||||
|
-fflush(stderr);
|
||||||
|
-
|
||||||
|
ret = send(sd, &l, sizeof(l), 0);
|
||||||
|
if (ret != sizeof(l)) s_error("send size", ret, sizeof(l), errno);
|
||||||
|
|
||||||
|
@@ -34,8 +32,6 @@ void recv_string(int sd, char *buf, unsigned int *buflen)
|
||||||
|
if (ret != sizeof(l)) s_error("recv size", ret, sizeof(l), errno);
|
||||||
|
|
||||||
|
if (l == 0) {
|
||||||
|
-fprintf(stderr, "r:0 ");
|
||||||
|
-fflush(stderr);
|
||||||
|
*buflen = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@@ -45,8 +41,6 @@ fflush(stderr);
|
||||||
|
ret = recv(sd, buf, l, 0);
|
||||||
|
if (ret != l) s_error("recv data", ret, l, errno);
|
||||||
|
|
||||||
|
-fprintf(stderr, "r:%ld ", ret);
|
||||||
|
-fflush(stderr);
|
||||||
|
*buflen = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -65,4 +59,18 @@ int getpath(void *context __attribute__((unused)), const char **path)
|
||||||
|
return SASL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void parse_cb(sasl_channel_binding_t *cb, char *buf, unsigned max, char *in)
|
||||||
|
+{
|
||||||
|
+ unsigned len;
|
||||||
|
+ int r;
|
||||||
|
|
||||||
|
+ r = sasl_decode64(in, strlen(in), buf, max, &len);
|
||||||
|
+ if (r != SASL_OK) {
|
||||||
|
+ saslerr(r, "failed to parse channel bindings");
|
||||||
|
+ exit(-1);
|
||||||
|
+ }
|
||||||
|
+ cb->name = "TEST BINDINGS";
|
||||||
|
+ cb->critical = 0;
|
||||||
|
+ cb->data = (unsigned char *)buf;
|
||||||
|
+ cb->len = len;
|
||||||
|
+}
|
||||||
|
diff --git a/tests/t_common.h b/tests/t_common.h
|
||||||
|
index 4ee1976..a10def1 100644
|
||||||
|
--- a/tests/t_common.h
|
||||||
|
+++ b/tests/t_common.h
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
-/* TBD, add (C) */
|
||||||
|
+/* Copyright (C) Simo Sorce <simo@redhat.com>
|
||||||
|
+ * See COPYING file for License */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
@@ -7,9 +8,11 @@
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <sasl.h>
|
||||||
|
+#include <saslutil.h>
|
||||||
|
|
||||||
|
void s_error(const char *hdr, ssize_t ret, ssize_t len, int err);
|
||||||
|
void send_string(int sd, const char *s, unsigned int l);
|
||||||
|
void recv_string(int sd, char *buf, unsigned int *buflen);
|
||||||
|
void saslerr(int why, const char *what);
|
||||||
|
int getpath(void *context __attribute__((unused)), const char **path);
|
||||||
|
+void parse_cb(sasl_channel_binding_t *cb, char *buf, unsigned max, char *in);
|
||||||
|
diff --git a/tests/t_gssapi_cli.c b/tests/t_gssapi_cli.c
|
||||||
|
index c833c05..a44a3f5 100644
|
||||||
|
--- a/tests/t_gssapi_cli.c
|
||||||
|
+++ b/tests/t_gssapi_cli.c
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
-/* TBD, add (C) */
|
||||||
|
+/* Copyright (C) Simo Sorce <simo@redhat.com>
|
||||||
|
+ * See COPYING file for License */
|
||||||
|
|
||||||
|
#include "t_common.h"
|
||||||
|
|
||||||
|
@@ -13,6 +14,7 @@
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <saslplug.h>
|
||||||
|
+#include <saslutil.h>
|
||||||
|
|
||||||
|
static int setup_socket(void)
|
||||||
|
{
|
||||||
|
@@ -32,7 +34,7 @@ static int setup_socket(void)
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
|
+int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
sasl_callback_t callbacks[2] = {};
|
||||||
|
char buf[8192];
|
||||||
|
@@ -40,8 +42,20 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
|
sasl_conn_t *conn;
|
||||||
|
const char *data;
|
||||||
|
unsigned int len;
|
||||||
|
+ sasl_channel_binding_t cb = {0};
|
||||||
|
+ char cb_buf[256];
|
||||||
|
int sd;
|
||||||
|
- int r;
|
||||||
|
+ int c, r;
|
||||||
|
+
|
||||||
|
+ while ((c = getopt(argc, argv, "c:")) != EOF) {
|
||||||
|
+ switch (c) {
|
||||||
|
+ case 'c':
|
||||||
|
+ parse_cb(&cb, cb_buf, 256, optarg);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* initialize the sasl library */
|
||||||
|
callbacks[0].id = SASL_CB_GETPATH;
|
||||||
|
@@ -60,6 +74,10 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (cb.name) {
|
||||||
|
+ sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
r = sasl_client_start(conn, "GSSAPI", NULL, &data, &len, &chosenmech);
|
||||||
|
if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
saslerr(r, "starting SASL negotiation");
|
||||||
|
diff --git a/tests/t_gssapi_srv.c b/tests/t_gssapi_srv.c
|
||||||
|
index 29f538d..ef1217f 100644
|
||||||
|
--- a/tests/t_gssapi_srv.c
|
||||||
|
+++ b/tests/t_gssapi_srv.c
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
-/* TBD, add (C) */
|
||||||
|
+/* Copyright (C) Simo Sorce <simo@redhat.com>
|
||||||
|
+ * See COPYING file for License */
|
||||||
|
|
||||||
|
#include "t_common.h"
|
||||||
|
|
||||||
|
@@ -44,15 +45,28 @@ static int setup_socket(void)
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
|
+int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
sasl_callback_t callbacks[2] = {};
|
||||||
|
char buf[8192];
|
||||||
|
sasl_conn_t *conn;
|
||||||
|
const char *data;
|
||||||
|
unsigned int len;
|
||||||
|
+ sasl_channel_binding_t cb = {0};
|
||||||
|
+ unsigned char cb_buf[256];
|
||||||
|
int sd;
|
||||||
|
- int r;
|
||||||
|
+ int c, r;
|
||||||
|
+
|
||||||
|
+ while ((c = getopt(argc, argv, "c:")) != EOF) {
|
||||||
|
+ switch (c) {
|
||||||
|
+ case 'c':
|
||||||
|
+ parse_cb(&cb, cb_buf, 256, optarg);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
|
/* initialize the sasl library */
|
||||||
|
callbacks[0].id = SASL_CB_GETPATH;
|
||||||
|
@@ -72,6 +86,10 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (cb.name) {
|
||||||
|
+ sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
sd = setup_socket();
|
||||||
|
|
||||||
|
len = 8192;
|
||||||
|
--
|
||||||
|
2.18.2
|
||||||
|
|
641
SOURCES/cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch
Normal file
641
SOURCES/cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
From 82e299e970461c153a036bb1fbc84e808f926e12 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simo Sorce <simo@redhat.com>
|
||||||
|
Date: Tue, 5 May 2020 14:06:57 -0400
|
||||||
|
Subject: [PATCH] Add basic test infrastructure
|
||||||
|
|
||||||
|
First test is for SASL/GSSAPI
|
||||||
|
|
||||||
|
Backport of upstream commit id:
|
||||||
|
18ff41d5d18f61c2ded7235dad1d9618aa84784b
|
||||||
|
|
||||||
|
Signed-off-by: Simo Sorce <simo@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.am | 2 +-
|
||||||
|
configure.ac | 3 +-
|
||||||
|
tests/Makefile.am | 79 +++++++++++++++++++
|
||||||
|
tests/runtests.py | 179 +++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
tests/t_common.c | 68 ++++++++++++++++
|
||||||
|
tests/t_common.h | 15 ++++
|
||||||
|
tests/t_gssapi_cli.c | 95 +++++++++++++++++++++++
|
||||||
|
tests/t_gssapi_srv.c | 111 +++++++++++++++++++++++++++
|
||||||
|
8 files changed, 550 insertions(+), 2 deletions(-)
|
||||||
|
create mode 100644 tests/Makefile.am
|
||||||
|
create mode 100755 tests/runtests.py
|
||||||
|
create mode 100644 tests/t_common.c
|
||||||
|
create mode 100644 tests/t_common.h
|
||||||
|
create mode 100644 tests/t_gssapi_cli.c
|
||||||
|
create mode 100644 tests/t_gssapi_srv.c
|
||||||
|
|
||||||
|
diff --git a/Makefile.am b/Makefile.am
|
||||||
|
index 83dae6f..fc24509 100644
|
||||||
|
--- a/Makefile.am
|
||||||
|
+++ b/Makefile.am
|
||||||
|
@@ -70,7 +70,7 @@ else
|
||||||
|
INSTALLOSX =
|
||||||
|
endif
|
||||||
|
|
||||||
|
-SUBDIRS=include sasldb common lib plugins utils $(PWC) $(SAM) $(JAV) $(SAD)
|
||||||
|
+SUBDIRS=include sasldb common lib plugins utils $(PWC) $(SAM) $(JAV) $(SAD) tests
|
||||||
|
EXTRA_DIST=config doc docsrc win32 mac dlcompat-20010505 NTMakefile \
|
||||||
|
INSTALL.TXT libsasl2.pc.in
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index ca5936a..c1d2182 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -1575,7 +1575,8 @@ java/javax/Makefile
|
||||||
|
java/javax/security/Makefile
|
||||||
|
java/javax/security/auth/Makefile
|
||||||
|
java/javax/security/auth/callback/Makefile
|
||||||
|
-pwcheck/Makefile)
|
||||||
|
+pwcheck/Makefile
|
||||||
|
+tests/Makefile)
|
||||||
|
|
||||||
|
AC_MSG_NOTICE([
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..1edf010
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/Makefile.am
|
||||||
|
@@ -0,0 +1,79 @@
|
||||||
|
+# Makefile.am -- automake input for cyrus-sasl tests
|
||||||
|
+# Simo Sorce
|
||||||
|
+#
|
||||||
|
+################################################################
|
||||||
|
+# Copyright (c) 2000 Carnegie Mellon University. All rights reserved.
|
||||||
|
+#
|
||||||
|
+# Redistribution and use in source and binary forms, with or without
|
||||||
|
+# modification, are permitted provided that the following conditions
|
||||||
|
+# are met:
|
||||||
|
+#
|
||||||
|
+# 1. Redistributions of source code must retain the above copyright
|
||||||
|
+# notice, this list of conditions and the following disclaimer.
|
||||||
|
+#
|
||||||
|
+# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
+# notice, this list of conditions and the following disclaimer in
|
||||||
|
+# the documentation and/or other materials provided with the
|
||||||
|
+# distribution.
|
||||||
|
+#
|
||||||
|
+# 3. The name "Carnegie Mellon University" must not be used to
|
||||||
|
+# endorse or promote products derived from this software without
|
||||||
|
+# prior written permission. For permission or any other legal
|
||||||
|
+# details, please contact
|
||||||
|
+# Office of Technology Transfer
|
||||||
|
+# Carnegie Mellon University
|
||||||
|
+# 5000 Forbes Avenue
|
||||||
|
+# Pittsburgh, PA 15213-3890
|
||||||
|
+# (412) 268-4387, fax: (412) 268-7395
|
||||||
|
+# tech-transfer@andrew.cmu.edu
|
||||||
|
+#
|
||||||
|
+# 4. Redistributions of any form whatsoever must retain the following
|
||||||
|
+# acknowledgment:
|
||||||
|
+# "This product includes software developed by Computing Services
|
||||||
|
+# at Carnegie Mellon University (http://www.cmu.edu/computing/)."
|
||||||
|
+#
|
||||||
|
+# CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||||
|
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
+# AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
|
||||||
|
+# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||||
|
+# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
+# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
+#
|
||||||
|
+################################################################
|
||||||
|
+
|
||||||
|
+AM_CPPFLAGS=-I$(top_srcdir)/include -DPLUGINDIR='"${top_srcdir}/plugins/.libs"'
|
||||||
|
+
|
||||||
|
+COMMON_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET)
|
||||||
|
+
|
||||||
|
+t_gssapi_cli_SOURCES = \
|
||||||
|
+ t_common.c \
|
||||||
|
+ t_gssapi_cli.c
|
||||||
|
+
|
||||||
|
+t_gssapi_cli_LDADD = $(COMMON_LDADD)
|
||||||
|
+
|
||||||
|
+t_gssapi_srv_SOURCES = \
|
||||||
|
+ t_common.c \
|
||||||
|
+ t_gssapi_srv.c
|
||||||
|
+
|
||||||
|
+t_gssapi_srv_LDADD = $(COMMON_LDADD)
|
||||||
|
+
|
||||||
|
+check_PROGRAMS = \
|
||||||
|
+ t_gssapi_cli \
|
||||||
|
+ t_gssapi_srv \
|
||||||
|
+ $(NULL)
|
||||||
|
+
|
||||||
|
+noinst_PROGRAMS = $(check_PROGRAMS)
|
||||||
|
+
|
||||||
|
+EXTRA_DIST = \
|
||||||
|
+ runtests.py \
|
||||||
|
+ $(NULL)
|
||||||
|
+
|
||||||
|
+all: $(check_PROGRAMS)
|
||||||
|
+
|
||||||
|
+check:
|
||||||
|
+if MACOSX
|
||||||
|
+# skip Mac OSX for now
|
||||||
|
+else
|
||||||
|
+ $(srcdir)/runtests.py $(CHECKARGS)
|
||||||
|
+endif
|
||||||
|
diff --git a/tests/runtests.py b/tests/runtests.py
|
||||||
|
new file mode 100755
|
||||||
|
index 0000000..f645adf
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/runtests.py
|
||||||
|
@@ -0,0 +1,179 @@
|
||||||
|
+#!/usr/bin/python3
|
||||||
|
+
|
||||||
|
+import argparse
|
||||||
|
+import os
|
||||||
|
+import shutil
|
||||||
|
+import signal
|
||||||
|
+import subprocess
|
||||||
|
+import time
|
||||||
|
+from string import Template
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def setup_socket_wrappers(testdir):
|
||||||
|
+ """ Try to set up socket wrappers """
|
||||||
|
+ wrapdir = os.path.join(testdir, 'w')
|
||||||
|
+ os.makedirs(wrapdir)
|
||||||
|
+
|
||||||
|
+ wrappers = subprocess.Popen(['pkg-config', '--exists', 'socket_wrapper'])
|
||||||
|
+ wrappers.wait()
|
||||||
|
+ if wrappers.returncode != 0:
|
||||||
|
+ raise Exception('Socket Wrappers not available')
|
||||||
|
+
|
||||||
|
+ wrappers = subprocess.Popen(['pkg-config', '--exists', 'nss_wrapper'])
|
||||||
|
+ wrappers.wait()
|
||||||
|
+ if wrappers.returncode != 0:
|
||||||
|
+ raise Exception('NSS Wrappers not available')
|
||||||
|
+
|
||||||
|
+ hosts = os.path.join(wrapdir, 'hosts')
|
||||||
|
+ with open(hosts, 'w+') as conffile:
|
||||||
|
+ conffile.write('127.0.0.9 host.realm.test')
|
||||||
|
+
|
||||||
|
+ return {'LD_PRELOAD': 'libsocket_wrapper.so libnss_wrapper.so',
|
||||||
|
+ 'SOCKET_WRAPPER_DIR': wrapdir,
|
||||||
|
+ 'SOCKET_WRAPPER_DEFAULT_IFACE': '9',
|
||||||
|
+ 'NSS_WRAPPER_HOSTNAME': 'host.realm.test',
|
||||||
|
+ 'NSS_WRAPPER_HOSTS': hosts}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+KERBEROS_CONF = '''
|
||||||
|
+[libdefaults]
|
||||||
|
+ default_realm = REALM.TEST
|
||||||
|
+ dns_lookup_realm = false
|
||||||
|
+ dns_lookup_kdc = false
|
||||||
|
+ rdns = false
|
||||||
|
+ ticket_lifetime = 24h
|
||||||
|
+ forwardable = yes
|
||||||
|
+ default_ccache_name = FILE://${TESTDIR}/ccache
|
||||||
|
+ udp_preference_limit = 1
|
||||||
|
+
|
||||||
|
+[domain_realm]
|
||||||
|
+ .realm.test = REALM.TEST
|
||||||
|
+ realm.test = REALM.TEST
|
||||||
|
+
|
||||||
|
+[realms]
|
||||||
|
+ REALM.TEST = {
|
||||||
|
+ kdc = 127.0.0.9
|
||||||
|
+ admin_server = 127.0.0.9
|
||||||
|
+ acl_file = ${TESTDIR}/kadm.acl
|
||||||
|
+ dict_file = /usr/share/dict/words
|
||||||
|
+ admin_keytab = ${TESTDIR}/kadm.keytab
|
||||||
|
+ database_name = ${TESTDIR}/kdc.db
|
||||||
|
+ key_stash_file = ${TESTDIR}/kdc.stash
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+[kdcdefaults]
|
||||||
|
+ kdc_ports = 88
|
||||||
|
+ kdc_tcp_ports = 88
|
||||||
|
+
|
||||||
|
+[logging]
|
||||||
|
+ kdc = FILE:${TESTDIR}/kdc.log
|
||||||
|
+ admin_server = FILE:${TESTDIR}/kadm.log
|
||||||
|
+ default = FILE:${TESTDIR}/krb5.log
|
||||||
|
+'''
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def setup_kdc(testdir, env):
|
||||||
|
+ """ Setup KDC and start process """
|
||||||
|
+ krbconf = os.path.join(testdir, 'krb.conf')
|
||||||
|
+ env['KRB5_CONFIG'] = krbconf
|
||||||
|
+
|
||||||
|
+ kenv = {'KRB5_KDC_PROFILE': krbconf,
|
||||||
|
+ 'PATH': '/sbin:/bin:/usr/sbin:/usr/bin'}
|
||||||
|
+ kenv.update(env)
|
||||||
|
+
|
||||||
|
+ # KDC/KRB5 CONFIG
|
||||||
|
+ templ = Template(KERBEROS_CONF)
|
||||||
|
+ text = templ.substitute({'TESTDIR': testdir})
|
||||||
|
+ with open(krbconf, 'w+') as conffile:
|
||||||
|
+ conffile.write(text)
|
||||||
|
+
|
||||||
|
+ testlog = os.path.join(testdir, 'kdc.log')
|
||||||
|
+ log = open(testlog, 'a')
|
||||||
|
+
|
||||||
|
+ subprocess.check_call([
|
||||||
|
+ "kdb5_util", "create",
|
||||||
|
+ "-r", "REALM.TEST", "-s", "-P", "password"
|
||||||
|
+ ], stdout=log, stderr=log, env=kenv, timeout=5)
|
||||||
|
+
|
||||||
|
+ kdc = subprocess.Popen(['krb5kdc', '-n'], env=kenv, preexec_fn=os.setsid)
|
||||||
|
+ time.sleep(5)
|
||||||
|
+
|
||||||
|
+ # Add a user and genrate a keytab
|
||||||
|
+ keytab = os.path.join(testdir, "user.keytab")
|
||||||
|
+ subprocess.check_call([
|
||||||
|
+ "kadmin.local", "-q",
|
||||||
|
+ "addprinc -randkey user"
|
||||||
|
+ ], stdout=log, stderr=log, env=kenv, timeout=5)
|
||||||
|
+
|
||||||
|
+ subprocess.check_call([
|
||||||
|
+ "kadmin.local", "-q",
|
||||||
|
+ "ktadd -k {} user".format(keytab)
|
||||||
|
+ ], stdout=log, stderr=log, env=kenv, timeout=5)
|
||||||
|
+ env['KRB5_CLIENT_KTNAME'] = keytab
|
||||||
|
+
|
||||||
|
+ # Add a service and genrate a keytab
|
||||||
|
+ keytab = os.path.join(testdir, "test.keytab")
|
||||||
|
+ subprocess.check_call([
|
||||||
|
+ "kadmin.local", "-q",
|
||||||
|
+ "addprinc -randkey test/host.realm.test"
|
||||||
|
+ ], stdout=log, stderr=log, env=kenv, timeout=5)
|
||||||
|
+
|
||||||
|
+ subprocess.check_call([
|
||||||
|
+ "kadmin.local", "-q",
|
||||||
|
+ "ktadd -k {} test/host.realm.test".format(keytab)
|
||||||
|
+ ], stdout=log, stderr=log, env=kenv, timeout=5)
|
||||||
|
+ env['KRB5_KTNAME'] = keytab
|
||||||
|
+
|
||||||
|
+ return kdc, env
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def gssapi_tests(testdir):
|
||||||
|
+ """ SASL/GSSAPI Tests """
|
||||||
|
+ env = setup_socket_wrappers(testdir)
|
||||||
|
+ kdc, kenv = setup_kdc(testdir, env)
|
||||||
|
+ #print("KDC: {}, ENV: {}".format(kdc, kenv))
|
||||||
|
+ kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
|
||||||
|
+
|
||||||
|
+ try:
|
||||||
|
+ srv = subprocess.Popen(["../tests/t_gssapi_srv"],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ srv.stdout.readline() # Wait for srv to say it is ready
|
||||||
|
+ cli = subprocess.Popen(["../tests/t_gssapi_cli"],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ try:
|
||||||
|
+ cli.wait(timeout=5)
|
||||||
|
+ srv.wait(timeout=5)
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("Failed on {}".format(e));
|
||||||
|
+ cli.kill()
|
||||||
|
+ srv.kill()
|
||||||
|
+ if cli.returncode != 0 or srv.returncode != 0:
|
||||||
|
+ raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
|
||||||
|
+ cli.returncode, cli.stderr.read().decode('utf-8'),
|
||||||
|
+ srv.returncode, srv.stderr.read().decode('utf-8')))
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("FAIL: {}".format(e))
|
||||||
|
+
|
||||||
|
+ print("PASS: CLI({}) SRV({})".format(
|
||||||
|
+ cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
+ srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+
|
||||||
|
+ os.killpg(kdc.pid, signal.SIGTERM)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+if __name__ == "__main__":
|
||||||
|
+
|
||||||
|
+ P = argparse.ArgumentParser(description='Cyrus SASL Tests')
|
||||||
|
+ P.add_argument('--testdir', default=os.path.join(os.getcwd(), '.tests'),
|
||||||
|
+ help="Directory for running tests")
|
||||||
|
+ A = vars(P.parse_args())
|
||||||
|
+
|
||||||
|
+ T = A['testdir']
|
||||||
|
+
|
||||||
|
+ if os.path.exists(T):
|
||||||
|
+ shutil.rmtree(T)
|
||||||
|
+ os.makedirs(T)
|
||||||
|
+
|
||||||
|
+ gssapi_tests(T)
|
||||||
|
diff --git a/tests/t_common.c b/tests/t_common.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..7168b2f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/t_common.c
|
||||||
|
@@ -0,0 +1,68 @@
|
||||||
|
+/* TBD, add (C) */
|
||||||
|
+
|
||||||
|
+#include <t_common.h>
|
||||||
|
+
|
||||||
|
+void s_error(const char *hdr, ssize_t ret, ssize_t len, int err)
|
||||||
|
+{
|
||||||
|
+ fprintf(stderr, "%s l:%ld/%ld [%d] %s",
|
||||||
|
+ hdr, ret, len, err, strerror(err));
|
||||||
|
+ exit(-1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void send_string(int sd, const char *s, unsigned int l)
|
||||||
|
+{
|
||||||
|
+ ssize_t ret;
|
||||||
|
+
|
||||||
|
+fprintf(stderr, "s:%u ", l);
|
||||||
|
+fflush(stderr);
|
||||||
|
+
|
||||||
|
+ ret = send(sd, &l, sizeof(l), 0);
|
||||||
|
+ if (ret != sizeof(l)) s_error("send size", ret, sizeof(l), errno);
|
||||||
|
+
|
||||||
|
+ if (l == 0) return;
|
||||||
|
+
|
||||||
|
+ ret = send(sd, s, l, 0);
|
||||||
|
+ if (ret != l) s_error("send data", ret, l, errno);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void recv_string(int sd, char *buf, unsigned int *buflen)
|
||||||
|
+{
|
||||||
|
+ unsigned int l;
|
||||||
|
+ ssize_t ret;
|
||||||
|
+
|
||||||
|
+ ret = recv(sd, &l, sizeof(l), MSG_WAITALL);
|
||||||
|
+ if (ret != sizeof(l)) s_error("recv size", ret, sizeof(l), errno);
|
||||||
|
+
|
||||||
|
+ if (l == 0) {
|
||||||
|
+fprintf(stderr, "r:0 ");
|
||||||
|
+fflush(stderr);
|
||||||
|
+ *buflen = 0;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (*buflen < l) s_error("recv len", l, *buflen, E2BIG);
|
||||||
|
+
|
||||||
|
+ ret = recv(sd, buf, l, 0);
|
||||||
|
+ if (ret != l) s_error("recv data", ret, l, errno);
|
||||||
|
+
|
||||||
|
+fprintf(stderr, "r:%ld ", ret);
|
||||||
|
+fflush(stderr);
|
||||||
|
+ *buflen = ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void saslerr(int why, const char *what)
|
||||||
|
+{
|
||||||
|
+ fprintf(stderr, "%s: %s", what, sasl_errstring(why, NULL, NULL));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int getpath(void *context __attribute__((unused)), const char **path)
|
||||||
|
+{
|
||||||
|
+ if (! path) {
|
||||||
|
+ return SASL_BADPARAM;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *path = PLUGINDIR;
|
||||||
|
+ return SASL_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
diff --git a/tests/t_common.h b/tests/t_common.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..4ee1976
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/t_common.h
|
||||||
|
@@ -0,0 +1,15 @@
|
||||||
|
+/* TBD, add (C) */
|
||||||
|
+
|
||||||
|
+#include "config.h"
|
||||||
|
+
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <sys/socket.h>
|
||||||
|
+
|
||||||
|
+#include <sasl.h>
|
||||||
|
+
|
||||||
|
+void s_error(const char *hdr, ssize_t ret, ssize_t len, int err);
|
||||||
|
+void send_string(int sd, const char *s, unsigned int l);
|
||||||
|
+void recv_string(int sd, char *buf, unsigned int *buflen);
|
||||||
|
+void saslerr(int why, const char *what);
|
||||||
|
+int getpath(void *context __attribute__((unused)), const char **path);
|
||||||
|
diff --git a/tests/t_gssapi_cli.c b/tests/t_gssapi_cli.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..c833c05
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/t_gssapi_cli.c
|
||||||
|
@@ -0,0 +1,95 @@
|
||||||
|
+/* TBD, add (C) */
|
||||||
|
+
|
||||||
|
+#include "t_common.h"
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+#include <ctype.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_UNISTD_H
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#include <arpa/inet.h>
|
||||||
|
+#include <saslplug.h>
|
||||||
|
+
|
||||||
|
+static int setup_socket(void)
|
||||||
|
+{
|
||||||
|
+ struct sockaddr_in addr;
|
||||||
|
+ int sock, ret;
|
||||||
|
+
|
||||||
|
+ sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
+ if (sock < 0) s_error("socket", 0, 0, errno);
|
||||||
|
+
|
||||||
|
+ addr.sin_family = AF_INET;
|
||||||
|
+ addr.sin_addr.s_addr = inet_addr("127.0.0.9");
|
||||||
|
+ addr.sin_port = htons(9000);
|
||||||
|
+
|
||||||
|
+ ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
+ if (ret != 0) s_error("connect", 0, 0, errno);
|
||||||
|
+
|
||||||
|
+ return sock;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
|
+{
|
||||||
|
+ sasl_callback_t callbacks[2] = {};
|
||||||
|
+ char buf[8192];
|
||||||
|
+ const char *chosenmech;
|
||||||
|
+ sasl_conn_t *conn;
|
||||||
|
+ const char *data;
|
||||||
|
+ unsigned int len;
|
||||||
|
+ int sd;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ /* initialize the sasl library */
|
||||||
|
+ callbacks[0].id = SASL_CB_GETPATH;
|
||||||
|
+ callbacks[0].proc = (sasl_callback_ft)&getpath;
|
||||||
|
+ callbacks[0].context = NULL;
|
||||||
|
+ callbacks[1].id = SASL_CB_LIST_END;
|
||||||
|
+ callbacks[1].proc = NULL;
|
||||||
|
+ callbacks[1].context = NULL;
|
||||||
|
+
|
||||||
|
+ r = sasl_client_init(callbacks);
|
||||||
|
+ if (r != SASL_OK) exit(-1);
|
||||||
|
+
|
||||||
|
+ r = sasl_client_new("test", "host.realm.test", NULL, NULL, NULL, 0, &conn);
|
||||||
|
+ if (r != SASL_OK) {
|
||||||
|
+ saslerr(r, "allocating connection state");
|
||||||
|
+ exit(-1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ r = sasl_client_start(conn, "GSSAPI", NULL, &data, &len, &chosenmech);
|
||||||
|
+ if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
+ saslerr(r, "starting SASL negotiation");
|
||||||
|
+ printf("\n%s\n", sasl_errdetail(conn));
|
||||||
|
+ exit(-1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sd = setup_socket();
|
||||||
|
+
|
||||||
|
+ while (r == SASL_CONTINUE) {
|
||||||
|
+ send_string(sd, data, len);
|
||||||
|
+ len = 8192;
|
||||||
|
+ recv_string(sd, buf, &len);
|
||||||
|
+
|
||||||
|
+ r = sasl_client_step(conn, buf, len, NULL, &data, &len);
|
||||||
|
+ if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
+ saslerr(r, "performing SASL negotiation");
|
||||||
|
+ printf("\n%s\n", sasl_errdetail(conn));
|
||||||
|
+ exit(-1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (r != SASL_OK) exit(-1);
|
||||||
|
+
|
||||||
|
+ if (len > 0) {
|
||||||
|
+ send_string(sd, data, len);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fprintf(stdout, "DONE\n");
|
||||||
|
+ fflush(stdout);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
diff --git a/tests/t_gssapi_srv.c b/tests/t_gssapi_srv.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..29f538d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/t_gssapi_srv.c
|
||||||
|
@@ -0,0 +1,111 @@
|
||||||
|
+/* TBD, add (C) */
|
||||||
|
+
|
||||||
|
+#include "t_common.h"
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+#include <ctype.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_UNISTD_H
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#include <arpa/inet.h>
|
||||||
|
+#include <saslplug.h>
|
||||||
|
+
|
||||||
|
+static int setup_socket(void)
|
||||||
|
+{
|
||||||
|
+ struct sockaddr_in addr;
|
||||||
|
+ int sock, ret, sd;
|
||||||
|
+
|
||||||
|
+ sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
+ if (sock < 0) s_error("socket", 0, 0, errno);
|
||||||
|
+
|
||||||
|
+ addr.sin_family = AF_INET;
|
||||||
|
+ addr.sin_addr.s_addr = inet_addr("127.0.0.9");
|
||||||
|
+ addr.sin_port = htons(9000);
|
||||||
|
+
|
||||||
|
+ ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
+ if (ret != 0) s_error("bind", 0, 0, errno);
|
||||||
|
+
|
||||||
|
+ ret = listen(sock, 1);
|
||||||
|
+ if (ret != 0) s_error("listen", 0, 0, errno);
|
||||||
|
+
|
||||||
|
+ /* signal we are ready */
|
||||||
|
+ fprintf(stdout, "READY\n");
|
||||||
|
+ fflush(stdout);
|
||||||
|
+
|
||||||
|
+ /* block until the client connects */
|
||||||
|
+ sd = accept(sock, NULL, NULL);
|
||||||
|
+ if (sd < 0) s_error("accept", 0, 0, errno);
|
||||||
|
+
|
||||||
|
+ close(sock);
|
||||||
|
+ return sd;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
|
+{
|
||||||
|
+ sasl_callback_t callbacks[2] = {};
|
||||||
|
+ char buf[8192];
|
||||||
|
+ sasl_conn_t *conn;
|
||||||
|
+ const char *data;
|
||||||
|
+ unsigned int len;
|
||||||
|
+ int sd;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ /* initialize the sasl library */
|
||||||
|
+ callbacks[0].id = SASL_CB_GETPATH;
|
||||||
|
+ callbacks[0].proc = (sasl_callback_ft)&getpath;
|
||||||
|
+ callbacks[0].context = NULL;
|
||||||
|
+ callbacks[1].id = SASL_CB_LIST_END;
|
||||||
|
+ callbacks[1].proc = NULL;
|
||||||
|
+ callbacks[1].context = NULL;
|
||||||
|
+
|
||||||
|
+ r = sasl_server_init(callbacks, "t_gssapi_srv");
|
||||||
|
+ if (r != SASL_OK) exit(-1);
|
||||||
|
+
|
||||||
|
+ r = sasl_server_new("test", "host.realm.test", NULL, NULL, NULL,
|
||||||
|
+ callbacks, 0, &conn);
|
||||||
|
+ if (r != SASL_OK) {
|
||||||
|
+ saslerr(r, "allocating connection state");
|
||||||
|
+ exit(-1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sd = setup_socket();
|
||||||
|
+
|
||||||
|
+ len = 8192;
|
||||||
|
+ recv_string(sd, buf, &len);
|
||||||
|
+
|
||||||
|
+ r = sasl_server_start(conn, "GSSAPI", buf, len, &data, &len);
|
||||||
|
+ if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
+ saslerr(r, "starting SASL negotiation");
|
||||||
|
+ printf("\n%s\n", sasl_errdetail(conn));
|
||||||
|
+ exit(-1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (r == SASL_CONTINUE) {
|
||||||
|
+ send_string(sd, data, len);
|
||||||
|
+ len = 8192;
|
||||||
|
+ recv_string(sd, buf, &len);
|
||||||
|
+
|
||||||
|
+ r = sasl_server_step(conn, buf, len, &data, &len);
|
||||||
|
+ if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
+ saslerr(r, "performing SASL negotiation");
|
||||||
|
+ printf("\n%s\n", sasl_errdetail(conn));
|
||||||
|
+ exit(-1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (r != SASL_OK) exit(-1);
|
||||||
|
+
|
||||||
|
+ if (len > 0) {
|
||||||
|
+ send_string(sd, data, len);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fprintf(stdout, "DONE\n");
|
||||||
|
+ fflush(stdout);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
--
|
||||||
|
2.18.2
|
||||||
|
|
@ -0,0 +1,435 @@
|
|||||||
|
From 49e965f41257a0ed299c58a7cf1c120ddf944aaa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simo Sorce <simo@redhat.com>
|
||||||
|
Date: Tue, 5 May 2020 14:51:36 -0400
|
||||||
|
Subject: [PATCH] Add support for setting max ssf 0 to GSS-SPNEGO
|
||||||
|
|
||||||
|
Bacport form this proposed PR (still open at bacport time):
|
||||||
|
https://github.com/cyrusimap/cyrus-sasl/pull/603
|
||||||
|
|
||||||
|
Signed-off-by: Simo Sorce <simo@redhat.com>
|
||||||
|
---
|
||||||
|
m4/sasl2.m4 | 13 +++++++
|
||||||
|
plugins/gssapi.c | 44 ++++++++++++++++++++-
|
||||||
|
tests/runtests.py | 91 ++++++++++++++++++++++++++++++++++++++++----
|
||||||
|
tests/t_common.c | 13 ++++---
|
||||||
|
tests/t_common.h | 3 +-
|
||||||
|
tests/t_gssapi_cli.c | 25 ++++++++++--
|
||||||
|
tests/t_gssapi_srv.c | 28 +++++++++++---
|
||||||
|
7 files changed, 194 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/m4/sasl2.m4 b/m4/sasl2.m4
|
||||||
|
index 56e0504..6effe99 100644
|
||||||
|
--- a/m4/sasl2.m4
|
||||||
|
+++ b/m4/sasl2.m4
|
||||||
|
@@ -287,6 +287,19 @@ if test "$gssapi" != no; then
|
||||||
|
AC_CHECK_FUNCS(gss_oid_equal)
|
||||||
|
LIBS="$cmu_save_LIBS"
|
||||||
|
|
||||||
|
+ cmu_save_LIBS="$LIBS"
|
||||||
|
+ LIBS="$LIBS $GSSAPIBASE_LIBS"
|
||||||
|
+ if test "$ac_cv_header_gssapi_gssapi_krb5_h" = "yes"; then
|
||||||
|
+ AC_CHECK_DECL(GSS_KRB5_CRED_NO_CI_FLAGS_X,
|
||||||
|
+ [AC_DEFINE(HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X,1,
|
||||||
|
+ [Define if your GSSAPI implementation supports GSS_KRB5_CRED_NO_CI_FLAGS_X])],,
|
||||||
|
+ [
|
||||||
|
+ AC_INCLUDES_DEFAULT
|
||||||
|
+ #include <gssapi/gssapi_krb5.h>
|
||||||
|
+ ])
|
||||||
|
+ fi
|
||||||
|
+ LIBS="$cmu_save_LIBS"
|
||||||
|
+
|
||||||
|
cmu_save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $GSSAPIBASE_LIBS"
|
||||||
|
AC_CHECK_FUNCS(gss_get_name_attribute)
|
||||||
|
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
|
||||||
|
index 5d900c5..7480316 100644
|
||||||
|
--- a/plugins/gssapi.c
|
||||||
|
+++ b/plugins/gssapi.c
|
||||||
|
@@ -1783,7 +1783,49 @@ static int gssapi_client_mech_step(void *conn_context,
|
||||||
|
/* We want to try for privacy */
|
||||||
|
req_flags |= GSS_C_CONF_FLAG;
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
+#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
|
||||||
|
+ /* The krb5 mechanism automatically adds INTEG and CONF flags even when
|
||||||
|
+ * not specified, this has the effect of rendering explicit requests
|
||||||
|
+ * of no confidentiality and integrity via setting maxssf 0 moot.
|
||||||
|
+ * However to interoperate with Windows machines it needs to be
|
||||||
|
+ * possible to unset these flags as Windows machines refuse to allow
|
||||||
|
+ * two layers (say TLS and GSSAPI) to both provide these services.
|
||||||
|
+ * So if we do not suppress these flags a SASL/GSS-SPNEGO negotiation
|
||||||
|
+ * over, say, LDAPS will fail against Windows Servers */
|
||||||
|
+ } else if (params->props.max_ssf == 0) {
|
||||||
|
+ gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
|
||||||
|
+ if (client_creds == GSS_C_NO_CREDENTIAL) {
|
||||||
|
+ gss_OID_set_desc mechs = { 0 };
|
||||||
|
+ gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
|
||||||
|
+ if (text->mech_type != GSS_C_NO_OID) {
|
||||||
|
+ mechs.count = 1;
|
||||||
|
+ mechs.elements = text->mech_type;
|
||||||
|
+ desired_mechs = &mechs;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME,
|
||||||
|
+ GSS_C_INDEFINITE, desired_mechs,
|
||||||
|
+ GSS_C_INITIATE,
|
||||||
|
+ &text->client_creds, NULL, NULL);
|
||||||
|
+ if (GSS_ERROR(maj_stat)) {
|
||||||
|
+ sasl_gss_seterror(text->utils, maj_stat, min_stat);
|
||||||
|
+ sasl_gss_free_context_contents(text);
|
||||||
|
+ return SASL_FAIL;
|
||||||
|
+ }
|
||||||
|
+ client_creds = text->client_creds;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ maj_stat = gss_set_cred_option(&min_stat, &client_creds,
|
||||||
|
+ (gss_OID)GSS_KRB5_CRED_NO_CI_FLAGS_X,
|
||||||
|
+ &empty_buffer);
|
||||||
|
+ if (GSS_ERROR(maj_stat)) {
|
||||||
|
+ sasl_gss_seterror(text->utils, maj_stat, min_stat);
|
||||||
|
+ sasl_gss_free_context_contents(text);
|
||||||
|
+ return SASL_FAIL;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
|
if (params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) {
|
||||||
|
req_flags = req_flags | GSS_C_DELEG_FLAG;
|
||||||
|
diff --git a/tests/runtests.py b/tests/runtests.py
|
||||||
|
index fc9cf24..4106401 100755
|
||||||
|
--- a/tests/runtests.py
|
||||||
|
+++ b/tests/runtests.py
|
||||||
|
@@ -6,6 +6,7 @@ import os
|
||||||
|
import shutil
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
+import sys
|
||||||
|
import time
|
||||||
|
from string import Template
|
||||||
|
|
||||||
|
@@ -149,11 +150,12 @@ def gssapi_basic_test(kenv):
|
||||||
|
srv.returncode, srv.stderr.read().decode('utf-8')))
|
||||||
|
except Exception as e:
|
||||||
|
print("FAIL: {}".format(e))
|
||||||
|
- return
|
||||||
|
+ return 1
|
||||||
|
|
||||||
|
print("PASS: CLI({}) SRV({})".format(
|
||||||
|
cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+ return 0
|
||||||
|
|
||||||
|
def gssapi_channel_binding_test(kenv):
|
||||||
|
try:
|
||||||
|
@@ -178,11 +180,12 @@ def gssapi_channel_binding_test(kenv):
|
||||||
|
srv.returncode, srv.stderr.read().decode('utf-8')))
|
||||||
|
except Exception as e:
|
||||||
|
print("FAIL: {}".format(e))
|
||||||
|
- return
|
||||||
|
+ return 1
|
||||||
|
|
||||||
|
print("PASS: CLI({}) SRV({})".format(
|
||||||
|
cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+ return 0
|
||||||
|
|
||||||
|
def gssapi_channel_binding_mismatch_test(kenv):
|
||||||
|
result = "FAIL"
|
||||||
|
@@ -212,11 +215,70 @@ def gssapi_channel_binding_mismatch_test(kenv):
|
||||||
|
cli.returncode, cli_err, srv.returncode, srv_err))
|
||||||
|
except Exception as e:
|
||||||
|
print("{}: {}".format(result, e))
|
||||||
|
- return
|
||||||
|
+ return 0
|
||||||
|
|
||||||
|
print("FAIL: This test should fail [CLI({}) SRV({})]".format(
|
||||||
|
cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+ return 1
|
||||||
|
+
|
||||||
|
+def gss_spnego_basic_test(kenv):
|
||||||
|
+ try:
|
||||||
|
+ srv = subprocess.Popen(["../tests/t_gssapi_srv", "-N"],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ srv.stdout.readline() # Wait for srv to say it is ready
|
||||||
|
+ cli = subprocess.Popen(["../tests/t_gssapi_cli", "-N"],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ try:
|
||||||
|
+ cli.wait(timeout=5)
|
||||||
|
+ srv.wait(timeout=5)
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("Failed on {}".format(e));
|
||||||
|
+ cli.kill()
|
||||||
|
+ srv.kill()
|
||||||
|
+ if cli.returncode != 0 or srv.returncode != 0:
|
||||||
|
+ raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
|
||||||
|
+ cli.returncode, cli.stderr.read().decode('utf-8'),
|
||||||
|
+ srv.returncode, srv.stderr.read().decode('utf-8')))
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("FAIL: {}".format(e))
|
||||||
|
+ return 1
|
||||||
|
+
|
||||||
|
+ print("PASS: CLI({}) SRV({})".format(
|
||||||
|
+ cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
+ srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+ return 0
|
||||||
|
+
|
||||||
|
+def gss_spnego_zeromaxssf_test(kenv):
|
||||||
|
+ try:
|
||||||
|
+ srv = subprocess.Popen(["../tests/t_gssapi_srv", "-N", "-z"],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ srv.stdout.readline() # Wait for srv to say it is ready
|
||||||
|
+ cli = subprocess.Popen(["../tests/t_gssapi_cli", "-N", "-z"],
|
||||||
|
+ stdout=subprocess.PIPE,
|
||||||
|
+ stderr=subprocess.PIPE, env=kenv)
|
||||||
|
+ try:
|
||||||
|
+ cli.wait(timeout=5)
|
||||||
|
+ srv.wait(timeout=5)
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("Failed on {}".format(e));
|
||||||
|
+ cli.kill()
|
||||||
|
+ srv.kill()
|
||||||
|
+ if cli.returncode != 0 or srv.returncode != 0:
|
||||||
|
+ raise Exception("CLI ({}): {} --> SRV ({}): {}".format(
|
||||||
|
+ cli.returncode, cli.stderr.read().decode('utf-8'),
|
||||||
|
+ srv.returncode, srv.stderr.read().decode('utf-8')))
|
||||||
|
+ except Exception as e:
|
||||||
|
+ print("FAIL: {}".format(e))
|
||||||
|
+ return 1
|
||||||
|
+
|
||||||
|
+ print("PASS: CLI({}) SRV({})".format(
|
||||||
|
+ cli.stdout.read().decode('utf-8').strip(),
|
||||||
|
+ srv.stdout.read().decode('utf-8').strip()))
|
||||||
|
+ return 0
|
||||||
|
|
||||||
|
def gssapi_tests(testdir):
|
||||||
|
""" SASL/GSSAPI Tests """
|
||||||
|
@@ -225,20 +287,32 @@ def gssapi_tests(testdir):
|
||||||
|
#print("KDC: {}, ENV: {}".format(kdc, kenv))
|
||||||
|
kenv['KRB5_TRACE'] = os.path.join(testdir, 'trace.log')
|
||||||
|
|
||||||
|
+ err = 0
|
||||||
|
+
|
||||||
|
print('GSSAPI BASIC:')
|
||||||
|
print(' ', end='')
|
||||||
|
- gssapi_basic_test(kenv)
|
||||||
|
+ err += gssapi_basic_test(kenv)
|
||||||
|
|
||||||
|
print('GSSAPI CHANNEL BINDING:')
|
||||||
|
print(' ', end='')
|
||||||
|
- gssapi_channel_binding_test(kenv)
|
||||||
|
+ err += gssapi_channel_binding_test(kenv)
|
||||||
|
|
||||||
|
print('GSSAPI CHANNEL BINDING MISMTACH:')
|
||||||
|
print(' ', end='')
|
||||||
|
- gssapi_channel_binding_mismatch_test(kenv)
|
||||||
|
+ err += gssapi_channel_binding_mismatch_test(kenv)
|
||||||
|
+
|
||||||
|
+ print('GSS-SPNEGO BASIC:')
|
||||||
|
+ print(' ', end='')
|
||||||
|
+ err += gss_spnego_basic_test(kenv)
|
||||||
|
+
|
||||||
|
+ print('GSS-SPNEGO 0 MAXSSF:')
|
||||||
|
+ print(' ', end='')
|
||||||
|
+ err += gss_spnego_zeromaxssf_test(kenv)
|
||||||
|
|
||||||
|
os.killpg(kdc.pid, signal.SIGTERM)
|
||||||
|
|
||||||
|
+ return err
|
||||||
|
+
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
@@ -253,4 +327,7 @@ if __name__ == "__main__":
|
||||||
|
shutil.rmtree(T)
|
||||||
|
os.makedirs(T)
|
||||||
|
|
||||||
|
- gssapi_tests(T)
|
||||||
|
+ err = gssapi_tests(T)
|
||||||
|
+ if err != 0:
|
||||||
|
+ print('{} test(s) FAILED'.format(err))
|
||||||
|
+ sys.exit(-1)
|
||||||
|
diff --git a/tests/t_common.c b/tests/t_common.c
|
||||||
|
index 478e6a1..f56098e 100644
|
||||||
|
--- a/tests/t_common.c
|
||||||
|
+++ b/tests/t_common.c
|
||||||
|
@@ -23,20 +23,21 @@ void send_string(int sd, const char *s, unsigned int l)
|
||||||
|
if (ret != l) s_error("send data", ret, l, errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void recv_string(int sd, char *buf, unsigned int *buflen)
|
||||||
|
+void recv_string(int sd, char *buf, unsigned int *buflen, bool allow_eof)
|
||||||
|
{
|
||||||
|
+ unsigned int bufsize = *buflen;
|
||||||
|
unsigned int l;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
+ *buflen = 0;
|
||||||
|
+
|
||||||
|
ret = recv(sd, &l, sizeof(l), MSG_WAITALL);
|
||||||
|
+ if (allow_eof && ret == 0) return;
|
||||||
|
if (ret != sizeof(l)) s_error("recv size", ret, sizeof(l), errno);
|
||||||
|
|
||||||
|
- if (l == 0) {
|
||||||
|
- *buflen = 0;
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
+ if (l == 0) return;
|
||||||
|
|
||||||
|
- if (*buflen < l) s_error("recv len", l, *buflen, E2BIG);
|
||||||
|
+ if (bufsize < l) s_error("recv len", l, bufsize, E2BIG);
|
||||||
|
|
||||||
|
ret = recv(sd, buf, l, 0);
|
||||||
|
if (ret != l) s_error("recv data", ret, l, errno);
|
||||||
|
diff --git a/tests/t_common.h b/tests/t_common.h
|
||||||
|
index a10def1..be24a53 100644
|
||||||
|
--- a/tests/t_common.h
|
||||||
|
+++ b/tests/t_common.h
|
||||||
|
@@ -4,6 +4,7 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
@@ -12,7 +13,7 @@
|
||||||
|
|
||||||
|
void s_error(const char *hdr, ssize_t ret, ssize_t len, int err);
|
||||||
|
void send_string(int sd, const char *s, unsigned int l);
|
||||||
|
-void recv_string(int sd, char *buf, unsigned int *buflen);
|
||||||
|
+void recv_string(int sd, char *buf, unsigned int *buflen, bool allow_eof);
|
||||||
|
void saslerr(int why, const char *what);
|
||||||
|
int getpath(void *context __attribute__((unused)), const char **path);
|
||||||
|
void parse_cb(sasl_channel_binding_t *cb, char *buf, unsigned max, char *in);
|
||||||
|
diff --git a/tests/t_gssapi_cli.c b/tests/t_gssapi_cli.c
|
||||||
|
index a44a3f5..d9eafe1 100644
|
||||||
|
--- a/tests/t_gssapi_cli.c
|
||||||
|
+++ b/tests/t_gssapi_cli.c
|
||||||
|
@@ -46,12 +46,21 @@ int main(int argc, char *argv[])
|
||||||
|
char cb_buf[256];
|
||||||
|
int sd;
|
||||||
|
int c, r;
|
||||||
|
+ const char *sasl_mech = "GSSAPI";
|
||||||
|
+ bool spnego = false;
|
||||||
|
+ bool zeromaxssf = false;
|
||||||
|
|
||||||
|
- while ((c = getopt(argc, argv, "c:")) != EOF) {
|
||||||
|
+ while ((c = getopt(argc, argv, "c:zN")) != EOF) {
|
||||||
|
switch (c) {
|
||||||
|
case 'c':
|
||||||
|
parse_cb(&cb, cb_buf, 256, optarg);
|
||||||
|
break;
|
||||||
|
+ case 'z':
|
||||||
|
+ zeromaxssf = true;
|
||||||
|
+ break;
|
||||||
|
+ case 'N':
|
||||||
|
+ spnego = true;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -78,7 +87,17 @@ int main(int argc, char *argv[])
|
||||||
|
sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
- r = sasl_client_start(conn, "GSSAPI", NULL, &data, &len, &chosenmech);
|
||||||
|
+ if (spnego) {
|
||||||
|
+ sasl_mech = "GSS-SPNEGO";
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (zeromaxssf) {
|
||||||
|
+ /* set all security properties to 0 including maxssf */
|
||||||
|
+ sasl_security_properties_t secprops = { 0 };
|
||||||
|
+ sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ r = sasl_client_start(conn, sasl_mech, NULL, &data, &len, &chosenmech);
|
||||||
|
if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
saslerr(r, "starting SASL negotiation");
|
||||||
|
printf("\n%s\n", sasl_errdetail(conn));
|
||||||
|
@@ -90,7 +109,7 @@ int main(int argc, char *argv[])
|
||||||
|
while (r == SASL_CONTINUE) {
|
||||||
|
send_string(sd, data, len);
|
||||||
|
len = 8192;
|
||||||
|
- recv_string(sd, buf, &len);
|
||||||
|
+ recv_string(sd, buf, &len, false);
|
||||||
|
|
||||||
|
r = sasl_client_step(conn, buf, len, NULL, &data, &len);
|
||||||
|
if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
diff --git a/tests/t_gssapi_srv.c b/tests/t_gssapi_srv.c
|
||||||
|
index ef1217f..448a218 100644
|
||||||
|
--- a/tests/t_gssapi_srv.c
|
||||||
|
+++ b/tests/t_gssapi_srv.c
|
||||||
|
@@ -56,12 +56,21 @@ int main(int argc, char *argv[])
|
||||||
|
unsigned char cb_buf[256];
|
||||||
|
int sd;
|
||||||
|
int c, r;
|
||||||
|
+ const char *sasl_mech = "GSSAPI";
|
||||||
|
+ bool spnego = false;
|
||||||
|
+ bool zeromaxssf = false;
|
||||||
|
|
||||||
|
- while ((c = getopt(argc, argv, "c:")) != EOF) {
|
||||||
|
+ while ((c = getopt(argc, argv, "c:zN")) != EOF) {
|
||||||
|
switch (c) {
|
||||||
|
case 'c':
|
||||||
|
parse_cb(&cb, cb_buf, 256, optarg);
|
||||||
|
break;
|
||||||
|
+ case 'z':
|
||||||
|
+ zeromaxssf = true;
|
||||||
|
+ break;
|
||||||
|
+ case 'N':
|
||||||
|
+ spnego = true;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -90,12 +99,22 @@ int main(int argc, char *argv[])
|
||||||
|
sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (spnego) {
|
||||||
|
+ sasl_mech = "GSS-SPNEGO";
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (zeromaxssf) {
|
||||||
|
+ /* set all security properties to 0 including maxssf */
|
||||||
|
+ sasl_security_properties_t secprops = { 0 };
|
||||||
|
+ sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
sd = setup_socket();
|
||||||
|
|
||||||
|
len = 8192;
|
||||||
|
- recv_string(sd, buf, &len);
|
||||||
|
+ recv_string(sd, buf, &len, false);
|
||||||
|
|
||||||
|
- r = sasl_server_start(conn, "GSSAPI", buf, len, &data, &len);
|
||||||
|
+ r = sasl_server_start(conn, sasl_mech, buf, len, &data, &len);
|
||||||
|
if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
saslerr(r, "starting SASL negotiation");
|
||||||
|
printf("\n%s\n", sasl_errdetail(conn));
|
||||||
|
@@ -105,7 +124,7 @@ int main(int argc, char *argv[])
|
||||||
|
while (r == SASL_CONTINUE) {
|
||||||
|
send_string(sd, data, len);
|
||||||
|
len = 8192;
|
||||||
|
- recv_string(sd, buf, &len);
|
||||||
|
+ recv_string(sd, buf, &len, true);
|
||||||
|
|
||||||
|
r = sasl_server_step(conn, buf, len, &data, &len);
|
||||||
|
if (r != SASL_OK && r != SASL_CONTINUE) {
|
||||||
|
@@ -113,7 +132,6 @@ int main(int argc, char *argv[])
|
||||||
|
printf("\n%s\n", sasl_errdetail(conn));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != SASL_OK) exit(-1);
|
||||||
|
--
|
||||||
|
2.18.2
|
||||||
|
|
29
SOURCES/cyrus-sasl-2.1.27-CVE-2019-19906.patch
Normal file
29
SOURCES/cyrus-sasl-2.1.27-CVE-2019-19906.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
From bcb6c06ec17728f7c9c492dc257b1e541a6830da Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simo Sorce <simo@redhat.com>
|
||||||
|
Date: Tue, 5 May 2020 14:41:06 -0400
|
||||||
|
Subject: [PATCH] CVE-2019-19906
|
||||||
|
|
||||||
|
Backport of commit id:
|
||||||
|
dcc9f51cbd4ed622cfb0f9b1c141eb2ffe3b12f1
|
||||||
|
|
||||||
|
Signed-off-by: Simo Sorce <simo@redhat.com>
|
||||||
|
---
|
||||||
|
lib/common.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/lib/common.c b/lib/common.c
|
||||||
|
index bc3bf1d..9969d6a 100644
|
||||||
|
--- a/lib/common.c
|
||||||
|
+++ b/lib/common.c
|
||||||
|
@@ -190,7 +190,7 @@ int _sasl_add_string(char **out, size_t *alloclen,
|
||||||
|
|
||||||
|
if (add==NULL) add = "(null)";
|
||||||
|
|
||||||
|
- addlen=strlen(add); /* only compute once */
|
||||||
|
+ addlen=strlen(add)+1; /* only compute once */
|
||||||
|
if (_buf_alloc(out, alloclen, (*outlen)+addlen)!=SASL_OK)
|
||||||
|
return SASL_NOMEM;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.18.2
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From ec070b2e83a4ee698c08d6d68c205aea4d90b0bb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simo Sorce <simo@redhat.com>
|
||||||
|
Date: Tue, 5 May 2020 14:31:10 -0400
|
||||||
|
Subject: [PATCH] Emit debug log only in case of errors
|
||||||
|
|
||||||
|
Backport of commit id:
|
||||||
|
ccc5e547d4b40ee2b182a9945f8f6cc10b4fdf48
|
||||||
|
|
||||||
|
Signed-off-by: Simo Sorce <simo@redhat.com>
|
||||||
|
---
|
||||||
|
plugins/gssapi.c | 7 +++----
|
||||||
|
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
|
||||||
|
index 7480316..6bcd78e 100644
|
||||||
|
--- a/plugins/gssapi.c
|
||||||
|
+++ b/plugins/gssapi.c
|
||||||
|
@@ -1444,9 +1444,6 @@ gssapi_server_mech_step(void *conn_context,
|
||||||
|
|
||||||
|
if (text == NULL) return SASL_BADPROT;
|
||||||
|
|
||||||
|
- params->utils->log(params->utils->conn, SASL_LOG_DEBUG,
|
||||||
|
- "GSSAPI server step %d\n", text->state);
|
||||||
|
-
|
||||||
|
switch (text->state) {
|
||||||
|
|
||||||
|
case SASL_GSSAPI_STATE_AUTHNEG:
|
||||||
|
@@ -1496,8 +1493,10 @@ gssapi_server_mech_step(void *conn_context,
|
||||||
|
}
|
||||||
|
|
||||||
|
oparams->doneflag = 1;
|
||||||
|
+ } else {
|
||||||
|
+ params->utils->log(params->utils->conn, SASL_LOG_DEBUG,
|
||||||
|
+ "GSSAPI server step failed: %d\n", text->state);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.18.2
|
||||||
|
|
@ -8,7 +8,7 @@
|
|||||||
Summary: The Cyrus SASL library
|
Summary: The Cyrus SASL library
|
||||||
Name: cyrus-sasl
|
Name: cyrus-sasl
|
||||||
Version: 2.1.27
|
Version: 2.1.27
|
||||||
Release: 1%{?dist}
|
Release: 5%{?dist}
|
||||||
License: BSD with advertising
|
License: BSD with advertising
|
||||||
Group: System Environment/Libraries
|
Group: System Environment/Libraries
|
||||||
# Source0 originally comes from https://www.cyrusimap.org/releases/;
|
# Source0 originally comes from https://www.cyrusimap.org/releases/;
|
||||||
@ -30,6 +30,11 @@ Patch23: cyrus-sasl-2.1.23-man.patch
|
|||||||
Patch24: cyrus-sasl-2.1.21-sizes.patch
|
Patch24: cyrus-sasl-2.1.21-sizes.patch
|
||||||
Patch49: cyrus-sasl-2.1.26-md5global.patch
|
Patch49: cyrus-sasl-2.1.26-md5global.patch
|
||||||
Patch60: cyrus-sasl-pr559-RC4-openssl.patch
|
Patch60: cyrus-sasl-pr559-RC4-openssl.patch
|
||||||
|
Patch830: cyrus-sasl-2.1.27-CVE-2019-19906.patch
|
||||||
|
Patch831: cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch
|
||||||
|
Patch832: cyrus-sasl-2.1.27-Add-Channel-Binding-support-for-GSSAPI-GSS-SPNEGO.patch
|
||||||
|
Patch833: cyrus-sasl-2.1.27-Add-support-for-setting-max-ssf-0-to-GSS-SPNEGO.patch
|
||||||
|
Patch834: cyrus-sasl-2.1.27-Emit-debug-log-only-in-case-of-errors.patch
|
||||||
|
|
||||||
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
BuildRequires: autoconf, automake, libtool, gdbm-devel, groff
|
BuildRequires: autoconf, automake, libtool, gdbm-devel, groff
|
||||||
@ -39,6 +44,8 @@ BuildRequires: libdb-devel
|
|||||||
%if ! %{bootstrap_cyrus_sasl}
|
%if ! %{bootstrap_cyrus_sasl}
|
||||||
BuildRequires: openldap-devel
|
BuildRequires: openldap-devel
|
||||||
%endif
|
%endif
|
||||||
|
#build reqs for make check
|
||||||
|
BuildRequires: python36 nss_wrapper socket_wrapper krb5-server
|
||||||
%{?systemd_requires}
|
%{?systemd_requires}
|
||||||
Requires(post): chkconfig
|
Requires(post): chkconfig
|
||||||
Requires(pre): /usr/sbin/useradd /usr/sbin/groupadd
|
Requires(pre): /usr/sbin/useradd /usr/sbin/groupadd
|
||||||
@ -161,6 +168,11 @@ the GS2 authentication scheme.
|
|||||||
%patch24 -p1 -b .sizes
|
%patch24 -p1 -b .sizes
|
||||||
%patch49 -p1 -b .md5global.h
|
%patch49 -p1 -b .md5global.h
|
||||||
%patch60 -p1 -b .openssl_rc4
|
%patch60 -p1 -b .openssl_rc4
|
||||||
|
%patch830 -p1 -b .CVE-2019-19906
|
||||||
|
%patch831 -p1 -b .tests
|
||||||
|
%patch832 -p1 -b .gssapi_cbs
|
||||||
|
%patch833 -p1 -b .maxssf0
|
||||||
|
%patch834 -p1 -b .nolog
|
||||||
|
|
||||||
%build
|
%build
|
||||||
# reconfigure
|
# reconfigure
|
||||||
@ -300,6 +312,8 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/sasl2/*.la
|
|||||||
rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
|
rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
|
||||||
rm -f $RPM_BUILD_ROOT%{_mandir}/cat8/saslauthd.8
|
rm -f $RPM_BUILD_ROOT%{_mandir}/cat8/saslauthd.8
|
||||||
|
|
||||||
|
%check
|
||||||
|
make check %{?_smp_mflags}
|
||||||
|
|
||||||
%pre
|
%pre
|
||||||
getent group %{username} >/dev/null || groupadd -g 76 -r %{username}
|
getent group %{username} >/dev/null || groupadd -g 76 -r %{username}
|
||||||
@ -392,6 +406,22 @@ getent passwd %{username} >/dev/null || useradd -r -g %{username} -d %{homedir}
|
|||||||
%{_sbindir}/sasl2-shared-mechlist
|
%{_sbindir}/sasl2-shared-mechlist
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue May 5 2020 Simo Sorce <simo@redhat.com> - 2.1.27-5
|
||||||
|
- Reduce excessive GSSAPI plugin logging
|
||||||
|
- Resolves: rhbz#1274734
|
||||||
|
|
||||||
|
* Tue May 5 2020 Simo Sorce <simo@redhat.com> - 2.1.27-4
|
||||||
|
- Add support for setting maxssf=0 in GSS-SPNEGO
|
||||||
|
- Resolves: rhbz#1822133
|
||||||
|
|
||||||
|
* Tue May 5 2020 Simo Sorce <simo@redhat.com> - 2.1.27-3
|
||||||
|
- Backport GSSAPI Channel Bindings support
|
||||||
|
- Resolves: rhbz#1817054
|
||||||
|
|
||||||
|
* Tue May 5 2020 Simo Sorce <simo@redhat.com> - 2.1.27-2
|
||||||
|
- Backport fix for CVE-2019-19906
|
||||||
|
- Resolves: rhbz#1804036
|
||||||
|
|
||||||
* Fri Jun 14 2019 Simo Sorce <simo@redhat.com> - 2.1.27-1
|
* Fri Jun 14 2019 Simo Sorce <simo@redhat.com> - 2.1.27-1
|
||||||
- Rc7 to final source
|
- Rc7 to final source
|
||||||
- Resovles bz#1618744
|
- Resovles bz#1618744
|
||||||
|
Loading…
Reference in New Issue
Block a user