Hello community,
here is the log from the commit of package python-pykerberos for openSUSE:Factory checked in at 2019-02-05 11:19:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pykerberos (Old)
and /work/SRC/openSUSE:Factory/.python-pykerberos.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pykerberos"
Tue Feb 5 11:19:06 2019 rev:5 rq:671252 version:1.2.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pykerberos/python-pykerberos.changes 2018-02-10 17:57:24.833768401 +0100
+++ /work/SRC/openSUSE:Factory/.python-pykerberos.new.28833/python-pykerberos.changes 2019-02-05 11:19:10.432882188 +0100
@@ -1,0 +2,19 @@
+Tue Feb 5 05:19:12 UTC 2019 - Thomas Bechtold
+
+- update to 1.2.1:
+ * add crusty CMake support
+ * minor change to CBT struct
+ * get build working on OSX again
+ * changes based on upstream PR
+ * add CHANGELOG with entries for 1.2.1.beta1
+ * add winrm-style IOV encryption support
+ * bump repo version to 1.2.1dev
+ * Removing 3.2 from travis b/c it is no longer fully supported
+ * Added method to build the CBT structure and modified authGSSClientStep
+ to pass along this CBT structure if it is set
+ * obviously, verify shouldn't be const
+ * 1.2.1 final release
+ * Adding life support note to README
+- Use %license macro
+
+-------------------------------------------------------------------
Old:
----
pykerberos-1.1.14.tar.gz
New:
----
pykerberos-1.2.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pykerberos.spec ++++++
--- /var/tmp/diff_new_pack.gBr64H/_old 2019-02-05 11:19:10.940881909 +0100
+++ /var/tmp/diff_new_pack.gBr64H/_new 2019-02-05 11:19:10.940881909 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-pykerberos
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,13 +12,13 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pykerberos
-Version: 1.1.14
+Version: 1.2.1
Release: 0
Summary: High-level interface to Kerberos
License: Apache-2.0
@@ -53,7 +53,8 @@
%files %{python_files}
%defattr(-,root,root,-)
-%doc README.txt LICENSE
+%doc README.txt
+%license LICENSE
%{python_sitearch}/*
%changelog
++++++ pykerberos-1.1.14.tar.gz -> pykerberos-1.2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/PKG-INFO new/pykerberos-1.2.1/PKG-INFO
--- old/pykerberos-1.1.14/PKG-INFO 2017-01-26 08:32:40.000000000 +0100
+++ new/pykerberos-1.2.1/PKG-INFO 2017-12-20 19:27:02.000000000 +0100
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: pykerberos
-Version: 1.1.14
+Version: 1.2.1
Summary: High-level interface to Kerberos
Home-page: UNKNOWN
Author: UNKNOWN
Author-email: UNKNOWN
License: ASL 2.0
+Description-Content-Type: UNKNOWN
Description:
This Python package is a high-level wrapper for Kerberos (GSSAPI) operations.
The goal is to avoid having to build a module that wraps the entire Kerberos.framework,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/README.txt new/pykerberos-1.2.1/README.txt
--- old/pykerberos-1.1.14/README.txt 2014-03-25 10:21:31.000000000 +0100
+++ new/pykerberos-1.2.1/README.txt 2017-12-07 02:02:50.000000000 +0100
@@ -1,3 +1,6 @@
+NOTE: this fork of ccs-kerberos is currently on life support mode as Apple has resumed work on upstream. Please try to use https://pypi.python.org/pypi/kerberos instead of this fork if possible.
+
+
=========================================================
PyKerberos Package
@@ -62,6 +65,59 @@
-p : password for basic authenticate
-s : service principal for GSSAPI authentication (defaults to 'http@host.example.com')
+================
+CHANNEL BINDINGS
+================
+
+You can use this library to authenticate with Channel Binding support. Channel
+Bindings are tags that identify the particular data channel being used with the
+authentication. You can use Channel bindings to offer more proof of a valid
+identity. Some services like Microsoft's Extended Protection can enforce
+Channel Binding support on authorisation and you can use this library to meet
+those requirements.
+
+More details on Channel Bindings as set through the GSSAPI can be found here
+https://docs.oracle.com/cd/E19455-01/806-3814/overview-52/index.html. Using
+TLS as a example this is how you would add Channel Binding support to your
+authentication mechanism. The following code snippet is based on RFC5929
+https://tools.ietf.org/html/rfc5929 using the 'tls-server-endpoint-point'
+type.
+
+.. code-block:: python
+
+ import hashlib
+
+ def get_channel_bindings_application_data(socket):
+ # This is a highly simplified example, there are other use cases
+ # where you might need to use different hash types or get a socket
+ # object somehow.
+ server_certificate = socket.getpeercert(True)
+ certificate_hash = hashlib.sha256(server_certificate).hexdigest().upper()
+ certificate_digest = base64.b16decode(certificate_hash)
+ application_data = b'tls-server-end-point:%s' % certificate_digest
+
+ return application_data
+
+ def main():
+ # Code to setup a socket with the server
+ # A lot of code to setup the handshake and start the auth process
+ socket = getsocketsomehow()
+
+ # Connect to the host and start the auth process
+
+ # Build the channel bindings object
+ application_data = get_channel_bindings_application_data(socket)
+ channel_bindings = kerberos.channelBindings(application_data=application_data)
+
+ # More work to get responses from the server
+
+ result, context = kerberos.authGSSClientInit(kerb_spn, gssflags=gssflags, principal=principal)
+
+ # Pass through the channel_bindings object as created in the kerberos.channelBindings method
+ result = kerberos.authGSSClientStep(context, neg_resp_value, channel_bindings=channel_bindings)
+
+ # Repeat as necessary
+
===========
Python APIs
===========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/pykerberos.egg-info/PKG-INFO new/pykerberos-1.2.1/pykerberos.egg-info/PKG-INFO
--- old/pykerberos-1.1.14/pykerberos.egg-info/PKG-INFO 2017-01-26 08:32:40.000000000 +0100
+++ new/pykerberos-1.2.1/pykerberos.egg-info/PKG-INFO 2017-12-20 19:27:02.000000000 +0100
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: pykerberos
-Version: 1.1.14
+Version: 1.2.1
Summary: High-level interface to Kerberos
Home-page: UNKNOWN
Author: UNKNOWN
Author-email: UNKNOWN
License: ASL 2.0
+Description-Content-Type: UNKNOWN
Description:
This Python package is a high-level wrapper for Kerberos (GSSAPI) operations.
The goal is to avoid having to build a module that wraps the entire Kerberos.framework,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/pysrc/kerberos.py new/pykerberos-1.2.1/pysrc/kerberos.py
--- old/pykerberos-1.1.14/pysrc/kerberos.py 2017-01-26 08:32:32.000000000 +0100
+++ new/pykerberos-1.2.1/pysrc/kerberos.py 2017-12-07 02:02:59.000000000 +0100
@@ -130,13 +130,16 @@
@return: a result code (see above).
"""
-def authGSSClientStep(context, challenge):
+def authGSSClientStep(context, challenge, **kwargs):
"""
Processes a single GSSAPI client-side step using the supplied server data.
@param context: the context object returned from authGSSClientInit.
@param challenge: a string containing the base64-encoded server data (which may be empty
for the first step).
+ @param channel_bindings: Optional channel bindings to bind onto the auth request. This
+ struct can be built using the channelBindings function and it not specified, this process
+ will pass along GSS_C_NO_CHANNEL_BINDINGS as a default
@return: a result code (see above).
"""
@@ -238,3 +241,74 @@
@param context: the context object returned from authGSSServerInit.
@return: a string containing the target name.
"""
+
+"""
+Address Types for Channel Bindings
+https://docs.oracle.com/cd/E19455-01/806-3814/6jcugr7dp/index.html#reference...
+"""
+
+GSS_C_AF_UNSPEC = 0
+GSS_C_AF_LOCAL = 1
+GSS_C_AF_INET = 2
+GSS_C_AF_IMPLINK = 3
+GSS_C_AF_PUP = 4
+GSS_C_AF_CHAOS = 5
+GSS_C_AF_NS = 6
+GSS_C_AF_NBS = 7
+GSS_C_AF_ECMA = 8
+GSS_C_AF_DATAKIT = 9
+GSS_C_AF_CCITT = 10
+GSS_C_AF_SNA = 11
+GSS_C_AF_DECnet = 12
+GSS_C_AF_DLI = 13
+GSS_C_AF_LAT = 14
+GSS_C_AF_HYLINK = 15
+GSS_C_AF_APPLETALK = 16
+GSS_C_AF_BSC = 17
+GSS_C_AF_DSS = 18
+GSS_C_AF_OSI = 19
+GSS_C_AF_X25 = 21
+GSS_C_AF_NULLADDR = 255
+
+def channelBindings(**kwargs):
+ """
+ Builds a gss_channel_bindings_struct which can be used to pass onto authGSSClientStep to bind
+ onto the auth. Details on Channel Bindings can be found at https://tools.ietf.org/html/rfc5929.
+ More details on the struct can be found at https://docs.oracle.com/cd/E19455-01/806-3814/overview-52/index.html
+
+ @param initiator_addrtype: Optional integer used to set the
+ initiator_addrtype, defaults to GSS_C_AF_UNSPEC if not set
+ @param initiator_address: Optional byte string containing the
+ initiator_address
+ @param acceptor_addrtype: Optional integer used to set the
+ acceptor_addrtype, defaults to GSS_C_AF_UNSPEC if not set
+ @param acceptor_address: Optional byte string containing the
+ acceptor_address
+ @param application_data: Optional byte string containing the
+ application_data. An example would be 'tls-server-end-point:{cert-hash}'
+ where {cert-hash} is the byte string hash of the server's certificate
+ @return: The gss_channel_bindings_struct pointer, which is the channel
+ bindings structure that can be passed onto authGSSClientStep
+ """
+
+def authGSSWinRMEncryptMessage(context, message):
+ """
+ Encrypts a message body with the current Kerberos session key using IOV settings for WinRM
+
+ @param context: The context object returned from L{authGSSClientInit}.
+ @param message: The plaintext message to be encrypted.
+ @return: A tuple of (encrypted_data, header) where encrypted_data is the
+ ciphertext result of the encryption operation, and header is the GSSAPI
+ header describing the encryption parameters. Both strings contain opaque
+ binary data.
+ """
+
+def authGSSWinRMDecryptMessage(context, encrypted_data, header):
+ """
+ Decrypts a ciphertext message body with the current Kerberos session key using IOV settings for WinRM
+
+ @param context: The context object returned from L{authGSSClientInit}.
+ @param encrypted_data: The ciphertext message to be decrypted.
+ @param header: The GSSAPI message header containing the encryption parameters.
+ @return: The decrypted message text.
+ """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/setup.cfg new/pykerberos-1.2.1/setup.cfg
--- old/pykerberos-1.1.14/setup.cfg 2017-01-26 08:32:40.000000000 +0100
+++ new/pykerberos-1.2.1/setup.cfg 2017-12-20 19:27:02.000000000 +0100
@@ -1,5 +1,4 @@
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/setup.py new/pykerberos-1.2.1/setup.py
--- old/pykerberos-1.1.14/setup.py 2017-01-26 08:32:32.000000000 +0100
+++ new/pykerberos-1.2.1/setup.py 2017-12-20 19:20:04.000000000 +0100
@@ -58,7 +58,7 @@
setup (
name = "pykerberos",
- version = "1.1.14",
+ version = "1.2.1",
description = "High-level interface to Kerberos",
long_description=long_description,
license="ASL 2.0",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/src/kerberos.c new/pykerberos-1.2.1/src/kerberos.c
--- old/pykerberos-1.1.14/src/kerberos.c 2017-01-26 08:32:32.000000000 +0100
+++ new/pykerberos-1.2.1/src/kerberos.c 2017-12-08 18:24:45.000000000 +0100
@@ -50,7 +50,7 @@
const char *pswd = NULL;
const char *service = NULL;
const char *default_realm = NULL;
- const int verify = 1;
+ int verify = 1;
int result = 0;
if (!PyArg_ParseTuple(args, "ssss|b", &user, &pswd, &service, &default_realm, &verify)) {
@@ -163,13 +163,82 @@
return Py_BuildValue("i", AUTH_GSS_COMPLETE);
}
-static PyObject *authGSSClientStep(PyObject *self, PyObject *args) {
+#if PY_MAJOR_VERSION >= 3
+void destruct_channel_bindings(PyObject* o) {
+ struct gss_channel_bindings_struct *channel_bindings = PyCapsule_GetPointer(o, NULL);
+#else
+void destruct_channel_bindings(void* o) {
+ struct gss_channel_bindings_struct *channel_bindings = (struct gss_channel_bindings_struct *)o;
+#endif
+
+ if (channel_bindings != NULL) {
+ if (channel_bindings->initiator_address.value != NULL) {
+ PyMem_Free(channel_bindings->initiator_address.value);
+ }
+
+ if (channel_bindings->acceptor_address.value != NULL) {
+ PyMem_Free(channel_bindings->acceptor_address.value);
+ }
+
+ if (channel_bindings->application_data.value != NULL) {
+ PyMem_Free(channel_bindings->application_data.value);
+ }
+
+ free(channel_bindings);
+ }
+}
+
+static PyObject *channelBindings(PyObject *self, PyObject *args, PyObject* keywds) {
+ int initiator_addrtype = GSS_C_AF_UNSPEC;
+ int acceptor_addrtype = GSS_C_AF_UNSPEC;
+
+ const char *encoding = NULL;
+ char *initiator_address = NULL;
+ char *acceptor_address = NULL;
+ char *application_data = NULL;
+ int initiator_length = 0;
+ int acceptor_length = 0;
+ int application_length = 0;
+
+ PyObject *pychan_bindings = NULL;
+ struct gss_channel_bindings_struct *input_chan_bindings;
+ static char *kwlist[] = {"initiator_addrtype", "initiator_address", "acceptor_addrtype",
+ "acceptor_address", "application_data", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iet#iet#et#", kwlist,
+ &initiator_addrtype, &encoding, &initiator_address, &initiator_length,
+ &acceptor_addrtype, &encoding, &acceptor_address, &acceptor_length,
+ &encoding, &application_data, &application_length)) {
+ return NULL;
+ }
+
+ input_chan_bindings = (struct gss_channel_bindings_struct *) malloc(sizeof(struct gss_channel_bindings_struct));
+ pychan_bindings = PyNew(input_chan_bindings, &destruct_channel_bindings);
+
+ input_chan_bindings->initiator_addrtype = initiator_addrtype;
+ input_chan_bindings->initiator_address.length = initiator_length;
+ input_chan_bindings->initiator_address.value = initiator_address;
+
+ input_chan_bindings->acceptor_addrtype = acceptor_addrtype;
+ input_chan_bindings->acceptor_address.length = acceptor_length;
+ input_chan_bindings->acceptor_address.value = acceptor_address;
+
+ input_chan_bindings->application_data.length = application_length;
+ input_chan_bindings->application_data.value = application_data;
+
+ return Py_BuildValue("N", pychan_bindings);
+}
+
+static PyObject *authGSSClientStep(PyObject *self, PyObject *args, PyObject* keywds) {
gss_client_state *state;
PyObject *pystate;
char *challenge = NULL;
+ PyObject *pychan_bindings = NULL;
+ struct gss_channel_bindings_struct *channel_bindings;
+ static char *kwlist[] = {"state", "challenge", "channel_bindings", NULL};
int result = 0;
- if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge)) {
+ if (! PyArg_ParseTupleAndKeywords(args, keywds, "Os|O", kwlist, &pystate, &challenge, &pychan_bindings)) {
return NULL;
}
@@ -183,7 +252,17 @@
return NULL;
}
- result = authenticate_gss_client_step(state, challenge);
+ if (pychan_bindings == NULL) {
+ channel_bindings = GSS_C_NO_CHANNEL_BINDINGS;
+ } else {
+ if (!PyCheck(pychan_bindings)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a gss_channel_bindings_struct object");
+ return NULL;
+ }
+ channel_bindings = PyGet(pychan_bindings, struct gss_channel_bindings_struct);
+ }
+
+ result = authenticate_gss_client_step(state, challenge, channel_bindings);
if (result == AUTH_GSS_ERROR) {
return NULL;
}
@@ -506,6 +585,137 @@
return Py_BuildValue("s", state->targetname);
}
+#ifdef GSSAPI_EXT
+static PyObject* authGSSWinRMEncryptMessage(PyObject* self, PyObject* args)
+{
+ char *input = NULL;
+ char *header = NULL;
+ int header_len = 0;
+ char *enc_output = NULL;
+ int enc_output_len = 0;
+ PyObject *pystate = NULL;
+ gss_client_state *state = NULL;
+ int result = 0;
+ PyObject *pyresult = NULL;
+
+ // NB: use et so we get a copy of the string (since gss_wrap_iov mutates it), and so we're certain it's always
+ // a UTF8 byte string
+ if (! PyArg_ParseTuple(args, "Oet", &pystate, "UTF-8", &input)) {
+ pyresult = NULL;
+ goto end;
+ }
+
+ if (!PyCheck(pystate)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a context object");
+ pyresult = NULL;
+ goto end;
+ }
+
+ state = PyGet(pystate, gss_client_state);
+ if (state == NULL) {
+ pyresult = NULL;
+ goto end;
+ }
+
+ result = encrypt_message(state, input, &header, &header_len, &enc_output, &enc_output_len);
+
+ if (result == AUTH_GSS_ERROR) {
+ pyresult = NULL;
+ goto end;
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ pyresult = Py_BuildValue("y# y#", enc_output, enc_output_len, header, header_len);
+#else
+ pyresult = Py_BuildValue("s# s#", enc_output, enc_output_len, header, header_len);
+#endif
+
+end:
+ if (input) {
+ PyMem_Free(input);
+ }
+ if (header) {
+ free(header);
+ }
+ if (enc_output) {
+ free(enc_output);
+ }
+
+ return pyresult;
+}
+
+static PyObject* authGSSWinRMDecryptMessage(PyObject* self, PyObject* args)
+{
+ char *header = NULL;
+ int header_len = 0;
+ char *enc_data = NULL;
+ int enc_data_len = 0;
+ PyObject *pystate = NULL;
+ PyObject *pyheader = NULL;
+ PyObject *pyenc_data = NULL;
+ gss_client_state *state = NULL;
+ char *dec_output = NULL;
+ int dec_output_len = 0;
+ int result = 0;
+ PyObject *pyresult = 0;
+
+ // NB: since the sig/data strings are arbitrary binary and don't conform to
+ // a valid encoding, none of the normal string marshaling types will work. We'll
+ // have to extract the data later.
+ if (! PyArg_ParseTuple(args, "OOO", &pystate, &pyenc_data, &pyheader)) {
+ pyresult = NULL;
+ goto end;
+ }
+
+ if (!PyCheck(pystate)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a context object");
+ pyresult = NULL;
+ goto end;
+ }
+
+ state = PyGet(pystate, gss_client_state);
+ if (state == NULL) {
+ pyresult = NULL;
+ goto end;
+ }
+
+ // request the length and copy the header and encrypted input data from the Python strings
+ header_len = (int) PyBytes_Size(pyheader);
+ header = malloc(header_len);
+ memcpy(header, PyBytes_AsString(pyheader), header_len);
+
+ enc_data_len = (int) PyBytes_Size(pyenc_data);
+ enc_data = malloc(enc_data_len);
+ memcpy(enc_data, PyBytes_AsString(pyenc_data), enc_data_len);
+
+ result = decrypt_message(state, header, header_len, enc_data, enc_data_len, &dec_output, &dec_output_len);
+
+ if (result == AUTH_GSS_ERROR) {
+ pyresult = NULL;
+ goto end;
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ pyresult = Py_BuildValue("y#", dec_output, dec_output_len);
+#else
+ pyresult = Py_BuildValue("s#", dec_output, dec_output_len);
+#endif
+
+end:
+ if (header) {
+ free(header);
+ }
+ if (enc_data) {
+ free(enc_data);
+ }
+ if (dec_output) {
+ free(dec_output);
+ }
+
+ return pyresult;
+}
+#endif
+
static PyMethodDef KerberosMethods[] = {
{"checkPassword", checkPassword, METH_VARARGS,
"Check the supplied user/password against Kerberos KDC."},
@@ -517,7 +727,7 @@
"Initialize client-side GSSAPI operations."},
{"authGSSClientClean", authGSSClientClean, METH_VARARGS,
"Terminate client-side GSSAPI operations."},
- {"authGSSClientStep", authGSSClientStep, METH_VARARGS,
+ {"authGSSClientStep", (PyCFunction)authGSSClientStep, METH_VARARGS | METH_KEYWORDS,
"Do a client-side GSSAPI step."},
{"authGSSClientResponse", authGSSClientResponse, METH_VARARGS,
"Get the response from the last client-side GSSAPI step."},
@@ -531,11 +741,17 @@
"Do a GSSAPI wrap."},
{"authGSSClientUnwrap", authGSSClientUnwrap, METH_VARARGS,
"Do a GSSAPI unwrap."},
+ {"channelBindings", (PyCFunction)channelBindings, METH_VARARGS | METH_KEYWORDS,
+ "Build the Channel Bindings Structure based on the input."},
#ifdef GSSAPI_EXT
{"authGSSClientWrapIov", authGSSClientWrapIov, METH_VARARGS,
"Do a GSSAPI iov wrap."},
{"authGSSClientUnwrapIov", authGSSClientUnwrapIov, METH_VARARGS,
"Do a GSSAPI iov unwrap."},
+ {"authGSSWinRMEncryptMessage", authGSSWinRMEncryptMessage, METH_VARARGS,
+ "Encrypt a message"},
+ {"authGSSWinRMDecryptMessage", authGSSWinRMDecryptMessage, METH_VARARGS,
+ "Decrypt a message"},
#endif
{"authGSSServerClean", authGSSServerClean, METH_VARARGS,
"Terminate server-side GSSAPI operations."},
@@ -620,6 +836,29 @@
PyDict_SetItemString(d, "GSS_MECH_OID_KRB5", PyNew(&krb5_mech_oid, NULL));
PyDict_SetItemString(d, "GSS_MECH_OID_SPNEGO", PyNew(&spnego_mech_oid, NULL));
+ PyDict_SetItemString(d, "GSS_C_AF_UNSPEC", PyInt_FromLong(GSS_C_AF_UNSPEC));
+ PyDict_SetItemString(d, "GSS_C_AF_LOCAL", PyInt_FromLong(GSS_C_AF_LOCAL));
+ PyDict_SetItemString(d, "GSS_C_AF_INET", PyInt_FromLong(GSS_C_AF_INET));
+ PyDict_SetItemString(d, "GSS_C_AF_IMPLINK", PyInt_FromLong(GSS_C_AF_IMPLINK));
+ PyDict_SetItemString(d, "GSS_C_AF_PUP", PyInt_FromLong(GSS_C_AF_PUP));
+ PyDict_SetItemString(d, "GSS_C_AF_CHAOS", PyInt_FromLong(GSS_C_AF_CHAOS));
+ PyDict_SetItemString(d, "GSS_C_AF_NS", PyInt_FromLong(GSS_C_AF_NS));
+ PyDict_SetItemString(d, "GSS_C_AF_NBS", PyInt_FromLong(GSS_C_AF_NBS));
+ PyDict_SetItemString(d, "GSS_C_AF_ECMA", PyInt_FromLong(GSS_C_AF_ECMA));
+ PyDict_SetItemString(d, "GSS_C_AF_DATAKIT", PyInt_FromLong(GSS_C_AF_DATAKIT));
+ PyDict_SetItemString(d, "GSS_C_AF_CCITT", PyInt_FromLong(GSS_C_AF_CCITT));
+ PyDict_SetItemString(d, "GSS_C_AF_SNA", PyInt_FromLong(GSS_C_AF_SNA));
+ PyDict_SetItemString(d, "GSS_C_AF_DECnet", PyInt_FromLong(GSS_C_AF_DECnet));
+ PyDict_SetItemString(d, "GSS_C_AF_DLI", PyInt_FromLong(GSS_C_AF_DLI));
+ PyDict_SetItemString(d, "GSS_C_AF_LAT", PyInt_FromLong(GSS_C_AF_LAT));
+ PyDict_SetItemString(d, "GSS_C_AF_HYLINK", PyInt_FromLong(GSS_C_AF_HYLINK));
+ PyDict_SetItemString(d, "GSS_C_AF_APPLETALK", PyInt_FromLong(GSS_C_AF_APPLETALK));
+ PyDict_SetItemString(d, "GSS_C_AF_BSC", PyInt_FromLong(GSS_C_AF_BSC));
+ PyDict_SetItemString(d, "GSS_C_AF_DSS", PyInt_FromLong(GSS_C_AF_DSS));
+ PyDict_SetItemString(d, "GSS_C_AF_OSI", PyInt_FromLong(GSS_C_AF_OSI));
+ PyDict_SetItemString(d, "GSS_C_AF_X25", PyInt_FromLong(GSS_C_AF_X25));
+ PyDict_SetItemString(d, "GSS_C_AF_NULLADDR", PyInt_FromLong(GSS_C_AF_NULLADDR));
+
error:
if (PyErr_Occurred())
PyErr_SetString(PyExc_ImportError, "kerberos: init failed");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/src/kerberosgss.c new/pykerberos-1.2.1/src/kerberosgss.c
--- old/pykerberos-1.1.14/src/kerberosgss.c 2017-01-26 08:32:32.000000000 +0100
+++ new/pykerberos-1.2.1/src/kerberosgss.c 2017-12-08 18:24:45.000000000 +0100
@@ -205,7 +205,7 @@
return ret;
}
-int authenticate_gss_client_step(gss_client_state* state, const char* challenge)
+int authenticate_gss_client_step(gss_client_state* state, const char* challenge, struct gss_channel_bindings_struct* channel_bindings)
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
@@ -238,7 +238,7 @@
state->mech_oid,
(OM_uint32)state->gss_flags,
0,
- NULL, //GSS_C_NO_CHANNEL_BINDINGS,
+ channel_bindings,
&input_token,
NULL,
&output_token,
@@ -840,3 +840,85 @@
PyErr_SetObject(GssException_class, Py_BuildValue("((s:i)(s:i))", buf_maj, err_maj, buf_min, err_min));
}
+
+#ifdef GSSAPI_EXT
+int encrypt_message(gss_client_state *state, char *message_input, char **header, int *header_len, char **encrypted_data, int *encrypted_data_len)
+{
+ OM_uint32 maj_stat;
+ OM_uint32 min_stat;
+ int ret;
+ char *outloc = NULL;
+
+ gss_iov_buffer_desc iov[3];
+ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+ // NB: this will modify the message buffer in place, ensure caller has copied the string if necessary
+ iov[1].buffer.value = message_input;
+ iov[1].buffer.length = strlen(message_input);
+ iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+
+ maj_stat = gss_wrap_iov(&min_stat, state->context, 1, GSS_C_QOP_DEFAULT, NULL, iov, 3);
+
+ if (GSS_ERROR(maj_stat)) {
+ set_gss_error(maj_stat, min_stat);
+ ret = AUTH_GSS_ERROR;
+ goto end;
+ }
+
+ *header_len = iov[0].buffer.length;
+ *header = malloc(*header_len);
+ memcpy(*header, iov[0].buffer.value, *header_len);
+
+ // copy encrypted data, concatenate padding buffer if present
+ *encrypted_data_len = iov[1].buffer.length + iov[2].buffer.length;
+ *encrypted_data = malloc(*encrypted_data_len);
+ outloc = *encrypted_data;
+ outloc = mempcpy(outloc, iov[1].buffer.value, iov[1].buffer.length);
+ // NB: no-op if no padding is necessary (which seems to always be the case with aes256-cts-hmac-sha1-96)
+ mempcpy(outloc, iov[2].buffer.value, iov[2].buffer.length);
+
+ ret = 0;
+end:
+ maj_stat = gss_release_iov_buffer(&min_stat, iov, 3);
+
+ return ret;
+}
+
+int decrypt_message(gss_client_state *state, char *header, int header_len, char *data, int data_len, char **decrypted_output, int *decrypted_output_len)
+{
+ OM_uint32 maj_stat;
+ OM_uint32 min_stat;
+ int ret = 0;
+ int conf_state;
+ gss_qop_t qop_state;
+
+ // NB: ensure the caller has copied the python input buffer
+ // so we're not mutating somebody else's string
+
+ gss_iov_buffer_desc iov[3];
+ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
+ iov[0].buffer.value = header;
+ iov[0].buffer.length = header_len;
+
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[1].buffer.value = data;
+ iov[1].buffer.length = data_len;
+
+ maj_stat = gss_unwrap_iov(&min_stat, state->context, &conf_state, &qop_state, iov, 2);
+
+ if (GSS_ERROR(maj_stat)) {
+ set_gss_error(maj_stat, min_stat);
+ ret = AUTH_GSS_ERROR;
+ goto end;
+ }
+
+ *decrypted_output = malloc(iov[1].buffer.length);
+ *decrypted_output_len = iov[1].buffer.length;
+
+ memcpy(*decrypted_output, iov[1].buffer.value, iov[1].buffer.length);
+
+ ret = 0;
+end:
+ return ret;
+}
+#endif
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pykerberos-1.1.14/src/kerberosgss.h new/pykerberos-1.2.1/src/kerberosgss.h
--- old/pykerberos-1.1.14/src/kerberosgss.h 2017-01-26 08:32:32.000000000 +0100
+++ new/pykerberos-1.2.1/src/kerberosgss.h 2017-12-07 02:02:50.000000000 +0100
@@ -56,7 +56,7 @@
int authenticate_gss_client_init(const char* service, const char* principal, long int gss_flags, gss_OID mech_oid, gss_client_state* state);
int authenticate_gss_client_clean(gss_client_state *state);
-int authenticate_gss_client_step(gss_client_state *state, const char *challenge);
+int authenticate_gss_client_step(gss_client_state *state, const char *challenge, struct gss_channel_bindings_struct *channel_bindings);
int authenticate_gss_client_unwrap(gss_client_state* state, const char* challenge);
int authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user, int protect);
#ifdef GSSAPI_EXT
@@ -66,3 +66,5 @@
int authenticate_gss_server_init(const char* service, gss_server_state* state);
int authenticate_gss_server_clean(gss_server_state *state);
int authenticate_gss_server_step(gss_server_state *state, const char *challenge);
+int encrypt_message(gss_client_state *state, char *message_input, char **header, int *header_len, char **encrypted_data, int *encrypted_data_len);
+int decrypt_message(gss_client_state *state, char *header, int header_len, char *data, int data_len, char **decrypted_output, int *decrypted_output_len);