apple / ccs-pykerberos

Python Kerberos library used by CalendarServer
https://www.calendarserver.org
Apache License 2.0
117 stars 65 forks source link

Cbt support #55

Closed jborean93 closed 7 years ago

jborean93 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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

dreness commented 7 years ago

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 commented 7 years ago

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

pychan_bindings = PyCObject_FromVoidPtr(input_chan_bindings, free);

dreness commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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

behackett commented 7 years ago

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

dreness commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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;
cyrusdaboo commented 7 years ago

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 commented 7 years ago

Some other things:

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

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

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

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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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

dreness commented 7 years ago

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

dreness commented 7 years ago

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

jborean93 commented 7 years ago

Thanks @dreness and others who helped with this PR.