Xpra-org / xpra

Persistent remote applications for X11; screen sharing for X11, MacOS and MSWindows.
https://xpra.org/
GNU General Public License v2.0
2k stars 171 forks source link

kerberos authentication #1691

Closed totaam closed 6 years ago

totaam commented 7 years ago

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

See also #1255, #1692

totaam commented 6 years ago

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?

totaam commented 6 years ago

2018-03-11 10:38:10: antoine commented


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:
* handling it for the html5 client: [Kerberos via javascript or HTML 5](https://stackoverflow.com/questions/8949141/kerberos-via-javascript-or-html-5)
* channel binding
totaam commented 6 years ago

2018-03-12 14:31:34: antoine commented


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!)
totaam commented 6 years ago

2018-03-18 07:30:25: antoine uploaded file winkerberos-mingw.patch (1.6 KiB)

patch for building with mingw

totaam commented 6 years ago

2018-03-18 07:36:03: antoine commented


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].

totaam commented 6 years ago

2018-03-18 07:51:16: antoine commented


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

2018-03-18 13:58:31: antoine commented


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.

totaam commented 6 years ago

2018-03-21 12:49:05: antoine commented


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

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.

totaam commented 5 years ago

The changes have been merged upstream, we should package this in mingw: #2170

totaam commented 5 years ago

See also: #1796

totaam commented 4 years ago

MSYS2 packaging for these modules: #2170.