[Freeipa-devel] [PATCH] added kerberos backend and kdc locator plugin

Sumit Bose sbose at redhat.com
Mon Jun 29 09:37:06 UTC 2009


On Fri, Jun 26, 2009 at 02:35:23PM -0400, Stephen Gallagher wrote:
> On 06/26/2009 11:40 AM, Sumit Bose wrote:
> > Am 25.06.2009 21:26, schrieb Stephen Gallagher:
> >> On 06/25/2009 03:24 PM, Stephen Gallagher wrote:
> >>> On 06/23/2009 11:05 AM, Stephen Gallagher wrote:
> >>>> On 06/23/2009 10:49 AM, Sumit Bose wrote:
> >>>>> fixed krb5pluginpath for different $libdir.
> >>>>> bye,
> >>>>> Sumit
> >>>> Ack. I think that's the last of the issues I've seen.
> >>> Correction: one more (very minor) issue to address. You're linking the
> >>> kerberos backend against libsss_crypt.la. There's no need to do this, as
> >>> it will inherit that from the sssd_be binary.
> >>> _______________________________________________
> >>> Freeipa-devel mailing list
> >>> Freeipa-devel at redhat.com
> >>> https://www.redhat.com/mailman/listinfo/freeipa-devel
> >>
> >>
> >> Sorry, make that two things:
> >> Please also create a manpage for sssd-krb5 (similar to sssd-ldap.5) so
> >> the available options are spelled out.
> >>
> > 
> > I have remove the library and added a short man page. I will extend the
> > man page when more options are added. Can somebody please check the
> > spelling and the general (mis)use of the english/american language?
> > 
> > bye,
> > Sumit
> 
> I have a few suggestions in the attached patch. If you like them, please
> merge them in.
> 

Thanks. The following patch contains the suggestions from Stephen.

bye,
Sumit
-------------- next part --------------
>From 6a8f053b5c2147151bd4e8b7a705626475662c89 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 15 Jun 2009 15:06:40 +0200
Subject: [PATCH 1/2] added kerberos locator plugin

---
 server/Makefile.am                            |   14 +++
 server/conf_macros.m4                         |   14 +++-
 server/configure.ac                           |    2 +
 server/external/krb5.m4                       |   11 ++
 server/krb5_plugin/sssd_krb5_locator_plugin.c |  131 +++++++++++++++++++++++++
 server/krb5_plugin/sssd_krb5_locator_plugin.h |    8 ++
 sssd.spec.in                                  |    5 +-
 7 files changed, 183 insertions(+), 2 deletions(-)
 create mode 100644 server/external/krb5.m4
 create mode 100644 server/krb5_plugin/sssd_krb5_locator_plugin.c
 create mode 100644 server/krb5_plugin/sssd_krb5_locator_plugin.h

diff --git a/server/Makefile.am b/server/Makefile.am
index bed9060..b15c230 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -3,6 +3,7 @@ topdir=.
 sssdlibexecdir = $(libexecdir)/sssd
 sssdlibdir = $(libdir)/sssd
 ldblibdir = $(libdir)/ldb
+krb5plugindir = @krb5pluginpath@
 sssdconfdir = $(sysconfdir)/sssd
 dbusintrospectdir = $(datarootdir)/sssd/introspect
 dbuspolicydir = $(sysconfdir)/dbus-1/system.d
@@ -80,6 +81,9 @@ sssdlib_LTLIBRARIES = \
 ldblib_LTLIBRARIES = \
     memberof.la
 
+krb5plugin_LTLIBRARIES = \
+    sssd_krb5_locator_plugin.la
+
 noinst_LTLIBRARIES = \
     libsss_crypt.la
 libsss_crypt_la_SOURCES = \
@@ -208,6 +212,7 @@ dist_noinst_HEADERS = \
     providers/dp_backend.h \
     providers/providers.h \
     tools/tools_util.h \
+    krb5_plugin/sssd_krb5_locator_plugin.h \
     $(infopipe_headers) \
     $(polkit_headers)
 
@@ -403,6 +408,15 @@ memberof_la_LDFLAGS = \
     -avoid-version \
     -module
 
+sssd_krb5_locator_plugin_la_SOURCES = \
+    krb5_plugin/sssd_krb5_locator_plugin.c
+sssd_krb5_locator_plugin_la_CFLAGS = \
+    $(AM_CFLAGS) \
+    $(KRB5_CFLAGS)
+sssd_krb5_locator_plugin_la_LDFLAGS = \
+    -avoid-version \
+    -module
+
 ############
 # MANPAGES #
 ############
diff --git a/server/conf_macros.m4 b/server/conf_macros.m4
index 7e230bb..c67b47b 100644
--- a/server/conf_macros.m4
+++ b/server/conf_macros.m4
@@ -132,7 +132,6 @@ AC_DEFUN([WITH_INIT_DIR],
     AC_SUBST(initdir)
   ])
 
-
 AC_DEFUN([WITH_SHADOW_UTILS_PATH],
   [ AC_ARG_WITH([shadow-utils-path],
                 [AC_HELP_STRING([--with-shadow-utils-path=PATH],
@@ -177,3 +176,16 @@ AC_DEFUN([WITH_XML_CATALOG],
     AC_SUBST([SGML_CATALOG_FILES])
   ])
 
+AC_DEFUN([WITH_KRB5_PLUGIN_PATH],
+  [ AC_ARG_WITH([krb5-plugin-path],
+                [AC_HELP_STRING([--with-krb5-plugin-path=PATH],
+                                [Path to kerberos plugin store [/usr/lib/krb5/plugins/libkrb5]]
+                               )
+                ]
+               )
+    krb5pluginpath="${libdir}/krb5/plugins/libkrb5"
+    if test x"$with_krb5_plugin_path" != x; then
+        krb5pluginpath=$with_krb5_plugin_path
+    fi
+    AC_SUBST(krb5pluginpath)
+  ])
diff --git a/server/configure.ac b/server/configure.ac
index 8803276..facefe2 100644
--- a/server/configure.ac
+++ b/server/configure.ac
@@ -49,6 +49,7 @@ WITH_INIT_DIR
 WITH_SHADOW_UTILS_PATH
 WITH_MANPAGES
 WITH_XML_CATALOG
+WITH_KRB5_PLUGIN_PATH
 
 m4_include([external/pkg.m4])
 m4_include([external/libpopt.m4])
@@ -59,6 +60,7 @@ m4_include([external/libldb.m4])
 m4_include([external/pam.m4])
 m4_include([external/ldap.m4])
 m4_include([external/libpcre.m4])
+m4_include([external/krb5.m4])
 m4_include([util/signal.m4])
 
 PKG_CHECK_MODULES([DBUS],[dbus-1])
diff --git a/server/external/krb5.m4 b/server/external/krb5.m4
new file mode 100644
index 0000000..1ed5064
--- /dev/null
+++ b/server/external/krb5.m4
@@ -0,0 +1,11 @@
+AC_SUBST(KRB5_CFLAGS)
+AC_SUBST(KRB5_LIBS)
+AC_PATH_PROG(KRB5_CONFIG, krb5-config)
+AC_MSG_CHECKING(for working krb5-config)
+if test -x "$KRB5_CONFIG"; then
+  KRB5_CFLAGS="`$KRB5_CONFIG --cflags`"
+  KRB5_LIBS="`$KRB5_CONFIG --libs`"
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_ERROR(no. Please install MIT kerberos devel package)
+fi
diff --git a/server/krb5_plugin/sssd_krb5_locator_plugin.c b/server/krb5_plugin/sssd_krb5_locator_plugin.c
new file mode 100644
index 0000000..699cad4
--- /dev/null
+++ b/server/krb5_plugin/sssd_krb5_locator_plugin.c
@@ -0,0 +1,131 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <krb5/locate_plugin.h>
+
+#include "krb5_plugin/sssd_krb5_locator_plugin.h"
+
+struct sssd_ctx {
+    char *sssd_realm;
+    char *sssd_kdc;
+};
+
+krb5_error_code sssd_krb5_locator_init(krb5_context context,
+                                       void **private_data)
+{
+    struct sssd_ctx *ctx;
+    char *dummy;
+
+    ctx = calloc(1,sizeof(struct sssd_ctx));
+    if (ctx == NULL) return ENOMEM;
+
+    dummy = getenv(SSSD_REALM);
+    if (dummy == NULL) goto failed;
+    ctx->sssd_realm = strdup(dummy);
+    if (ctx->sssd_realm == NULL) goto failed;
+
+    dummy = getenv(SSSD_KDC);
+    if (dummy == NULL) goto failed;
+    ctx->sssd_kdc = strdup(dummy);
+    if (ctx->sssd_kdc == NULL) goto failed;
+
+    *private_data = ctx;
+
+    return 0;
+failed:
+    free(ctx->sssd_realm);
+    free(ctx->sssd_kdc);
+    free(ctx);
+
+    private_data = NULL;
+
+    return EINVAL;
+}
+
+void sssd_krb5_locator_close(void *private_data)
+{
+    struct sssd_ctx *ctx;
+
+    if (private_data == NULL) return;
+
+    ctx = (struct sssd_ctx *) private_data;
+    free(ctx->sssd_realm);
+    free(ctx->sssd_kdc);
+    free(ctx);
+
+    return;
+}
+
+krb5_error_code sssd_krb5_locator_lookup(void *private_data,
+                    enum locate_service_type svc,
+                    const char *realm,
+                    int socktype,
+                    int family,
+                    int (*cbfunc)(void *, int, struct sockaddr *),
+                    void *cbdata)
+{
+    int ret;
+    struct sockaddr_in addr;
+    struct sssd_ctx *ctx;
+
+    if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE;
+    ctx = (struct sssd_ctx *) private_data;
+
+#ifdef KRB5_PLUGIN_DEBUG
+    fprintf(stderr,"[%s][%s][%s][%d][%d][%d]\n", realm, ctx->sssd_realm,
+                                                 ctx->sssd_kdc, socktype,
+                                                 family, svc);
+#endif
+
+    switch (svc) {
+        case locate_service_kdc:
+        case locate_service_master_kdc:
+        case locate_service_kadmin:
+            break;
+        case locate_service_krb524:
+        case locate_service_kpasswd:
+            return KRB5_PLUGIN_NO_HANDLE;
+        default:
+            return EINVAL;
+    }
+
+    switch (family) {
+        case AF_UNSPEC:
+        case AF_INET:
+            break;
+        default:
+            return KRB5_PLUGIN_NO_HANDLE;
+    }
+
+    switch (socktype) {
+        case SOCK_STREAM:
+        case SOCK_DGRAM:
+            break;
+        default:
+            return EINVAL;
+    }
+
+    if (strcmp(realm, ctx->sssd_realm) != 0)
+        return KRB5_PLUGIN_NO_HANDLE;
+
+    addr.sin_family = AF_INET;
+    ret = inet_aton(ctx->sssd_kdc, &addr.sin_addr);
+    if (ret == 0) return EINVAL;
+    addr.sin_port = htons(88);
+
+    ret = cbfunc(cbdata, socktype, (struct sockaddr *) &addr);
+
+    return 0;
+}
+
+const krb5plugin_service_locate_ftable service_locator = {
+    0, /* version */
+    sssd_krb5_locator_init,
+    sssd_krb5_locator_close,
+    sssd_krb5_locator_lookup,
+};
diff --git a/server/krb5_plugin/sssd_krb5_locator_plugin.h b/server/krb5_plugin/sssd_krb5_locator_plugin.h
new file mode 100644
index 0000000..ab41689
--- /dev/null
+++ b/server/krb5_plugin/sssd_krb5_locator_plugin.h
@@ -0,0 +1,8 @@
+#ifndef __SSSD_KRB5_LOCATOR_PLUGIN_H__
+#define __SSSD_KRB5_LOCATOR_PLUGIN_H__
+
+#define SSSD_KDC "SSSD_KDC"
+#define SSSD_REALM "SSSD_REALM"
+
+#endif /* __SSSD_KRB5_LOCATOR_PLUGIN_H__ */
+
diff --git a/sssd.spec.in b/sssd.spec.in
index 2053576..719e6b7 100644
--- a/sssd.spec.in
+++ b/sssd.spec.in
@@ -42,6 +42,7 @@ BuildRequires: pcre-devel
 BuildRequires: libxslt
 BuildRequires: libxml2
 BuildRequires: docbook-style-xsl
+BuildRequires: krb5-devel
 
 %description
 Provides a set of daemons to manage access to remote directories and
@@ -78,7 +79,8 @@ rm -f \
     $RPM_BUILD_ROOT/%{_lib}/security/pam_sss.la \
     $RPM_BUILD_ROOT/%{_libdir}/ldb/memberof.la \
     $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_ldap.la \
-    $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_proxy.la
+    $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_proxy.la \
+    $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.la
 
 %clean
 rm -rf $RPM_BUILD_ROOT
@@ -97,6 +99,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_libexecdir}/%{servicename}/
 %{_libdir}/%{name}/
 %{_libdir}/ldb/memberof.so
+%{_libdir}/krb5/plugins/libkrb5/*
 %dir %{_sharedstatedir}/sss/
 %attr(700,root,root) %dir %{_sharedstatedir}/sss/db
 %dir %{_sharedstatedir}/sss/pipes
-- 
1.6.2.5

-------------- next part --------------
>From 5ee778d685d7b4271451dbcf1e450bec2509ffca Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 15 Jun 2009 15:07:39 +0200
Subject: [PATCH 2/2] added kerberos backend with tevent_req event handling

---
 server/Makefile.am                    |   17 +-
 server/man/sssd-krb5.5.xml            |   98 ++++++
 server/providers/data_provider.h      |    2 +
 server/providers/dp_auth_util.c       |    6 +
 server/providers/krb5/krb5_auth.c     |  585 +++++++++++++++++++++++++++++++++
 server/providers/krb5/krb5_auth.h     |   92 +++++
 server/providers/krb5/tgt_req_child.c |  179 ++++++++++
 server/responder/pam/pamsrv_cmd.c     |   20 +-
 sss_client/pam_sss.c                  |    2 +-
 sssd.spec.in                          |    1 +
 10 files changed, 999 insertions(+), 3 deletions(-)
 create mode 100644 server/man/sssd-krb5.5.xml
 create mode 100644 server/providers/krb5/krb5_auth.c
 create mode 100644 server/providers/krb5/krb5_auth.h
 create mode 100644 server/providers/krb5/tgt_req_child.c

diff --git a/server/Makefile.am b/server/Makefile.am
index b15c230..01f3037 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -76,6 +76,7 @@ endif
 
 sssdlib_LTLIBRARIES = \
     libsss_ldap.la \
+    libsss_krb5.la \
     libsss_proxy.la
 
 ldblib_LTLIBRARIES = \
@@ -211,6 +212,7 @@ dist_noinst_HEADERS = \
     providers/dp_interfaces.h \
     providers/dp_backend.h \
     providers/providers.h \
+    providers/krb5/krb5_auth.h \
     tools/tools_util.h \
     krb5_plugin/sssd_krb5_locator_plugin.h \
     $(infopipe_headers) \
@@ -400,6 +402,19 @@ libsss_proxy_la_LDFLAGS = \
     -version-info 1:0:0 \
     -module
 
+libsss_krb5_la_SOURCES = \
+    providers/krb5/krb5_auth.c \
+    providers/krb5/tgt_req_child.c
+libsss_krb5_la_CFLAGS = \
+    $(AM_CFLAGS) \
+    $(KRB5_CFLAGS)
+libsss_krb5_la_LIBADD = \
+    $(PAM_LIBS) \
+    $(KRB5_LIBS)
+libsss_krb5_la_LDFLAGS = \
+    -version-info 1:0:0 \
+    -module
+
 memberof_la_SOURCES = \
     ldb_modules/memberof.c
 memberof_la_CFLAGS = \
@@ -429,7 +444,7 @@ XSLTPROC_FLAGS = --catalogs --xinclude --nonet
 
 dist_man_MANS = man/sss_useradd.8 man/sss_userdel.8 man/sss_usermod.8 \
 		man/sss_groupadd.8 man/sss_groupdel.8 man/sss_groupmod.8 \
-		man/sssd.8 man/sssd.conf.5 man/sssd-ldap.5
+		man/sssd.8 man/sssd.conf.5 man/sssd-ldap.5 man/sssd-krb5.5
 
 SUFFIXES = .1.xml .1 .3.xml .3 .5.xml .5 .8.xml .8
 .1.xml.1:
diff --git a/server/man/sssd-krb5.5.xml b/server/man/sssd-krb5.5.xml
new file mode 100644
index 0000000..a75193a
--- /dev/null
+++ b/server/man/sssd-krb5.5.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<reference>
+<title>SSSD Manual pages</title>
+<refentry>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/upstream.xml" />
+
+    <refmeta>
+        <refentrytitle>sssd-krb5</refentrytitle>
+        <manvolnum>5</manvolnum>
+        <refmiscinfo class="manual">File Formats and Conventions</refmiscinfo>
+    </refmeta>
+
+    <refnamediv id='name'>
+        <refname>sssd-krb5</refname>
+        <refpurpose>the configuration file for SSSD</refpurpose>
+    </refnamediv>
+
+    <refsect1 id='description'>
+        <title>DESCRIPTION</title>
+        <para>
+            This manual page describes the configuration of the Kerberos
+            5 authentication backend for
+            <citerefentry>
+                <refentrytitle>sssd</refentrytitle>
+                <manvolnum>8</manvolnum>
+            </citerefentry>.
+            For a detailed syntax reference, please refer to the <quote>FILE FORMAT</quote> section of the
+            <citerefentry>
+                <refentrytitle>sssd.conf</refentrytitle>
+                <manvolnum>5</manvolnum>
+            </citerefentry> manual page
+        </para>
+    </refsect1>
+
+    <refsect1 id='file-format'>
+        <title>CONFIGURATION OPTIONS</title>
+        <para>
+	    If the auth-module krb5 is used in a SSSD domain, the following
+            options must be used. See the
+            <citerefentry>
+                <refentrytitle>sssd.conf</refentrytitle>
+                <manvolnum>5</manvolnum>
+            </citerefentry> manual page, section <quote>DOMAIN SECTIONS</quote>
+            for details on the configuration of a SSSD domain.
+            <variablelist>
+                <varlistentry>
+                    <term>krb5KDCIP (string)</term>
+                    <listitem>
+                        <para>
+                            Specifies the IP address of the Kerberos server.
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>krb5REALM (string)</term>
+                    <listitem>
+                        <para>
+                            The name of the Kerberos realm.
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+        </para>
+    </refsect1>
+
+    <refsect1 id='example'>
+        <title>EXAMPLE</title>
+        <para>
+            The following example assumes that SSSD is correctly
+            configured and FOO is one of the domains in the
+            <replaceable>[domains]</replaceable> section.
+        </para>
+        <para>
+<programlisting>
+    [domains/FOO]
+    auth-module = krb5
+    krb5KDCIP = 192.168.1.1
+    krb5REALM = EXAMPLE.COM
+</programlisting>
+        </para>
+    </refsect1>
+
+    <refsect1 id='see_also'>
+        <title>SEE ALSO</title>
+        <para>
+            <citerefentry>
+                <refentrytitle>sssd.conf</refentrytitle><manvolnum>5</manvolnum>
+            </citerefentry>,
+            <citerefentry>
+                <refentrytitle>sssd</refentrytitle><manvolnum>8</manvolnum>
+            </citerefentry>
+        </para>
+    </refsect1>
+</refentry>
+</reference>
diff --git a/server/providers/data_provider.h b/server/providers/data_provider.h
index 95a1b37..b747e69 100644
--- a/server/providers/data_provider.h
+++ b/server/providers/data_provider.h
@@ -117,6 +117,8 @@ struct pam_data {
 
     bool offline_auth;
     int priv;
+    uid_t pw_uid;
+    gid_t gr_gid;
 };
 
 void pam_print_data(int l, struct pam_data *pd);
diff --git a/server/providers/dp_auth_util.c b/server/providers/dp_auth_util.c
index 279e50b..7219917 100644
--- a/server/providers/dp_auth_util.c
+++ b/server/providers/dp_auth_util.c
@@ -35,6 +35,8 @@ void pam_print_data(int l, struct pam_data *pd)
     DEBUG(l, ("newauthtok type: %d\n", pd->newauthtok_type));
     DEBUG(l, ("newauthtok size: %d\n", pd->newauthtok_size));
     DEBUG(l, ("priv: %d\n", pd->priv));
+    DEBUG(l, ("pw_uid: %d\n", pd->pw_uid));
+    DEBUG(l, ("gr_gid: %d\n", pd->gr_gid));
 }
 
 int pam_add_response(struct pam_data *pd, enum response_type type,
@@ -83,6 +85,8 @@ bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd)
                                        &(pd->newauthtok),
                                        pd->newauthtok_size,
                                    DBUS_TYPE_INT32, &(pd->priv),
+                                   DBUS_TYPE_INT32, &(pd->pw_uid),
+                                   DBUS_TYPE_INT32, &(pd->gr_gid),
                                    DBUS_TYPE_INVALID);
 
     return ret;
@@ -109,6 +113,8 @@ bool dp_unpack_pam_request(DBusMessage *msg, struct pam_data *pd, DBusError *dbu
                                     &(pd->newauthtok),
                                     &(pd->newauthtok_size),
                                 DBUS_TYPE_INT32, &(pd->priv),
+                                DBUS_TYPE_INT32, &(pd->pw_uid),
+                                DBUS_TYPE_INT32, &(pd->gr_gid),
                                 DBUS_TYPE_INVALID);
 
     return ret;
diff --git a/server/providers/krb5/krb5_auth.c b/server/providers/krb5/krb5_auth.c
new file mode 100644
index 0000000..ce26614
--- /dev/null
+++ b/server/providers/krb5/krb5_auth.c
@@ -0,0 +1,585 @@
+/*
+    SSSD
+
+    Kerberos 5 Backend Module
+
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2009 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <errno.h>
+#include <sys/time.h>
+#include <krb5/krb5.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+
+#include <security/pam_modules.h>
+
+#include "util/util.h"
+#include "providers/dp_backend.h"
+#include "db/sysdb.h"
+#include "../sss_client/sss_cli.h"
+#include "krb5_plugin/sssd_krb5_locator_plugin.h"
+#include "providers/krb5/krb5_auth.h"
+
+static void fd_nonblocking(int fd) {
+    int flags;
+
+    flags = fcntl(fd, F_GETFL, 0);
+    if (flags == -1) {
+        DEBUG(1, ("F_GETFL failed [%d][%s].\n", errno, strerror(errno)));
+        return;
+    }
+
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
+        DEBUG(1, ("F_SETFL failed [%d][%s].\n", errno, strerror(errno)));
+    }
+
+    return;
+}
+
+static int save_cc_file(size_t len, uint8_t *buf)
+{
+
+    return EOK;
+}
+static void krb5_cleanup(struct krb5_req *kr)
+{
+    if (kr == NULL) return;
+
+    /* FIXME: is it safe to drop the "!= NULL" checks? */
+    if (kr->options != NULL)
+        krb5_get_init_creds_opt_free(kr->ctx, kr->options);
+    if (kr->creds != NULL)
+        krb5_free_cred_contents(kr->ctx, kr->creds);
+    if (kr->name != NULL)
+        krb5_free_unparsed_name(kr->ctx, kr->name);
+    if (kr->princ != NULL)
+        krb5_free_principal(kr->ctx, kr->princ);
+    if (kr->cc != NULL)
+        krb5_cc_close(kr->ctx, kr->cc);
+    if (kr->ctx != NULL)
+        krb5_free_context(kr->ctx);
+
+    talloc_free(kr);
+}
+
+static int krb5_setup(struct be_req *req, struct krb5_req **krb5_req)
+{
+    struct krb5_req *kr = NULL;
+    struct krb5_ctx *krb5_ctx;
+    struct pam_data *pd;
+    krb5_error_code kerr = 0;
+    char *user_princ_str = NULL;
+
+    pd = talloc_get_type(req->req_data, struct pam_data);
+
+    krb5_ctx = talloc_get_type(req->be_ctx->pvt_auth_data, struct krb5_ctx);
+
+    kr = talloc_zero(req, struct krb5_req);
+    if (kr == NULL) {
+        DEBUG(1, ("talloc failed.\n"));
+        kerr = ENOMEM;
+        goto failed;
+    }
+
+    kr->pd = pd;
+    kr->req = req;
+
+    kerr = krb5_init_context(&kr->ctx);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        goto failed;
+    }
+
+/* TODO: try to read user principal from id backend, use user + realm as a
+   fallback */
+    if (kr->pd->user != NULL && krb5_ctx->realm != NULL) {
+        user_princ_str = talloc_asprintf(kr, "%s@%s", kr->pd->user,
+                                                      krb5_ctx->realm);
+    }
+    if (user_princ_str == NULL) {
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        kerr = ENOMEM;
+        goto failed;
+    }
+
+    kerr = krb5_parse_name(kr->ctx, user_princ_str, &kr->princ);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        goto failed;
+    }
+
+    kerr = krb5_unparse_name(kr->ctx, kr->princ, &kr->name);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        goto failed;
+    }
+
+    kr->creds = talloc_zero(kr, krb5_creds);
+    if (kr->creds == NULL) {
+        DEBUG(1, ("talloc_zero failed.\n"));
+        kerr = ENOMEM;
+        goto failed;
+    }
+
+    kerr = krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        goto failed;
+    }
+
+/* TODO: set options, e.g.
+ *  krb5_get_init_creds_opt_set_tkt_life
+ *  krb5_get_init_creds_opt_set_renew_life
+ *  krb5_get_init_creds_opt_set_forwardable
+ *  krb5_get_init_creds_opt_set_proxiable
+ *  krb5_get_init_creds_opt_set_etype_list
+ *  krb5_get_init_creds_opt_set_address_list
+ *  krb5_get_init_creds_opt_set_preauth_list
+ *  krb5_get_init_creds_opt_set_salt
+ *  krb5_get_init_creds_opt_set_change_password_prompt
+ *  krb5_get_init_creds_opt_set_pa
+ */
+
+    *krb5_req = kr;
+    return EOK;
+
+failed:
+    krb5_cleanup(kr);
+
+    return kerr;
+}
+
+/* TODO: remove later
+ * These functions are available in the latest tevent and are the ones that
+ * should be used as tevent_req is rightfully opaque there */
+#ifndef tevent_req_data
+#define tevent_req_data(req, type) ((type *)req->private_state)
+#endif
+
+#ifndef tevent_req_set_callback
+#define tevent_req_set_callback(req, func, data) \
+    do { req->async.fn = func; req->async.private_data = data; } while(0)
+#endif
+
+#ifndef tevent_req_callback_data
+#define tevent_req_callback_data(req, type) ((type *)req->async.private_data)
+#endif
+
+static void wait_for_child_handler(struct tevent_context *ev,
+                                struct tevent_signal *sige, int signum,
+                                int count, void *__siginfo, void *pvt)
+{
+    int ret;
+    int child_status;
+    siginfo_t *siginfo = (siginfo_t *)__siginfo;
+
+    errno = 0;
+    do {
+        ret = waitpid(siginfo->si_pid, &child_status, WNOHANG);
+    } while (ret == -1 && errno == EINTR);
+    if (ret == siginfo->si_pid) {
+        DEBUG(4, ("child status [%d].\n", child_status));
+        if (WEXITSTATUS(child_status) != 0) {
+            DEBUG(1, ("child failed.\n"));
+        }
+    } else if (ret == 0) {
+        DEBUG(1, ("waitpid did not found a child with changed status.\n", ret));
+    } else if (ret >= 0 && ret != siginfo->si_pid) {
+        DEBUG(1, ("waitpid returned wrong child pid [%d], continue waiting.\n", ret));
+    } else if (ret == -1 && errno == ECHILD) {
+        DEBUG(1, ("no child with pid [%d].\n", siginfo->si_pid));
+    } else {
+        DEBUG(1, ("waitpid failed [%s].\n", strerror(errno)));
+    }
+
+    return;
+}
+
+static int fork_tgt_req_child(struct krb5_req *kr)
+{
+    int pipefd[2];
+    pid_t pid;
+    int ret;
+
+    ret = pipe(pipefd);
+    if (ret == -1) {
+        DEBUG(1, ("pipe failed [%d][%s].\n", errno, strerror(errno)));
+        return -1;
+    }
+    pid = fork();
+
+    if (pid == 0) { /* child */
+        close(pipefd[0]);
+        tgt_req_child(pipefd[1], kr);
+    } else if (pid > 0) { /* parent */
+        kr->child_pid = pid;
+        kr->fd = pipefd[0];
+        close(pipefd[1]);
+
+        fd_nonblocking(kr->fd);
+
+    } else { /* error */
+        DEBUG(1, ("fork failed [%d][%s].\n", errno, strerror(errno)));
+        return -1;
+    }
+
+    return EOK;
+}
+
+
+struct read_pipe_state {
+    int fd;
+    uint8_t *buf;
+    size_t len;
+};
+
+static void read_pipe_done(struct tevent_context *ev, struct tevent_fd *fde,
+                         uint16_t flags, void *pvt);
+
+static struct tevent_req *read_pipe_send(TALLOC_CTX *memctx,
+                                       struct tevent_context *ev,
+                                       int fd)
+{
+    struct tevent_req *req;
+    struct read_pipe_state *state;
+    struct tevent_fd *fde;
+
+
+    req = tevent_req_create(memctx, &state, struct read_pipe_state);
+    if (req == NULL) return NULL;
+
+    state->fd = fd;
+    state->buf = talloc_array(state, uint8_t, MAX_CHILD_MSG_SIZE);
+    if (state->buf == NULL) goto fail;
+
+    fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ,
+                       read_pipe_done, req);
+    if (fde == NULL) {
+        DEBUG(1, ("tevent_add_fd failed.\n"));
+        goto fail;
+    }
+
+    return req;
+
+fail:
+    talloc_zfree(req);
+    return NULL;
+}
+
+static void read_pipe_done(struct tevent_context *ev, struct tevent_fd *fde,
+                         uint16_t flags, void *pvt)
+{
+    ssize_t size;
+    struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
+    struct read_pipe_state *state = tevent_req_data(req, struct read_pipe_state);
+
+    if (flags & TEVENT_FD_WRITE) {
+        DEBUG(1, ("client_response_handler called with TEVENT_FD_WRITE, this should not happen.\n"));
+        tevent_req_error(req, EINVAL);
+        return;
+    }
+
+    size = read(state->fd, state->buf, talloc_get_size(state->buf));
+    if (size == -1) {
+        if (errno == EAGAIN || errno == EINTR) return;
+        DEBUG(1, ("read failed [%d][%s].\n", errno, strerror(errno)));
+        tevent_req_error(req, errno);
+        return;
+    }
+    state->len = size;
+
+    tevent_req_done(req);
+    return;
+}
+
+static ssize_t read_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+                        uint8_t **buf, uint64_t *error) {
+    struct read_pipe_state *state = tevent_req_data(req,
+                                                    struct read_pipe_state);
+    enum tevent_req_state tstate;
+
+    if (tevent_req_is_error(req, &tstate, error)) {
+        return -1;
+    }
+
+    *buf = talloc_move(mem_ctx, &state->buf);
+    return state->len;
+}
+
+struct tgt_req_state {
+    struct krb5_req *kr;
+    ssize_t len;
+    uint8_t *buf;
+};
+
+static void tgt_req_done(struct tevent_req *subreq);
+
+static struct tevent_req *tgt_req_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+                        struct krb5_req *kr)
+{
+    int ret;
+    struct tevent_req *req;
+    struct tevent_req *subreq;
+    struct tgt_req_state *state;
+
+    ret = fork_tgt_req_child(kr);
+    if (ret != EOK) {
+        DEBUG(1, ("fork_tgt_req_child failed.\n"));
+        return NULL;
+    }
+
+    req = tevent_req_create(mem_ctx, &state, struct tgt_req_state);
+    if (req == NULL) {
+        return NULL;
+    }
+
+    state->kr = kr;
+
+    subreq = read_pipe_send(state, ev, kr->fd);
+    if (tevent_req_nomem(subreq, req)) {
+        return tevent_req_post(req, ev);
+    }
+    tevent_req_set_callback(subreq, tgt_req_done, req);
+    return req;
+}
+
+static void tgt_req_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct tgt_req_state *state = tevent_req_data(req, struct tgt_req_state);
+    uint64_t error;
+
+    state->len = read_pipe_recv(subreq, state, &state->buf, &error);
+    talloc_zfree(subreq);
+    close(state->kr->fd);
+    if (state->len == -1) {
+        tevent_req_error(req, error);
+        return;
+    }
+
+    tevent_req_done(req);
+    return;
+}
+
+static ssize_t tgt_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+                     uint8_t **buf, uint64_t *error) {
+    struct tgt_req_state *state = tevent_req_data(req, struct tgt_req_state);
+    enum tevent_req_state tstate;
+
+    if (tevent_req_is_error(req, &tstate, error)) {
+        return -1;
+    }
+
+    *buf = talloc_move(mem_ctx, &state->buf);
+    return state->len;
+}
+
+static void krb5_pam_handler_done(struct tevent_req *req);
+
+static void krb5_pam_handler(struct be_req *be_req)
+{
+    struct krb5_req *kr = NULL;
+    struct tevent_req *req;
+    int ret;
+    struct pam_data *pd;
+    int pam_status=PAM_SYSTEM_ERR;
+
+    pd = talloc_get_type(be_req->req_data, struct pam_data);
+
+    if (pd->cmd != SSS_PAM_AUTHENTICATE) {
+        DEBUG(4, ("krb5 does not handles pam task %d.\n", pd->cmd));
+        pam_status = PAM_SUCCESS;
+        goto done;
+    }
+
+    ret = krb5_setup(be_req, &kr);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_setup failed.\n"));
+        goto done;
+    }
+
+    req = tgt_req_send(be_req, be_req->be_ctx->ev, kr);
+    if (req == NULL) {
+        DEBUG(1, ("tgt_req_send failed.\n"));
+        goto done;
+    }
+
+    tevent_req_set_callback(req, krb5_pam_handler_done, kr);
+    return;
+
+done:
+    krb5_cleanup(kr);
+
+    pd->pam_status = pam_status;
+
+    be_req->fn(be_req, pam_status, NULL);
+}
+
+static void krb5_pam_handler_done(struct tevent_req *req)
+{
+    struct krb5_req *kr = tevent_req_callback_data(req, struct krb5_req);
+    struct pam_data *pd = kr->pd;
+    struct be_req *be_req = kr->req;
+    struct krb5_ctx *krb5_ctx = talloc_get_type(be_req->be_ctx->pvt_auth_data,
+                                                struct krb5_ctx);
+    struct tgt_req_state *state = tevent_req_data(req, struct tgt_req_state);
+    int ret;
+    uint8_t *buf;
+    ssize_t len;
+    uint64_t error;
+    int p;
+    int32_t *msg_status;
+    int32_t *msg_type;
+    int32_t *msg_len;
+
+    pd->pam_status = PAM_SYSTEM_ERR;
+    krb5_cleanup(kr);
+
+    len = tgt_req_recv(req, state, &buf, &error);
+    talloc_zfree(req);
+    if (len == -1) {
+        DEBUG(1, ("tgt_req request failed\n"));
+        goto done;
+    }
+
+    if ((size_t) len < 3*sizeof(int32_t)) {
+        DEBUG(1, ("message too short.\n"));
+        goto done;
+    }
+
+    p=0;
+    msg_status = ((int32_t *)(buf+p));
+    p += sizeof(int32_t);
+
+    msg_type = ((int32_t *)(buf+p));
+    p += sizeof(int32_t);
+
+    msg_len = ((int32_t *)(buf+p));
+    p += sizeof(int32_t);
+
+    DEBUG(4, ("child response [%d][%d][%d].\n", *msg_status, *msg_type,
+                                                *msg_len));
+
+    if ((p + *msg_len) != len) {
+        DEBUG(1, ("message format error.\n"));
+        goto done;
+    }
+
+    if (msg_type == PAM_ENV_ITEM && krb5_ctx->enable_cc_remover == TRUE) {
+        ret = save_cc_file(*msg_len, &buf[p]);
+        if (ret != EOK) {
+            DEBUG(2, ("save_cc_file failed. cc_remover might not be able to "
+                      "remove this file\n"));
+        }
+    }
+
+    ret=pam_add_response(kr->pd, *msg_type, *msg_len, &buf[p]);
+    if (ret != EOK) {
+        DEBUG(1, ("pam_add_response failed.\n"));
+        goto done;
+    }
+
+    pd->pam_status = *msg_status;
+
+done:
+    be_req->fn(be_req, pd->pam_status, NULL);
+}
+
+
+struct be_auth_ops krb5_auth_ops = {
+    .pam_handler = krb5_pam_handler,
+    .finalize = NULL,
+};
+
+
+int sssm_krb5_auth_init(struct be_ctx *bectx, struct be_auth_ops **ops,
+                   void **pvt_auth_data)
+{
+    struct krb5_ctx *ctx = NULL;
+    bool bool_value = FALSE;
+    char *value = NULL;
+    int ret;
+    struct tevent_signal *sige;
+
+    ctx = talloc_zero(bectx, struct krb5_ctx);
+    if (!ctx) {
+        DEBUG(1, ("talloc failed.\n"));
+        return ENOMEM;
+    }
+
+    ctx->action = INIT_PW;
+
+    ret = confdb_get_bool(bectx->cdb, ctx, bectx->conf_path,
+                            "enableCCRemover", FALSE, &bool_value);
+    if (ret != EOK) goto fail;
+    ctx->enable_cc_remover = bool_value;
+
+    ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path,
+                            "krb5KDCIP", NULL, &value);
+    if (ret != EOK) goto fail;
+    if (value == NULL) {
+        DEBUG(2, ("Missing krb5KDCIP, authentication might fail.\n"));
+    } else {
+        ret = setenv(SSSD_KDC, value, 1);
+        if (ret != EOK) {
+            DEBUG(2, ("setenv %s failed, authentication might fail.\n",
+                      SSSD_KDC));
+        }
+    }
+    ctx->kdcip = value;
+
+    ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path,
+                            "krb5REALM", NULL, &value);
+    if (ret != EOK) goto fail;
+    if (value == NULL) {
+        DEBUG(4, ("Missing krb5REALM authentication might fail.\n"));
+    } else {
+        ret = setenv(SSSD_REALM, value, 1);
+        if (ret != EOK) {
+            DEBUG(2, ("setenv %s failed, authentication might fail.\n",
+                      SSSD_REALM));
+        }
+    }
+    ctx->realm = value;
+
+/* TODO: set options */
+
+    sige = tevent_add_signal(bectx->ev, ctx, SIGCHLD, SA_SIGINFO,
+                       wait_for_child_handler, NULL);
+    if (sige == NULL) {
+        DEBUG(1, ("tevent_add_signal failed.\n"));
+        ret = ENOMEM;
+        goto fail;
+    }
+
+
+    *ops = &krb5_auth_ops;
+    *pvt_auth_data = ctx;
+    return EOK;
+
+fail:
+    talloc_free(ctx);
+    return ret;
+}
diff --git a/server/providers/krb5/krb5_auth.h b/server/providers/krb5/krb5_auth.h
new file mode 100644
index 0000000..4ae91dd
--- /dev/null
+++ b/server/providers/krb5/krb5_auth.h
@@ -0,0 +1,92 @@
+/*
+    SSSD
+
+    Kerberos Backend, private header file
+
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2009 Red Hat
+
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __KRB5_AUTH_H__
+#define __KRB5_AUTH_H__
+
+#define MAX_CHILD_MSG_SIZE 255
+#define CCACHE_ENV_NAME "KRB5CCNAME"
+
+typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
+
+struct krb5_ctx {
+    /* opts taken from kinit */
+    /* in seconds */
+    krb5_deltat starttime;
+    krb5_deltat lifetime;
+    krb5_deltat rlife;
+
+    int forwardable;
+    int proxiable;
+    int addresses;
+
+    int not_forwardable;
+    int not_proxiable;
+    int no_addresses;
+
+    int verbose;
+
+    char* principal_name;
+    char* service_name;
+    char* keytab_name;
+    char* k5_cache_name;
+    char* k4_cache_name;
+
+    action_type action;
+
+    int num_pa_opts;
+    krb5_gic_opt_pa_data *pa_opts;
+
+    char *kdcip;
+    char *realm;
+    bool enable_cc_remover;
+};
+
+struct krb5_req {
+    krb5_context ctx;
+    krb5_ccache cc;
+    krb5_principal princ;
+    char* name;
+    krb5_creds *creds;
+    krb5_get_init_creds_opt *options;
+    pid_t child_pid;
+    int fd;
+
+    struct be_req *req;
+    struct pam_data *pd;
+    struct krb5_ctx *krb5_ctx;
+};
+
+static krb5_context krb5_error_ctx;
+static const char *__krb5_error_msg;
+#define KRB5_DEBUG(level, krb5_error) do { \
+    __krb5_error_msg = krb5_get_error_message(krb5_error_ctx, krb5_error); \
+    DEBUG(level, ("%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg)); \
+    krb5_free_error_message(krb5_error_ctx, __krb5_error_msg); \
+} while(0);
+
+void tgt_req_child(int fd, struct krb5_req *kr);
+
+#endif /* __KRB5_AUTH_H__ */
diff --git a/server/providers/krb5/tgt_req_child.c b/server/providers/krb5/tgt_req_child.c
new file mode 100644
index 0000000..edb3d18
--- /dev/null
+++ b/server/providers/krb5/tgt_req_child.c
@@ -0,0 +1,179 @@
+/*
+    SSSD
+
+    Kerberos 5 Backend Module -- tgt_req child
+
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2009 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <krb5/krb5.h>
+#include <sys/types.h>
+
+#include <security/pam_modules.h>
+
+#include "util/util.h"
+#include "providers/dp_backend.h"
+#include "providers/krb5/krb5_auth.h"
+
+static int pack_response_packet(uint8_t *buf, int status, int type,
+                                const char *data)
+{
+    int len;
+    int p=0;
+
+    if ((3*sizeof(int32_t) + strlen(data)+1) > MAX_CHILD_MSG_SIZE) {
+        return -1;
+    }
+
+    ((int32_t *)(&buf[p]))[0] = status;
+    p += sizeof(int32_t);
+
+    ((int32_t *)(&buf[p]))[0] = type;
+    p += sizeof(int32_t);
+
+    len = strlen(data)+1;
+    ((int32_t *)(&buf[p]))[0] = len;
+    p += sizeof(int32_t);
+
+    memcpy(&buf[p], data, len);
+    p += len;
+
+    return p;
+}
+
+void tgt_req_child(int fd, struct krb5_req *kr)
+{
+    int ret;
+    krb5_error_code kerr = 0;
+    char *pass_str = NULL;
+    uint8_t buf[MAX_CHILD_MSG_SIZE];
+    int size = 0;
+    const char *cc_name;
+    char *env;
+    const char *krb5_error_msg;
+
+    ret = setgid(kr->pd->gr_gid);
+    if (ret == -1) {
+        DEBUG(1, ("setgid failed [%d][%s].\n", errno, strerror(errno)));
+        _exit(-1);
+    }
+
+    ret = setuid(kr->pd->pw_uid);
+    if (ret == -1) {
+        DEBUG(1, ("setuid failed [%d][%s].\n", errno, strerror(errno)));
+        _exit(-1);
+    }
+
+    ret = setegid(kr->pd->gr_gid);
+    if (ret == -1) {
+        DEBUG(1, ("setegid failed [%d][%s].\n", errno, strerror(errno)));
+        _exit(-1);
+    }
+
+    ret = seteuid(kr->pd->pw_uid);
+    if (ret == -1) {
+        DEBUG(1, ("seteuid failed [%d][%s].\n", errno, strerror(errno)));
+        _exit(-1);
+    }
+
+    pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
+                              kr->pd->authtok_size);
+    if (pass_str == NULL) {
+        DEBUG(1, ("talloc_strndup failed.\n"));
+        _exit(-1);
+    }
+
+    kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
+                                        pass_str, NULL, NULL, 0, NULL,
+                                        kr->options);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        goto childfailed;
+    }
+
+    memset(pass_str, 0, kr->pd->authtok_size);
+    talloc_free(pass_str);
+    memset(kr->pd->authtok, 0, kr->pd->authtok_size);
+
+    kerr = krb5_cc_default(kr->ctx, &kr->cc);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        goto childfailed;
+    }
+
+    kerr = krb5_cc_initialize(kr->ctx, kr->cc, kr->princ);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        goto childfailed;
+    }
+
+    kerr = krb5_cc_store_cred(kr->ctx, kr->cc, kr->creds);
+    if (kerr != 0) {
+        KRB5_DEBUG(1, kerr);
+        krb5_cc_destroy(kr->ctx, kr->cc);
+        goto childfailed;
+    }
+
+    cc_name = krb5_cc_get_name(kr->ctx, kr->cc);
+    if (cc_name == NULL) {
+        DEBUG(1, ("krb5_cc_get_name failed.\n"));
+        krb5_cc_destroy(kr->ctx, kr->cc);
+        _exit(-1);
+    }
+
+    env = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, cc_name);
+    if (env == NULL) {
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        krb5_cc_destroy(kr->ctx, kr->cc);
+        _exit(-1);
+    }
+
+    size = pack_response_packet(buf, PAM_SUCCESS, PAM_ENV_ITEM, env);
+    if (size < 0) {
+        DEBUG(1, ("failed to create response message.\n"));
+        krb5_cc_destroy(kr->ctx, kr->cc);
+        _exit(-1);
+    }
+
+    kerr = 0;
+
+childfailed:
+    if (kerr != 0 ) {
+        krb5_error_msg = krb5_get_error_message(krb5_error_ctx, kerr);
+        size = pack_response_packet(buf, PAM_SYSTEM_ERR, PAM_USER_INFO,
+                                    krb5_error_msg);
+        if (size < 0) {
+            DEBUG(1, ("failed to create response message.\n"));
+            krb5_cc_destroy(kr->ctx, kr->cc);
+            _exit(-1);
+        }
+        krb5_free_error_message(krb5_error_ctx, krb5_error_msg);
+    }
+
+    ret = write(fd, buf, size);
+    if (ret == -1) {
+        DEBUG(1, ("write failed [%d][%s].\n", errno, strerror(errno)));
+        krb5_cc_destroy(kr->ctx, kr->cc);
+        _exit(ret);
+    }
+
+    krb5_cc_close(kr->ctx, kr->cc);
+
+
+    _exit(0);
+}
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index e065490..9b02146 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -22,6 +22,7 @@
 
 #include <time.h>
 #include "util/util.h"
+#include "db/sysdb.h"
 #include "confdb/confdb.h"
 #include "responder/common/responder_packet.h"
 #include "responder/common/responder.h"
@@ -387,7 +388,6 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
     size_t blen;
     int timeout;
     int ret;
-
     preq = talloc_zero(cctx, struct pam_auth_req);
     if (!preq) {
         return ENOMEM;
@@ -716,6 +716,24 @@ static void pam_check_user_callback(void *ptr, int status,
     case 1:
 
         /* BINGO */
+        preq->pd->pw_uid =
+            ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_UIDNUM, -1);
+        if (preq->pd->pw_uid == -1) {
+            DEBUG(1, ("Failed to find uid for user [%s] in domain [%s].\n",
+                      preq->pd->user, preq->pd->domain));
+            preq->pd->pam_status = PAM_SYSTEM_ERR;
+            pam_reply(preq);
+        }
+
+        preq->pd->gr_gid =
+            ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_GIDNUM, -1);
+        if (preq->pd->gr_gid == -1) {
+            DEBUG(1, ("Failed to find gid for user [%s] in domain [%s].\n",
+                      preq->pd->user, preq->pd->domain));
+            preq->pd->pam_status = PAM_SYSTEM_ERR;
+            pam_reply(preq);
+        }
+
         pam_dom_forwarder(preq);
         return;
 
diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c
index ccc205c..a10e0ea 100644
--- a/sss_client/pam_sss.c
+++ b/sss_client/pam_sss.c
@@ -426,7 +426,7 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf)
                     break;
                 }
                 logger(pamh, LOG_INFO, "user info: [%s]", &buf[p]);
-                ret = do_pam_conversation(pamh, PAM_USER_INFO, (char *) &buf[p],
+                ret = do_pam_conversation(pamh, PAM_TEXT_INFO, (char *) &buf[p],
                                           NULL, NULL);
                 if (ret != PAM_SUCCESS) {
                     D(("do_pam_conversation, canot display user info."));
diff --git a/sssd.spec.in b/sssd.spec.in
index 719e6b7..1fa847d 100644
--- a/sssd.spec.in
+++ b/sssd.spec.in
@@ -80,6 +80,7 @@ rm -f \
     $RPM_BUILD_ROOT/%{_libdir}/ldb/memberof.la \
     $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_ldap.la \
     $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_proxy.la \
+    $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_krb5.la \
     $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.la
 
 %clean
-- 
1.6.2.5



More information about the Freeipa-devel mailing list