[SSSD] [PATCH] Add experimental support to receive PAC via GSSAPI

Sumit Bose sbose at redhat.com
Wed Jun 15 13:57:10 UTC 2011


On Tue, Jun 07, 2011 at 02:14:56PM +0200, Jan Zelený wrote:
> > Hi,
> > 
> > this series of patches adds support to receive a windows PAC via GSSAPI
> > and to create a user based on the data in the PAC. This is useful
> > because in an environment with lots of trust relationships between AD
> > server it might be quite time consuming to find out about all the group
> > memberships of a domain user by querying the domain controllers. But the
> > PAC contains all information about group memberships of the
> > corresponding user.
> > 
> > The general idea is to add the user, if it doesn't exist in the cache,
> > to the cache of the corresponding domain (see thread about sub-domains,
> > currently this patch add the user to the local domain for simplicity)
> > and to add all group memberships (currently not implemented). If one of
> > the groups cannot be found in the cache a dummy entry with all data
> > needed to resolve this group quickly is added to the cache.
> > 
> > Currently there are a couple of loose end, e.g.
> > - groups and group memberships are not handled
> > - PAC is not validated
> > - missing sub-domains
> > - no real SID to uid/gid mapping
> > 
> > etc, but I like to start the discussion about the code and the general
> > direction as soon as possible. Currently sssd with these patches can
> > only be build on rawhide, because of the dependencies to the samba4
> > package (libndr-krb5pac).
> > 
> > Patch 0007 contains a little example that demonstrates that the pac
> > responder can also be used to add user and groups based on other input,
> > e.g. it can be used as a backend for the sss_* utilities. This would
> > allow a much better control about which user is allowed to do what kind
> > of operation. Currently only the root user can add and modify user and
> > group entries with the sss_* tools.
> > 
> > I have used 'pac' as a part of names here because this was the original
> > target, but I would be happy to change it to a more generic keyword if
> > anyone has a good suggestion.
> > 
> > bye,
> > Sumit
> 
> 
> Hi,
> 
> I'm sending some comments based on code review (I didn't actually try the 
> code). I skipped all autotools parts, since it's not my area of expertise and 
> it still makes my eyes bleed.
> 
> 0002
> - pac_get_config() seems redundant

removed, we can easily add it if we start using config options

> - what is the pac_ctx structure for? Is it there for some future
>   extensibility? So far it seems to be redundant

yes, there is a similar context in the pam and nss responders and I
expect that we will have more data in the context in future.

> 
> 0004
> - would it be possible to wrap those unbelievably long and lines in
>   pac_add_pac_user() in some kind of macro or function?
> - the block on lines 149-156 doesn't make any sense (should the last line
>   be deleted)

I have restructured this file a bit and hope it makes the intention more
clear now.

> 
> 0005
> - as we discussed on IRC, functions sssdpac_externalize() and
>   sssdpac_internalize() might be redundant. If they are mandatory, please
>   try to find out if it's ok just to place a return in them, it would be better
>   I think
> - the sssdpac_size() function is mandatory?

all three are mandatory and have to return to data, because all three
are used as a substitute is the copy call, which is optional, is not
available. See src/lib/krb5/krb/authdata.c in the MIT sources starting
at line 960 for details.

> - can you just briefly explain, what does the flag AD_USAGE_TGS_REQ in
>   sssdpac_flags() mean. It's little confusing for me

ah, thanks, AD_USAGE_TGS_REQ is wrong here. I have changed it to
'AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL' which means that we are
interested in data issued by the KDC and the caller must not fail if an
error occurs. With AD_USAGE_TGS_REQ the client can add data in the TGS
request. See http://k5wiki.kerberos.org/wiki/Projects/VerifyAuthData for
some more information.

> 
> 0007
> - as I pointed out before, I'm against implementing functions which won't be
>   used
> - considering we wanted to push the patch anyway, what is the purpose of
>   pac_cmd_handler() function? I mean why don't we call pac_putpwent() and
>   other similar functions directly?
> 

I dropped the patch completely for now but I keep it in my tree. If
someone finds a good use case I can update it and send it again.

> 
> Thanks
> Jan

Thank you very much for the review.

bye,
Sumit


> _______________________________________________
> sssd-devel mailing list
> sssd-devel at lists.fedorahosted.org
> https://fedorahosted.org/mailman/listinfo/sssd-devel

-------------- next part --------------
From 895456996743d130cc480368a2c683604b0fedba Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 13 May 2011 18:44:15 +0200
Subject: [PATCH 1/6] Add configure option to build pac responder

---
 configure.ac                  |    1 +
 src/external/pac_responder.m4 |   29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)
 create mode 100644 src/external/pac_responder.m4

diff --git a/configure.ac b/configure.ac
index 972c24c..71dc14e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,6 +113,7 @@ m4_include([src/external/nsupdate.m4])
 m4_include([src/external/libkeyutils.m4])
 m4_include([src/external/libnl.m4])
 m4_include([src/external/systemd.m4])
+m4_include([src/external/pac_responder.m4])
 m4_include([src/util/signal.m4])
 
 WITH_INITSCRIPT
diff --git a/src/external/pac_responder.m4 b/src/external/pac_responder.m4
new file mode 100644
index 0000000..a3f997e
--- /dev/null
+++ b/src/external/pac_responder.m4
@@ -0,0 +1,29 @@
+AC_SUBST(NDR_KRB5PAC_CFLAGS)
+AC_SUBST(NDR_KRB5PAC_LIBS)
+
+AC_ARG_ENABLE([experimental-pac-responder],
+              [AS_HELP_STRING([--enable-experimental-pac-responder],
+                              [build experimental pac responder])],
+              [build_pac_responder=$enableval],
+              [build_pac_responder=no])
+
+if test x$build_pac_responder == xyes
+then
+    PKG_CHECK_MODULES(NDR_KRB5PAC, ndr_krb5pac,,
+        AC_MSG_ERROR([Cannot build pac responder without libndr_krb5pac]))
+
+    AC_PATH_PROG(KRB5_CONFIG, krb5-config)
+    AC_MSG_CHECKING(for supported MIT krb5 version)
+    KRB5_VERSION="`$KRB5_CONFIG --version`"
+    case $KRB5_VERSION in
+        Kerberos\ 5\ release\ 1.9*)
+            AC_MSG_RESULT(yes)
+            ;;
+        *)
+            AC_MSG_ERROR([Cannot build authdata plugin with this version of
+                          MIT Kerberos, please use 1.9.x])
+    esac
+fi
+
+AM_CONDITIONAL([BUILD_PAC_RESPONDER], [test x$build_pac_responder = xyes ])
+
-- 
1.7.5.2

-------------- next part --------------
From 9eeb6e2f63fe5fe529e719829c6cc835445ac7b8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 19 Apr 2011 15:49:01 +0200
Subject: [PATCH 2/6] Add infrastructure for pac responder

---
 Makefile.am                    |   20 ++++
 src/confdb/confdb.h            |    3 +
 src/monitor/monitor.c          |    2 +-
 src/responder/pac/pacsrv.c     |  205 ++++++++++++++++++++++++++++++++++++++++
 src/responder/pac/pacsrv.h     |   51 ++++++++++
 src/responder/pac/pacsrv_cmd.c |   60 ++++++++++++
 6 files changed, 340 insertions(+), 1 deletions(-)
 create mode 100644 src/responder/pac/pacsrv.c
 create mode 100644 src/responder/pac/pacsrv.h
 create mode 100644 src/responder/pac/pacsrv_cmd.c

diff --git a/Makefile.am b/Makefile.am
index b8423ba..ec011b2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -65,6 +65,10 @@ sssdlibexec_PROGRAMS = \
     ldap_child \
     proxy_child
 
+if BUILD_PAC_RESPONDER
+    sssdlibexec_PROGRAMS += sssd_pac
+endif
+
 if HAVE_CHECK
     non_interactive_check_based_tests = \
         sysdb-tests \
@@ -190,6 +194,7 @@ AM_CPPFLAGS = \
     -DSSSD_CONF_DIR=\"$(sssdconfdir)\" \
     -DSSS_NSS_SOCKET_NAME=\"$(pipepath)/nss\" \
     -DSSS_PAM_SOCKET_NAME=\"$(pipepath)/pam\" \
+    -DSSS_PAC_SOCKET_NAME=\"$(pipepath)/pac\" \
     -DSSS_PAM_PRIV_SOCKET_NAME=\"$(pipepath)/private/pam\" \
     -DLOCALEDIR=\"$(localedir)\"
 
@@ -288,6 +293,7 @@ dist_noinst_HEADERS = \
     src/responder/nss/nsssrv.h \
     src/responder/nss/nsssrv_private.h \
     src/responder/nss/nsssrv_netgroup.h \
+    src/responder/pac/pacsrv.h \
     src/responder/common/negcache.h \
     src/sbus/sbus_client.h \
     src/sbus/sssd_dbus.h \
@@ -398,6 +404,20 @@ sssd_pam_LDADD = \
     $(SSSD_LIBS) \
     libsss_util.la
 
+sssd_pac_SOURCES = \
+    src/responder/pac/pacsrv.c \
+    src/responder/pac/pacsrv_cmd.c \
+    $(SSSD_UTIL_OBJ) \
+    $(SSSD_RESPONDER_OBJ)
+sssd_pac_CFLAGS = \
+    $(AM_CFLAGS) \
+    $(NDR_KRB5PAC_CFLAGS)
+sssd_pac_LDADD = \
+    $(NDR_KRB5PAC_LIBS) \
+    $(TDB_LIBS) \
+    $(SSSD_LIBS) \
+    libsss_util.la
+
 sssd_be_SOURCES = \
     src/providers/data_provider_be.c \
     src/providers/data_provider_fo.c \
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index c2ae9fc..4f75af8 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -88,6 +88,9 @@
 #define CONFDB_PAM_ID_TIMEOUT "pam_id_timeout"
 #define CONFDB_PAM_PWD_EXPIRATION_WARNING "pam_pwd_expiration_warning"
 
+/* PAC */
+#define CONFDB_PAC_CONF_ENTRY "config/pac"
+
 /* Data Provider */
 #define CONFDB_DP_CONF_ENTRY "config/dp"
 
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index d1f2e66..bb47a53 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -818,7 +818,7 @@ static int check_local_domain_unique(struct sss_domain_info *domains)
 
 static char *check_services(char **services)
 {
-    const char *known_services[] = { "nss", "pam", NULL };
+    const char *known_services[] = { "nss", "pam", "pac", NULL };
     int i;
     int ii;
 
diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
new file mode 100644
index 0000000..d308665
--- /dev/null
+++ b/src/responder/pac/pacsrv.c
@@ -0,0 +1,205 @@
+/*
+   SSSD
+
+   PAC Responder
+
+   Copyright (C) Sumit Bose <sbose at redhat.com> 2011
+
+   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 <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include "popt.h"
+#include "util/util.h"
+#include "responder/pac/pacsrv.h"
+#include "db/sysdb.h"
+#include "confdb/confdb.h"
+#include "dbus/dbus.h"
+#include "sbus/sssd_dbus.h"
+#include "responder/common/responder_packet.h"
+#include "responder/common/responder.h"
+#include "providers/data_provider.h"
+#include "monitor/monitor_interfaces.h"
+#include "sbus/sbus_client.h"
+
+#define SSS_PAC_PIPE_NAME "pac"
+
+struct sbus_method monitor_pac_methods[] = {
+    { MON_CLI_METHOD_PING, monitor_common_pong },
+    { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
+    { MON_CLI_METHOD_ROTATE, monitor_common_rotate_logs },
+    { NULL, NULL }
+};
+
+struct sbus_interface monitor_pac_interface = {
+    MONITOR_INTERFACE,
+    MONITOR_PATH,
+    SBUS_DEFAULT_VTABLE,
+    monitor_pac_methods,
+    NULL
+};
+
+static struct sbus_method pac_dp_methods[] = {
+    { NULL, NULL }
+};
+
+struct sbus_interface pac_dp_interface = {
+    DP_INTERFACE,
+    DP_PATH,
+    SBUS_DEFAULT_VTABLE,
+    pac_dp_methods,
+    NULL
+};
+
+
+/* TODO: check if this can be made generic for all responders */
+static void pac_dp_reconnect_init(struct sbus_connection *conn,
+                                  int status, void *pvt)
+{
+    struct be_conn *be_conn = talloc_get_type(pvt, struct be_conn);
+    int ret;
+
+    /* Did we reconnect successfully? */
+    if (status == SBUS_RECONNECT_SUCCESS) {
+        DEBUG(1, ("Reconnected to the Data Provider.\n"));
+
+        /* Identify ourselves to the data provider */
+        ret = dp_common_send_id(be_conn->conn,
+                                DATA_PROVIDER_VERSION,
+                                "PAC");
+        /* all fine */
+        if (ret == EOK) {
+            handle_requests_after_reconnect();
+            return;
+        }
+    }
+
+    /* Failed to reconnect */
+    DEBUG(0, ("Could not reconnect to %s provider.\n",
+              be_conn->domain->name));
+
+    /* FIXME: kill the frontend and let the monitor restart it ? */
+    /* nss_shutdown(rctx); */
+}
+
+int pac_process_init(TALLOC_CTX *mem_ctx,
+                     struct tevent_context *ev,
+                     struct confdb_ctx *cdb)
+{
+    struct sss_cmd_table *pac_cmds;
+    struct be_conn *iter;
+    struct pac_ctx *pac_ctx;
+    int ret, max_retries;
+
+    pac_ctx = talloc_zero(mem_ctx, struct pac_ctx);
+    if (!pac_ctx) {
+        DEBUG(0, ("fatal error initializing pac_ctx\n"));
+        return ENOMEM;
+    }
+
+    pac_cmds = get_pac_cmds();
+
+    ret = sss_process_init(pac_ctx, ev, cdb,
+                           pac_cmds,
+                           SSS_PAC_SOCKET_NAME, NULL,
+                           CONFDB_PAC_CONF_ENTRY,
+                           PAC_SBUS_SERVICE_NAME,
+                           PAC_SBUS_SERVICE_VERSION,
+                           &monitor_pac_interface,
+                           "PAC", &pac_dp_interface,
+                           &pac_ctx->rctx);
+    if (ret != EOK) {
+        return ret;
+    }
+    pac_ctx->rctx->pvt_ctx = pac_ctx;
+
+    /* Enable automatic reconnection to the Data Provider */
+    ret = confdb_get_int(pac_ctx->rctx->cdb, pac_ctx->rctx,
+                         CONFDB_PAC_CONF_ENTRY,
+                         CONFDB_SERVICE_RECON_RETRIES,
+                         3, &max_retries);
+    if (ret != EOK) {
+        DEBUG(0, ("Failed to set up automatic reconnection\n"));
+        return ret;
+    }
+
+    for (iter = pac_ctx->rctx->be_conns; iter; iter = iter->next) {
+        sbus_reconnect_init(iter->conn, max_retries,
+                            pac_dp_reconnect_init, iter);
+    }
+
+    DEBUG(1, ("PAC Initialization complete\n"));
+
+    return EOK;
+}
+
+int main(int argc, const char *argv[])
+{
+    int opt;
+    poptContext pc;
+    struct main_context *main_ctx;
+    int ret;
+
+    struct poptOption long_options[] = {
+        POPT_AUTOHELP
+        SSSD_MAIN_OPTS
+        POPT_TABLEEND
+    };
+
+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+    while((opt = poptGetNextOpt(pc)) != -1) {
+        switch(opt) {
+        default:
+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
+                  poptBadOption(pc, 0), poptStrerror(opt));
+            poptPrintUsage(pc, stderr, 0);
+            return 1;
+        }
+    }
+
+    poptFreeContext(pc);
+
+   /* set up things like debug, signals, daemonization, etc... */
+    debug_log_file = "sssd_pac";
+
+    ret = server_setup("sssd[pac]", 0, CONFDB_PAC_CONF_ENTRY, &main_ctx);
+    if (ret != EOK) return 2;
+
+    ret = die_if_parent_died();
+    if (ret != EOK) {
+        /* This is not fatal, don't return */
+        DEBUG(2, ("Could not set up to exit when parent process does\n"));
+    }
+
+    ret = pac_process_init(main_ctx,
+                           main_ctx->event_ctx,
+                           main_ctx->confdb_ctx);
+    if (ret != EOK) return 3;
+
+    /* loop on main */
+    server_loop(main_ctx);
+
+    return 0;
+}
+
diff --git a/src/responder/pac/pacsrv.h b/src/responder/pac/pacsrv.h
new file mode 100644
index 0000000..1b28254
--- /dev/null
+++ b/src/responder/pac/pacsrv.h
@@ -0,0 +1,51 @@
+/*
+   SSSD
+
+   PAC Responder, header file
+
+   Copyright (C) Sumit Bose <sbose at redhat.com> 2011
+
+   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 __PACSRV_H__
+#define __PACSRV_H__
+
+#include <stdint.h>
+#include <sys/un.h>
+#include "config.h"
+#include "talloc.h"
+#include "tevent.h"
+#include "ldb.h"
+#include "dbus/dbus.h"
+#include "sbus/sssd_dbus.h"
+#include "responder/common/responder_packet.h"
+#include "responder/common/responder.h"
+
+#define PAC_SBUS_SERVICE_VERSION 0x0001
+#define PAC_SBUS_SERVICE_NAME "pac"
+
+#define PAC_PACKET_MAX_RECV_SIZE 1024
+
+struct getent_ctx;
+
+struct pac_ctx {
+    struct resp_ctx *rctx;
+};
+
+int pac_cmd_execute(struct cli_ctx *cctx);
+
+struct sss_cmd_table *get_pac_cmds(void);
+
+#endif /* __PACSRV_H__ */
diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c
new file mode 100644
index 0000000..42ff3f8
--- /dev/null
+++ b/src/responder/pac/pacsrv_cmd.c
@@ -0,0 +1,60 @@
+/*
+   SSSD
+
+   PAC Responder
+
+   Copyright (C) Sumit Bose <sbose at redhat.com> 2011
+
+   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 "util/util.h"
+#include "responder/pac/pacsrv.h"
+#include "confdb/confdb.h"
+#include "db/sysdb.h"
+
+struct cli_protocol_version *register_cli_protocol_version(void)
+{
+    static struct cli_protocol_version pac_cli_protocol_version[] = {
+        {1, "2011-04-12", "initial version"},
+        {0, NULL, NULL}
+    };
+
+    return pac_cli_protocol_version;
+}
+
+static struct sss_cmd_table pac_cmds[] = {
+    {SSS_GET_VERSION, sss_cmd_get_version},
+    {SSS_CLI_NULL, NULL}
+};
+
+struct sss_cmd_table *get_pac_cmds(void) {
+    return pac_cmds;
+}
+
+int pac_cmd_execute(struct cli_ctx *cctx)
+{
+    enum sss_cli_command cmd;
+    int i;
+
+    cmd = sss_packet_get_cmd(cctx->creq->in);
+
+    for (i = 0; pac_cmds[i].cmd != SSS_CLI_NULL; i++) {
+        if (cmd == pac_cmds[i].cmd) {
+            return pac_cmds[i].fn(cctx);
+        }
+    }
+
+    return EINVAL;
+}
-- 
1.7.5.2

-------------- next part --------------
From 62d118ee7b600a266be0b9632ebf5d39e46cfa07 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 13 May 2011 18:41:16 +0200
Subject: [PATCH 3/6] Add pac support to client

---
 src/sss_client/common.c  |   33 +++++++++++++++++++++++++++++++++
 src/sss_client/sss_cli.h |    5 +++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index b603305..537f28e 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -373,6 +373,8 @@ static bool sss_cli_check_version(const char *socket_name)
     } else if (strcmp(socket_name, SSS_PAM_SOCKET_NAME) == 0 ||
                strcmp(socket_name, SSS_PAM_PRIV_SOCKET_NAME) == 0) {
         expected_version = SSS_PAM_PROTOCOL_VERSION;
+    } else if (strcmp(socket_name, SSS_PAC_SOCKET_NAME) == 0) {
+        expected_version = SSS_PAC_PROTOCOL_VERSION;
     } else {
         return false;
     }
@@ -705,6 +707,37 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
     }
 }
 
+int sss_pac_make_request(enum sss_cli_command cmd,
+                         struct sss_cli_req_data *rd,
+                         uint8_t **repbuf, size_t *replen,
+                         int *errnop)
+{
+    enum sss_status ret;
+    char *envval;
+
+    /* avoid looping in the nss daemon */
+    envval = getenv("_SSS_LOOPS");
+    if (envval && strcmp(envval, "NO") == 0) {
+        return NSS_STATUS_NOTFOUND;
+    }
+
+    ret = sss_cli_check_socket(errnop, SSS_PAC_SOCKET_NAME);
+    if (ret != SSS_STATUS_SUCCESS) {
+        return NSS_STATUS_UNAVAIL;
+    }
+
+    ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+    switch (ret) {
+    case SSS_STATUS_TRYAGAIN:
+        return NSS_STATUS_TRYAGAIN;
+    case SSS_STATUS_SUCCESS:
+        return NSS_STATUS_SUCCESS;
+    case SSS_STATUS_UNAVAIL:
+    default:
+        return NSS_STATUS_UNAVAIL;
+    }
+}
+
 errno_t check_server_cred(int sockfd)
 {
 #ifdef HAVE_UCRED
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index ebdcc26..7c0ec11 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -37,6 +37,7 @@ typedef int errno_t;
 
 #define SSS_NSS_PROTOCOL_VERSION 1
 #define SSS_PAM_PROTOCOL_VERSION 3
+#define SSS_PAC_PROTOCOL_VERSION 1
 
 /**
  * @defgroup sss_cli_command SSS client commands
@@ -444,6 +445,10 @@ int sss_pam_make_request(enum sss_cli_command cmd,
                                      struct sss_cli_req_data *rd,
                                      uint8_t **repbuf, size_t *replen,
                                      int *errnop);
+int sss_pac_make_request(enum sss_cli_command cmd,
+                         struct sss_cli_req_data *rd,
+                         uint8_t **repbuf, size_t *replen,
+                         int *errnop);
 
 #ifndef SAFEALIGN_COPY_UINT32
 static inline void
-- 
1.7.5.2

-------------- next part --------------
From 033f0935afbb5c818ea3e285ab1b452f51a72287 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 18 May 2011 13:28:17 +0200
Subject: [PATCH 4/6] Add server-side pac support

---
 src/responder/pac/pacsrv.c     |    2 +-
 src/responder/pac/pacsrv_cmd.c |  248 ++++++++++++++++++++++++++++++++++++++++
 src/sss_client/sss_cli.h       |    3 +
 3 files changed, 252 insertions(+), 1 deletions(-)

diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
index d308665..b67f2f0 100644
--- a/src/responder/pac/pacsrv.c
+++ b/src/responder/pac/pacsrv.c
@@ -48,7 +48,7 @@
 struct sbus_method monitor_pac_methods[] = {
     { MON_CLI_METHOD_PING, monitor_common_pong },
     { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, monitor_common_rotate_logs },
+    { MON_CLI_METHOD_ROTATE, responder_logrotate },
     { NULL, NULL }
 };
 
diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c
index 42ff3f8..18394fc 100644
--- a/src/responder/pac/pacsrv_cmd.c
+++ b/src/responder/pac/pacsrv_cmd.c
@@ -24,6 +24,253 @@
 #include "confdb/confdb.h"
 #include "db/sysdb.h"
 
+#include <util/data_blob.h>
+#include <ndr.h>
+
+#include "gen_ndr/krb5pac.h"
+#include "gen_ndr/ndr_krb5pac.h"
+
+#define PAC_USER_OFFSET 200000
+#define PAC_HOME_PATH "/home/"
+#define PAC_DEFAULT_SHELL "/bin/bash"
+
+static errno_t pac_cmd_done(struct cli_ctx *cctx, int cmd_ret)
+{
+    int ret;
+
+    ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
+                         &cctx->creq->out);
+    if (ret != EOK) {
+        DEBUG(1, ("sss_packet_new failed [%d][%s].\n", ret, strerror(ret)));
+        return ret;
+    }
+
+    sss_packet_set_error(cctx->creq->out, cmd_ret);
+
+    sss_cmd_done(cctx, NULL);
+
+    return EOK;
+}
+
+static errno_t domsid_rid_to_uid(struct dom_sid2 *domsid, uint32_t rid,
+                                 uid_t *uid)
+{
+    /* Replace with a proper mapping  */
+    *uid = (uid_t) rid + PAC_USER_OFFSET;
+    return EOK;
+}
+
+static errno_t domsid_rid_to_gid(struct dom_sid2 *domsid, uint32_t rid,
+                                 gid_t *gid)
+{
+    /* Replace with a proper mapping  */
+    *gid = (gid_t) rid + PAC_USER_OFFSET;
+    return EOK;
+}
+
+static errno_t get_data_from_pac(TALLOC_CTX *mem_ctx,
+                                uint8_t *pac_blob, size_t pac_len,
+                                struct passwd **_pwd, char **domain)
+{
+    DATA_BLOB blob;
+    struct ndr_pull *ndr_pull;
+    struct PAC_DATA *pac_data;
+    enum ndr_err_code ndr_err;
+    struct passwd *pwd = NULL;
+    size_t c;
+    struct netr_SamBaseInfo *base_info;
+    int ret;
+
+    blob.data = pac_blob;
+    blob.length = pac_len;
+
+    ndr_pull = ndr_pull_init_blob(&blob, mem_ctx);
+    if (ndr_pull == NULL) {
+        DEBUG(1, ("ndr_pull_init_blob failed.\n"));
+        return ENOMEM;
+    }
+    ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC; /* FIXME: is this really needed ? */
+
+    pac_data = talloc_zero(mem_ctx, struct PAC_DATA);
+    if (pac_data == NULL) {
+        DEBUG(1, ("talloc_zero failed.\n"));
+    return EOK;
+        return ENOMEM;
+    }
+
+    ndr_err = ndr_pull_PAC_DATA(ndr_pull, NDR_SCALARS|NDR_BUFFERS, pac_data);
+    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+        DEBUG(1, ("ndr_pull_PAC_DATA failed [%d]\n", ndr_err));
+        return EBADMSG;
+    }
+
+    pwd = talloc_zero(mem_ctx, struct passwd);
+    if (pwd == NULL) {
+        DEBUG(1, ("talloc_zero failed.\n"));
+        return ENOMEM;
+    }
+
+    for(c = 0; c < pac_data->num_buffers; c++) {
+        if (pac_data->buffers[c].type == PAC_TYPE_LOGON_INFO) {
+            base_info = &pac_data->buffers[c].info->logon_info.info->info3.base;
+
+            if (base_info->account_name.size != 0) {
+                pwd->pw_name = talloc_strdup(pwd,
+                                             base_info->account_name.string);
+                if (pwd->pw_name == NULL) {
+                    DEBUG(1, ("talloc_strdup failed.\n"));
+                    ret = ENOMEM;
+                    goto done;
+                }
+            } else {
+                DEBUG(1, ("Missing account name in PAC.\n"));
+                ret = EINVAL;
+                goto done;
+            }
+
+            if (base_info->rid > 0) {
+                ret = domsid_rid_to_uid(base_info->domain_sid,
+                                        base_info->rid,
+                                        &pwd->pw_uid);
+                if (ret != EOK) {
+                    DEBUG(1, ("domsid_rid_to_uid failed.\n"));
+                    goto done;
+                }
+            } else {
+                DEBUG(1, ("Missing user RID in PAC.\n"));
+                ret = EINVAL;
+                goto done;
+            }
+
+            if (base_info->primary_gid > 0) {
+                ret = domsid_rid_to_gid(base_info->domain_sid,
+                                        base_info->primary_gid,
+                                        &pwd->pw_gid);
+                if (ret != EOK) {
+                    DEBUG(1, ("domsid_rid_to_gid failed.\n"));
+                    goto done;
+                }
+            } else {
+                DEBUG(1, ("Missing primary GID in PAC.\n"));
+                ret = EINVAL;
+                goto done;
+            }
+
+            if (base_info->full_name.size != 0) {
+                pwd->pw_gecos = talloc_strdup(pwd, base_info->full_name.string);
+            } else {
+                DEBUG(1, ("Missing full name in PAC using account name for gecos.\n"));
+                pwd->pw_gecos = talloc_strdup(pwd,
+                                              base_info->account_name.string);
+            }
+            if (pwd->pw_gecos == NULL) {
+                DEBUG(1, ("talloc_strdup failed.\n"));
+                ret = ENOMEM;
+                goto done;
+            }
+
+            pwd->pw_dir = talloc_asprintf(mem_ctx, PAC_HOME_PATH"%s",
+                                         base_info->account_name.string);
+            if (pwd->pw_dir == NULL) {
+                DEBUG(1, ("talloc_asprintf failed.\n"));
+                ret = ENOMEM;
+                goto done;
+            }
+
+            pwd->pw_shell = talloc_strdup(pwd, PAC_DEFAULT_SHELL);
+            if (pwd->pw_shell == NULL) {
+                DEBUG(1, ("talloc_strdup failed.\n"));
+                ret = ENOMEM;
+                goto done;
+            }
+
+            *domain = talloc_strdup(mem_ctx, base_info->domain.string);
+            if (*domain == NULL) {
+                DEBUG(1, ("talloc_strdup failed.\n"));
+                ret = ENOMEM;
+                goto done;
+            }
+
+            *_pwd = pwd;
+
+            return EOK;
+        }
+    }
+
+    ret = EINVAL;
+
+done:
+    talloc_free(pwd);
+    return ret;
+}
+
+
+static errno_t pac_add_pac_user(struct cli_ctx *cctx)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    int ret;
+    struct sysdb_ctx *sysdb;
+    char *domain_name;
+    struct sss_domain_info *dom = NULL;
+    struct passwd *pwd;
+    uint8_t *body;
+    size_t blen;
+
+    sss_packet_get_body(cctx->creq->in, &body, &blen);
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(1, ("talloc_new failed.\n"));
+        return ENOMEM;
+    }
+
+    ret = get_data_from_pac(tmp_ctx, body, blen, &pwd, &domain_name);
+    if (ret != EOK) {
+        DEBUG(1, ("get_pwd_from_pac failed.\n"));
+        goto done;
+    }
+
+    for (dom = cctx->rctx->domains; dom; dom = dom->next) {
+        if (strcasecmp(dom->provider, domain_name) == 0) break;
+    }
+    if (dom == NULL) {
+        /* TODO: Maybe remove this fallback if sssd can handle sub-domains */
+        DEBUG(1, ("Domain [%s] not found, trying local domain.\n", domain_name));
+        for (dom = cctx->rctx->domains; dom; dom = dom->next) {
+            if (strcasecmp(dom->provider, "local") == 0) break;
+        }
+        if (dom == NULL) {
+            DEBUG(1, ("No local domain found.\n"));
+            ret = ENOENT;
+            goto done;
+        }
+
+        /* The local domain is an mpg domain, gid will be set automatically
+         * and has to be zero */
+        pwd->pw_gid = 0;
+    }
+
+
+    ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, dom, &sysdb);
+    if (ret != EOK) {
+        DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
+        goto done;
+    }
+
+    ret = sysdb_store_user(tmp_ctx, sysdb, dom, pwd->pw_name, NULL,
+                           pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,
+                           pwd->pw_shell, NULL, NULL, 0);
+    if (ret != EOK) {
+        DEBUG(1, ("sysdb_store_user failed [%d][%s].\n", ret, strerror(ret)));
+        goto done;
+    }
+
+done:
+    talloc_free(tmp_ctx);
+
+    return pac_cmd_done(cctx, ret);
+}
+
 struct cli_protocol_version *register_cli_protocol_version(void)
 {
     static struct cli_protocol_version pac_cli_protocol_version[] = {
@@ -36,6 +283,7 @@ struct cli_protocol_version *register_cli_protocol_version(void)
 
 static struct sss_cmd_table pac_cmds[] = {
     {SSS_GET_VERSION, sss_cmd_get_version},
+    {SSS_PAC_ADD_PAC_USER, pac_add_pac_user},
     {SSS_CLI_NULL, NULL}
 };
 
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index 7c0ec11..c5751fd 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -144,6 +144,9 @@ enum sss_cli_command {
     SSS_NSS_ENDSPENT       = 0x00B5,
 #endif
 
+/* PAC responder calls */
+    SSS_PAC_ADD_PAC_USER     = 0x00E1,
+
 /* PAM related calls */
     SSS_PAM_AUTHENTICATE     = 0x00F1, /**< see pam_sm_authenticate(3) for
                                         * details.
-- 
1.7.5.2

-------------- next part --------------
From cc382cbcdd46a2926460fd8e1e8a2b40e3dd9343 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 24 May 2011 11:12:28 +0200
Subject: [PATCH 5/6] Add krb5 authdata plugin to send the pac

---
 Makefile.am                        |   21 +++
 configure.ac                       |    1 +
 src/conf_macros.m4                 |   14 ++
 src/sss_client/krb5_authdata_int.h |  185 ++++++++++++++++++++++++
 src/sss_client/sssd_pac.c          |  276 ++++++++++++++++++++++++++++++++++++
 5 files changed, 497 insertions(+), 0 deletions(-)
 create mode 100644 src/sss_client/krb5_authdata_int.h
 create mode 100644 src/sss_client/sssd_pac.c

diff --git a/Makefile.am b/Makefile.am
index ec011b2..949f4b7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,6 +18,9 @@ ldblibdir = @ldblibdir@
 if BUILD_KRB5_LOCATOR_PLUGIN
 krb5plugindir = @krb5pluginpath@
 endif
+if BUILD_PAC_RESPONDER
+krb5authdata_plugindir = @krb5authdatapluginpath@
+endif
 sssdconfdir = $(sysconfdir)/sssd
 sssdapiplugindir = $(sssdconfdir)/sssd.api.d
 dbusintrospectdir = $(datarootdir)/sssd/introspect
@@ -116,6 +119,11 @@ krb5plugin_LTLIBRARIES = \
     sssd_krb5_locator_plugin.la
 endif
 
+if BUILD_PAC_RESPONDER
+krb5authdata_plugin_LTLIBRARIES = \
+    sssd_pac_plugin.la
+endif
+
 noinst_LTLIBRARIES = \
     libsss_crypt.la
 
@@ -987,6 +995,19 @@ sssd_krb5_locator_plugin_la_LDFLAGS = \
     -module
 endif
 
+sssd_pac_plugin_la_SOURCES = \
+    src/sss_client/sssd_pac.c \
+    src/sss_client/common.c \
+    src/sss_client/sss_cli.h \
+    src/sss_client/krb5_authdata_int.h
+sssd_pac_plugin_la_CFLAGS = \
+    $(AM_CFLAGS) \
+    $(KRB5_CFLAGS)
+sssd_pac_plugin_la_LDFLAGS = \
+    -lkrb5 \
+    -avoid-version \
+    -module
+
 if BUILD_PYTHON_BINDINGS
 pysss_la_SOURCES = \
     $(SSSD_TOOLS_OBJ) \
diff --git a/configure.ac b/configure.ac
index 71dc14e..212e9f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,6 +82,7 @@ WITH_TEST_DIR
 WITH_MANPAGES
 WITH_XML_CATALOG
 WITH_KRB5_PLUGIN_PATH
+WITH_KRB5AUTHDATA_PLUGIN_PATH
 WITH_PYTHON_BINDINGS
 WITH_SELINUX
 WITH_NSCD
diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
index af9cb4f..626772b 100644
--- a/src/conf_macros.m4
+++ b/src/conf_macros.m4
@@ -204,6 +204,20 @@ AC_DEFUN([WITH_KRB5_PLUGIN_PATH],
     AC_SUBST(krb5pluginpath)
   ])
 
+AC_DEFUN([WITH_KRB5AUTHDATA_PLUGIN_PATH],
+  [ AC_ARG_WITH([krb5authdata-plugin-path],
+                [AC_HELP_STRING([--with-krb5authdata-plugin-path=PATH],
+                                [Path to kerberos authdata plugin store [/usr/lib/krb5/plugins/authdata]]
+                               )
+                ]
+               )
+    krb5authdatapluginpath="${libdir}/krb5/plugins/authdata"
+    if test x"$with_krb5authdata_plugin_path" != x; then
+        krb5authdatapluginpath=$with_krb5authdata_plugin_path
+    fi
+    AC_SUBST(krb5authdatapluginpath)
+  ])
+
 AC_DEFUN([WITH_PYTHON_BINDINGS],
   [ AC_ARG_WITH([python-bindings],
                 [AC_HELP_STRING([--with-python-bindings],
diff --git a/src/sss_client/krb5_authdata_int.h b/src/sss_client/krb5_authdata_int.h
new file mode 100644
index 0000000..5e0cf5e
--- /dev/null
+++ b/src/sss_client/krb5_authdata_int.h
@@ -0,0 +1,185 @@
+/*
+    SSSD - MIT Kerberos authdata plugin
+
+    This file contains definitions and declarations to build authdata plugins
+    for MIT Kerberos outside of the MIT Kerberos source tree.
+*/
+
+#ifndef _KRB5_AUTHDATA_INT_H
+#define _KRB5_AUTHDATA_INT_H
+
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_int32(krb5_int32, krb5_octet **, size_t *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_ser_unpack_int32(krb5_int32 *, krb5_octet **, size_t *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_bytes(krb5_octet *, size_t, krb5_octet **, size_t *);
+
+#define AD_USAGE_AS_REQ         0x01
+#define AD_USAGE_TGS_REQ        0x02
+#define AD_USAGE_AP_REQ         0x04
+#define AD_USAGE_KDC_ISSUED     0x08
+#define AD_USAGE_MASK           0x0F
+#define AD_INFORMATIONAL        0x10
+
+struct _krb5_authdata_context;
+typedef struct _krb5_authdata_context *krb5_authdata_context;
+
+typedef void
+(*authdata_client_plugin_flags_proc)(krb5_context kcontext,
+                                     void *plugin_context,
+                                     krb5_authdatatype ad_type,
+                                     krb5_flags *flags);
+
+typedef krb5_error_code
+(*authdata_client_plugin_init_proc)(krb5_context context,
+                                    void **plugin_context);
+typedef void
+(*authdata_client_plugin_fini_proc)(krb5_context kcontext,
+                                    void *plugin_context);
+
+typedef krb5_error_code
+(*authdata_client_request_init_proc)(krb5_context kcontext,
+                                     struct _krb5_authdata_context *context,
+                                     void *plugin_context,
+                                     void **request_context);
+
+typedef void
+(*authdata_client_request_fini_proc)(krb5_context kcontext,
+                                     struct _krb5_authdata_context *context,
+                                     void *plugin_context,
+                                     void *request_context);
+
+typedef krb5_error_code
+(*authdata_client_import_authdata_proc)(krb5_context kcontext,
+                                        struct _krb5_authdata_context *context,
+                                        void *plugin_context,
+                                        void *request_context,
+                                        krb5_authdata **authdata,
+                                        krb5_boolean kdc_issued_flag,
+                                        krb5_const_principal issuer);
+
+typedef krb5_error_code
+(*authdata_client_export_authdata_proc)(krb5_context kcontext,
+                                        struct _krb5_authdata_context *context,
+                                        void *plugin_context,
+                                        void *request_context,
+                                        krb5_flags usage,
+                                        krb5_authdata ***authdata);
+
+typedef krb5_error_code
+(*authdata_client_get_attribute_types_proc)(krb5_context kcontext,
+                                            struct _krb5_authdata_context *context,
+                                            void *plugin_context,
+                                            void *request_context,
+                                            krb5_data **attrs);
+
+typedef krb5_error_code
+(*authdata_client_get_attribute_proc)(krb5_context kcontext,
+                                      struct _krb5_authdata_context *context,
+                                      void *plugin_context,
+                                      void *request_context,
+                                      const krb5_data *attribute,
+                                      krb5_boolean *authenticated,
+                                      krb5_boolean *complete,
+                                      krb5_data *value,
+                                      krb5_data *display_value,
+                                      int *more);
+
+typedef krb5_error_code
+(*authdata_client_set_attribute_proc)(krb5_context kcontext,
+                                      struct _krb5_authdata_context *context,
+                                      void *plugin_context,
+                                      void *request_context,
+                                      krb5_boolean complete,
+                                      const krb5_data *attribute,
+                                      const krb5_data *value);
+
+typedef krb5_error_code
+(*authdata_client_delete_attribute_proc)(krb5_context kcontext,
+                                         struct _krb5_authdata_context *context,
+                                         void *plugin_context,
+                                         void *request_context,
+                                         const krb5_data *attribute);
+
+typedef krb5_error_code
+(*authdata_client_export_internal_proc)(krb5_context kcontext,
+                                        struct _krb5_authdata_context *context,
+                                        void *plugin_context,
+                                        void *request_context,
+                                        krb5_boolean restrict_authenticated,
+                                        void **ptr);
+
+typedef void
+(*authdata_client_free_internal_proc)(krb5_context kcontext,
+                                      struct _krb5_authdata_context *context,
+                                      void *plugin_context,
+                                      void *request_context,
+                                      void *ptr);
+
+typedef krb5_error_code
+(*authdata_client_verify_proc)(krb5_context kcontext,
+                               struct _krb5_authdata_context *context,
+                               void *plugin_context,
+                               void *request_context,
+                               const krb5_auth_context *auth_context,
+                               const krb5_keyblock *key,
+                               const krb5_ap_req *req);
+
+typedef krb5_error_code
+(*authdata_client_size_proc)(krb5_context kcontext,
+                             struct _krb5_authdata_context *context,
+                             void *plugin_context,
+                             void *request_context,
+                             size_t *sizep);
+
+typedef krb5_error_code
+(*authdata_client_externalize_proc)(krb5_context kcontext,
+                                    struct _krb5_authdata_context *context,
+                                    void *plugin_context,
+                                    void *request_context,
+                                    krb5_octet **buffer,
+                                    size_t *lenremain);
+
+typedef krb5_error_code
+(*authdata_client_internalize_proc)(krb5_context kcontext,
+                                    struct _krb5_authdata_context *context,
+                                    void *plugin_context,
+                                    void *request_context,
+                                    krb5_octet **buffer,
+                                    size_t *lenremain);
+
+typedef krb5_error_code
+(*authdata_client_copy_proc)(krb5_context kcontext,
+                             struct _krb5_authdata_context *context,
+                             void *plugin_context,
+                             void *request_context,
+                             void *dst_plugin_context,
+                             void *dst_request_context);
+
+typedef struct krb5plugin_authdata_client_ftable_v0 {
+    char *name;
+    krb5_authdatatype *ad_type_list;
+    authdata_client_plugin_init_proc init;
+    authdata_client_plugin_fini_proc fini;
+    authdata_client_plugin_flags_proc flags;
+    authdata_client_request_init_proc request_init;
+    authdata_client_request_fini_proc request_fini;
+    authdata_client_get_attribute_types_proc get_attribute_types;
+    authdata_client_get_attribute_proc get_attribute;
+    authdata_client_set_attribute_proc set_attribute;
+    authdata_client_delete_attribute_proc delete_attribute;
+    authdata_client_export_authdata_proc export_authdata;
+    authdata_client_import_authdata_proc import_authdata;
+    authdata_client_export_internal_proc export_internal;
+    authdata_client_free_internal_proc free_internal;
+    authdata_client_verify_proc verify;
+    authdata_client_size_proc size;
+    authdata_client_externalize_proc externalize;
+    authdata_client_internalize_proc internalize;
+    authdata_client_copy_proc copy; /* optional */
+} krb5plugin_authdata_client_ftable_v0;
+
+#endif /* _KRB5_AUTHDATA_INT_H */
diff --git a/src/sss_client/sssd_pac.c b/src/sss_client/sssd_pac.c
new file mode 100644
index 0000000..838276c
--- /dev/null
+++ b/src/sss_client/sssd_pac.c
@@ -0,0 +1,276 @@
+/*
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2011 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* A short documentation about authdata plugins can be found in
+ * http://http://k5wiki.kerberos.org/wiki/Projects/VerifyAuthData */
+
+#include <krb5/krb5.h>
+#include <errno.h>
+
+#include "krb5_authdata_int.h"
+#include "sss_cli.h"
+
+
+struct sssd_context {
+    krb5_data data;
+};
+
+static krb5_error_code
+sssdpac_init(krb5_context kcontext, void **plugin_context)
+{
+    *plugin_context = NULL;
+    return 0;
+}
+
+static void
+sssdpac_flags(krb5_context kcontext,
+              void *plugin_context,
+              krb5_authdatatype ad_type,
+              krb5_flags *flags)
+{
+    *flags = AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL;
+}
+
+static void
+sssdpac_fini(krb5_context kcontext, void *plugin_context)
+{
+    return;
+}
+
+static krb5_error_code
+sssdpac_request_init(krb5_context kcontext,
+                     krb5_authdata_context context,
+                     void *plugin_context,
+                     void **request_context)
+{
+    struct sssd_context *sssdctx;
+
+    sssdctx = (struct sssd_context *)calloc(1, sizeof(*sssdctx));
+    if (sssdctx == NULL)
+        return ENOMEM;
+
+    *request_context = sssdctx;
+
+    return 0;
+}
+
+static krb5_error_code
+sssdpac_import_authdata(krb5_context kcontext,
+                        krb5_authdata_context context,
+                        void *plugin_context,
+                        void *request_context,
+                        krb5_authdata **authdata,
+                        krb5_boolean kdc_issued,
+                        krb5_const_principal kdc_issuer)
+{
+    struct sss_cli_req_data sss_data;
+    int ret;
+    uint8_t *repbuf;
+    size_t replen;
+    int errnop;
+    char *data = NULL;
+    struct sssd_context *sssdctx = (struct sssd_context *)request_context;
+
+    if (authdata[0] == NULL) {
+        return EINVAL;
+    }
+
+    sss_data.len = authdata[0]->length;
+    sss_data.data = authdata[0]->contents;
+
+    ret = sss_pac_make_request(SSS_PAC_ADD_PAC_USER, &sss_data,
+                               &repbuf, &replen, &errnop);
+    if (ret != 0) {
+        /* Ignore the error */
+    }
+
+    if (authdata[0]->length > 0) {
+        data = malloc(sizeof(char) * authdata[0]->length);
+        if (data == NULL) {
+            return ENOMEM;
+        }
+        memcpy(data, authdata[0]->contents, authdata[0]->length);
+    }
+
+    if (sssdctx->data.data != NULL) {
+        krb5_free_data_contents(kcontext, &sssdctx->data);
+    }
+
+    sssdctx->data.length = authdata[0]->length;
+    sssdctx->data.data = data;
+    return 0;
+}
+
+static void
+sssdpac_request_fini(krb5_context kcontext,
+                     krb5_authdata_context context,
+                     void *plugin_context,
+                     void *request_context)
+{
+    struct sssd_context *sssdctx = (struct sssd_context *)request_context;
+
+    if (sssdctx != NULL) {
+        if (sssdctx->data.data != NULL)
+            krb5_free_data_contents(kcontext, &sssdctx->data);
+
+        free(sssdctx);
+    }
+}
+
+static krb5_error_code
+sssdpac_size(krb5_context kcontext,
+             krb5_authdata_context context,
+             void *plugin_context,
+             void *request_context,
+             size_t *sizep)
+{
+    struct sssd_context *sssdctx = (struct sssd_context *)request_context;
+
+    *sizep += sizeof(krb5_int32);
+
+    *sizep += sssdctx->data.length;
+
+    *sizep += sizeof(krb5_int32);
+
+    return 0;
+}
+
+static krb5_error_code
+sssdpac_externalize(krb5_context kcontext,
+                    krb5_authdata_context context,
+                    void *plugin_context,
+                    void *request_context,
+                    krb5_octet **buffer,
+                    size_t *lenremain)
+{
+    krb5_error_code code = 0;
+    struct sssd_context *sssdctx = (struct sssd_context *)request_context;
+    size_t required = 0;
+    krb5_octet *bp;
+    size_t remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    if (sssdctx->data.data != NULL) {
+        sssdpac_size(kcontext, context, plugin_context,
+                   request_context, &required);
+
+        if (required <= remain) {
+            krb5_ser_pack_int32((krb5_int32)sssdctx->data.length,
+                                &bp, &remain);
+            krb5_ser_pack_bytes((krb5_octet *)sssdctx->data.data,
+                                (size_t)sssdctx->data.length,
+                                &bp, &remain);
+            krb5_ser_pack_int32(0,
+                                &bp, &remain);
+        } else {
+            code = ENOMEM;
+        }
+    } else {
+        krb5_ser_pack_int32(0, &bp, &remain); /* length */
+        krb5_ser_pack_int32(0, &bp, &remain); /* verified */
+    }
+
+    *buffer = bp;
+    *lenremain = remain;
+
+    return code;
+}
+
+static krb5_error_code
+sssdpac_internalize(krb5_context kcontext,
+                    krb5_authdata_context context,
+                    void *plugin_context,
+                    void *request_context,
+                    krb5_octet **buffer,
+                    size_t *lenremain)
+{
+    struct sssd_context *sssdctx = (struct sssd_context *)request_context;
+    krb5_error_code code;
+    krb5_int32 ibuf;
+    krb5_octet *bp;
+    size_t remain;
+    krb5_data data;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    /* length */
+    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+    if (code != 0)
+        return code;
+
+    if (ibuf != 0) {
+
+        data.length = ibuf;
+        data.data = malloc(sizeof(char) * ibuf);
+        if (data.data == NULL) {
+            return ENOMEM;
+        }
+        memcpy(data.data, bp, ibuf);
+
+        bp += ibuf;
+        remain -= ibuf;
+    }
+
+    /* verified */
+    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+    if (code != 0) {
+        return code;
+    }
+
+    if (sssdctx->data.data != NULL) {
+        krb5_free_data_contents(kcontext, &sssdctx->data);
+    }
+
+    sssdctx->data.length = data.length;
+    sssdctx->data.data = data.data;
+
+    *buffer = bp;
+    *lenremain = remain;
+
+    return 0;
+}
+
+static krb5_authdatatype sssdpac_ad_types[] = { KRB5_AUTHDATA_WIN2K_PAC, 0 };
+
+krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
+    ((void *)((uintptr_t)("sssd_sssdpac"))),
+    sssdpac_ad_types,
+    sssdpac_init,
+    sssdpac_fini,
+    sssdpac_flags,
+    sssdpac_request_init,
+    sssdpac_request_fini,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    sssdpac_import_authdata,
+    NULL,
+    NULL,
+    NULL,
+    sssdpac_size,
+    sssdpac_externalize,
+    sssdpac_internalize,
+    NULL
+};
-- 
1.7.5.2

-------------- next part --------------
From e5543508175a8b11122a802eecbae93bd10fec8c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 24 May 2011 11:57:09 +0200
Subject: [PATCH 6/6] Build pac responder in example spec file

---
 contrib/sssd.spec.in |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index b148180..532de77 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -132,6 +132,7 @@ done
 autoreconf -ivf
 
 %configure \
+    --enable-experimental-pac-responder \
     --with-db-path=%{dbpath} \
     --with-pipe-path=%{pipepath} \
     --with-pubconf-path=%{pubconfpath} \
@@ -181,6 +182,7 @@ rm -f \
     $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_ipa.la \
     $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_simple.la \
     $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.la \
+    $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/authdata/sssd_pac_plugin.la \
     $RPM_BUILD_ROOT/%{python_sitearch}/pysss.la
 
 # Older versions of rpmbuild can only handle one -f option
@@ -243,6 +245,7 @@ rm -rf $RPM_BUILD_ROOT
 /%{_lib}/libnss_sss.so.2
 /%{_lib}/security/pam_sss.so
 %{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so
+%{_libdir}/krb5/plugins/authdata/sssd_pac_plugin.so
 %{_mandir}/man8/pam_sss.8*
 %{_mandir}/man8/sssd_krb5_locator_plugin.8*
 
-- 
1.7.5.2



More information about the sssd-devel mailing list