[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