Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Cbt support #55

Merged
merged 1 commit into from
Jun 27, 2017
Merged

Cbt support #55

merged 1 commit into from
Jun 27, 2017

Conversation

jborean93
Copy link
Contributor

@jborean93 jborean93 commented Apr 11, 2017

Added support for creating an input channel bindings value and passing that into the authGSSClientStep as an optional argument. Will continue on with the default behavior if this isn't specified.

I'm fairly new to C so happy to take any pointers and ideas on ways this could be better improved. I've tested this manually on an IIS and WinRM endpoint where the channel bindings token is set to required and verified it worked.

Test Result:

This is the environment set up I had to verify the test results, please ask me any questions around it or if you know of a better way to add automated tests.

Windows Configuration

Run this script on a Server 2008 or newer host that is hooked up to a domain https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1. This will set up a WinRM listener over HTTPS with a self signed cert and open and firewall rules

After running this run the following command in Powershell to set the CBT policy to Strict

Set-Item -Path "WSMan:\localhost\Service\Auth\CbtHardeningLevel" -Value Strict

You can verify the setting by running this in powershell

winrm get winrm/config/service/auth

Auth
    Basic = true
    Kerberos = true
    Negotiate = true
    Certificate = false
    CredSSP = false
    CbtHardeningLevel = Strict

Python Host Config

On the *nix server you are using for testing run the following command to install the relevant libraries and set everything up

pip install pywinrm
pip install git+https://github.com/jborean93/requests-kerberos@add-cbt
git clone https://github.com/jborean93/ccs-pykerberos.git
cd ccs-pykerberos
git checkout cbt-support
pip install .

Create the python script below

from winrm.protocol import Protocol

p = Protocol(
    endpoint='https://host-fqdnl:5986/wsman',
    transport='kerberos',
    server_cert_validation='ignore'
)
shell_id = p.open_shell()
command_id = p.run_command(shell_id, 'ipconfig', ['/all'])
std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
p.cleanup_command(shell_id, command_id)
p.close_shell(shell_id)

print("Return Code: {0}".format(status_code))
print("STDOUT: {0}".format(std_out))
print("STDERR: {0}".format(std_err))

Run the following commands to get a kerberos ticket and test out the script

kinit user@REALM.COM
python test-winrm.py

You get the Windows IP configuration returned

image

If you are using the stock standard kerberos and requests-kerberos library you would get the following error returned

image

@jborean93
Copy link
Contributor Author

I couldn't get an instance of CalendarServer up and running and interacting with LDAP so I did the next best thing and just create a site backed by Apache and mod_auth_kerb. Here is the testing setup info and details if you wish to test it manually yourself.

Kerberos Setup

/etc/krb5.conf

This is my Kerberos config setup and configured to connect to the JORDAN.LOCAL realm.

# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/

includedir /var/lib/sss/pubconf/krb5.include.d/
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
# default_realm = EXAMPLE.COM
 default_ccache_name = KEYRING:persistent:%{uid}

 default_realm = JORDAN.LOCAL
[realms]
# EXAMPLE.COM = {
#  kdc = kerberos.example.com
#  admin_server = kerberos.example.com
# }

 JORDAN.LOCAL = {
  kdc = dc01.jordan.local
  admin_server = dc01.jordan.local
 }

[domain_realm]
# .example.com = EXAMPLE.COM
# example.com = EXAMPLE.COM
 jordan.local = JORDAN.LOCAL
 .jordan.local = JORDAN.LOCAL

SPN

I have manually set the SPN HTTP/centos01.jordan.local on my test AD server

image

Keytab

This is my keytab setup at etc/krb5.keytab

image

Apache Setup

Apache Kerberos Config

My Kerberos config at /etc/httpd/conf.d/auth_kerberos.conf is configured like

<Directory /var/www/centos01.jordan.local>
    AuthType Kerberos
    AuthName "Kerberos Authentication"
    KrbAuthRealms JORDAN.LOCAL
    Krb5KeyTab /etc/krb5.keytab
    KrbMethodNegotiate On
    KrbMethodK5Passwd off
    KrbVerifyKDC Off
    Require user user1@JORDAN.LOCAL
</Directory>

I also just have a basic HTML site configured on port 80 at `/etc/httpd/sites-available/centos01.jordan.local.conf

<VirtualHost *:80>
    ServerName centos01.jordan.local
    ServerAlias centos01.jordan.local
    DocumentRoot /var/www/centos01.jordan.local/public_html
    ErrorLog /var/www/centos01.jordan.local/error.log
    CustomLog /var/www/centos01.jordan.local/requests.log combined
</VirtualHost>

Test Script

This is the script I used to test out all 4 existing tests with the Kerberos backed website. It tests it with both Python 2.7.13 and Python 3.6.1.

I had to modify the existing tests to support both Python 2 and 3 (committed) and modify the principal to work outside of CalendarServer (just done through a sed line replacement)

# Change to run in root to makes things simpler
su

# Ensure any leftover tests are cleared before testing again
rm -rf /testing

# Setup testing repo
mkdir /testing
cd /testing
git clone https://github.com/jborean93/ccs-pykerberos.git -b cbt-support
cd ccs-pykerberos

# Show the current git commit hash for verification
git show --oneline -s

# Change the uri for the server test as we aren't using calendar server
sed -i '/uri = "\/principals\/"/c\    uri = "\/"' test.py

# Get kerberos ticket for Kerberos user
kinit user1@JORDAN.LOCAL

# Create virtual env for Python 2.7.13
virtualenv /testing/py27-venv -p /usr/local/bin/python2.7
source /testing/py27-venv/bin/activate
python --version

# Install new ccs-pykerberos library with CBT support
pip install .

# Run tests for Python 2.7.13
python test.py -s HTTP@centos01.jordan.local service
python test.py -u user1 -p Password01 -s HTTP@centos01.jordan.local -r JORDAN.LOCAL basic

python test.py -s HTTP@centos01.jordan.local -r JORDAN.LOCAL gssapi
python test.py -s HTTP@centos01.jordan.local -h centos01.jordan.local -i 80 server

# Create virtual env for Python 3.6.1 and run tests
deactivate
virtualenv /testing/py36-venv -p /usr/local/bin/python3.6
source /testing/py36-venv/bin/activate
python --version

pip install .

python test.py -s HTTP@centos01.jordan.local service
python test.py -u user1 -p Password01 -s HTTP@centos01.jordan.local -r JORDAN.LOCAL basic

python test.py -s HTTP@centos01.jordan.local -r JORDAN.LOCAL gssapi
python test.py -s HTTP@centos01.jordan.local -h centos01.jordan.local -i 80 server

Test Output

This is the test output from the script

[administrator@CENTOS01 ~]$ # Change to run in root to makes things simpler
[administrator@CENTOS01 ~]$ su
Password: 
[root@CENTOS01 administrator]# 
[root@CENTOS01 administrator]# # Ensure any leftover tests are cleared before testing again
[root@CENTOS01 administrator]# rm -rf /testing
[root@CENTOS01 administrator]# 
[root@CENTOS01 administrator]# # Setup testing repo
[root@CENTOS01 administrator]# mkdir /testing
[root@CENTOS01 administrator]# cd /testing
[root@CENTOS01 testing]# git clone https://github.com/jborean93/ccs-pykerberos.git -b cbt-support
Cloning into 'ccs-pykerberos'...
remote: Counting objects: 609, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 609 (delta 2), reused 6 (delta 2), pack-reused 603
Receiving objects: 100% (609/609), 144.42 KiB | 0 bytes/s, done.
Resolving deltas: 100% (425/425), done.
[root@CENTOS01 testing]# cd ccs-pykerberos
[root@CENTOS01 ccs-pykerberos]# 
[root@CENTOS01 ccs-pykerberos]# # Show the current git commit hash for verification
[root@CENTOS01 ccs-pykerberos]# git show --oneline -s
d87a465 I broke Python 2 now I need to have a fix for both
[root@CENTOS01 ccs-pykerberos]# 
[root@CENTOS01 ccs-pykerberos]# # Change the uri for the server test as we aren't using calendar server
[root@CENTOS01 ccs-pykerberos]# sed -i '/uri = "\/principals\/"/c\    uri = "\/"' test.py
[root@CENTOS01 ccs-pykerberos]# 
[root@CENTOS01 ccs-pykerberos]# # Get kerberos ticket for Kerberos user
[root@CENTOS01 ccs-pykerberos]# kinit user1@JORDAN.LOCAL
Password for user1@JORDAN.LOCAL: 
[root@CENTOS01 ccs-pykerberos]# 
[root@CENTOS01 ccs-pykerberos]# # Create virtual env for Python 2.7.13
[root@CENTOS01 ccs-pykerberos]# virtualenv /testing/py27-venv -p /usr/local/bin/python2.7
Running virtualenv with interpreter /usr/local/bin/python2.7
New python executable in /testing/py27-venv/bin/python2.7
Also creating executable in /testing/py27-venv/bin/python
Installing setuptools, pip, wheel...done.
[root@CENTOS01 ccs-pykerberos]# source /testing/py27-venv/bin/activate
(py27-venv) [root@CENTOS01 ccs-pykerberos]# python --version
Python 2.7.13
(py27-venv) [root@CENTOS01 ccs-pykerberos]# 
(py27-venv) [root@CENTOS01 ccs-pykerberos]# # Install new ccs-pykerberos library with CBT support
(py27-venv) [root@CENTOS01 ccs-pykerberos]# pip install .
Processing /testing/ccs-pykerberos
Building wheels for collected packages: kerberos
  Running setup.py bdist_wheel for kerberos ... done
  Stored in directory: /root/.cache/pip/wheels/7c/f0/16/7c29c46808274738267e8967235b93dda40a58a04af5c2b1c0
Successfully built kerberos
Installing collected packages: kerberos
Successfully installed kerberos-1.2.6
(py27-venv) [root@CENTOS01 ccs-pykerberos]# 
(py27-venv) [root@CENTOS01 ccs-pykerberos]# # Run tests for Python 2.7.13
(py27-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -s HTTP@centos01.jordan.local service

*** Running Service Principal test
Kerberos service principal for HTTP/centos01.jordan.local succeeded: HTTP/centos01.jordan.local@JORDAN.LOCAL

*** Done

(py27-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -u user1 -p Password01 -s HTTP@centos01.jordan.local -r JORDAN.LOCAL basic

*** Running basic test
Kerberos authentication for user1 succeeded

*** Done

(py27-venv) [root@CENTOS01 ccs-pykerberos]# 
(py27-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -s HTTP@centos01.jordan.local -r JORDAN.LOCAL gssapi

*** Running GSSAPI test
Status for authGSSClientInit = Complete
Status for authGSSServerInit = Complete
Status for authGSSClientStep = Continue
Status for authGSSServerStep = Complete
Status for authGSSClientStep = Complete
Server user name: user1@JORDAN.LOCAL
Server target name: None
Client user name: user1@JORDAN.LOCAL
Status for authGSSClientClean = Complete
Status for authGSSServerClean = Complete

*** Done

(py27-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -s HTTP@centos01.jordan.local -h centos01.jordan.local -i 80 server

*** Running HTTP test
Authenticated successfully

*** Done

(py27-venv) [root@CENTOS01 ccs-pykerberos]# 
(py27-venv) [root@CENTOS01 ccs-pykerberos]# # Create virtual env for Python 3.6.1 and run tests
(py27-venv) [root@CENTOS01 ccs-pykerberos]# deactivate
[root@CENTOS01 ccs-pykerberos]# virtualenv /testing/py36-venv -p /usr/local/bin/python3.6
Already using interpreter /usr/local/bin/python3.6
Using base prefix '/usr/local'
New python executable in /testing/py36-venv/bin/python3.6
Also creating executable in /testing/py36-venv/bin/python
Installing setuptools, pip, wheel...done.
[root@CENTOS01 ccs-pykerberos]# source /testing/py36-venv/bin/activate
(py36-venv) [root@CENTOS01 ccs-pykerberos]# python --version
Python 3.6.1
(py36-venv) [root@CENTOS01 ccs-pykerberos]# 
(py36-venv) [root@CENTOS01 ccs-pykerberos]# pip install .
Processing /testing/ccs-pykerberos
Building wheels for collected packages: kerberos
  Running setup.py bdist_wheel for kerberos ... done
  Stored in directory: /root/.cache/pip/wheels/7c/f0/16/7c29c46808274738267e8967235b93dda40a58a04af5c2b1c0
Successfully built kerberos
Installing collected packages: kerberos
Successfully installed kerberos-1.2.6
(py36-venv) [root@CENTOS01 ccs-pykerberos]# 
(py36-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -s HTTP@centos01.jordan.local service

*** Running Service Principal test
Kerberos service principal for HTTP/centos01.jordan.local succeeded: HTTP/centos01.jordan.local@JORDAN.LOCAL

*** Done

(py36-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -u user1 -p Password01 -s HTTP@centos01.jordan.local -r JORDAN.LOCAL basic

*** Running basic test
Kerberos authentication for user1 succeeded

*** Done

(py36-venv) [root@CENTOS01 ccs-pykerberos]# 
(py36-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -s HTTP@centos01.jordan.local -r JORDAN.LOCAL gssapi

*** Running GSSAPI test
Status for authGSSClientInit = Complete
Status for authGSSServerInit = Complete
Status for authGSSClientStep = Continue
Status for authGSSServerStep = Complete
Status for authGSSClientStep = Complete
Server user name: user1@JORDAN.LOCAL
Server target name: None
Client user name: user1@JORDAN.LOCAL
Status for authGSSClientClean = Complete
Status for authGSSServerClean = Complete

*** Done

(py36-venv) [root@CENTOS01 ccs-pykerberos]# python test.py -s HTTP@centos01.jordan.local -h centos01.jordan.local -i 80 server

*** Running HTTP test
Authenticated successfully

*** Done

(py36-venv) [root@CENTOS01 ccs-pykerberos]# 

Hopefully this manual test and my test with a CBT endpoint as shown in the first post helps to alleviate any concerns about backwards compatibility. If you have anything else you want me to try or do differently just ask and I should be able to do it.

@jborean93
Copy link
Contributor Author

@dreness I hope you were the person I was talking to in IRC, just hoping the above information is good enough to cover the testing side of things. Not sure what you would like me to do next.

@dreness
Copy link
Member

dreness commented May 23, 2017

@jborean93 I am. Your testing efforts have been substantial and are well received. I will dig into this and get some comments from others, and can hopefully merge this soon.

@jborean93
Copy link
Contributor Author

Thanks for that, I might spend some time on another PR soon to get integration with travis to make this easier in the future but it all depends on how much time I have.

@m0rgen
Copy link
Contributor

m0rgen commented May 26, 2017

This looks good -- one question: for this malloc...

input_chan_bindings = (struct gss_channel_bindings_struct *) malloc(sizeof(struct gss_channel_bindings_struct));

Who is responsible for freeing it? Is it handled by Python object reference counting?

@jborean93
Copy link
Contributor Author

I'm not sure on that (my inexperience shining through) but I suppose after the library using this get's a successful authentication it should free it. Is there a way to do this in python or do I need to pass in the object to another method on the C side?

@m0rgen
Copy link
Contributor

m0rgen commented May 26, 2017

I am not familiar with the Python/CObjects API, but I do see in the docs that PyCObject_FromVoidPtr( ) can take a destructor function which gets called with the python object is reclaimed. Perhaps it needs to be passed a function that does the free? We need to get someone more familiar with this to chime in.

@jborean93
Copy link
Contributor Author

I'll do some research and will see what I can find.

@dreness
Copy link
Member

dreness commented May 26, 2017

I'm trying to get this loaded up in xcode so I can point the clang static analyzer at it, which should help identify lifecycle issues.

@m0rgen
Copy link
Contributor

m0rgen commented May 26, 2017

So I think you want to pass "free" to PyCObject_FromVoidPtr, e.g.:

pychan_bindings = PyCObject_FromVoidPtr(input_chan_bindings, free);

@dreness
Copy link
Member

dreness commented May 26, 2017

I received a hot tip from another frog right around the time that a similar conclusion was reached by m0rgen: If "free" is passed instead of NULL, that should free the C-side object. Doing some testing on that...

@jborean93
Copy link
Contributor Author

So if I pass free to that Python will automatically free the memory or do I still have to call that somewhere else when ready?

@dreness
Copy link
Member

dreness commented May 26, 2017

The python object is reclaimed automatically, and this "destr" argument is a facility for allowing that reclamation to flow back to the C-side, by the C. sure. (cough). The argument itself is the function that is called (with one argument: a pointer to the thing being freed) when the python object is reclaimed, so to do the moral equivalent on the C-side, we can just pass 'free'.

@jborean93
Copy link
Contributor Author

Made those changes plus I bumped the version. I checked with my original test and the CBT stuff still works after the test.

src/kerberos.c Outdated
}

input_chan_bindings = (struct gss_channel_bindings_struct *) malloc(sizeof(struct gss_channel_bindings_struct));
pychan_bindings = PyCObject_FromVoidPtr(input_chan_bindings, free);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Python 3.x, PyCObject_FromVoidPtr is an alias for PyCapsule_New (see line 40). The destructor passed as the second argument here will end up being called on the PyCapsule itself, not the gss_channel_bindings_struct. That's almost certainly not what you want.

https://docs.python.org/3.1/c-api/capsule.html#PyCapsule_New

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do I need to do something like line 109 at https://github.com/02strich/pykerberos/blob/master/src/kerberos.c where I free the struct in the code?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an example that deals with both python 2 and 3:
https://github.com/02strich/pykerberos/blob/v1.1.9/src/kerberos.c#L102-L116

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks I'll give it a shot and will hopefully get it working.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, just to say the words out loud for my own benefit: the differences between python 2 and 3 for instantiating python objects are abstracted by the macros near the top of src/kerberos.c, and the destructor function is conditionally defined based on the python version.

@behackett
Copy link
Contributor

It would be really helpful if you could update the docstring for authGSSClientStep with the new parameter and an example of how to use it here:

https://github.com/apple/ccs-pykerberos/blob/master/pysrc/kerberos.py

src/kerberos.c Outdated
static char *kwlist[] = {"initiator_addrtype", "initiator_address", "accept_addrtype",
"acceptor_address", "application_data", NULL};

if (!PyArg_ParseTupleAndKeywords(args, keywds, "|is#is#s#", kwlist,
Copy link
Contributor

@behackett behackett May 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the PyCObject / PyCapsule used to hold the binding struct may outlive the Python strings used to pass in the addresses, I think you need to use es# here, and call PyMem_Free on each string in your destructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I need to free all the char* that can possibly be used in the structure in what I have just added?

Copy link
Contributor

@behackett behackett May 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, specifically using PyMem_Free, since PyArg_ParseTuple allocates the storage for you. The thing that worries me about using s# is that PyArg_ParseTuple just gives you a pointer to the internal storage of the Python string / unicode object. If that object's ref count falls to zero while the application is still using the binding object you'll have a problem.

The C API docs for python 3.6 make this clear:

In general, when a format sets a pointer to a buffer, the buffer is managed by the corresponding Python object, and the buffer shares the lifetime of this object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to use et# instead as we are actually passing in a byte string not a unicode string. Hopefully the changes I've put through are correct I'm going into uncharted territory for me.

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
Copy link
Contributor

@behackett behackett May 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you'll also want to add module constants for GSS_C_AF_UNSPEC and whatever other values are valid for *addrtype, similar to the definitions for things like AUTH_GSS_COMPLETE, GSS_C_DELEG_FLAG, etc. here:

https://github.com/apple/ccs-pykerberos/blob/PyKerberos-1.2.5/src/kerberos.c#L802-L835

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks I was thinking about that when doing the docs for this, will update it accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in the latest commit.

@dreness
Copy link
Member

dreness commented May 31, 2017

Looking good! @jborean93 - do you still have the test environment available? If so, would it be possible for you to run through the testing and validation again with all the recent changes applied?

@jborean93
Copy link
Contributor Author

Yep I just reran the original tests and the WinRM test and here is the output. Also is there a way of having a collapsable block of text in Github?

Cloning into 'ccs-pykerberos'...
1200d2a More improvements to handle memory deallocation
New python executable in /testing/py27-venv/bin/python2.7
Also creating executable in /testing/py27-venv/bin/python
Installing setuptools, pip, wheel...done.
Running virtualenv with interpreter /usr/local/bin/python2.7
Python 2.7.13
Processing /testing/ccs-pykerberos
Building wheels for collected packages: kerberos
  Running setup.py bdist_wheel for kerberos: started
  Running setup.py bdist_wheel for kerberos: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/7c/f0/16/7c29c46808274738267e8967235b93dda40a58a04af5c2b1c0
Successfully built kerberos
Installing collected packages: kerberos
Successfully installed kerberos-1.3.0
Collecting pywinrm
  Using cached pywinrm-0.2.2-py2.py3-none-any.whl
Collecting xmltodict (from pywinrm)
  Using cached xmltodict-0.11.0-py2.py3-none-any.whl
Collecting requests-ntlm>=0.3.0 (from pywinrm)
  Using cached requests_ntlm-1.0.0-py2.py3-none-any.whl
Requirement already satisfied: six in /testing/py27-venv/lib/python2.7/site-packages (from pywinrm)
Collecting requests>=2.9.1 (from pywinrm)
  Using cached requests-2.17.3-py2.py3-none-any.whl
Collecting ntlm-auth>=1.0.2 (from requests-ntlm>=0.3.0->pywinrm)
  Using cached ntlm_auth-1.0.4-py2.py3-none-any.whl
Collecting idna<2.6,>=2.5 (from requests>=2.9.1->pywinrm)
  Using cached idna-2.5-py2.py3-none-any.whl
Collecting urllib3<1.22,>=1.21.1 (from requests>=2.9.1->pywinrm)
  Using cached urllib3-1.21.1-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.9.1->pywinrm)
  Using cached chardet-3.0.3-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=2.9.1->pywinrm)
  Using cached certifi-2017.4.17-py2.py3-none-any.whl
Collecting ordereddict (from ntlm-auth>=1.0.2->requests-ntlm>=0.3.0->pywinrm)
Installing collected packages: xmltodict, ordereddict, ntlm-auth, idna, urllib3, chardet, certifi, requests, requests-ntlm, pywinrm
Successfully installed certifi-2017.4.17 chardet-3.0.3 idna-2.5 ntlm-auth-1.0.4 ordereddict-1.1 pywinrm-0.2.2 requests-2.17.3 requests-ntlm-1.0.0 urllib3-1.21.1 xmltodict-0.11.0
Collecting git+https://github.com/jborean93/requests-kerberos@add-cbt
  Cloning https://github.com/jborean93/requests-kerberos (to add-cbt) to /tmp/pip-MFU6oE-build
Requirement already satisfied: requests>=1.1.0 in /testing/py27-venv/lib/python2.7/site-packages (from requests-kerberos==0.11.0)
Collecting pyasn1 (from requests-kerberos==0.11.0)
  Using cached pyasn1-0.2.3-py2.py3-none-any.whl
Collecting pyasn1-modules (from requests-kerberos==0.11.0)
  Using cached pyasn1_modules-0.0.8-py2.py3-none-any.whl
Requirement already satisfied: kerberos<2.0.0,>=1.2.5 in /testing/py27-venv/lib/python2.7/site-packages (from requests-kerberos==0.11.0)
Requirement already satisfied: idna<2.6,>=2.5 in /testing/py27-venv/lib/python2.7/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Requirement already satisfied: urllib3<1.22,>=1.21.1 in /testing/py27-venv/lib/python2.7/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /testing/py27-venv/lib/python2.7/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Requirement already satisfied: certifi>=2017.4.17 in /testing/py27-venv/lib/python2.7/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Installing collected packages: pyasn1, pyasn1-modules, requests-kerberos
  Running setup.py install for requests-kerberos: started
    Running setup.py install for requests-kerberos: finished with status 'done'
Successfully installed pyasn1-0.2.3 pyasn1-modules-0.0.8 requests-kerberos-0.11.0

*** Running Service Principal test
Kerberos service principal for HTTP/centos01.jordan.local succeeded: HTTP/centos01.jordan.local@JORDAN.LOCAL

*** Done


*** Running basic test
Kerberos authentication for user1 succeeded

*** Done


*** Running GSSAPI test
Status for authGSSClientInit = Complete
Status for authGSSServerInit = Complete
Status for authGSSClientStep = Continue
Status for authGSSServerStep = Complete
Status for authGSSClientStep = Complete
Server user name: user1@JORDAN.LOCAL
Server target name: None
Client user name: user1@JORDAN.LOCAL
Status for authGSSClientClean = Complete
Status for authGSSServerClean = Complete

*** Done


*** Running HTTP test
Authenticated successfully

*** Done

Return Code: 0
STDOUT: 
Windows IP Configuration

   Host Name . . . . . . . . . . . . : APP01
   Primary Dns Suffix  . . . . . . . : jordan.local
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : jordan.local

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : Microsoft Hyper-V Network Adapter
   Physical Address. . . . . . . . . : 00-15-5D-01-03-02
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::e1d3:888b:78d2:b891%5(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.1.152(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1
   DHCPv6 IAID . . . . . . . . . . . : 50337117
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-20-80-CD-75-00-15-5D-01-03-02
   DNS Servers . . . . . . . . . . . : 192.168.1.151
   NetBIOS over Tcpip. . . . . . . . : Enabled

Tunnel adapter isatap.{D3EFED2A-9F5A-4D9C-B331-6669AC9E118B}:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : Microsoft ISATAP Adapter
   Physical Address. . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes

Tunnel adapter Teredo Tunneling Pseudo-Interface:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : Teredo Tunneling Pseudo-Interface
   Physical Address. . . . . . . . . : 00-00-00-00-00-00-00-E0
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes

STDERR: 
Using base prefix '/usr/local'
New python executable in /testing/py36-venv/bin/python3.6
Also creating executable in /testing/py36-venv/bin/python
Installing setuptools, pip, wheel...done.
Running virtualenv with interpreter /usr/local/bin/python3.6
Python 3.6.1
Processing /testing/ccs-pykerberos
Building wheels for collected packages: kerberos
  Running setup.py bdist_wheel for kerberos: started
  Running setup.py bdist_wheel for kerberos: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/7c/f0/16/7c29c46808274738267e8967235b93dda40a58a04af5c2b1c0
Successfully built kerberos
Installing collected packages: kerberos
Successfully installed kerberos-1.3.0
Collecting pywinrm
  Using cached pywinrm-0.2.2-py2.py3-none-any.whl
Collecting xmltodict (from pywinrm)
  Using cached xmltodict-0.11.0-py2.py3-none-any.whl
Collecting requests-ntlm>=0.3.0 (from pywinrm)
  Using cached requests_ntlm-1.0.0-py2.py3-none-any.whl
Collecting requests>=2.9.1 (from pywinrm)
  Using cached requests-2.17.3-py2.py3-none-any.whl
Requirement already satisfied: six in /testing/py36-venv/lib/python3.6/site-packages (from pywinrm)
Collecting ntlm-auth>=1.0.2 (from requests-ntlm>=0.3.0->pywinrm)
  Using cached ntlm_auth-1.0.4-py2.py3-none-any.whl
Collecting idna<2.6,>=2.5 (from requests>=2.9.1->pywinrm)
  Using cached idna-2.5-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=2.9.1->pywinrm)
  Using cached certifi-2017.4.17-py2.py3-none-any.whl
Collecting urllib3<1.22,>=1.21.1 (from requests>=2.9.1->pywinrm)
  Using cached urllib3-1.21.1-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.9.1->pywinrm)
  Using cached chardet-3.0.3-py2.py3-none-any.whl
Collecting ordereddict (from ntlm-auth>=1.0.2->requests-ntlm>=0.3.0->pywinrm)
Installing collected packages: xmltodict, idna, certifi, urllib3, chardet, requests, ordereddict, ntlm-auth, requests-ntlm, pywinrm
Successfully installed certifi-2017.4.17 chardet-3.0.3 idna-2.5 ntlm-auth-1.0.4 ordereddict-1.1 pywinrm-0.2.2 requests-2.17.3 requests-ntlm-1.0.0 urllib3-1.21.1 xmltodict-0.11.0
Collecting git+https://github.com/jborean93/requests-kerberos@add-cbt
  Cloning https://github.com/jborean93/requests-kerberos (to add-cbt) to /tmp/pip-5rln0mag-build
Requirement already satisfied: requests>=1.1.0 in /testing/py36-venv/lib/python3.6/site-packages (from requests-kerberos==0.11.0)
Collecting pyasn1 (from requests-kerberos==0.11.0)
  Using cached pyasn1-0.2.3-py2.py3-none-any.whl
Collecting pyasn1-modules (from requests-kerberos==0.11.0)
  Using cached pyasn1_modules-0.0.8-py2.py3-none-any.whl
Requirement already satisfied: kerberos<2.0.0,>=1.2.5 in /testing/py36-venv/lib/python3.6/site-packages (from requests-kerberos==0.11.0)
Requirement already satisfied: certifi>=2017.4.17 in /testing/py36-venv/lib/python3.6/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Requirement already satisfied: idna<2.6,>=2.5 in /testing/py36-venv/lib/python3.6/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Requirement already satisfied: urllib3<1.22,>=1.21.1 in /testing/py36-venv/lib/python3.6/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /testing/py36-venv/lib/python3.6/site-packages (from requests>=1.1.0->requests-kerberos==0.11.0)
Installing collected packages: pyasn1, pyasn1-modules, requests-kerberos
  Running setup.py install for requests-kerberos: started
    Running setup.py install for requests-kerberos: finished with status 'done'
Successfully installed pyasn1-0.2.3 pyasn1-modules-0.0.8 requests-kerberos-0.11.0

*** Running Service Principal test
Kerberos service principal for HTTP/centos01.jordan.local succeeded: HTTP/centos01.jordan.local@JORDAN.LOCAL

*** Done


*** Running basic test
Kerberos authentication for user1 succeeded

*** Done


*** Running GSSAPI test
Status for authGSSClientInit = Complete
Status for authGSSServerInit = Complete
Status for authGSSClientStep = Continue
Status for authGSSServerStep = Complete
Status for authGSSClientStep = Complete
Server user name: user1@JORDAN.LOCAL
Server target name: None
Client user name: user1@JORDAN.LOCAL
Status for authGSSClientClean = Complete
Status for authGSSServerClean = Complete

*** Done


*** Running HTTP test
Authenticated successfully

*** Done

Return Code: 0
STDOUT: b'\r\nWindows IP Configuration\r\n\r\n   Host Name . . . . . . . . . . . . : APP01\r\n   Primary Dns Suffix  . . . . . . . : jordan.local\r\n   Node Type . . . . . . . . . . . . : Hybrid\r\n   IP Routing Enabled. . . . . . . . : No\r\n   WINS Proxy Enabled. . . . . . . . : No\r\n   DNS Suffix Search List. . . . . . : jordan.local\r\n\r\nEthernet adapter Ethernet:\r\n\r\n   Connection-specific DNS Suffix  . : \r\n   Description . . . . . . . . . . . : Microsoft Hyper-V Network Adapter\r\n   Physical Address. . . . . . . . . : 00-15-5D-01-03-02\r\n   DHCP Enabled. . . . . . . . . . . : No\r\n   Autoconfiguration Enabled . . . . : Yes\r\n   Link-local IPv6 Address . . . . . : fe80::e1d3:888b:78d2:b891%5(Preferred) \r\n   IPv4 Address. . . . . . . . . . . : 192.168.1.152(Preferred) \r\n   Subnet Mask . . . . . . . . . . . : 255.255.255.0\r\n   Default Gateway . . . . . . . . . : 192.168.1.1\r\n   DHCPv6 IAID . . . . . . . . . . . : 50337117\r\n   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-20-80-CD-75-00-15-5D-01-03-02\r\n   DNS Servers . . . . . . . . . . . : 192.168.1.151\r\n   NetBIOS over Tcpip. . . . . . . . : Enabled\r\n\r\nTunnel adapter isatap.{D3EFED2A-9F5A-4D9C-B331-6669AC9E118B}:\r\n\r\n   Media State . . . . . . . . . . . : Media disconnected\r\n   Connection-specific DNS Suffix  . : \r\n   Description . . . . . . . . . . . : Microsoft ISATAP Adapter\r\n   Physical Address. . . . . . . . . : 00-00-00-00-00-00-00-E0\r\n   DHCP Enabled. . . . . . . . . . . : No\r\n   Autoconfiguration Enabled . . . . : Yes\r\n\r\nTunnel adapter Teredo Tunneling Pseudo-Interface:\r\n\r\n   Media State . . . . . . . . . . . : Media disconnected\r\n   Connection-specific DNS Suffix  . : \r\n   Description . . . . . . . . . . . : Teredo Tunneling Pseudo-Interface\r\n   Physical Address. . . . . . . . . : 00-00-00-00-00-00-00-E0\r\n   DHCP Enabled. . . . . . . . . . . : No\r\n   Autoconfiguration Enabled . . . . : Yes\r\n'
STDERR: b''

@cyrusdaboo
Copy link
Contributor

In buildChannelBindingsStruct the "et#" format is not being used properly. This causes warnings when compiling:

src/kerberos.c:272:51: warning: incompatible pointer to integer conversion assigning to 'size_t' (aka 'unsigned long') from 'int *' [-Wint-conversion]
input_chan_bindings->initiator_address.length = initiator_length;
^ ~~~~~~~~~~~~~~~~

I've attached a diff to correct this. Please run all your tests again after this fix.

diff --git a/src/kerberos.c b/src/kerberos.c
index 406f5c1..440831d 100644
--- a/src/kerberos.c
+++ b/src/kerberos.c
@@ -244,12 +244,12 @@ static PyObject *buildChannelBindingsStruct(PyObject *self, PyObject *args, PyOb
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 = NULL;
  • int *acceptor_length = NULL;
  • int *application_length = 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;

    int result = 0;

@cyrusdaboo
Copy link
Contributor

Ugh! My diff got messed up. Let's try again:

diff --git a/src/kerberos.c b/src/kerberos.c
index 406f5c1..440831d 100644
--- a/src/kerberos.c
+++ b/src/kerberos.c
@@ -244,12 +244,12 @@ static PyObject *buildChannelBindingsStruct(PyObject *self, PyObject *args, PyOb
     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 = NULL;
-    int *acceptor_length = NULL;
-    int *application_length = 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;

     int result = 0;

@cyrusdaboo
Copy link
Contributor

Some other things:

  1. I think "buildChannelBindingsStruct" should be renamed to "channelBindings".

  2. I think the keyword argument for authGSSClientStep should be "channel_bindings" rather than "input_chan_bindings".

  3. I think "channelBindings" should just return the py object and not the tuple of integer result and py object. Reasons:

  • The result is always set to zero - it never changes - so it is completely redundant
  • It will make python code cleaner:
kerberos.authGSSClientStep(..., ..., channel_bindings=kerberos.channelBindings(initiator_addrtype=0, initiator_address="foobar"))

Slightly better than having to always append "[1]" to the channelBindings result to get the py object.

@jborean93
Copy link
Contributor Author

@cyrusdaboo thanks for the feedback, I've made the changes you have requested and commit them. I also reran the tests and it still works fine. Please let me know if you wish for any more changes.

@jborean93
Copy link
Contributor Author

Merged in the latest changes from the master branch and pushed them to this branch. Looks like the travis build is working fine. Please let me know if there is anything else you need from me.

@jborean93
Copy link
Contributor Author

@dreness @cyrusdaboo any chance you can have another look, I am hoping to get a consensus with this PR and the Windows equivalent mongodb/winkerberos#17 and I am nearing the end of that PR.

@dreness
Copy link
Member

dreness commented Jun 22, 2017

@jborean93 I think we're looking good here. I'm going to ping one more possibly interested stakeholder, but personally I'm satisfied.

@dreness dreness merged commit 6bdbce2 into apple:master Jun 27, 2017
@dreness
Copy link
Member

dreness commented Jun 27, 2017

Thanks again @jborean93 - very nice job on this PR :)

@jborean93
Copy link
Contributor Author

Thanks @dreness and others who helped with this PR.

@jborean93 jborean93 deleted the cbt-support branch August 7, 2017 20:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants