示例#1
0
    def krbLogin(self, krb_req, proxyuser=None):
        """Authenticate the user using the base64-encoded
        AP_REQ message in krb_req.  If proxyuser is not None,
        log in that user instead of the user associated with the
        Kerberos principal.  The principal must be an authorized
        "proxy_principal" in the server config."""
        if self.logged_in:
            raise koji.AuthError("Already logged in")

        if not (context.opts.get('AuthPrincipal') and context.opts.get('AuthKeytab')):
            raise koji.AuthError('not configured for Kerberos authentication')

        ctx = krbV.default_context()
        srvprinc = krbV.Principal(name=context.opts.get('AuthPrincipal'), context=ctx)
        srvkt = krbV.Keytab(name=context.opts.get('AuthKeytab'), context=ctx)

        ac = krbV.AuthContext(context=ctx)
        ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE|krbV.KRB5_AUTH_CONTEXT_DO_TIME
        conninfo = self.getConnInfo()
        ac.addrs = conninfo

        # decode and read the authentication request
        req = base64.decodestring(krb_req)
        ac, opts, sprinc, ccreds = ctx.rd_req(req, server=srvprinc, keytab=srvkt,
                                              auth_context=ac,
                                              options=krbV.AP_OPTS_MUTUAL_REQUIRED)
        cprinc = ccreds[2]

        # Successfully authenticated via Kerberos, now log in
        if proxyuser:
            proxyprincs = [princ.strip() for princ in context.opts.get('ProxyPrincipals', '').split(',')]
            if cprinc.name in proxyprincs:
                login_principal = proxyuser
            else:
                raise koji.AuthError(
                      'Kerberos principal %s is not authorized to log in other users' % cprinc.name)
        else:
            login_principal = cprinc.name
        user_id = self.getUserIdFromKerberos(login_principal)
        if not user_id:
            if context.opts.get('LoginCreatesUser'):
                user_id = self.createUserFromKerberos(login_principal)
            else:
                raise koji.AuthError('Unknown Kerberos principal: %s' % login_principal)

        self.checkLoginAllowed(user_id)

        hostip = self.get_remote_ip()

        sinfo = self.createSession(user_id, hostip, koji.AUTHTYPE_KERB)

        # encode the reply
        rep = ctx.mk_rep(auth_context=ac)
        rep_enc = base64.encodestring(rep)

        # encrypt and encode the login info
        sinfo_priv = ac.mk_priv('%(session-id)s %(session-key)s' % sinfo)
        sinfo_enc = base64.encodestring(sinfo_priv)

        return (rep_enc, sinfo_enc, conninfo)
示例#2
0
    def test_krb_login(self):
        if not krbV:
            raise SkipTest('krbV module not found')
        server_princ_name = turbogears.config.get(
            'identity.krb_auth_principal', None)
        if not server_princ_name:  # XXX FIXME dead test
            raise SkipTest('server not configured for krbV')

        # build krb request
        ctx = krbV.default_context()
        try:
            ccache = ctx.default_ccache()
            client_princ = ccache.principal()
        except krbV.Krb5Error:
            raise SkipTest('client ticket not found, run kinit first')
        server_princ = krbV.Principal(name=server_princ_name, context=ctx)
        ac = krbV.AuthContext(context=ctx)
        ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
        ac.rcache = ctx.default_rcache()
        ac, req = ctx.mk_req(server=sprinc,
                             client=cprinc,
                             auth_context=ac,
                             ccache=ccache,
                             options=krbV.AP_OPTS_MUTUAL_REQUIRED)
        encoded_req = base64.encodestring(req)

        # attempt to log in
        server = self.get_server()
        server.auth.login_krbv(encoded_req)
def handle_udp(opts, sock):
    data, addr = sock.recvfrom(4096)
    ctx = krbV.default_context()
    sprinc = krbV.Principal(name=opts.principal, context=ctx)
    keytab = krbV.Keytab(name=opts.keytab, context=ctx)
    ac = krbV.AuthContext(context=ctx)
    ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
    ac, options, sprinc, ccreds = ctx.rd_req(
        data,
        server=sprinc,
        keytab=keytab,
        auth_context=ac,
        options=krbV.AP_OPTS_MUTUAL_REQUIRED)
    cprinc = ccreds[2]
    print 'Successfully authenticated via udp: %s' % cprinc.name
    rep = ctx.mk_rep(auth_context=ac)
    sock.sendto(rep, addr)
    msg_enc, addr = sock.recvfrom(4096)
    print 'Using addresses: %s' % str(
        (opts.serveraddr[0], opts.serveraddr[1], addr[0], addr[1]))
    ac.addrs = (opts.serveraddr[0], opts.serveraddr[1], addr[0], addr[1])
    msg = ac.rd_priv(msg_enc)
    print '  Received: %s' % msg
    resp_enc = ac.mk_priv(msg)
    sock.sendto(resp_enc, addr)
def udp_client(opts, sock, addr):
    ctx = krbV.default_context()
    if opts.ccache:
        ccache = krbV.CCache(name='FILE:' + opts.ccache, context=ctx)
    else:
        ccache = ctx.default_ccache()
    cprinc = ccache.principal()
    sprinc = krbV.Principal(name=opts.principal, context=ctx)
    ac = krbV.AuthContext(context=ctx)
    ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
    ac.rcache = ctx.default_rcache()
    ac, req = ctx.mk_req(server=sprinc,
                         client=cprinc,
                         auth_context=ac,
                         ccache=ccache,
                         options=krbV.AP_OPTS_MUTUAL_REQUIRED)
    sock.sendto(req, addr)
    rep, saddr = sock.recvfrom(4096)
    rep_tup = ctx.rd_rep(rep, auth_context=ac)
    print 'Successfully authenticated via udp to service: %s' % sprinc.name
    try:
        addrinfo = socket.getaddrinfo(socket.gethostname(),
                                      sock.getsockname()[1], opts.addr_family)
        localaddr = addrinfo[0][4]
    except socket.gaierror, e:
        gai_error(opts, 'local', socket.gethostname(), e)
示例#5
0
def login_krbv(request, krb_request, proxy_user=None):
    """login_krbv(krb_request, proxy_user=None): session_key"""
    import krbV

    context = krbV.default_context()
    server_principal = krbV.Principal(name=settings.KRB_AUTH_PRINCIPAL, context=context)
    server_keytab = krbV.Keytab(name=settings.KRB_AUTH_KEYTAB, context=context)

    auth_context = krbV.AuthContext(context=context)
    auth_context.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
    auth_context.addrs = (socket.gethostbyname(request.META["HTTP_HOST"]), 0, request.META["REMOTE_ADDR"], 0)

    # decode and read the authentication request
    decoded_request = base64.decodestring(krb_request)
    auth_context, opts, server_principal, cache_credentials = context.rd_req(decoded_request, server=server_principal, keytab=server_keytab, auth_context=auth_context, options=krbV.AP_OPTS_MUTUAL_REQUIRED)
    cprinc = cache_credentials[2]

    # remove @REALM
    username = cprinc.name.split("@")[0]
    backend = Krb5RemoteUserBackend()
    user = backend.authenticate(username)
    if user is None:
        raise PermissionDenied()
    user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
    django.contrib.auth.login(request, user)
    return request.session.session_key
示例#6
0
    def login_krbV(self, krb_request, proxy_user=None):
        """
        Authenticates the current session using Kerberos.
        The caller may act as a proxy on behalf of another user by passing the
        *proxy_user* argument. This requires that the caller has 'proxy_auth'
        permission.
        :param krb_request: KRB_AP_REQ message containing client credentials,
        as produced by :c:func:`krb5_mk_req`
        :type krb_request: base64-encoded string
        :param proxy_user: username on whose behalf the caller is proxying
        :type proxy_user: string or None
        This method is also available under the alias :meth:`auth.login_krbv`,
        for compatibility with `Kobo`_.
        """
        import krbV
        import base64

        context = krbV.default_context()
        server_principal = krbV.Principal(name=KRB_AUTH_PRINCIPAL,
                                          context=context)
        server_keytab = krbV.Keytab(name=KRB_AUTH_KEYTAB, context=context)

        auth_context = krbV.AuthContext(context=context)
        auth_context.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
        auth_context.addrs = (socket.gethostbyname(
            cherrypy.request.remote_host), 0, cherrypy.request.remote_addr, 0)

        # decode and read the authentication request
        decoded_request = base64.decodestring(krb_request)
        auth_context, opts, server_principal, cache_credentials = context.rd_req(
            decoded_request,
            server=server_principal,
            keytab=server_keytab,
            auth_context=auth_context,
            options=krbV.AP_OPTS_MUTUAL_REQUIRED)
        cprinc = cache_credentials[2]

        # remove @REALM
        username = cprinc.name.split("@")[0]
        user = User.by_user_name(username)
        if user is None:
            raise LoginException(_(u'Invalid username'))
        if not user.can_log_in():
            raise LoginException(_(u'Invalid username'))
        if proxy_user:
            if not user.has_permission(u'proxy_auth'):
                raise LoginException(
                    _(u'%s does not have proxy_auth permission') %
                    user.user_name)
            proxied_user = User.by_user_name(proxy_user)
            if proxied_user is None:
                raise LoginException(
                    _(u'Proxy user %s does not exist') % proxy_user)
            identity.set_authentication(proxied_user, proxied_by=user)
        else:
            identity.set_authentication(user)
        return username
示例#7
0
    def _login_krbv(self):
        """Login using kerberos credentials (uses python-krbV)."""

        # read default values from settings
        principal = self._conf.get("KRB_PRINCIPAL")
        keytab = self._conf.get("KRB_KEYTAB")
        service = self._conf.get("KRB_SERVICE")
        realm = self._conf.get("KRB_REALM")
        ccache = self._conf.get("KRB_CCACHE")
        proxyuser = self._conf.get("KRB_PROXYUSER")

        import krbV
        ctx = krbV.default_context()

        if ccache is not None:
            ccache = krbV.CCache(name='FILE:' + ccache, context=ctx)
        else:
            ccache = ctx.default_ccache()

        if principal is not None:
            if keytab is not None:
                cprinc = krbV.Principal(name=principal, context=ctx)
                keytab = krbV.Keytab(name=keytab, context=ctx)
                ccache.init(cprinc)
                ccache.init_creds_keytab(principal=cprinc, keytab=keytab)
            else:
                raise ImproperlyConfigured(
                    "Cannot specify a principal without a keytab")
        else:
            # connect using existing credentials
            cprinc = ccache.principal()

        sprinc = krbV.Principal(name=self.get_server_principal(service=service,
                                                               realm=realm),
                                context=ctx)

        ac = krbV.AuthContext(context=ctx)
        ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
        ac.rcache = ctx.default_rcache()

        # create and encode the authentication request
        try:
            ac, req = ctx.mk_req(server=sprinc,
                                 client=cprinc,
                                 auth_context=ac,
                                 ccache=ccache,
                                 options=krbV.AP_OPTS_MUTUAL_REQUIRED)
        except krbV.Krb5Error as ex:
            if getattr(ex, "err_code", None) == -1765328377:
                ex.message += ". Make sure you correctly set KRB_REALM (current value: %s)." % realm
                ex.args = (ex.err_code, ex.message)
            raise ex
        encode_func = base64.encodebytes if hasattr(
            base64, "encodebytes") else base64.encodestring
        req_enc = encode_func(req)

        self._hub.auth.login_krbv(req_enc)
示例#8
0
def login_krbv():
    """
    Authenticates the current session using Kerberos.
    The caller may act as a proxy on behalf of another user by passing the
    *proxy_user* key. This requires that the caller has 'proxy_auth'
    permission. The request body must be a JSON object containing krb_request.
    Proxy_user is optional.

    :jsonparam base64-encoded-string krb_request: KRB_AP_REQ message containing
        client credentials, as produced by :c:func:`krb5_mk_req`
    :jsonparam string proxy_user: Username on whose behalf the caller is proxying
    """
    import krbV
    import base64

    payload = read_json_request(request)
    krb_request = payload.get('krb_request')
    proxy_user = payload.get('proxy_user')

    context = krbV.default_context()
    server_principal = krbV.Principal(name=KRB_AUTH_PRINCIPAL, context=context)
    server_keytab = krbV.Keytab(name=KRB_AUTH_KEYTAB, context=context)

    auth_context = krbV.AuthContext(context=context)
    auth_context.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
    auth_context.addrs = (socket.gethostbyaddr(request.remote_addr), 0,
                          request.remote_addr, 0)

    # decode and read the authentication request
    decoded_request = base64.decodestring(krb_request)
    auth_context, opts, server_principal, cache_credentials = context.rd_req(
        decoded_request,
        server=server_principal,
        keytab=server_keytab,
        auth_context=auth_context,
        options=krbV.AP_OPTS_MUTUAL_REQUIRED)
    cprinc = cache_credentials[2]

    # remove @REALM
    username = cprinc.name.split("@")[0]
    user = User.by_user_name(username)
    if user is None:
        raise Unauthorised401(u'Invalid username')
    if not user.can_log_in():
        raise Unauthorised401(u'Invalid username')
    if proxy_user:
        if not user.has_permission(u'proxy_auth'):
            raise Unauthorised401(u'%s does not have proxy_auth permission' %
                                  user.user_name)
        proxied_user = User.by_user_name(proxy_user)
        if proxied_user is None:
            raise Unauthorised401(u'Proxy user %s does not exist' % proxy_user)
        identity.set_authentication(proxied_user, proxied_by=user)
    else:
        identity.set_authentication(user)
    return jsonify({'username': user.user_name})
示例#9
0
    def get_encoded_request(self, full_principal):
        sprinc = krbV.Principal(name=full_principal, context=self.context)
        ac = krbV.AuthContext(context=self.context)
        ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
        ac.rcache = self.context.default_rcache()

        # create and encode the authentication request
        try:
            req = self._create_request(sprinc, ac)
        except krbV.Krb5Error, e:
            if 'Ticket expired' in str(e):
                self.reinit()
                req = self._create_request(sprinc, ac)
            else:
                raise
示例#10
0
文件: hub.py 项目: joyxu/beaker
    def _login_krbv(self):
        """Login using kerberos credentials (uses python-krbV)."""
        def get_server_principal(service=None, realm=None):
            """Convert hub url to kerberos principal."""
            hostname = urlparse.urlparse(self._hub_url)[1]
            # remove port from hostname
            hostname = hostname.split(":")[0]

            if realm is None:
                # guess realm: last two parts from hostname
                realm = ".".join(hostname.split(".")[-2:]).upper()
            if service is None:
                service = "HTTP"
            return '%s/%s@%s' % (service, hostname, realm)

        # read default values from settings
        principal = self._conf.get("KRB_PRINCIPAL")
        keytab = self._conf.get("KRB_KEYTAB")
        service = self._conf.get("KRB_SERVICE")
        realm = self._conf.get("KRB_REALM")
        ccache = self._conf.get("KRB_CCACHE")
        proxyuser = self._conf.get("PROXY_USER")

        import krbV
        ctx = krbV.default_context()

        if ccache is not None:
            ccache = krbV.CCache(name='FILE:' + ccache, context=ctx)
        elif keytab is not None:
            # If we will be init'ing the ccache using a keytab, we need to
            # always avoid using the default shared ccache, as a workaround for
            # a race condition in krb5_cc_initialize() between unlink() and open()
            # (see RHBZ#1313580).
            ccache_tmpfile = tempfile.NamedTemporaryFile(prefix='krb5cc_bkr_')
            ccache = krbV.CCache(name='FILE:' + ccache_tmpfile.name,
                                 context=ctx)
        else:
            ccache = ctx.default_ccache()

        if principal is not None:
            if keytab is not None:
                cprinc = krbV.Principal(name=principal, context=ctx)
                keytab = krbV.Keytab(name=keytab, context=ctx)
                ccache.init(cprinc)
                ccache.init_creds_keytab(principal=cprinc, keytab=keytab)
            else:
                raise ImproperlyConfigured(
                    "Cannot specify a principal without a keytab")
        else:
            # connect using existing credentials
            cprinc = ccache.principal()

        sprinc = krbV.Principal(name=get_server_principal(service=service,
                                                          realm=realm),
                                context=ctx)

        ac = krbV.AuthContext(context=ctx)
        ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
        ac.rcache = ctx.default_rcache()

        # create and encode the authentication request
        try:
            ac, req = ctx.mk_req(server=sprinc,
                                 client=cprinc,
                                 auth_context=ac,
                                 ccache=ccache,
                                 options=krbV.AP_OPTS_MUTUAL_REQUIRED)
        except krbV.Krb5Error, ex:
            if getattr(ex, "err_code", None) == -1765328377:
                ex.message += ". Make sure you correctly set KRB_REALM (current value: %s)." % realm
                ex.args = (ex.err_code, ex.message)
            raise ex
 def finish_state(self):
     if self.state == self.STATE_SETUP:
         self.state = self.STATE_READING
     elif self.state == self.STATE_READING:
         authmgr = self.coord.app.auth
         remprinc = self.read_vals['remprinc']
         creds = (authmgr.primary_principal,
                  krbV.Principal(remprinc, context=authmgr.context),
                  (0, None), (0, 0, 0, 0), None, None, None, None,
                  self.read_vals['reqdata'], None)
         ac = None
         req = None
         need_retry = 10
         while need_retry:
             need_retry -= 1
             try:
                 ocreds = authmgr.ccache.get_credentials(
                     creds, options=krbV.KRB5_GC_USER_USER)
                 ac = krbV.AuthContext(context=authmgr.context)
                 ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE
                 opts = krbV.AP_OPTS_USE_SESSION_KEY | krbV.AP_OPTS_MUTUAL_REQUIRED
                 req = authmgr.context.mk_req(options=opts,
                                              creds=ocreds,
                                              auth_context=ac,
                                              ccache=authmgr.ccache)
                 need_retry = 0
             except krbV.Krb5Error, e:
                 if not need_retry: raise
                 if e.err_code != krbV.KRB5KRB_AP_ERR_TKT_EXPIRED:
                     raise
                 authmgr.reinit()
         ourid = None
         if self.idmap.has_key(self.read_vals['remid']):
             ourid = self.idmap[self.read_vals['remid']]
             assert type(ourid) in (tuple, list)
             self.cnx = ourid[1]
             self.cnx.cnxid = ourid[0]
             ourid = ourid[0]
         else:
             for I in self.coord.all_cnxs:
                 if I.cnxaddr and socket.gethostbyname(
                         I.cnxaddr[0]) == socket.gethostbyname(
                             self.addr[0]
                         ) and I.name == self.read_vals['remname']:
                     if I.cnx_state == I.CNX_CONNECTED:
                         # If we have an outgoing connection with the same info, we just drop this incoming one on the floor.
                         self.coord.log(
                             'Dropping incoming connection from %s because it matches outgoing connection %#x',
                             self.addr,
                             id(I),
                             level='debug',
                             local=1)
                         return self.fail()
                     else:
                         I.set_cnx_state(I.CNX_TERMINATED, do_lock=1)
             ourid = apiary.util.get_rand_str(prand=1)
             self.cnx = Connection(self.coord, cnxid=ourid)
         assert self.cnx.connector != self
         if self.cnx.connector:
             self.cnx.connector.fail()
         self.cnx.connector = self
         self.cnx.set_cnx_state(self.cnx.CNX_CONNECTING, do_lock=1)
         self.write_vals = {
             'localname': self.cnx.coord.app.localname,
             'cnxid': ourid,
             'localprinc': creds[0].name,
             'reqdata': req[1]
         }
         ac.genaddrs(self.cnxsock,
                     flags=krbV.KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
                     | krbV.KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)
         self.read_vals['ac'] = ac
         self.read_vals['user'] = remprinc
         assert type(remprinc) == str
         self.state = self.STATE_WRITING
         'cnxid': self.cnx.cnxid,
         'localprinc': princ.name,
         'reqdata': ocreds[7],
         'useruserkey': ocreds[2]
     }
     self.state = self.STATE_WRITING
 elif self.state == self.STATE_WRITING:
     self.state = self.STATE_READING
 elif self.state == self.STATE_READING:
     ac = None
     res = None
     need_retry = 1
     authmgr = self.cnx.coord.app.auth
     while need_retry:
         try:
             ac = krbV.AuthContext(context=authmgr.context)
             ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE
             ac.useruserkey = self.write_vals['useruserkey']
             res = authmgr.context.rd_req(
                 self.read_vals['reqdata'],
                 auth_context=ac,
                 server=authmgr.primary_principal)
             need_retry = 0
         except krbV.Krb5Error, e:
             if e.err_code != krbV.KRB5KRB_AP_ERR_TKT_EXPIRED:
                 return self.fail("Kerberos error %s/%s" %
                                  (e.err_code, e.message))
             authmgr.reinit()
     ac.genaddrs(self.cnxsock,
                 flags=krbV.KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
                 | krbV.KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)
示例#13
0
    def _login_krbv(self):
        """Login using kerberos credentials (uses python-krbV)."""
        def get_server_principal(service=None, realm=None):
            """Convert hub url to kerberos principal."""
            hostname = urlparse.urlparse(self._hub_url)[1]
            # remove port from hostname
            hostname = hostname.split(":")[0]

            if realm is None:
                # guess realm: last two parts from hostname
                realm = ".".join(hostname.split(".")[-2:]).upper()
            if service is None:
                service = "HTTP"
            return '%s/%s@%s' % (service, hostname, realm)

        # read default values from settings
        principal = self._conf.get("KRB_PRINCIPAL")
        keytab = self._conf.get("KRB_KEYTAB")
        service = self._conf.get("KRB_SERVICE")
        realm = self._conf.get("KRB_REALM")
        ccache = self._conf.get("KRB_CCACHE")
        proxyuser = self._conf.get("KRB_PROXYUSER")

        import krbV
        ctx = krbV.default_context()

        if ccache is not None:
            ccache = krbV.CCache(name='FILE:' + ccache, context=ctx)
        else:
            ccache = ctx.default_ccache()

        if principal is not None:
            if keytab is not None:
                cprinc = krbV.Principal(name=principal, context=ctx)
                keytab = krbV.Keytab(name=keytab, context=ctx)
                ccache.init(cprinc)
                ccache.init_creds_keytab(principal=cprinc, keytab=keytab)
            else:
                raise ImproperlyConfigured(
                    "Cannot specify a principal without a keytab")
        else:
            # connect using existing credentials
            cprinc = ccache.principal()

        sprinc = krbV.Principal(name=get_server_principal(service=service,
                                                          realm=realm),
                                context=ctx)

        ac = krbV.AuthContext(context=ctx)
        ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
        ac.rcache = ctx.default_rcache()

        # create and encode the authentication request
        try:
            ac, req = ctx.mk_req(server=sprinc,
                                 client=cprinc,
                                 auth_context=ac,
                                 ccache=ccache,
                                 options=krbV.AP_OPTS_MUTUAL_REQUIRED)
        except krbV.Krb5Error as ex:
            if getattr(ex, "err_code", None) == -1765328377:
                ex.message += ". Make sure you correctly set KRB_REALM (current value: %s)." % realm
                ex.args = (ex.err_code, ex.message)
            raise ex
        req_enc = base64.encodestring(req)

        self._hub.auth.login_krbv(req_enc)