[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Freeipa-devel] [PATCH 64] Implement password based session login



This patch adds support for password based session login (see detailed
comments in patch)

Only the server side is implemented, someone will have to add password
based login to the UI, when they do they should update the unauthorized
messges to include the new method, those message occur in two places.

   * in install/html/unauthorized.html
   * in the function error_handler() in install/ui/ipa.js:442

Sending the login requires sending the username (not the principal) and
password as application/x-www-form-urlencoded parameters in a GET or
POST request. Note, I only tested GET, but POST should work. Attached is a curl script I used to test (send_login_password).

There is one other minor issue not included in any previous patches nor
this one, the VERSION file should be updated to force the apache
configuration to be updated.

--
John Dennis <jdennis redhat com>

Looking to carve out IT costs?
www.redhat.com/carveoutcosts/
>From 03dd3ca3fbe053765335ac08008f1950ff45ee12 Mon Sep 17 00:00:00 2001
From: John Dennis <jdennis redhat com>
Date: Sat, 25 Feb 2012 13:39:19 -0500
Subject: [PATCH 64] Implement password based session login
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

* Adjust URL's
  - rename /ipa/login -> /ipa/session/login_kerberos
  - add /ipa/session/login_password

* Adjust Kerberos protection on URL's in ipa.conf

* Adjust login URL in ipa.js

* Add InvalidSessionPassword to errors.py

* Rename krblogin class to login_kerberos for consistency with
  new login_password class

* Implement login_password.kinit() method which invokes
  /usr/bin/kinit as a subprocess

* Add login_password class for WSGI dispatch, accepts either
  GET or POST application/x-www-form-urlencoded user & password
  parameters. We form the Kerberos principal from the server's
  realm.

* Add function  krb5_unparse_ccache()

* Refactor code to share common code

* Clean up use of ccache names, be consistent

* Replace read_krbccache_file(), store_krbccache_file(), delete_krbccache_file()
  with load_ccache_data(), bind_ipa_ccache(), release_ipa_ccache().
  bind_ipa_ccache() now sets environment KRB5CCNAME variable.
  release_ipa_ccache() now clears environment KRB5CCNAME variable.

* ccache names should now support any ccache storage scheme,
  not just FILE based ccaches

* Add utilies to return HTTP status from wsgi handlers,
  use constants for HTTP status code for consistency.
  Use utilies for returning from wsgi handlers rather than
  duplicated code.

* Add KerberosSession.finalize_kerberos_acquisition() method
  so different login handlers can share common code.

* add Requires: krb5-workstation to server (server now calls kinit)
---
 freeipa.spec.in                |    1 +
 install/conf/ipa.conf          |    8 +-
 install/ui/ipa.js              |    2 +-
 ipalib/errors.py               |    7 +
 ipalib/krb_utils.py            |   13 ++-
 ipalib/session.py              |   79 +++++++++----
 ipaserver/plugins/xmlserver.py |    5 +-
 ipaserver/rpcserver.py         |  245 +++++++++++++++++++++++++++++++---------
 8 files changed, 271 insertions(+), 89 deletions(-)

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 47f0a82..2c3e5f3 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -95,6 +95,7 @@ Requires: nss
 Requires: nss-tools
 Requires: krb5-server >= 1.9.2-6
 Requires: krb5-pkinit-openssl
+Requires: krb5-workstation
 Requires: cyrus-sasl-gssapi%{?_isa}
 Requires: ntp
 Requires: httpd
diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf
index cd806be..673f56f 100644
--- a/install/conf/ipa.conf
+++ b/install/conf/ipa.conf
@@ -60,7 +60,13 @@ KrbConstrainedDelegationLock ipa
 </Location>
 
 # Turn off Apache authentication for sessions
-<Location "/ipa/session">
+<Location "/ipa/session/json">
+  Satisfy Any
+  Order Deny,Allow
+  Allow from all
+</Location>
+
+<Location "/ipa/session/login_password">
   Satisfy Any
   Order Deny,Allow
   Allow from all
diff --git a/install/ui/ipa.js b/install/ui/ipa.js
index a599f6a..433d7fe 100644
--- a/install/ui/ipa.js
+++ b/install/ui/ipa.js
@@ -60,7 +60,7 @@ var IPA = function() {
         // if current path matches live server path, use live data
         if (that.url && window.location.pathname.substring(0, that.url.length) === that.url) {
             that.json_url = params.url || '/ipa/session/json';
-            that.login_url = params.url || '/ipa/login';
+            that.login_url = params.url || '/ipa/session/login_kerberos';
 
         } else { // otherwise use fixtures
             that.json_path = params.url || "test/data";
diff --git a/ipalib/errors.py b/ipalib/errors.py
index bdc4a5e..dba3f56 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -612,6 +612,13 @@ class SessionError(AuthenticationError):
     format= _('Session error')
 
 
+class InvalidSessionPassword(SessionError):
+    """
+    Raised when we cannot obtain a TGT for a principal.
+    """
+    errno = 1201
+    format= _('Principal %(principal)s cannot be authenticated: %(message)s')
+
 ##############################################################################
 # 2000 - 2999: Authorization errors
 class AuthorizationError(PublicError):
diff --git a/ipalib/krb_utils.py b/ipalib/krb_utils.py
index 7e68bf6..a8f7751 100644
--- a/ipalib/krb_utils.py
+++ b/ipalib/krb_utils.py
@@ -42,7 +42,7 @@ ccache_name_re = re.compile(r'^((\w+):)?(.+)')
 
 #-------------------------------------------------------------------------------
 
-def krb5_parse_ccache(name):
+def krb5_parse_ccache(ccache_name):
     '''
     Given a Kerberos ccache name parse it into it's scheme and
     location components. Currently valid values for the scheme
@@ -55,12 +55,12 @@ def krb5_parse_ccache(name):
     does not exist it defaults to FILE.
 
     :parameters:
-      name
+      ccache_name
         The name of the Kerberos ccache.
     :returns:
       A two-tuple of (scheme, ccache)
     '''
-    match = ccache_name_re.search(name)
+    match = ccache_name_re.search(ccache_name)
     if match:
         scheme = match.group(2)
         location = match.group(3)
@@ -71,7 +71,10 @@ def krb5_parse_ccache(name):
 
         return scheme, location
     else:
-        raise ValueError('Invalid ccache name = "%s"' % name)
+        raise ValueError('Invalid ccache name = "%s"' % ccache_name)
+
+def krb5_unparse_ccache(scheme, name):
+    return '%s:%s' % (scheme.upper(), name)
 
 def krb5_format_principal_name(user, realm):
     '''
@@ -388,5 +391,5 @@ class KRB5_CCache(object):
         except KeyError:
             pass
 
-        self.debug('"%s" ccache endtime=%s (%s)', self.ccache_str(), result, krb5_format_time(result))
+        self.debug('KRB5_CCache %s endtime=%s (%s)', self.ccache_str(), result, krb5_format_time(result))
         return result
diff --git a/ipalib/session.py b/ipalib/session.py
index 5c71a92..c742363 100644
--- a/ipalib/session.py
+++ b/ipalib/session.py
@@ -1197,34 +1197,61 @@ class MemcacheSessionManager(SessionManager):
 krbccache_dir ='/var/run/ipa_memcached'
 krbccache_prefix = 'krbcc_'
 
-def get_krbccache_pathname():
+def _get_krbccache_pathname():
     return os.path.join(krbccache_dir, '%s%s' % (krbccache_prefix, os.getpid()))
 
-def read_krbccache_file(krbccache_pathname):
-    root_logger.debug('reading krbccache data from "%s"', krbccache_pathname)
-    src = open(krbccache_pathname)
-    ccache_data = src.read()
-    src.close()
-    return ccache_data
-
-def store_krbccache_file(ccache_data):
-    krbccache_pathname = get_krbccache_pathname()
-    root_logger.debug('storing krbccache data into "%s"', krbccache_pathname)
-    dst = open(krbccache_pathname, 'w')
-    dst.write(ccache_data)
-    dst.close()
-
-    return krbccache_pathname
-
-def delete_krbccache_file(krbccache_pathname=None):
-    if krbccache_pathname is None:
-        krbccache_pathname = get_krbccache_pathname()
-
-    try:
-        os.unlink(krbccache_pathname)
-    except Exception, e:
-        root_logger.error('unable to delete session krbccache file "%s", %s',
-                          krbccache_pathname, e)
+def get_ipa_ccache_name(scheme='FILE'):
+    if scheme == 'FILE':
+        name = os.path.join(krbccache_dir, '%s%s' % (krbccache_prefix, os.getpid()))
+    else:
+        raise ValueError('ccache scheme "%s" unsupported', scheme)
+
+    ccache_name = krb5_unparse_ccache(scheme, name)
+    return ccache_name
+
+
+def load_ccache_data(ccache_name):
+    scheme, name = krb5_parse_ccache(ccache_name)
+    if scheme == 'FILE':
+        root_logger.debug('reading ccache data from file "%s"', name)
+        src = open(name)
+        ccache_data = src.read()
+        src.close()
+        return ccache_data
+    else:
+        raise ValueError('ccache scheme "%s" unsupported (%s)', scheme, ccache_name)
+
+def bind_ipa_ccache(ccache_data, scheme='FILE'):
+    if scheme == 'FILE':
+        name = _get_krbccache_pathname()
+        root_logger.debug('storing ccache data into file "%s"', name)
+        dst = open(name, 'w')
+        dst.write(ccache_data)
+        dst.close()
+    else:
+        raise ValueError('ccache scheme "%s" unsupported', scheme)
+
+    ccache_name = krb5_unparse_ccache(scheme, name)
+    os.environ['KRB5CCNAME'] = ccache_name
+    return ccache_name
+
+def release_ipa_ccache(ccache_name):
+    if os.environ.has_key('KRB5CCNAME'):
+        if ccache_name != os.environ['KRB5CCNAME']:
+            root_logger.error('release_ipa_ccache: ccache_name (%s) != KRB5CCNAME environment variable (%s)',
+                              ccache_name, os.environ['KRB5CCNAME'])
+        del os.environ['KRB5CCNAME']
+    else:
+        root_logger.error('release_ipa_ccache: KRB5CCNAME environment variable not set')
+
+    scheme, name = krb5_parse_ccache(ccache_name)
+    if scheme == 'FILE':
+        try:
+            os.unlink(name)
+        except Exception, e:
+            root_logger.error('unable to delete session ccache file "%s", %s', name, e)
+    else:
+        raise ValueError('ccache scheme "%s" unsupported (%s)', scheme, ccache_name)
 
 
 #-------------------------------------------------------------------------------
diff --git a/ipaserver/plugins/xmlserver.py b/ipaserver/plugins/xmlserver.py
index d2a28ec..4ae9149 100644
--- a/ipaserver/plugins/xmlserver.py
+++ b/ipaserver/plugins/xmlserver.py
@@ -25,9 +25,10 @@ Loads WSGI server plugins.
 from ipalib import api
 
 if 'in_server' in api.env and api.env.in_server is True:
-    from ipaserver.rpcserver import wsgi_dispatch, xmlserver, jsonserver_kerb, jsonserver_session, krblogin
+    from ipaserver.rpcserver import wsgi_dispatch, xmlserver, jsonserver_kerb, jsonserver_session, login_kerberos, login_password
     api.register(wsgi_dispatch)
     api.register(xmlserver)
     api.register(jsonserver_kerb)
     api.register(jsonserver_session)
-    api.register(krblogin)
+    api.register(login_kerberos)
+    api.register(login_password)
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 0b8aa40..5b1897c 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -27,14 +27,15 @@ from cgi import parse_qs
 from xml.sax.saxutils import escape
 from xmlrpclib import Fault
 from ipalib.backend import Executioner
-from ipalib.errors import PublicError, InternalError, CommandError, JSONError, ConversionError, CCacheError, RefererError
+from ipalib.errors import PublicError, InternalError, CommandError, JSONError, ConversionError, CCacheError, RefererError, InvalidSessionPassword
 from ipalib.request import context, Connection, destroy_context
 from ipalib.rpc import xml_dumps, xml_loads
 from ipalib.util import make_repr, parse_time_duration
 from ipapython.compat import json
-from ipalib.session import session_mgr, AuthManager, read_krbccache_file, store_krbccache_file, delete_krbccache_file, fmt_time, default_max_session_duration
+from ipalib.session import session_mgr, AuthManager, get_ipa_ccache_name, load_ccache_data, bind_ipa_ccache, release_ipa_ccache, fmt_time, default_max_session_duration
 from ipalib.backend import Backend
-from ipalib.krb_utils import krb5_parse_ccache, KRB5_CCache, krb_ticket_expiration_threshold
+from ipalib.krb_utils import krb5_parse_ccache, KRB5_CCache, krb_ticket_expiration_threshold, krb5_format_principal_name
+from ipapython import ipautil
 from wsgiref.util import shift_path_info
 from ipapython.version import VERSION
 import base64
@@ -42,6 +43,11 @@ import os
 import string
 import datetime
 from decimal import Decimal
+import urlparse
+
+HTTP_STATUS_SUCCESS = '200 Success'
+HTTP_STATUS_SERVER_ERROR = '500 Internal Server Error'
+
 _not_found_template = """<html>
 <head>
 <title>404 Not Found</title>
@@ -54,6 +60,41 @@ The requested URL <strong>%(url)s</strong> was not found on this server.
 </body>
 </html>"""
 
+_bad_request_template = """<html>
+<head>
+<title>400 Bad Request</title>
+</head>
+<body>
+<h1>Bad Request</h1>
+<p>
+<strong>%(message)s</strong>
+</p>
+</body>
+</html>"""
+
+_internal_error_template = """<html>
+<head>
+<title>500 Internal Server Error</title>
+</head>
+<body>
+<h1>Internal Server Error</h1>
+<p>
+<strong>%(message)s</strong>
+</p>
+</body>
+</html>"""
+
+_invalid_auth_template = """<html>
+<head>
+<title>403 Forbidden</title>
+</head>
+<body>
+<h1>Invalid Authentication</h1>
+<p>
+<strong>%(message)s</strong>
+</p>
+</body>
+</html>"""
 
 def not_found(environ, start_response):
     """
@@ -67,6 +108,36 @@ def not_found(environ, start_response):
     )
     return [output]
 
+def bad_request(environ, start_response, message):
+    """
+    Return a 400 Bad Request error.
+    """
+    status = '400 Bad Request'
+    response_headers = [('Content-Type', 'text/html')]
+    start_response(status, response_headers)
+    output = _bad_request_template % dict(message=escape(message))
+    return [output]
+
+def internal_error(environ, start_response, message):
+    """
+    Return a 400 Bad Request error.
+    """
+    status = HTTP_STATUS_SERVER_ERROR
+    response_headers = [('Content-Type', 'text/html')]
+    start_response(status, response_headers)
+    output = _internal_error_template % dict(message=escape(message))
+    return [output]
+
+def invalid_auth(environ, start_response, message):
+    """
+    Return a 403 Forbidden error.
+    """
+    status = '403 Forbidden'
+    response_headers = [('Content-Type', 'text/html')]
+    start_response(status, response_headers)
+    output = _invalid_auth_template % dict(message=escape(message))
+    return [output]
+
 def read_input(environ):
     """
     Read the request body from environ['wsgi.input'].
@@ -267,12 +338,12 @@ class WSGIExecutioner(Executioner):
 
         self.debug('WSGI WSGIExecutioner.__call__:')
         try:
-            status = '200 OK'
+            status = HTTP_STATUS_SUCCESS
             response = self.wsgi_execute(environ)
             headers = [('Content-Type', self.content_type + '; charset=utf-8')]
         except StandardError, e:
             self.exception('WSGI %s.__call__():', self.name)
-            status = '500 Internal Server Error'
+            status = HTTP_STATUS_SERVER_ERROR
             response = status
             headers = [('Content-Type', 'text/plain')]
 
@@ -316,15 +387,14 @@ class xmlserver(WSGIExecutioner):
         '''
 
         self.debug('WSGI xmlserver.__call__:')
-        ccache=environ.get('KRB5CCNAME')
-        if ccache is None:
+        user_ccache=environ.get('KRB5CCNAME')
+        if user_ccache is None:
             return self.marshal(None, CCacheError())
-        self.create_context(ccache=ccache)
         try:
-            self.create_context(ccache=environ.get('KRB5CCNAME'))
+            self.create_context(ccache=user_ccache)
             response = super(xmlserver, self).__call__(environ, start_response)
         except PublicError, e:
-            status = '200 OK'
+            status = HTTP_STATUS_SUCCESS
             response = status
             headers = [('Content-Type', 'text/plain')]
             start_response(status, headers)
@@ -619,6 +689,34 @@ class KerberosSession(object):
                                                 max_age=krb_expiration,
                                                 duration_type=self.api.env.session_duration_type)
 
+
+    def finalize_kerberos_acquisition(self, who, ccache_name, environ, start_response, headers=[]):
+        # Retrieve the session data (or newly create)
+        session_data = session_mgr.load_session_data(environ.get('HTTP_COOKIE'))
+        session_id = session_data['session_id']
+
+        self.debug('finalize_kerberos_acquisition: %s ccache_name="%s" session_id="%s"',
+                   who, ccache_name, session_id)
+
+        # Copy the ccache file contents into the session data
+        session_data['ccache_data'] = load_ccache_data(ccache_name)
+
+        # Set when the session will expire
+        cc = KRB5_CCache(ccache_name)
+        endtime = cc.endtime(self.api.env.host, self.api.env.realm)
+        self.update_session_expiration(session_data, endtime)
+
+        # Store the session data now that it's been updated with the ccache
+        session_mgr.store_session_data(session_data)
+
+        # Return success and set session cookie
+        session_cookie = session_mgr.generate_cookie('/ipa', session_id)
+        headers.append(('Set-Cookie', session_cookie))
+
+        start_response(HTTP_STATUS_SUCCESS, headers)
+        return ['']
+
+
 class jsonserver_session(jsonserver, KerberosSession):
     """
     JSON RPC server protected with session auth.
@@ -668,13 +766,13 @@ class jsonserver_session(jsonserver, KerberosSession):
             self.debug('no ccache, need login')
             return self.need_login(start_response)
 
-        krbccache_pathname = store_krbccache_file(ccache_data)
+        ipa_ccache_name = bind_ipa_ccache(ccache_data)
 
         # Redirect to login if Kerberos credentials are expired
-        cc = KRB5_CCache(krbccache_pathname)
+        cc = KRB5_CCache(ipa_ccache_name)
         if not cc.valid(self.api.env.host, self.api.env.realm):
             self.debug('ccache expired, deleting session, need login')
-            delete_krbccache_file(krbccache_pathname)
+            release_ipa_ccache(ipa_ccache_name)
             return self.need_login(start_response)
 
         # Update the session expiration based on the Kerberos expiration
@@ -684,7 +782,7 @@ class jsonserver_session(jsonserver, KerberosSession):
         # Store the session data in the per-thread context
         setattr(context, 'session_data', session_data)
 
-        self.create_context(ccache=krbccache_pathname)
+        self.create_context(ccache=ipa_ccache_name)
 
         try:
             response = super(jsonserver_session, self).__call__(environ, start_response)
@@ -701,10 +799,10 @@ class jsonserver_session(jsonserver, KerberosSession):
             # data to invalidate the session credentials.
 
             if session_data.has_key('ccache_data'):
-                session_data['ccache_data'] = read_krbccache_file(krbccache_pathname)
+                session_data['ccache_data'] = load_ccache_data(ipa_ccache_name)
 
             # Delete the temporary ccache file we used
-            delete_krbccache_file(krbccache_pathname)
+            release_ipa_ccache(ipa_ccache_name)
             # Store the session data.
             session_mgr.store_session_data(session_data)
             destroy_context()
@@ -724,10 +822,10 @@ class jsonserver_kerb(jsonserver):
 
         self.debug('WSGI jsonserver_kerb.__call__:')
 
-        ccache=environ.get('KRB5CCNAME')
-        if ccache is None:
+        user_ccache=environ.get('KRB5CCNAME')
+        if user_ccache is None:
             return self.marshal(None, CCacheError())
-        self.create_context(ccache=ccache)
+        self.create_context(ccache=user_ccache)
 
         try:
             response = super(jsonserver_kerb, self).__call__(environ, start_response)
@@ -737,59 +835,98 @@ class jsonserver_kerb(jsonserver):
         return response
 
 
-class krblogin(Backend, KerberosSession):
-    key = '/login'
+class login_kerberos(Backend, KerberosSession):
+    key = '/session/login_kerberos'
 
     def __init__(self):
-        super(krblogin, self).__init__()
+        super(login_kerberos, self).__init__()
 
     def _on_finalize(self):
-        super(krblogin, self)._on_finalize()
+        super(login_kerberos, self)._on_finalize()
         self.api.Backend.wsgi_dispatch.mount(self, self.key)
         self.kerb_session_on_finalize()
 
     def __call__(self, environ, start_response):
-        headers = []
-
-        self.debug('WSGI krblogin.__call__:')
+        self.debug('WSGI login_kerberos.__call__:')
 
         # Get the ccache created by mod_auth_kerb
-        ccache=environ.get('KRB5CCNAME')
-        if ccache is None:
-            status = '500 Internal Error'
-            response = 'KRB5CCNAME not defined'
-            start_response(status, headers)
-            return [response]
+        user_ccache_name=environ.get('KRB5CCNAME')
+        if user_ccache_name is None:
+            return internal_error(environ, start_response, 'KRB5CCNAME not defined')
 
-        ccache_scheme, ccache_location = krb5_parse_ccache(ccache)
-        assert ccache_scheme == 'FILE'
+        return self.finalize_kerberos_acquisition('login_kerberos', user_ccache_name, environ, start_response)
 
-        # Retrieve the session data (or newly create)
-        session_data = session_mgr.load_session_data(environ.get('HTTP_COOKIE'))
-        session_id = session_data['session_id']
+class login_password(Backend, KerberosSession):
 
-        # Copy the ccache file contents into the session data
-        session_data['ccache_data'] = read_krbccache_file(ccache_location)
+    content_type = 'text/plain'
+    key = '/session/login_password'
 
-        # Set when the session will expire
-        cc = KRB5_CCache(ccache)
-        endtime = cc.endtime(self.api.env.host, self.api.env.realm)
-        self.update_session_expiration(session_data, endtime)
+    def __init__(self):
+        super(login_password, self).__init__()
 
-        # Store the session data now that it's been updated with the ccache
-        session_mgr.store_session_data(session_data)
+    def _on_finalize(self):
+        super(login_password, self)._on_finalize()
+        self.api.Backend.wsgi_dispatch.mount(self, self.key)
+        self.kerb_session_on_finalize()
 
-        self.debug('krblogin: ccache="%s" session_id="%s" ccache="%s"',
-                   ccache, session_id, ccache)
+    def __call__(self, environ, start_response):
+        self.debug('WSGI login_password.__call__:')
+
+        # Get the user and password parameters from the request
+        content_type = environ.get('CONTENT_TYPE', '').lower()
+        if content_type != 'application/x-www-form-urlencoded':
+            return bad_request(environ, start_response, "Content-Type must be application/x-www-form-urlencoded")
+
+        method = environ.get('REQUEST_METHOD', '').upper()
+        if method == 'POST':
+            query_string = read_input(environ)
+        elif method == 'GET':
+            query_string = environ.get('QUERY_STRING', '')
+        else:
+            return bad_request(environ, start_response, "method must be GET or POST")
 
-        # Return success and set session cookie
-        status = '200 Success'
-        response = ''
+        try:
+            query_dict = urlparse.parse_qs(query_string)
+        except Exception, e:
+            return bad_request(environ, start_response, "cannot parse query data")
 
-        session_cookie = session_mgr.generate_cookie('/ipa', session_id)
-        headers.append(('Set-Cookie', session_cookie))
+        user = query_dict.get('user', None)
+        if user is not None:
+            if len(user) == 1:
+                user = user[0]
+            else:
+                return bad_request(environ, start_response, "more than one user parameter")
+        else:
+            return bad_request(environ, start_response, "no user specified")
 
-        start_response(status, headers)
-        return [response]
+        password = query_dict.get('password', None)
+        if password is not None:
+            if len(password) == 1:
+                password = password[0]
+            else:
+                return bad_request(environ, start_response, "more than one password parameter")
+        else:
+            return bad_request(environ, start_response, "no password specified")
+
+        # Get the ccache we'll use and attempt to get credentials in it with user,password
+        ipa_ccache_name = get_ipa_ccache_name()
+        try:
+            self.kinit(user, self.api.env.realm, password, ipa_ccache_name)
+        except InvalidSessionPassword, e:
+            return invalid_auth(environ, start_response, str(e))
+
+        return self.finalize_kerberos_acquisition('login_password', ipa_ccache_name, environ, start_response)
+
+    def kinit(self, user, realm, password, ccache_name):
+        # Format the user as a kerberos principal
+        principal = krb5_format_principal_name(user, realm)
+
+        (stdout, stderr, returncode) = ipautil.run(['/usr/bin/kinit', principal],
+                                                   env={'KRB5CCNAME':ccache_name},
+                                                   stdin=password, raiseonerr=False)
+        self.debug('kinit: principal=%s returncode=%s, stderr="%s"',
+                   principal, returncode, stderr)
 
+        if returncode != 0:
+            raise InvalidSessionPassword(principal=principal, message=unicode(stderr))
 
-- 
1.7.7.6

#!/bin/sh

user="admin"
password="xxx"
scheme="https"
host=$ipaf16session
rpc_url="ipa/session/login_password"
query="?user=${user}&password=${password}"
url="${scheme}://${host}/${rpc_url}${query}"

echo $url

curl --dump-header login.response --ssl -k -H "Content-Type: application/x-www-form-urlencoded" $url

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]