xpra icon
Bug tracker and wiki

Opened 13 months ago

Closed 7 months ago

#1691 closed enhancement (worksforme)

kerberos authentication

Reported by: Antoine Martin Owned by: J. Max Mena
Priority: major Milestone: 2.3
Component: network Version: trunk
Keywords: Cc:

Description (last modified by Antoine Martin)

Looks like we can use pykerberos, if only there were better examples.

See also #1255, #1692

Attachments (1)

winkerberos-mingw.patch (1.6 KB) - added by Antoine Martin 9 months ago.
patch for building with mingw

Download all attachments as: .zip

Change History (11)

comment:1 Changed 13 months ago by Antoine Martin

Description: modified (diff)
Milestone: 2.22.3
Status: newassigned

comment:2 Changed 9 months ago by Antoine Martin

Added dumb implementation in r18693 using pykerberos.

Going forward, we should use the tokens rather than the password, and maybe even use python-gssapi for encryption?

comment:3 Changed 9 months ago by Antoine Martin

Based on centos 6: configuring a kerberos 5 server, and made harder by the fact that my LAN doesn't have a domain or DNS server...

hostname localdomain
/usr/sbin/kdb5_util create -s
cat > /etc/krb5.conf << EOF
includedir /etc/krb5.conf.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_ccache_name = KEYRING:persistent:%{uid}
 default_realm = LOCALDOMAIN

[realms]
 LOCALDOMAIN = {
  kdc = localhost
  admin_server = localhost
 }

[domain_realm]
 localdomain = LOCALDOMAIN
EOF
echo "*/admin@LOCALDOMAIN	*" > /var/kerberos/krb5kdc/kadm5.acl 
kadmind
krb5kdc
kadmin.local -q "addprinc test/admin"
kinit admin
kadmin -q "addprinc xpra"

The python-gssapi documentation at https://pythonhosted.org/python-gssapi/examples.html is out of date, but this one isn't: https://pythongssapi.github.io/python-gssapi/latest/gssapi.html.

For win32, we could use winkerberos instead of pykerberos.

  • with gssapi:

client:

$ python
import gssapi
service_name = gssapi.Name("xpra")
ctx = gssapi.SecurityContext(name=service_name, usage="initiate")
k = ctx.step()

server:

from gssapi import creds as gsscreds
from gssapi import sec_contexts as gssctx

server_creds = gsscreds.Credentials(usage='accept')
server_ctx = gssctx.SecurityContext(creds=server_creds)
server_ctx.step(k)
print(server_ctx.complete)
  • with kerberos:

client:

v,c = kerberos.authGSSClientInit("xpra")
assert v==1
kerberos.authGSSClientStep(c, "")
k = kerberos.authGSSClientResponse(c)

server:

v,c = kerberos.authGSSServerInit("xpra")
assert v==1
r = kerberos.authGSSServerStep(c, k)
assert r==1

Things to think about:

Last edited 9 months ago by Antoine Martin (previous) (diff)

comment:4 Changed 9 months ago by Antoine Martin

The overloading of the "digest" list to add and detect support for "kerberos" and "gss" options is a bit ugly, but it is the most backwards compatible way. Older clients will just state that they don't support "kerberos" (or "gss") rather than failing in more obscure ways.

Examples:

xpra start --start-child="xterm" --bind-tcp=0.0.0.0:10000 --tcp-auth=kerberos-token,service=xpra
xpra start --start-child="xterm" --bind-tcp=0.0.0.0:10000 --tcp-auth=gss,service=xpra

TODO:

  • packaging: builds and package libs for win32 (tricky: won't build) and macos
  • clients should be able to configure authentication: all|gui|tui|none|kerberos|gss
  • support multiple steps in auth modules (kerberos and gss may take multiple steps)
  • lots of testing, ideally against MS AD
  • add mutual authentication
  • security review
  • unit tests (hard!)
Last edited 9 months ago by Antoine Martin (previous) (diff)

Changed 9 months ago by Antoine Martin

Attachment: winkerberos-mingw.patch added

patch for building with mingw

comment:5 Changed 9 months ago by Antoine Martin

On win32, building winkerberos requires patching the header file to insert the missing SecPkgContext_Bindings structure definition then figuring out the equivallent gcc stanza for the msvc arguments. See patch attached, submitted upstream here: https://github.com/mongodb-labs/winkerberos/issues/21.

comment:6 Changed 9 months ago by Antoine Martin

Installing winkerberos from the modified source requires one more hack to prevent cx_freeze from messing up the packaging, as per stopping setup.py from installing as egg, we have to use pip to ensure it does not get installed as an egg:

pushd winkerberos-0.7.0
python2 setup.py sdist
popd
pip2 install ./winkerberos-0.7.0/dist/winkerberos-0.7.0.tar.gz
pip3 install ./winkerberos-0.7.0/dist/winkerberos-0.7.0.tar.gz

comment:7 Changed 9 months ago by Antoine Martin

First, install gss support: r18758, ie on x86_64:

pacman -S mingw-w64-x86_64-gss

Building python-gssapi:

  • use the correct gss header filename: gss.h with MSYS2 and not gssapi/gssapi.h:
    sed -i -e 's+gssapi/gssapi.h+gss.h+g' gssapi/raw/python_gssapi.h
    sed -i -e 's+gssapi/gssapi.h+gss.h+g' gssapi/raw/python_gssapi_ext.h
    sed -i -e 's+gssapi/gssapi_krb5.h+gss.h+g' gssapi/raw/python_gssapi_krb5.h
    
  • then we need to add the missing gss_mech_krb5 in gssapi/raw/mech_krb5.pyx:
    cdef extern from "python_gssapi_krb5.h":
        pass
    def make_OID(s):
        import struct
        v = struct.pack("@Is", len(s), s)
        return v
    pkrb5 = make_OID(b"\x2A\x86\x48\x86\xF7\x12\x01\x02\x02")
    cdef char *gss_mech_krb5_str = pkrb5
    pprincipal = make_OID(b"\x2A\x86\x48\x86\xF7\x12\x01\x02\x02");
    cdef char *GSS_KRB5_NT_PRINCIPAL_NAME_str = pprincipal
    cdef gss_OID gss_mech_krb5 = <gss_OID> gss_mech_krb5_str
    cdef gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = <gss_OID> GSS_KRB5_NT_PRINCIPAL_NAME_str
    

(and if I got this wrong, gss won't work...)

  • finally, find the magic incantation for the setup file:
    GSSAPI_MAIN_LIB=$MSYSTEM_PREFIX/bin/libgss-3.dll \
    GSSAPI_LINKER_ARGS="-lgss" \
    GSSAPI_COMPILER_ARGS="-fPIC" \
    python2 ./setup.py install
    

(clean and repeat with python3)

  • with python3, one also needs to skip the prefix test in setup.py:
    try:
        prefix = get_output('krb5-config gssapi --prefix')
    except:
        prefix = ""
    

Changes submitted upstream: support building against mingw headers.

Last edited 9 months ago by Antoine Martin (previous) (diff)

comment:8 Changed 9 months ago by Antoine Martin

Lots of improvements in r18780 (see commit message).

Examples (add -d auth for debug):

  • to only use kerberos authentication and with a specific service name "xpra":
    XPRA_KERBEROS_SERVICES="xpra" xpra attach tcp://localhost:10000/ --challenge-handlers=kerberos
    
  • to use the GUI prompt only for password (the URI password will be ignored):
    xpra attach tcp://username:unusedpassword@localhost:10000/ --challenge-handlers=prompt
    
  • to use the XPRA_PASSWORD environment variable for the first challenge, then the URI one for the second (when using multiple tcp-auth arguments when starting the server):
    XPRA_PASSWORD=password1 xpra attach tcp://username:passwordno2@localhost:10000/ --challenge-handlers=env,uri
    

comment:9 Changed 9 months ago by Antoine Martin

Owner: changed from Antoine Martin to J. Max Mena
Status: assignednew

Updates:

Ready for testing. There are packages for most platforms.

@maxmylyn: apart from testing the obvious command lines (ie: comment:8), the difficult thing is testing single-sign-on with gss / kerberos because this requires a domain controller on win32, and on macos: Authentication : kerberos
Please keep this ticket tidy as this will be the reference until the details are wiki-ized.

comment:10 Changed 7 months ago by Antoine Martin

Resolution: worksforme
Status: newclosed
Note: See TracTickets for help on using tickets.